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.*;
27 
28 import java.util.Iterator;
29 import java.util.List;
30 import java.io.*;
31 
32 import nsk.share.*;
33 import nsk.share.jpda.*;
34 import nsk.share.jdi.*;
35 
36 /**
37  * The test checks that the JDI method
38  * <code>com.sun.jdi.ObjectReference.setValue()</code>
39  * properly throws <i>InvalidTypeException</i> - if the Field is valid
40  * for this ObjectReference, but there is no a widening reference
41  * conversion from this object to the field's type.<br>
42  * The debuggee part of the test has set of static and instance fields
43  * of different types. The debugger part provokes the <i>InvalidTypeException</i>
44  * trying to set value of:
45  * <li>type not matched with the field's one, and without the widening
46  * reference conversion as well
47  * <li>boolean type which can be converted only to boolean.<br>
48  */
49 public class setvalue003 {
50     static final String DEBUGGEE_CLASS =
51         "nsk.jdi.ObjectReference.setValue.setvalue003t";
52 
53     // name of debuggee's main thread
54     static final String DEBUGGEE_THRNAME = "setvalue003tThr";
55 
56     // debuggee's local var used to find needed stack frame
57     static final String DEBUGGEE_LOCALVAR = "setvalue003tPipe";
58 
59     static final int ATTEMPTS = 5;
60 
61     static final String COMMAND_READY = "ready";
62     static final String COMMAND_QUIT = "quit";
63 
64     static final int FLDS_NUM = 34;
65     // list of debuggee's fields used to set values and ones
66     // used only to get their wrong non-conversionable values,
67     // see section "5.1.2 Widening Primitive Conversion" in the JLS
68     static final String DEBUGGEE_FLDS[][] = {
69         {"byteFld", "sStrFld"},
70         {"shortFld", "intFld"},
71         {"intFld", "longFld"},
72         {"longFld", "floatFld"},
73         {"floatFld", "doubleFld"},
74         {"doubleFld", "sBooleanFld"},
75         {"charFld", "strFld"},
76         {"booleanFld", "byteFld"},
77         {"strFld", "sCharFld"},
78         {"sByteFld", "sIntFld"},
79         {"sShortFld", "doubleFld"},
80         {"sIntFld", "sStrFld"},
81         {"sLongFld", "sFloatFld"},
82         {"sFloatFld", "sDoubleFld"},
83         {"sDoubleFld", "strFld"},
84         {"sCharFld", "sDoubleFld"},
85         {"sBooleanFld", "doubleFld"},
86         {"sStrFld", "sDoubleFld"},
87     // see section "5.1.1 Identity Conversions" in the JLS:
88     // "the only permitted conversion that involves the type boolean is
89     // the identity conversion from boolean to boolean"
90         {"byteFld", "booleanFld"},
91         {"shortFld", "booleanFld"},
92         {"intFld", "booleanFld"},
93         {"longFld", "booleanFld"},
94         {"floatFld", "booleanFld"},
95         {"doubleFld", "booleanFld"},
96         {"charFld", "booleanFld"},
97         {"strFld", "booleanFld"},
98         {"sByteFld", "booleanFld"},
99         {"sShortFld", "booleanFld"},
100         {"sIntFld", "booleanFld"},
101         {"sLongFld", "booleanFld"},
102         {"sFloatFld", "booleanFld"},
103         {"sDoubleFld", "booleanFld"},
104         {"sCharFld", "booleanFld"},
105         {"sStrFld", "booleanFld"}
106     };
107 
108     private Log log;
109     private IOPipe pipe;
110     private Debugee debuggee;
111     private ThreadReference thrRef = null;
112     private int tot_res = Consts.TEST_PASSED;
113 
main(String argv[])114     public static void main (String argv[]) {
115         System.exit(run(argv,System.out) + Consts.JCK_STATUS_BASE);
116     }
117 
run(String argv[], PrintStream out)118     public static int run(String argv[], PrintStream out) {
119         return new setvalue003().runIt(argv, out);
120     }
121 
runIt(String args[], PrintStream out)122     private int runIt(String args[], PrintStream out) {
123         ArgumentHandler argHandler = new ArgumentHandler(args);
124         log = new Log(out, argHandler);
125         Binder binder = new Binder(argHandler, log);
126         ObjectReference objRef;
127         ReferenceType rType;
128         String cmd;
129         int num = 0;
130 
131         debuggee = binder.bindToDebugee(DEBUGGEE_CLASS);
132         pipe = debuggee.createIOPipe();
133         debuggee.redirectStderr(log, "setvalue003t.err> ");
134         debuggee.resume();
135         cmd = pipe.readln();
136         if (!cmd.equals(COMMAND_READY)) {
137             log.complain("TEST BUG: unknown debuggee's command: " + cmd);
138             tot_res = Consts.TEST_FAILED;
139             return quitDebuggee();
140         }
141 
142         if ((thrRef =
143                 debuggee.threadByName(DEBUGGEE_THRNAME)) == null) {
144             log.complain("TEST FAILURE: Method Debugee.threadByName() returned null for debuggee's thread "
145                 + DEBUGGEE_THRNAME);
146             tot_res = Consts.TEST_FAILED;
147             return quitDebuggee();
148         }
149         thrRef.suspend();
150         while(!thrRef.isSuspended()) {
151             num++;
152             if (num > ATTEMPTS) {
153                 log.complain("TEST FAILED: Unable to suspend debuggee's thread");
154                 tot_res = Consts.TEST_FAILED;
155                 return quitDebuggee();
156             }
157             log.display("Waiting for debuggee's thread suspension ...");
158             try {
159                 Thread.sleep(1000);
160             } catch(InterruptedException ie) {
161                 ie.printStackTrace();
162                 log.complain("TEST FAILED: caught: " + ie);
163                 tot_res = Consts.TEST_FAILED;
164                 return quitDebuggee();
165             }
166         }
167 
168 // Check the tested assertion
169         try {
170             objRef = findObjRef(DEBUGGEE_LOCALVAR);
171             rType = objRef.referenceType();
172 
173             // provoke the InvalidTypeException
174             for (int i=0; i<FLDS_NUM; i++) {
175                 Field fld = rType.fieldByName(DEBUGGEE_FLDS[i][0]);
176                 try {
177                     log.display("\nTrying to set value for the field \""
178                         + fld.name() + "\"\n\tfrom the object reference \""
179                         + objRef
180                         + "\"\n\tusing not matched value's type \""
181                         + objRef.getValue(rType.fieldByName(DEBUGGEE_FLDS[i][1])).type() + "\" ...");
182                     objRef.setValue(fld,
183                         objRef.getValue(rType.fieldByName(DEBUGGEE_FLDS[i][1])));
184                     log.complain("TEST FAILED: expected InvalidTypeException was not thrown"
185                         + "\n\twhen attempted to set value for the "
186                         + fld.type() + " field \""
187                         + fld.name() + "\"\n\tfrom the debuggee's object reference \""
188                         + objRef
189                         + "\"\n\tusing not matched value's type \""
190                         + objRef.getValue(rType.fieldByName(DEBUGGEE_FLDS[i][1])).type() + "\"");
191                     tot_res = Consts.TEST_FAILED;
192                 } catch (InvalidTypeException ie) {
193                     log.display("CHECK PASSED: caught expected " + ie);
194                 } catch (Exception e) {
195                     e.printStackTrace();
196                     log.complain("TEST FAILED: ObjectReference.setValue(): caught unexpected "
197                         + e + "\n\tinstead of expected InvalidTypeException"
198                         + "\n\twhen attempted to set value for the "
199                         + fld.type() + " field \""
200                         + fld.name() + "\"\n\tfrom the debuggee's object reference \""
201                         + objRef
202                         + "\"\n\tusing not matched value's type \""
203                         + objRef.getValue(rType.fieldByName(DEBUGGEE_FLDS[i][1])).type() + "\"");
204                     tot_res = Consts.TEST_FAILED;
205                 }
206             }
207         } catch (Exception e) {
208             e.printStackTrace();
209             log.complain("TEST FAILURE: caught unexpected exception: " + e);
210             tot_res = Consts.TEST_FAILED;
211             return quitDebuggee();
212         }
213 
214 // Finish the test
215         return quitDebuggee();
216     }
217 
findObjRef(String varName)218     private ObjectReference findObjRef(String varName) {
219         try {
220             List frames = thrRef.frames();
221             Iterator iter = frames.iterator();
222             while (iter.hasNext()) {
223                 StackFrame stackFr = (StackFrame) iter.next();
224                 try {
225                     LocalVariable locVar = stackFr.visibleVariableByName(varName);
226 
227                     if (locVar == null) continue;
228 
229                     // return reference to the debuggee class' object
230                     return stackFr.thisObject();
231                 } catch(AbsentInformationException e) {
232                     // this is not needed stack frame, ignoring
233                 } catch(NativeMethodException ne) {
234                     // current method is native, also ignoring
235                 }
236             }
237         } catch (Exception e) {
238             e.printStackTrace();
239             tot_res = Consts.TEST_FAILED;
240             throw new Failure("findObjRef: caught unexpected exception: " + e);
241         }
242         throw new Failure("findObjRef: needed debuggee's stack frame not found");
243     }
244 
quitDebuggee()245     private int quitDebuggee() {
246         if (thrRef != null) {
247             if (thrRef.isSuspended())
248                 thrRef.resume();
249         }
250         pipe.println(COMMAND_QUIT);
251         debuggee.waitFor();
252         int debStat = debuggee.getStatus();
253         if (debStat != (Consts.JCK_STATUS_BASE + Consts.TEST_PASSED)) {
254             log.complain("TEST FAILED: debuggee's process finished with status: "
255                 + debStat);
256             tot_res = Consts.TEST_FAILED;
257         } else
258             log.display("Debuggee's process finished with the status: "
259                 + debStat);
260 
261         return tot_res;
262     }
263 
264 }
265