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.ClassType.NewInstance; 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: ClassType.NewInstance. 34 * 35 * See newinst001.README for description of test execution. 36 * 37 * This class represents debugger part of the test. 38 * Test is executed by invoking method runIt(). 39 * JDWP command is tested in the method testCommand(). 40 * 41 * @see #runIt() 42 * @see #testCommand() 43 */ 44 public class newinst001 { 45 46 // exit status constants 47 static final int JCK_STATUS_BASE = 95; 48 static final int PASSED = 0; 49 static final int FAILED = 2; 50 51 // package and classes names 52 static final String PACKAGE_NAME = "nsk.jdwp.ClassType.NewInstance"; 53 static final String TEST_CLASS_NAME = PACKAGE_NAME + "." + "newinst001"; 54 static final String DEBUGEE_CLASS_NAME = TEST_CLASS_NAME + "a"; 55 56 // tested JDWP command 57 static final String JDWP_COMMAND_NAME = "ClassType.NewInstance"; 58 static final int JDWP_COMMAND_ID = JDWP.Command.ClassType.NewInstance; 59 60 // tested class name and signature 61 static final String TESTED_CLASS_NAME = DEBUGEE_CLASS_NAME + "$" + "TestedObjectClass"; 62 static final String TESTED_CLASS_SIGNATURE = "L" + TESTED_CLASS_NAME.replace('.', '/') + ";"; 63 64 // field and method names 65 static final String RESULT_FIELD_NAME = "result"; 66 static final String TESTED_CONSTRUCTOR_NAME = "<init>"; 67 static final String BREAKPOINT_METHOD_NAME = "run"; 68 static final int BREAKPOINT_LINE_NUMBER = newinst001a.BREAKPOINT_LINE_NUMBER; 69 70 // data for invoked method 71 static final int ARGUMENTS_COUNT = 1; 72 static final int INITIAL_VALUE = newinst001a.INITIAL_VALUE; 73 static final int ARGUMENT_VALUE = newinst001a.FINAL_VALUE; 74 static final int RETURN_VALUE = INITIAL_VALUE; 75 static final int INVOKE_OPTIONS = 0; 76 77 // usual scaffold objects 78 ArgumentHandler argumentHandler = null; 79 Log log = null; 80 Binder binder = null; 81 Debugee debugee = null; 82 Transport transport = null; 83 IOPipe pipe = null; 84 boolean dead = false; 85 86 // data obtained from debuggee 87 long classID = 0; 88 long threadID = 0; 89 long methodID = 0; 90 91 // test passed or not 92 boolean success = true; 93 94 // ------------------------------------------------------------------- 95 96 /** 97 * Start test from command line. 98 */ main(String argv[])99 public static void main(String argv[]) { 100 System.exit(run(argv,System.out) + JCK_STATUS_BASE); 101 } 102 103 /** 104 * Start JCK-compilant test. 105 */ run(String argv[], PrintStream out)106 public static int run(String argv[], PrintStream out) { 107 return new newinst001().runIt(argv, out); 108 } 109 110 // ------------------------------------------------------------------- 111 112 /** 113 * Perform test execution. 114 */ runIt(String argv[], PrintStream out)115 public int runIt(String argv[], PrintStream out) { 116 117 // make log for debugger messages 118 argumentHandler = new ArgumentHandler(argv); 119 log = new Log(out, argumentHandler); 120 121 // execute test and display results 122 try { 123 log.display("\n>>> Starting debugee \n"); 124 125 // launch debuggee 126 binder = new Binder(argumentHandler, log); 127 log.display("Launching debugee VM"); 128 debugee = binder.bindToDebugee(DEBUGEE_CLASS_NAME); 129 transport = debugee.getTransport(); 130 log.display(" ... debuggee launched"); 131 132 // set timeout for debuggee responces 133 int waitTime = argumentHandler.getWaitTime(); // minutes 134 long timeout = waitTime * 60 * 1000; // milliseconds 135 log.display("Setting timeout for debuggee responces: " + waitTime + " minute(s)"); 136 transport.setReadTimeout(timeout); 137 log.display(" ... timeout set"); 138 139 // wait for VM_INIT event 140 log.display("Waiting for VM_INIT event"); 141 debugee.waitForVMInit(); 142 log.display(" ... VM_INIT event received"); 143 144 // query debugee for VM-dependent ID sizes 145 log.display("Querying for IDSizes"); 146 debugee.queryForIDSizes(); 147 log.display(" ... size of VM-dependent types adjusted"); 148 149 // run the test 150 runTest(); 151 152 // wait for VM_DEATH event 153 log.display("Waiting for VM_DEATH event"); 154 debugee.waitForVMDeath(); 155 log.display(" ... VM_DEATH event received"); 156 dead = true; 157 158 } catch (Failure e) { 159 log.complain("TEST FAILED: " + e.getMessage()); 160 success = false; 161 } catch (Exception e) { 162 e.printStackTrace(out); 163 log.complain("Caught unexpected exception while running the test:\n\t" + e); 164 success = false; 165 } finally { 166 log.display("\n>>> Finishing test \n"); 167 168 // disconnect debugee and wait for its exit 169 if (debugee != null) { 170 quitDebugee(); 171 } 172 } 173 174 // check result 175 if (!success) { 176 log.complain("TEST FAILED"); 177 return FAILED; 178 } 179 out.println("TEST PASSED"); 180 return PASSED; 181 } 182 183 /** 184 * Obtain required data and test JDWP command. 185 */ runTest()186 void runTest() { 187 log.display("\n>>> Obtaining required data \n"); 188 189 // wait for tested class loaded on debuggee startup and obtain its classID 190 log.display("Waiting for class loaded:\n\t" + TESTED_CLASS_NAME); 191 classID = debugee.waitForClassLoaded(TESTED_CLASS_NAME, JDWP.SuspendPolicy.ALL); 192 log.display(" ... got classID: " + classID); 193 log.display(""); 194 195 // query debuggee for tested methodID 196 log.display("Getting tested methodID by constructor name: " + TESTED_CONSTRUCTOR_NAME); 197 methodID = debugee.getMethodID(classID, TESTED_CONSTRUCTOR_NAME, true); 198 log.display(" ... got methodID: " + methodID); 199 log.display(""); 200 201 // set breakpoint and wait for debugee reached it 202 log.display("Waiting for breakpoint reached at: " 203 + BREAKPOINT_METHOD_NAME + ":" + BREAKPOINT_LINE_NUMBER); 204 threadID = debugee.waitForBreakpointReached(classID, 205 BREAKPOINT_METHOD_NAME, 206 BREAKPOINT_LINE_NUMBER, 207 JDWP.SuspendPolicy.EVENT_THREAD); 208 log.display(" ... breakpoint reached with threadID: " + threadID); 209 210 // test JDWP command 211 log.display("\n>> Testing JDWP command \n"); 212 testCommand(); 213 214 // check command results 215 if (success) { 216 log.display("\n>>> Checking command results \n"); 217 checkResult(); 218 } 219 220 // resume debuggee after the command 221 log.display("Resuming debuggee"); 222 debugee.resume(); 223 log.display(" ... debuggee resumed"); 224 } 225 226 /** 227 * Perform testing JDWP command. 228 */ testCommand()229 void testCommand() { 230 // create command packet and fill requred out data 231 log.display("Create command packet:"); 232 log.display("Command: " + JDWP_COMMAND_NAME); 233 CommandPacket command = new CommandPacket(JDWP_COMMAND_ID); 234 log.display(" classID: " + classID); 235 command.addReferenceTypeID(classID); 236 log.display(" threadID: " + threadID); 237 command.addObjectID(threadID); 238 log.display(" methodID: " + methodID); 239 command.addMethodID(methodID); 240 log.display(" arguments: " + ARGUMENTS_COUNT); 241 command.addInt(ARGUMENTS_COUNT); 242 for (int i = 0; i < ARGUMENTS_COUNT; i++) { 243 JDWP.Value value = new JDWP.Value(JDWP.Tag.INT, new Integer(ARGUMENT_VALUE)); 244 log.display(" arg: " + value); 245 command.addValue(value); 246 } 247 log.display(" options: " + INVOKE_OPTIONS); 248 command.addInt(INVOKE_OPTIONS); 249 command.setLength(); 250 251 // send command packet to debugee 252 try { 253 log.display("Sending command packet:\n" + command); 254 transport.write(command); 255 } catch (IOException e) { 256 log.complain("Unable to send command packet:\n\t" + e); 257 success = false; 258 return; 259 } 260 261 // receive reply packet from debugee 262 ReplyPacket reply = new ReplyPacket(); 263 try { 264 log.display("Waiting for reply packet"); 265 transport.read(reply); 266 log.display(" ... reply packet received:\n" + reply); 267 } catch (IOException e) { 268 log.complain("Unable to read reply packet for tested command:\n\t" + e); 269 success = false; 270 return; 271 } 272 273 // check reply packet header 274 try{ 275 log.display("Checking header of reply packet"); 276 reply.checkHeader(command.getPacketID()); 277 log.display(" ... packet header is correct"); 278 } catch (BoundException e) { 279 log.complain("Wrong header of reply packet for tested command:\n\t" 280 + e.getMessage()); 281 success = false; 282 return; 283 } 284 285 // start parsing reply packet data 286 log.display("Parsing reply packet data:"); 287 reply.resetPosition(); 288 289 // extract return value 290 JDWP.Value newObject = null; 291 try { 292 newObject = reply.getValue(); 293 log.display(" newObject: " + newObject); 294 } catch (BoundException e) { 295 log.complain("Unable to extract returnValues from reply packet:\n\t" 296 + e.getMessage()); 297 success = false; 298 return; 299 } 300 301 // extract exception tag 302 JDWP.Value exception = null; 303 try { 304 exception = reply.getValue(); 305 log.display(" exception: " + exception); 306 } catch (BoundException e) { 307 log.complain("Unable to extract exception from reply packet:\n\t" 308 + e.getMessage()); 309 success = false; 310 return; 311 } 312 313 // check for extra data in reply packet 314 if (!reply.isParsed()) { 315 log.complain("Extra trailing bytes found in reply packet at: " 316 + reply.offsetString()); 317 success = false; 318 } 319 320 log.display(" ... packed data parsed"); 321 322 // check that return value is an integer 323 if (newObject.getTag() != JDWP.Tag.OBJECT) { 324 log.complain("Unexpected tag of returnValue returned: " + newObject.getTag() 325 + " (expected: " + JDWP.Tag.OBJECT + ")"); 326 success = false; 327 } 328 329 // check that return value is as expected 330 long newObjectID = ((Long)newObject.getValue()).longValue(); 331 if (newObjectID == 0) { 332 log.complain("Unexpected null objectID for newObject value returned: " 333 + newObjectID + " (expected: not " + 0 + ")"); 334 success = false; 335 } 336 337 // check that exception value is an object 338 if (exception.getTag() != JDWP.Tag.OBJECT) { 339 log.complain("Unexpected tag of exception returned: " + exception.getTag() 340 + " (expected: " + JDWP.Tag.OBJECT + ")"); 341 success = false; 342 } 343 344 // check that exception object is null 345 long exceptionID = ((Long)exception.getValue()).longValue(); 346 if (exceptionID != 0) { 347 log.complain("Not null objectID for exception value returned: " + exceptionID 348 + " (expected: " + 0 + ")"); 349 success = false; 350 } 351 } 352 353 /** 354 * Check result of the tested JDWP command. 355 */ checkResult()356 void checkResult() { 357 // query debuggee for result value from a static field 358 log.display("Getting result value from static field: " + RESULT_FIELD_NAME); 359 int result = queryInt(classID, RESULT_FIELD_NAME, JDWP.Tag.INT); 360 log.display(" ... got result: " + result); 361 362 // check if the result value is changed as expected 363 if (result != ARGUMENT_VALUE) { 364 log.complain("Method has not been really invoked: \n\t" 365 + "variable not changed by the method: " + result 366 + " (expected: " + ARGUMENT_VALUE + ")"); 367 success = false; 368 } else { 369 log.display("Method has been really invoked: \n\t" 370 + " variable changed by the method: " + result 371 + " (expected: " + ARGUMENT_VALUE + ")"); 372 } 373 } 374 375 /** 376 * Query debuggee for value of static field of the class. 377 */ queryFieldValue(long classID, String fieldName, byte tag)378 JDWP.Value queryFieldValue(long classID, String fieldName, byte tag) { 379 // get fieledID for static field (declared in the class) 380 long fieldID = debugee.getClassFieldID(classID, fieldName, true); 381 // get value of the field 382 JDWP.Value value = debugee.getStaticFieldValue(classID, fieldID); 383 384 // check that value has THREAD tag 385 if (value.getTag() != tag) { 386 log.complain("unexpedted value tag returned from debuggee: " + value.getTag() 387 + " (expected: " + tag + ")"); 388 throw new Failure("Error occured while getting value from static field: " 389 + fieldName); 390 } 391 392 return value; 393 } 394 395 /** 396 * Query debuggee for objectID value of static field of the class. 397 */ queryObjectID(long classID, String fieldName, byte tag)398 long queryObjectID(long classID, String fieldName, byte tag) { 399 JDWP.Value value = queryFieldValue(classID, fieldName, tag); 400 long objectID = ((Long)value.getValue()).longValue(); 401 return objectID; 402 } 403 404 /** 405 * Query debuggee for int value of static field of the class. 406 */ queryInt(long classID, String fieldName, byte tag)407 int queryInt(long classID, String fieldName, byte tag) { 408 JDWP.Value value = queryFieldValue(classID, fieldName, tag); 409 int intValue = ((Integer)value.getValue()).intValue(); 410 return intValue; 411 } 412 413 /** 414 * Sending debugee signal to quit and waiting for it exits. 415 */ quitDebugee()416 void quitDebugee() { 417 if (debugee == null) 418 return; 419 420 // disconnect debuggee if not dead 421 if (!dead) { 422 try { 423 log.display("Disconnecting debuggee"); 424 debugee.dispose(); 425 log.display(" ... debuggee disconnected"); 426 } catch (Failure e) { 427 log.display("Failed to finally dispose debuggee:\n\t" + e.getMessage()); 428 } 429 } 430 431 // wait for debugee exits 432 log.display("Waiting for debuggee exits"); 433 int code = debugee.waitFor(); 434 log.display(" ... debuggee finished with exit code: " + code); 435 436 // analize debuggee exit status code 437 if (code != JCK_STATUS_BASE + PASSED) { 438 log.complain("Debuggee FAILED with exit code: " + code); 439 } 440 } 441 442 } 443