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.Event.SINGLE_STEP; 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 event: SINGLE_STEP. 34 * 35 * See singlestep002.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 event is tested in the method waitForTestedEvent(). 40 * 41 * @see #runIt() 42 * @see #waitForTestedEvent() 43 */ 44 public class singlestep002 { 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 constants 52 static final String PACKAGE_NAME = "nsk.jdwp.Event.SINGLE_STEP"; 53 static final String TEST_CLASS_NAME = PACKAGE_NAME + "." + "singlestep002"; 54 static final String DEBUGEE_CLASS_NAME = TEST_CLASS_NAME + "a"; 55 56 // tested JDWP event constants 57 static final byte TESTED_EVENT_KIND = JDWP.EventKind.SINGLE_STEP; 58 static final byte TESTED_EVENT_SUSPEND_POLICY = JDWP.SuspendPolicy.ALL; 59 static final int STEP_DEPTH = JDWP.StepDepth.INTO; 60 static final int STEP_SIZE = JDWP.StepSize.LINE; 61 62 // name and signature of the tested class 63 static final String TESTED_CLASS_NAME = DEBUGEE_CLASS_NAME + "$" + "TestedClass"; 64 static final String TESTED_CLASS_SIGNATURE = "L" + TESTED_CLASS_NAME.replace('.', '/') + ";"; 65 static final String TESTED_THREAD_NAME = "TestedThread"; 66 67 // name of field and method of tested class 68 static final String THREAD_FIELD_NAME = "thread"; 69 static final String BREAKPOINT_METHOD_NAME = "run"; 70 static final String STEP_METHOD_NAME = "methodForStep"; 71 static final int BREAKPOINT_LINE = singlestep002a.BREAKPOINT_LINE; 72 static final int SINGLE_STEP_LINE = singlestep002a.SINGLE_STEP_LINE; 73 74 // usual scaffold objects 75 ArgumentHandler argumentHandler = null; 76 Log log = null; 77 Binder binder = null; 78 Debugee debugee = null; 79 Transport transport = null; 80 int waitTime = 0; // minutes 81 long timeout = 0; // milliseconds 82 boolean dead = false; 83 boolean success = true; 84 85 // obtained data 86 long testedClassID = 0; 87 long testedThreadID = 0; 88 long testedMethodID = 0; 89 long stepMethodID = 0; 90 JDWP.Location testedLocation = null; 91 int eventRequestID = 0; 92 93 // ------------------------------------------------------------------- 94 95 /** 96 * Start test from command line. 97 */ main(String argv[])98 public static void main(String argv[]) { 99 System.exit(run(argv,System.out) + JCK_STATUS_BASE); 100 } 101 102 /** 103 * Start test from JCK-compilant environment. 104 */ run(String argv[], PrintStream out)105 public static int run(String argv[], PrintStream out) { 106 return new singlestep002().runIt(argv, out); 107 } 108 109 // ------------------------------------------------------------------- 110 111 /** 112 * Perform test execution. 113 */ runIt(String argv[], PrintStream out)114 public int runIt(String argv[], PrintStream out) { 115 116 // make log for debugger messages 117 argumentHandler = new ArgumentHandler(argv); 118 log = new Log(out, argumentHandler); 119 waitTime = argumentHandler.getWaitTime(); 120 timeout = waitTime * 60 * 1000; 121 122 // execute test and display results 123 try { 124 log.display("\n>>> Starting debugee \n"); 125 126 // launch debuggee 127 binder = new Binder(argumentHandler, log); 128 log.display("Launching debugee"); 129 debugee = binder.bindToDebugee(DEBUGEE_CLASS_NAME); 130 transport = debugee.getTransport(); 131 log.display(" ... debugee launched"); 132 log.display(""); 133 134 // set timeout for debuggee responces 135 log.display("Setting timeout for debuggee responces: " + waitTime + " minute(s)"); 136 transport.setReadTimeout(timeout); 137 log.display(" ... timeout set"); 138 139 // wait for debuggee started 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 // prepare debuggee 150 log.display("\n>>> Getting prepared for testing \n"); 151 prepareForTest(); 152 153 // test JDWP event 154 log.display("\n>>> Testing JDWP event \n"); 155 log.display("Making request for SINGLE_STEP event for class:\n\t" 156 + TESTED_CLASS_NAME); 157 requestTestedEvent(); 158 log.display(" ... got requestID: " + eventRequestID); 159 log.display(""); 160 161 // resume debuggee 162 log.display("Resumindg debuggee"); 163 debugee.resume(); 164 log.display(" ... debuggee resumed"); 165 log.display(""); 166 167 // wait for tested SINGLE_STEP event 168 log.display("Waiting for SINGLE_STEP event received"); 169 waitForTestedEvent(); 170 log.display(" ... event received"); 171 log.display(""); 172 173 // clear tested request for SINGLE_STEP event 174 log.display("Clearing request for tested event"); 175 clearTestedRequest(); 176 log.display(" ... request removed"); 177 178 // finish debuggee after testing 179 log.display("\n>>> Finishing debuggee \n"); 180 181 // resume debuggee 182 log.display("Resuming debuggee"); 183 debugee.resume(); 184 log.display(" ... debuggee resumed"); 185 186 // wait for debuggee exited 187 log.display("Waiting for VM_DEATH event"); 188 debugee.waitForVMDeath(); 189 dead = true; 190 log.display(" ... VM_DEATH event received"); 191 192 } catch (Failure e) { 193 log.complain("TEST FAILED: " + e.getMessage()); 194 success = false; 195 } catch (Exception e) { 196 e.printStackTrace(out); 197 log.complain("Caught unexpected exception while running the test:\n\t" + e); 198 success = false; 199 } finally { 200 // quit debugee 201 log.display("\n>>> Finishing test \n"); 202 quitDebugee(); 203 } 204 205 // check test results 206 if (!success) { 207 log.complain("TEST FAILED"); 208 return FAILED; 209 } 210 211 out.println("TEST PASSED"); 212 return PASSED; 213 214 } 215 216 /** 217 * Get debuggee prepared for testing and obtain required data. 218 */ prepareForTest()219 void prepareForTest() { 220 // wait for tested class loaded 221 log.display("Waiting for tested class loaded"); 222 testedClassID = debugee.waitForClassLoaded(TESTED_CLASS_NAME, JDWP.SuspendPolicy.ALL); 223 log.display(" ... got classID: " + testedClassID); 224 log.display(""); 225 226 // get methodID for the tested method 227 log.display("Getting tested methodID for method name: " + BREAKPOINT_METHOD_NAME); 228 testedMethodID = debugee.getMethodID(testedClassID, BREAKPOINT_METHOD_NAME, true); 229 log.display(" ... got methodID: " + testedMethodID); 230 231 // get methodID for the method with STEP_EVENT 232 log.display("Getting methodID for STEP_EVENT method name: " + STEP_METHOD_NAME); 233 stepMethodID = debugee.getMethodID(testedClassID, STEP_METHOD_NAME, true); 234 log.display(" ... got methodID: " + stepMethodID); 235 236 // get codeIndex for method entry line 237 log.display("Getting codeIndex for single step line: " + SINGLE_STEP_LINE); 238 long codeIndex = debugee.getCodeIndex(testedClassID, stepMethodID, SINGLE_STEP_LINE); 239 log.display(" ... got index: " + codeIndex); 240 241 // create location for method entry line 242 log.display("Creating location of single step event"); 243 testedLocation = new JDWP.Location(JDWP.TypeTag.CLASS, testedClassID, 244 stepMethodID, codeIndex); 245 log.display(" ... got location: " + testedLocation); 246 log.display(""); 247 248 // wait for breakpoint reached 249 log.display("Waiting for breakpoint reached at: " 250 + BREAKPOINT_METHOD_NAME + ":" + BREAKPOINT_LINE); 251 testedThreadID = debugee.waitForBreakpointReached(testedClassID, 252 BREAKPOINT_METHOD_NAME, 253 BREAKPOINT_LINE, 254 JDWP.SuspendPolicy.ALL); 255 log.display(" ... breakpoint reached with threadID: " + testedThreadID); 256 log.display(""); 257 } 258 259 /** 260 * Make request for tested SINGLE_STEP event. 261 */ requestTestedEvent()262 void requestTestedEvent() { 263 Failure failure = new Failure("Error occured while makind request for tested event"); 264 265 // create command packet and fill requred out data 266 log.display("Create command packet: " + "EventRequest.Set"); 267 CommandPacket command = new CommandPacket(JDWP.Command.EventRequest.Set); 268 log.display(" eventKind: " + TESTED_EVENT_KIND); 269 command.addByte(TESTED_EVENT_KIND); 270 log.display(" eventPolicy: " + TESTED_EVENT_SUSPEND_POLICY); 271 command.addByte(TESTED_EVENT_SUSPEND_POLICY); 272 log.display(" modifiers: " + 1); 273 command.addInt(1); 274 log.display(" modKind: " + JDWP.EventModifierKind.STEP + " (STEP)"); 275 command.addByte(JDWP.EventModifierKind.STEP); 276 log.display(" threadID: " + testedThreadID); 277 command.addObjectID(testedThreadID); 278 log.display(" size: " + STEP_SIZE); 279 command.addInt(STEP_SIZE); 280 log.display(" depth: " + STEP_DEPTH); 281 command.addInt(STEP_DEPTH); 282 command.setLength(); 283 log.display(" ... command packet composed"); 284 log.display(""); 285 286 // send command packet to debugee 287 try { 288 log.display("Sending command packet:\n" + command); 289 transport.write(command); 290 log.display(" ... command packet sent"); 291 } catch (IOException e) { 292 log.complain("Unable to send command packet:\n\t" + e); 293 success = false; 294 throw failure; 295 } 296 log.display(""); 297 298 ReplyPacket reply = new ReplyPacket(); 299 300 // receive reply packet from debugee 301 try { 302 log.display("Waiting for reply packet"); 303 transport.read(reply); 304 log.display(" ... packet received:\n" + reply); 305 } catch (IOException e) { 306 log.complain("Unable to read reply packet:\n\t" + e); 307 success = false; 308 throw failure; 309 } 310 log.display(""); 311 312 // check reply packet header 313 try{ 314 log.display("Checking header of reply packet"); 315 reply.checkHeader(command.getPacketID()); 316 log.display(" .. packet header is correct"); 317 } catch (BoundException e) { 318 log.complain("Bad header of reply packet:\n\t" + e.getMessage()); 319 success = false; 320 throw failure; 321 } 322 323 // start parsing reply packet data 324 log.display("Parsing reply packet:"); 325 reply.resetPosition(); 326 327 // extract requestID 328 int requestID = 0; 329 try { 330 requestID = reply.getInt(); 331 log.display(" requestID: " + requestID); 332 } catch (BoundException e) { 333 log.complain("Unable to extract requestID from request reply packet:\n\t" 334 + e.getMessage()); 335 success = false; 336 throw failure; 337 } 338 339 // check requestID 340 if (requestID == 0) { 341 log.complain("Unexpected null requestID returned: " + requestID); 342 success = false; 343 throw failure; 344 } 345 346 eventRequestID = requestID; 347 348 // check for extra data in reply packet 349 if (!reply.isParsed()) { 350 log.complain("Extra trailing bytes found in request reply packet at: " 351 + reply.offsetString()); 352 success = false; 353 } 354 355 log.display(" ... reply packet parsed"); 356 } 357 358 /** 359 * Clear request for tested SINGLE_STEP event. 360 */ clearTestedRequest()361 void clearTestedRequest() { 362 Failure failure = new Failure("Error occured while clearing request for tested event"); 363 364 // create command packet and fill requred out data 365 log.display("Create command packet: " + "EventRequest.Clear"); 366 CommandPacket command = new CommandPacket(JDWP.Command.EventRequest.Clear); 367 log.display(" event: " + TESTED_EVENT_KIND); 368 command.addByte(TESTED_EVENT_KIND); 369 log.display(" requestID: " + eventRequestID); 370 command.addInt(eventRequestID); 371 log.display(" ... command packet composed"); 372 log.display(""); 373 374 // send command packet to debugee 375 try { 376 log.display("Sending command packet:\n" + command); 377 transport.write(command); 378 log.display(" ... command packet sent"); 379 } catch (IOException e) { 380 log.complain("Unable to send command packet:\n\t" + e); 381 success = false; 382 throw failure; 383 } 384 log.display(""); 385 386 ReplyPacket reply = new ReplyPacket(); 387 388 // receive reply packet from debugee 389 try { 390 log.display("Waiting for reply packet"); 391 transport.read(reply); 392 log.display(" ... packet received:\n" + reply); 393 } catch (IOException e) { 394 log.complain("Unable to read reply packet:\n\t" + e); 395 success = false; 396 throw failure; 397 } 398 399 // check reply packet header 400 try{ 401 log.display("Checking header of reply packet"); 402 reply.checkHeader(command.getPacketID()); 403 log.display(" .. packet header is correct"); 404 } catch (BoundException e) { 405 log.complain("Bad header of reply packet:\n\t" + e.getMessage()); 406 success = false; 407 throw failure; 408 } 409 410 // start parsing reply packet data 411 log.display("Parsing reply packet:"); 412 reply.resetPosition(); 413 414 log.display(" no data"); 415 416 // check for extra data in reply packet 417 if (!reply.isParsed()) { 418 log.complain("Extra trailing bytes found in request reply packet at: " 419 + reply.offsetString()); 420 success = false; 421 } 422 423 log.display(" ... reply packet parsed"); 424 } 425 426 /** 427 * Wait for tested SINGLE_STEP event. 428 */ waitForTestedEvent()429 void waitForTestedEvent() { 430 431 EventPacket eventPacket = null; 432 433 // receive reply packet from debugee 434 try { 435 log.display("Waiting for event packet"); 436 eventPacket = debugee.getEventPacket(timeout); 437 log.display(" ... event packet received:\n" + eventPacket); 438 } catch (IOException e) { 439 log.complain("Unable to read tested event packet:\n\t" + e); 440 success = false; 441 return; 442 } 443 log.display(""); 444 445 // check reply packet header 446 try{ 447 log.display("Checking header of event packet"); 448 eventPacket.checkHeader(); 449 log.display(" ... packet header is correct"); 450 } catch (BoundException e) { 451 log.complain("Bad header of tested event packet:\n\t" 452 + e.getMessage()); 453 success = false; 454 return; 455 } 456 457 // start parsing reply packet data 458 log.display("Parsing event packet:"); 459 eventPacket.resetPosition(); 460 461 // get suspendPolicy value 462 byte suspendPolicy = 0; 463 try { 464 suspendPolicy = eventPacket.getByte(); 465 log.display(" suspendPolicy: " + suspendPolicy); 466 } catch (BoundException e) { 467 log.complain("Unable to get suspendPolicy value from tested event packet:\n\t" 468 + e.getMessage()); 469 success = false; 470 return; 471 } 472 473 // check suspendPolicy value 474 if (suspendPolicy != TESTED_EVENT_SUSPEND_POLICY) { 475 log.complain("Unexpected SuspendPolicy in tested event packet: " + 476 suspendPolicy + " (expected: " + TESTED_EVENT_SUSPEND_POLICY + ")"); 477 success = false; 478 } 479 480 // get events count 481 int events = 0; 482 try { 483 events = eventPacket.getInt(); 484 log.display(" events: " + events); 485 } catch (BoundException e) { 486 log.complain("Unable to get events count from tested event packet:\n\t" 487 + e.getMessage()); 488 success = false; 489 return; 490 } 491 492 // check events count 493 if (events < 0) { 494 log.complain("Negative value of events number in tested event packet: " + 495 events + " (expected: " + 1 + ")"); 496 success = false; 497 } else if (events != 1) { 498 log.complain("Invalid number of events in tested event packet: " + 499 events + " (expected: " + 1 + ")"); 500 success = false; 501 } 502 503 // extract each event 504 long eventThreadID = 0; 505 for (int i = 0; i < events; i++) { 506 log.display(" event #" + i + ":"); 507 508 // get eventKind 509 byte eventKind = 0; 510 try { 511 eventKind = eventPacket.getByte(); 512 log.display(" eventKind: " + eventKind); 513 } catch (BoundException e) { 514 log.complain("Unable to get eventKind of event #" + i + " from tested event packet:\n\t" 515 + e.getMessage()); 516 success = false; 517 return; 518 } 519 520 // check eventKind 521 if (eventKind == JDWP.EventKind.VM_DEATH) { 522 log.complain("Unexpected VM_DEATH event received: " + 523 eventKind + " (expected: " + JDWP.EventKind.SINGLE_STEP + ")"); 524 dead = true; 525 success = false; 526 return; 527 } else if (eventKind != JDWP.EventKind.SINGLE_STEP) { 528 log.complain("Unexpected eventKind of event " + i + " in tested event packet: " + 529 eventKind + " (expected: " + JDWP.EventKind.SINGLE_STEP + ")"); 530 success = false; 531 return; 532 } 533 534 // get requestID 535 int requestID = 0; 536 try { 537 requestID = eventPacket.getInt(); 538 log.display(" requestID: " + requestID); 539 } catch (BoundException e) { 540 log.complain("Unable to get requestID of event #" + i + " from tested event packet:\n\t" 541 + e.getMessage()); 542 success = false; 543 return; 544 } 545 546 // check requestID 547 if (requestID != eventRequestID) { 548 log.complain("Unexpected requestID of event " + i + " in tested event packet: " + 549 requestID + " (expected: " + eventRequestID + ")"); 550 success = false; 551 } 552 553 // get threadID 554 long threadID = 0; 555 try { 556 threadID = eventPacket.getObjectID(); 557 log.display(" threadID: " + threadID); 558 } catch (BoundException e) { 559 log.complain("Unable to get threadID of event #" + i + " from tested event packet:\n\t" 560 + e.getMessage()); 561 success = false; 562 return; 563 } 564 565 // check threadID 566 if (threadID != testedThreadID) { 567 log.complain("Unexpected threadID of event " + i + " in tested event packet: " + 568 threadID + " (expected: " + testedThreadID + ")"); 569 success = false; 570 } 571 572 // get location 573 JDWP.Location location = null; 574 try { 575 location = eventPacket.getLocation(); 576 log.display(" location: " + location); 577 } catch (BoundException e) { 578 log.complain("Unable to get location of event #" + i + " from tested event packet:\n\t" 579 + e.getMessage()); 580 success = false; 581 return; 582 } 583 584 // check location 585 if (location.getTag() != testedLocation.getTag()) { 586 log.complain("Unexpected class tag of location of event " + i 587 + " in tested event packet: " + location.getTag() 588 + " (expected: " + testedLocation.getTag() + ")"); 589 success = false; 590 } 591 if (location.getClassID() != testedLocation.getClassID()) { 592 log.complain("Unexpected classID of location of event " + i 593 + " in tested event packet: " + location.getClassID() 594 + " (expected: " + testedLocation.getClassID() + ")"); 595 success = false; 596 } 597 if (location.getMethodID() != testedLocation.getMethodID()) { 598 log.complain("Unexpected methodID of location of event " + i 599 + " in tested event packet: " + location.getMethodID() 600 + " (expected: " + testedLocation.getMethodID() + ")"); 601 success = false; 602 } 603 if (location.getIndex() != testedLocation.getIndex()) { 604 log.complain("Unexpected codeIndex of location of event " + i 605 + " in tested event packet: " + location.getIndex() 606 + " (expected: " + testedLocation.getIndex() + ")"); 607 success = false; 608 } 609 } 610 611 // check for extra data in event packet 612 if (!eventPacket.isParsed()) { 613 log.complain("Extra trailing bytes found in event packet at: " 614 + eventPacket.offsetString()); 615 success = false; 616 } 617 618 log.display(" ... event packet parsed"); 619 } 620 621 /** 622 * Disconnect debuggee and wait for it exited. 623 */ quitDebugee()624 void quitDebugee() { 625 if (debugee == null) 626 return; 627 628 // disconnect debugee 629 if (!dead) { 630 try { 631 log.display("Disconnecting debuggee"); 632 debugee.dispose(); 633 log.display(" ... debuggee disconnected"); 634 } catch (Failure e) { 635 log.display("Failed to finally disconnect debuggee:\n\t" 636 + e.getMessage()); 637 } 638 } 639 640 // wait for debugee exited 641 log.display("Waiting for debuggee exit"); 642 int code = debugee.waitFor(); 643 log.display(" ... debuggee exited with exit code: " + code); 644 645 // analize debugee exit status code 646 if (code != JCK_STATUS_BASE + PASSED) { 647 log.complain("Debuggee FAILED with exit code: " + code); 648 success = false; 649 } 650 } 651 652 } 653