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.ArrayReference.getValue;
25 
26 import nsk.share.*;
27 import nsk.share.jpda.*;
28 import nsk.share.jdi.*;
29 
30 import com.sun.jdi.*;
31 import java.io.*;
32 import java.util.*;
33 
34 public class getvalue003 {
35 
36     // exit code when test failed
37     public final static int TEST_FAILED = 2;
38     // exit code when test passed
39     public final static int TEST_PASSED = 0;
40     // shift of exit code
41     public final static int JCK_STATUS_BASE = 95;
42 
43     private final static String prefix = "nsk.jdi.ArrayReference.getValue.";
44     private final static String className = "getvalue003";
45     private final static String debuggerName = prefix + className;
46     private final static String debugeeName = debuggerName + "a";
47     private final static String fieldToCheck = "testedObj";
48 
49     private int exitStatus;
50     private Log log;
51     private Debugee debugee;
52     private IOPipe pipe;
53 
getvalue003()54     private getvalue003() {
55         log = null;
56         debugee = null;
57         pipe = null;
58     }
59 
main(String argv[])60     public static void main(String argv[]) {
61         System.exit(JCK_STATUS_BASE + run(argv, System.out));
62     }
63 
run(String argv[], PrintStream out)64     public static int run(String argv[], PrintStream out) {
65 
66         getvalue003 tstObj = new getvalue003();
67 
68         if ( tstObj.prepareDebugee(argv, out) ) {
69             tstObj.execTest();
70             tstObj.disposeOfDebugee();
71         }
72 
73         if ( tstObj.exitStatus ==  TEST_FAILED )
74             tstObj.complain("run:: TEST FAILED");
75         else
76             tstObj.display("run:: TEST PASSED");
77         return tstObj.exitStatus;
78     }
79 
prepareDebugee(String argv[], PrintStream out)80     private boolean prepareDebugee(String argv[], PrintStream out) {
81         ArgumentHandler argHandler = new ArgumentHandler(argv);
82         log = new Log(out, argHandler);
83         Binder binder = new Binder(argHandler, log);
84         display("prepareDebugee:: binder created.");
85 
86         debugee = binder.bindToDebugee(debugeeName);
87         log.display("prepareDebugee:: binded to debugee.");
88         pipe = debugee.createIOPipe();
89         log.display("prepareDebugee:: pipe created.");
90 
91         debugee.redirectStderr(out);
92         debugee.resume();
93 
94         String line = pipe.readln();
95         if ( line == null ) {
96             complain("prepareDebugee:: UNEXPECTED debugee's signal - null");
97             return false;
98         }
99         if ( !line.equals("ready") ) {
100             complain("prepareDebugee:: UNEXPECTED debugee's signal - "
101                       + line);
102             return false;
103         }
104 
105         display("prepareDebugee:: debugee's \"ready\" signal recieved.");
106         return true;
107     }
108 
disposeOfDebugee()109     private boolean disposeOfDebugee() {
110         pipe.println("quit");
111         debugee.waitFor();
112         int status = debugee.getStatus();
113 
114         if ( status != JCK_STATUS_BASE ) {
115             complain("disposeOfDebugee:: UNEXPECTED Debugee's exit "
116                        + "status (not " + JCK_STATUS_BASE + ") - " + status);
117             return false;
118         }
119         display("disposeOfDebugee:: expected Debugee's exit "
120                   + "status - " + status);
121         return true;
122     }
123 
display(String msg)124     private void display(String msg) {
125         if ( log != null )
126             log.display("debugger> " + msg);
127     }
128 
complain(String msg)129     private void complain(String msg) {
130         if ( log != null )
131             log.complain("debugger FAILURE> " + msg);
132     }
133 
execTest()134     private boolean execTest() {
135         exitStatus = TEST_FAILED;
136 
137         ReferenceType refType = debugee.classByName(debugeeName);
138         if ( refType == null ) {
139             complain("eventHandler:: Class '" + debugeeName + "' not found.");
140             return false;
141         }
142 
143         Field field = refType.fieldByName(fieldToCheck);
144         if ( field == null ) {
145             complain("eventHandler:: Field '" + fieldToCheck + "' not found.");
146             return false;
147         }
148 
149         Value value = refType.getValue(field);
150         if ( value == null ) {
151             complain("eventHandler:: Field '" + fieldToCheck + "' not initialized.");
152             return false;
153         }
154 
155         return checkObjectFields(value);
156     }
157 
checkObjectFields(Value value)158     public boolean checkObjectFields(Value value) {
159         List fieldList;
160         if ( ! (value instanceof ObjectReference) )
161             return false;
162 
163         fieldList = ((ClassType)value.type()).allFields();
164 
165         // Check all array fields from debugee
166         Field field;
167         display("\ncheckObjectFields:: Tests starts >>>");
168         for (int i = 0; i < fieldList.size(); i++) {
169             field = (Field)fieldList.get(i);
170 
171             display("");
172             display("checkObjectFields:: <" + field.name()  + "> field is being "
173                         + " checked.");
174 
175             // Check getting of item from field-array
176             if ( !checkFieldValue((ObjectReference)value, field) )
177                 return false;
178         }
179         exitStatus = TEST_PASSED;
180         return true;
181     }
182 
checkFieldValue(ObjectReference object, Field field)183     private boolean checkFieldValue(ObjectReference object, Field field) {
184         Value value;
185         ArrayReference arrayRef;
186         String fieldName = field.name();
187         try {
188             value = object.getValue(field);
189         } catch (IllegalArgumentException e) {
190             complain("checkFieldValue:: can not get value for field " + fieldName);
191             complain("checkFieldValue:: " + e);
192             return false;
193         }
194 
195         display("checkFieldValue:: ***" + fieldName + " = " + value);
196 
197         boolean checkNULL = false;
198         // scaning of non-initialized arrays
199         for ( int i = 0; i < getvalue003a.NON_INIT_FIELDS.length; i++ )
200         {
201             if ( fieldName.compareTo(getvalue003a.NON_INIT_FIELDS[i]) == 0 ) {
202                 checkNULL = true;
203                 break;
204             }
205         }
206 
207         // checking of field value
208         if ( checkNULL ) {
209 
210             // value is not null, but array has not to be initialized.
211             if ( value != null ) {
212                 complain("checkFieldValue:: Value of '" + fieldName + "' is " + value
213                             + ", but IndexOutOfBoundsException expected.");
214                 return false;
215 
216             // array is not initialized. Expected value is null
217             } else {
218                 display("checkFieldValue:: Expected value is null.");
219                 return true;
220             }
221         } else {
222 
223             // value is null, but array has to be initialized.
224             if ( value == null ) {
225                 complain("checkFieldValue:: Unexpected value of '" + fieldName
226                                 + "'" + value);
227                 return false;
228             }
229         }
230 
231         display("checkFieldValue:: *** type of " + fieldName + " = " + value.type());
232 
233         // check up type of value. it has to be ArrayType
234         if ( ! (value.type() instanceof ArrayType) ) {
235             display("checkFieldValue:: type of value is not ArrayType.");
236             return false;
237         }
238 
239         // Cast to ArrayReference. All fields in debugee are
240         // arrays, so ClassCastException should not be thrown
241         return checkValue(0, fieldName, (ArrayReference )value, ((ArrayReference )value).length() + 1) &&
242                     checkValue(0, fieldName, (ArrayReference )value, Integer.MAX_VALUE) &&
243                     checkValue(0, fieldName, (ArrayReference )value, Integer.MAX_VALUE + 1);
244     }
245 
checkValue(int depth, String name, ArrayReference arrayRef, long itemIndex)246     private boolean checkValue(int depth, String name, ArrayReference arrayRef,
247                                     long itemIndex) {
248 
249         Value itemValue;
250         int length = arrayRef.length();
251         try {
252             itemValue = arrayRef.getValue(0);
253             if ( itemValue != null ) {
254                 if ( itemValue.type() instanceof ArrayType ) {
255 
256                     // itemValue has array type, check it by the same way
257                     long index =  (length + 1 != itemIndex) ? itemIndex :
258                                         ((ArrayReference )itemValue).length() + 1;
259                     if ( !checkValue(depth + 1, name, (ArrayReference )itemValue, index) )
260                         return false;
261                 }
262             }
263             itemValue = arrayRef.getValue((int)itemIndex);
264             if ( itemIndex > length || itemIndex < 0 ) {
265                 complain("checkValue[" + depth + "]:: " + name + "[" + itemIndex + "] = "
266                                + itemValue + ", but IndexOutOfBoundsException expected.");
267                 return false;
268             }
269 
270         } catch (IndexOutOfBoundsException e) {
271             /* Index is always out of bounds, so
272              * IndexOutOfBoundsException is expected
273              */
274             display("checkValue[" + depth + "]:: expected IndexOutOfBoundsException " +
275                         "is thrown for " + itemIndex + " item.");
276         } catch (Exception e) {
277             complain("checkValue[" + depth + "]:: Unexpected exception: " + e);
278             return false;
279         }
280         return true;
281     }
282 
283 }
284