1 /*
2  * Copyright (c) 2002, 2018, Oracle and/or its affiliates. All rights reserved.
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * This code is free software; you can redistribute it and/or modify it
6  * under the terms of the GNU General Public License version 2 only, as
7  * published by the Free Software Foundation.
8  *
9  * This code is distributed in the hope that it will be useful, but WITHOUT
10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
12  * version 2 for more details (a copy is included in the LICENSE file that
13  * accompanied this code).
14  *
15  * You should have received a copy of the GNU General Public License version
16  * 2 along with this work; if not, write to the Free Software Foundation,
17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18  *
19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20  * or visit www.oracle.com if you need additional information or have any
21  * questions.
22  */
23 
24 package nsk.jdi.ObjectReference.setValue;
25 
26 import com.sun.jdi.ObjectReference;
27 import com.sun.jdi.ReferenceType;
28 import com.sun.jdi.ThreadReference;
29 import com.sun.jdi.LocalVariable;
30 import com.sun.jdi.StackFrame;
31 import com.sun.jdi.Field;
32 import com.sun.jdi.AbsentInformationException;
33 import com.sun.jdi.NativeMethodException;
34 
35 import java.util.Iterator;
36 import java.util.List;
37 import java.io.*;
38 
39 import nsk.share.*;
40 import nsk.share.jpda.*;
41 import nsk.share.jdi.*;
42 
43 /**
44  * The test checks that the JDI method
45  * <code>com.sun.jdi.ObjectReference.setValue()</code>
46  * properly throws <i>IllegalArgumentException</i> - if the
47  * field is not valid for this object's class.<br>
48  * The debuggee part of the test contains two classes: the main one
49  * <i>setvalue002t</i> and the dummy one <i>DummyClass</i>. Each of
50  * them has the same set of static and instance fields.<br>
51  * The debugger part provokes the IllegalArgumentException trying to
52  * set value of:
53  * <li>an object reference to the debuggee's class <i>setvalue002t</i>
54  * and Field's value from an object reference to the debuggee's class
55  * <i>DummyClass</i>
56  * <li>an object reference to the debuggee's class <i>DummyClass</i>
57  * and Field's value from an object reference to the debuggee's class
58  * <i>setvalue002t</i>.<br>
59  */
60 public class setvalue002 {
61     static final String DEBUGGEE_CLASS =
62         "nsk.jdi.ObjectReference.setValue.setvalue002t";
63 
64     // name of debuggee's main thread
65     static final String DEBUGGEE_THRNAME = "setvalue002tThr";
66 
67     // debuggee's local var used to find needed stack frame
68     static final String DEBUGGEE_LOCALVAR = "dummyCls";
69 
70     static final int ATTEMPTS = 5;
71 
72     static final String COMMAND_READY = "ready";
73     static final String COMMAND_QUIT = "quit";
74 
75     private Log log;
76     private IOPipe pipe;
77     private Debugee debuggee;
78     private ThreadReference thrRef = null;
79     private ObjectReference[] objRef = new ObjectReference[2];
80     private int tot_res = Consts.TEST_PASSED;
81 
main(String argv[])82     public static void main (String argv[]) {
83         System.exit(run(argv,System.out) + Consts.JCK_STATUS_BASE);
84     }
85 
run(String argv[], PrintStream out)86     public static int run(String argv[], PrintStream out) {
87         return new setvalue002().runIt(argv, out);
88     }
89 
runIt(String args[], PrintStream out)90     private int runIt(String args[], PrintStream out) {
91         ArgumentHandler argHandler = new ArgumentHandler(args);
92         log = new Log(out, argHandler);
93         Binder binder = new Binder(argHandler, log);
94         ReferenceType[] rType = new ReferenceType[2];
95         String cmd;
96         int num = 0;
97 
98         debuggee = binder.bindToDebugee(DEBUGGEE_CLASS);
99         pipe = debuggee.createIOPipe();
100         debuggee.redirectStderr(log, "setvalue002t.err> ");
101         debuggee.resume();
102         cmd = pipe.readln();
103         if (!cmd.equals(COMMAND_READY)) {
104             log.complain("TEST BUG: unknown debuggee's command: " + cmd);
105             tot_res = Consts.TEST_FAILED;
106             return quitDebuggee();
107         }
108 
109         if ((thrRef =
110                 debuggee.threadByName(DEBUGGEE_THRNAME)) == null) {
111             log.complain("TEST FAILURE: Method Debugee.threadByName() returned null for debuggee's thread "
112                 + DEBUGGEE_THRNAME);
113             tot_res = Consts.TEST_FAILED;
114             return quitDebuggee();
115         }
116         thrRef.suspend();
117         while(!thrRef.isSuspended()) {
118             num++;
119             if (num > ATTEMPTS) {
120                 log.complain("TEST FAILED: Unable to suspend debuggee's thread");
121                 tot_res = Consts.TEST_FAILED;
122                 return quitDebuggee();
123             }
124             log.display("Waiting for debuggee's thread suspension ...");
125             try {
126                 Thread.currentThread().sleep(1000);
127             } catch(InterruptedException ie) {
128                 log.complain("TEST FAILED: caught: " + ie);
129                 tot_res = Consts.TEST_FAILED;
130                 return quitDebuggee();
131             }
132         }
133 
134 // Check the tested assersion
135         try {
136             findObjRefs(DEBUGGEE_LOCALVAR);
137             rType[0] = objRef[0].referenceType();
138             rType[1] = objRef[1].referenceType();
139 
140             // provoke the IllegalArgumentException using an object reference
141             // to debuggee's main class "setvalue002t" and Field's value from
142             // an object reference to debuggee's dummy class "DummyClass"
143             provokeException(objRef[0], rType[0], objRef[1], rType[1]);
144 
145             // provoke the IllegalArgumentException using an object reference
146             // to debuggee's dummy class "DummyClass" and Field's value from
147             // an object reference to debuggee's main class "setvalue002t"
148             provokeException(objRef[1], rType[1], objRef[0], rType[0]);
149         } catch (Exception e) {
150             e.printStackTrace();
151             log.complain("TEST FAILURE: caught unexpected exception: " + e);
152             tot_res = Consts.TEST_FAILED;
153             return quitDebuggee();
154         }
155 
156 // Finish the test
157         thrRef.resume();
158         return quitDebuggee();
159     }
160 
findObjRefs(String varName)161     private void findObjRefs(String varName) {
162         try {
163             List frames = thrRef.frames();
164             Iterator iter = frames.iterator();
165             while (iter.hasNext()) {
166                 StackFrame stackFr = (StackFrame) iter.next();
167                 try {
168                     LocalVariable locVar = stackFr.visibleVariableByName(varName);
169                     if (locVar == null)
170                         continue;
171                     // main debuggee class
172                     objRef[0] = stackFr.thisObject();
173                     // dummy debuggee class
174                     objRef[1] = (ObjectReference)stackFr.getValue(locVar);
175                     return;
176                 } catch(AbsentInformationException e) {
177                     // this is not needed stack frame, ignoring
178                 } catch(NativeMethodException ne) {
179                     // current method is native, also ignoring
180                 }
181             }
182         } catch (Exception e) {
183             e.printStackTrace();
184             tot_res = Consts.TEST_FAILED;
185             throw new Failure("findObjRef: caught unexpected exception: " + e);
186         }
187         throw new Failure("findObjRef: needed debuggee's stack frame not found");
188     }
189 
provokeException(ObjectReference objRef, ReferenceType refType, ObjectReference fldObjRef, ReferenceType fldRefType)190     private void provokeException(ObjectReference objRef,
191             ReferenceType refType,
192             ObjectReference fldObjRef, ReferenceType fldRefType) {
193         List fields;
194 
195         try {
196             fields = fldRefType.allFields();
197         } catch (Exception e) {
198             e.printStackTrace();
199             log.complain("TEST FAILURE: allFields for "
200                 + fldObjRef + ": caught: " + e);
201             tot_res = Consts.TEST_FAILED;
202             throw new Failure("provokeException: caught unexpected exception");
203         }
204 
205         Iterator iter = fields.iterator();
206         while (iter.hasNext()) {
207             Field fld = (Field) iter.next();
208             try {
209                 log.display("\nTrying to set value for the field \""
210                     + fld.name() + "\"\n\tfrom the debuggee's object reference \""
211                     + objRef
212                     + "\"\n\tusing not valid Field's value from the other object reference \""
213                     + fldObjRef + "\" ...");
214                 objRef.setValue(fld, objRef.getValue(refType.fieldByName(fld.name())));
215                 log.complain("TEST FAILED: expected IllegalArgumentException was not thrown"
216                     + "\n\twhen attempted to set value for the field \""
217                     + fld.name() + "\"\n\tfrom the debuggee's object reference \""
218                     + objRef
219                     + "\n\tusing not valid Field's value from the other object reference \""
220                     + fldObjRef + "\"");
221                 tot_res = Consts.TEST_FAILED;
222             } catch (IllegalArgumentException ee) {
223                 log.display("CHECK PASSED: caught expected " + ee);
224             } catch (Exception e) {
225                 e.printStackTrace();
226                 log.complain("TEST FAILED: ObjectReference.setValue(): caught unexpected "
227                     + e + "\n\tinstead of expected IllegalArgumentException"
228                     + "\n\twhen attempted to set value for the field \""
229                     + fld.name() + "\"\n\tfrom the debuggee's object reference \""
230                     + objRef
231                     + "\n\tusing not valid Field's value from the other object reference \""
232                     + fldObjRef + "\"");
233                 tot_res = Consts.TEST_FAILED;
234             }
235         }
236     }
237 
quitDebuggee()238     private int quitDebuggee() {
239         if (thrRef != null) {
240             if (thrRef.isSuspended())
241                 thrRef.resume();
242         }
243         pipe.println(COMMAND_QUIT);
244         debuggee.waitFor();
245         int debStat = debuggee.getStatus();
246         if (debStat != (Consts.JCK_STATUS_BASE + Consts.TEST_PASSED)) {
247             log.complain("TEST FAILED: debuggee's process finished with status: "
248                 + debStat);
249             tot_res = Consts.TEST_FAILED;
250         } else
251             log.display("Debuggee's process finished with the status: "
252                 + debStat);
253 
254         return tot_res;
255     }
256 
257 }
258