1 /* 2 * Copyright (c) 2001, 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.jdwp.ArrayReference.GetValues; 25 26 import java.io.*; 27 28 import nsk.share.*; 29 import nsk.share.jpda.*; 30 import nsk.share.jdwp.*; 31 32 /** 33 * Test for JDWP command: ArrayReference.GetValues. 34 * 35 * See getvalues001.README for description of test execution. 36 * 37 * Test is executed by invoking method runIt(). 38 * JDWP command is tested in method testCommand(). 39 * 40 * @see #runIt() 41 * @see #testCommand() 42 */ 43 public class getvalues001 { 44 45 // exit status constants 46 static final int JCK_STATUS_BASE = 95; 47 static final int PASSED = 0; 48 static final int FAILED = 2; 49 50 // communication signals constants 51 static final String READY = "ready"; 52 static final String QUIT = "quit"; 53 54 // package and classes names constants 55 static final String PACKAGE_NAME = "nsk.jdwp.ArrayReference.GetValues"; 56 static final String TEST_CLASS_NAME = PACKAGE_NAME + "." + "getvalues001"; 57 static final String DEBUGEE_CLASS_NAME = TEST_CLASS_NAME + "a"; 58 59 // tested JDWP command constants 60 static final String JDWP_COMMAND_NAME = "ArrayReference.GetValues"; 61 static final int JDWP_COMMAND_ID = JDWP.Command.ArrayReference.GetValues; 62 63 // tested class name and signature constants 64 static final String TESTED_CLASS_NAME = DEBUGEE_CLASS_NAME + "$" + "TestedClass"; 65 static final String TESTED_CLASS_SIGNATURE = "L" + TESTED_CLASS_NAME.replace('.', '/') + ";"; 66 67 // name of the static field in the tested class with the tested object value 68 static final String ARRAY_FIELD_NAME = getvalues001a.ARRAY_FIELD_NAME; 69 static final int ARRAY_LENGTH = getvalues001a.ARRAY_LENGTH; 70 71 // first index and number of array components to get 72 static final int ARRAY_FIRST_INDEX = 4; 73 static final int ARRAY_ITEMS_COUNT = 10; 74 75 // usual scaffold objects 76 ArgumentHandler argumentHandler = null; 77 Log log = null; 78 Binder binder = null; 79 Debugee debugee = null; 80 Transport transport = null; 81 IOPipe pipe = null; 82 83 // test passed or not 84 boolean success = true; 85 86 // ------------------------------------------------------------------- 87 88 /** 89 * Start test from command line. 90 */ main(String argv[])91 public static void main (String argv[]) { 92 System.exit(run(argv,System.out) + JCK_STATUS_BASE); 93 } 94 95 /** 96 * Start JCK-compilant test. 97 */ run(String argv[], PrintStream out)98 public static int run(String argv[], PrintStream out) { 99 return new getvalues001().runIt(argv, out); 100 } 101 102 // ------------------------------------------------------------------- 103 104 /** 105 * Perform test execution. 106 */ runIt(String argv[], PrintStream out)107 public int runIt(String argv[], PrintStream out) { 108 109 // make log for debugger messages 110 argumentHandler = new ArgumentHandler(argv); 111 log = new Log(out, argumentHandler); 112 113 // execute test and display results 114 try { 115 log.display("\n>>> Preparing debugee for testing \n"); 116 117 // launch debugee 118 binder = new Binder(argumentHandler, log); 119 log.display("Launching debugee"); 120 debugee = binder.bindToDebugee(DEBUGEE_CLASS_NAME); 121 transport = debugee.getTransport(); 122 pipe = debugee.createIOPipe(); 123 124 // make debuggee ready for testing 125 prepareDebugee(); 126 127 // work with prepared debugee 128 try { 129 log.display("\n>>> Obtaining requred data from debugee \n"); 130 131 // query debugee for TypeID of tested class 132 log.display("Getting ReferenceTypeID by signature:\n" 133 + " " + TESTED_CLASS_SIGNATURE); 134 long classID = debugee.getReferenceTypeID(TESTED_CLASS_SIGNATURE); 135 log.display(" got classID: " + classID); 136 137 // query debuggee for arrayID value from static field 138 log.display("Getting arrayID value from static field: " 139 + ARRAY_FIELD_NAME); 140 long arrayID = queryObjectID(classID, 141 ARRAY_FIELD_NAME, JDWP.Tag.ARRAY); 142 log.display(" got arrayID: " + arrayID); 143 144 // perform testing JDWP command 145 log.display("\n>>> Testing JDWP command \n"); 146 testCommand(arrayID); 147 148 } finally { 149 // quit debugee 150 log.display("\n>>> Finishing test \n"); 151 quitDebugee(); 152 } 153 154 } catch (Failure e) { 155 log.complain("TEST FAILED: " + e.getMessage()); 156 e.printStackTrace(out); 157 success = false; 158 } catch (Exception e) { 159 log.complain("Caught unexpected exception:\n" + e); 160 e.printStackTrace(out); 161 success = false; 162 } 163 164 if (!success) { 165 log.complain("TEST FAILED"); 166 return FAILED; 167 } 168 169 out.println("TEST PASSED"); 170 return PASSED; 171 172 } 173 174 /** 175 * Prepare debugee for testing and waiting for ready signal. 176 */ prepareDebugee()177 void prepareDebugee() { 178 // wait for VM_INIT event from debugee 179 log.display("Waiting for VM_INIT event"); 180 debugee.waitForVMInit(); 181 182 // query debugee for VM-dependent ID sizes 183 log.display("Querying for IDSizes"); 184 debugee.queryForIDSizes(); 185 186 // resume initially suspended debugee 187 log.display("Resuming debugee VM"); 188 debugee.resume(); 189 190 // wait for READY signal from debugee 191 log.display("Waiting for signal from debugee: " + READY); 192 String signal = pipe.readln(); 193 log.display("Received signal from debugee: " + signal); 194 if (! signal.equals(READY)) { 195 throw new TestBug("Unexpected signal received form debugee: " + signal 196 + " (expected: " + READY + ")"); 197 } 198 } 199 200 /** 201 * Sending debugee signal to quit and waiting for it exits. 202 */ quitDebugee()203 void quitDebugee() { 204 // send debugee signal to quit 205 log.display("Sending signal to debugee: " + QUIT); 206 pipe.println(QUIT); 207 208 // wait for debugee exits 209 log.display("Waiting for debugee exits"); 210 int code = debugee.waitFor(); 211 212 // analize debugee exit status code 213 if (code == JCK_STATUS_BASE + PASSED) { 214 log.display("Debugee PASSED with exit code: " + code); 215 } else { 216 log.complain("Debugee FAILED with exit code: " + code); 217 success = false; 218 } 219 } 220 221 /** 222 * Query debuggee for objectID value of static class field. 223 */ queryObjectID(long classID, String fieldName, byte tag)224 long queryObjectID(long classID, String fieldName, byte tag) { 225 // get fieledID for static field (declared in the class) 226 long fieldID = debugee.getClassFieldID(classID, fieldName, true); 227 // get value of the field 228 JDWP.Value value = debugee.getStaticFieldValue(classID, fieldID); 229 230 // check that value has THREAD tag 231 if (value.getTag() != tag) { 232 throw new Failure("Wrong objectID tag received from field \"" + fieldName 233 + "\": " + value.getTag() + " (expected: " + tag + ")"); 234 } 235 236 // extract threadID from the value 237 long objectID = ((Long)value.getValue()).longValue(); 238 return objectID; 239 } 240 241 /** 242 * Perform testing JDWP command for specified objectID. 243 */ testCommand(long arrayID)244 void testCommand(long arrayID) { 245 // create command packet 246 log.display("Create command packet:"); 247 log.display("Command: " + JDWP_COMMAND_NAME); 248 CommandPacket command = new CommandPacket(JDWP_COMMAND_ID); 249 250 // add out data to the command packet 251 log.display(" arrayID: " + arrayID); 252 command.addObjectID(arrayID); 253 log.display(" firstIndex: " + ARRAY_FIRST_INDEX); 254 command.addInt(ARRAY_FIRST_INDEX); 255 log.display(" length: " + ARRAY_ITEMS_COUNT); 256 command.addInt(ARRAY_ITEMS_COUNT); 257 command.setLength(); 258 259 // send command packet to debugee 260 try { 261 log.display("Sending command packet:\n" + command); 262 transport.write(command); 263 } catch (IOException e) { 264 log.complain("Unable to send command packet:\n" + e); 265 success = false; 266 return; 267 } 268 269 ReplyPacket reply = new ReplyPacket(); 270 271 // receive reply packet from debugee 272 try { 273 log.display("Waiting for reply packet"); 274 transport.read(reply); 275 log.display("Reply packet received:\n" + reply); 276 } catch (IOException e) { 277 log.complain("Unable to read reply packet:\n" + e); 278 success = false; 279 return; 280 } 281 282 // check reply packet header 283 try{ 284 log.display("Checking reply packet header"); 285 reply.checkHeader(command.getPacketID()); 286 } catch (BoundException e) { 287 log.complain("Bad header of reply packet: " + e.getMessage()); 288 success = false; 289 } 290 291 // start parsing reply packet data 292 log.display("Parsing reply packet:"); 293 reply.resetPosition(); 294 295 // extract values tag 296 byte tag = (byte)0; 297 try { 298 tag = reply.getByte(); 299 log.display(" tag: " + tag); 300 301 } catch (BoundException e) { 302 log.complain("Unable to extract values tag from reply packet:\n\t" 303 + e.getMessage()); 304 success = false; 305 } 306 307 // check if number of values are as expected 308 if (tag != JDWP.Tag.INT) { 309 log.complain("Unexpected values tag received:" + tag 310 + " (expected: " + JDWP.Tag.INT + ")"); 311 success = false; 312 } 313 314 // extract number of values 315 int values = 0; 316 try { 317 values = reply.getInt(); 318 log.display(" values: " + values); 319 320 } catch (BoundException e) { 321 log.complain("Unable to extract number of values from reply packet:\n\t" 322 + e.getMessage()); 323 success = false; 324 } 325 326 // check if number of values are as expected 327 if (values < 0) { 328 log.complain("Negative number of values received:" + values 329 + " (expected: " + ARRAY_ITEMS_COUNT + ")"); 330 success = false; 331 } else if (values != ARRAY_ITEMS_COUNT) { 332 log.complain("Unexpected number of values received:" + values 333 + " (expected: " + ARRAY_ITEMS_COUNT + ")"); 334 success = false; 335 } 336 337 // extract and check each value 338 for (int i = 0; i < values; i++ ) { 339 int index = i + ARRAY_FIRST_INDEX; 340 log.display(" value #" + i + " (index: " + index + ")"); 341 342 // extract value 343 JDWP.UntaggedValue value = null; 344 try { 345 value = reply.getUntaggedValue(JDWP.Tag.INT); 346 log.display(" untagged_value: " + value); 347 } catch (BoundException e) { 348 log.complain("Unable to extract " + i + " value from reply packet:\n\t" 349 + e.getMessage()); 350 success = false; 351 break; 352 } 353 354 // check that extracted value is as expected 355 int intValue = ((Integer)value.getValue()).intValue(); 356 if (intValue != index * 10) { 357 log.complain("Unexpected value for " + index + " component received: " 358 + intValue + " (expected: " + (index * 10) + ")"); 359 success = false; 360 } 361 } 362 363 // check for extra data in reply packet 364 if (! reply.isParsed()) { 365 log.complain("Extra trailing bytes found in reply packet at: " 366 + "0x" + reply.toHexString(reply.currentDataPosition(), 4)); 367 success = false; 368 } 369 } 370 371 } 372