1 /* 2 * Copyright (c) 2001, 2019, 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.VirtualMachine.suspend; 25 26 import jdk.test.lib.Utils; 27 import nsk.share.*; 28 import nsk.share.jpda.*; 29 import nsk.share.jdi.*; 30 31 import com.sun.jdi.*; 32 import java.util.*; 33 import java.io.*; 34 35 import com.sun.jdi.event.*; 36 import com.sun.jdi.request.*; 37 38 /** 39 * The test for the implementation of an object of the type <BR> 40 * VirtualMachine. <BR> 41 * <BR> 42 * The test checks up that results of the method <BR> 43 * <code>com.sun.jdi.VirtualMachine.suspend()</code> <BR> 44 * complies with its spec. <BR> 45 * <BR> 46 * The cases for testing are as follows. <BR> 47 * After being started up, <BR> 48 * a debuggee creates a 'lockingObject' for synchronizing threads, <BR> 49 * enters a synchronized block in which it creates new thread, thread2, <BR> 50 * informs a debugger of the thread2 creation, and is waiting for reply.<BR> 51 * Since thread2 uses the same locking object in its 'run' method <BR> 52 * it is locked up until first thread leaves the synchronized block. <BR> 53 * Upon the receiption a message from the debuggee, the debugger : <BR> 54 * - sets up breakpoints for both thread2 and main thread in the debuggee,<BR> 55 * - gets both threads suspended at the breakpoints, <BR> 56 * - calls to the method VirtualMachine.suspend(), <BR> 57 * - resumes both threads individually, one time each, <BR> 58 * - sleeps for predefined time - a standard parameter of the test, <BR> 59 * - then checks up the value of debuggee's field "flagCount" which is <BR> 60 * incremented by both tested threads only after their points of <BR> 61 * suspension. Hence, if the value == 0 (initial), it has not been <BR> 62 * changed by any tested thread while the debugger has been sleeping. <BR> 63 */ 64 65 public class suspend001 { 66 67 //----------------------------------------------------- templete section 68 static final int PASSED = 0; 69 static final int FAILED = 2; 70 static final int PASS_BASE = 95; 71 72 //----------------------------------------------------- templete parameters 73 static final String 74 sHeader1 = "\n==> nsk/jdi/VirtualMachine/suspend/suspend001 ", 75 sHeader2 = "--> debugger: ", 76 sHeader3 = "##> debugger: "; 77 78 //----------------------------------------------------- main method 79 main(String argv[])80 public static void main (String argv[]) { 81 int result = run(argv, System.out); 82 System.exit(result + PASS_BASE); 83 } 84 run(String argv[], PrintStream out)85 public static int run (String argv[], PrintStream out) { 86 return new suspend001().runThis(argv, out); 87 } 88 89 //-------------------------------------------------- log procedures 90 91 private static Log logHandler; 92 log1(String message)93 private static void log1(String message) { 94 logHandler.display(sHeader1 + message); 95 } log2(String message)96 private static void log2(String message) { 97 logHandler.display(sHeader2 + message); 98 } log3(String message)99 private static void log3(String message) { 100 logHandler.complain(sHeader3 + message); 101 } 102 103 // ************************************************ test parameters 104 105 private String debuggeeName = 106 "nsk.jdi.VirtualMachine.suspend.suspend001a"; 107 108 private String testedClassName = 109 "nsk.jdi.VirtualMachine.suspend.VMsuspend001a"; 110 111 //String mName = "nsk.jdi.VirtualMachine.suspend"; 112 113 //====================================================== test program 114 //------------------------------------------------------ common section 115 116 static ArgumentHandler argsHandler; 117 118 static int waitTime; 119 120 static VirtualMachine vm = null; 121 static EventRequestManager eventRManager = null; 122 static EventQueue eventQueue = null; 123 static EventSet eventSet = null; 124 125 ReferenceType testedclass = null; 126 ThreadReference thread2 = null; 127 ThreadReference mainThread = null; 128 129 static int testExitCode = PASSED; 130 131 static final int returnCode0 = 0; 132 static final int returnCode1 = 1; 133 static final int returnCode2 = 2; 134 static final int returnCode3 = 3; 135 static final int returnCode4 = 4; 136 137 //------------------------------------------------------ methods 138 runThis(String argv[], PrintStream out)139 private int runThis (String argv[], PrintStream out) { 140 141 Debugee debuggee; 142 143 argsHandler = new ArgumentHandler(argv); 144 logHandler = new Log(out, argsHandler); 145 Binder binder = new Binder(argsHandler, logHandler); 146 147 if (argsHandler.verbose()) { 148 debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); 149 } else { 150 debuggee = binder.bindToDebugee(debuggeeName); 151 } 152 153 waitTime = argsHandler.getWaitTime(); 154 155 156 IOPipe pipe = new IOPipe(debuggee); 157 158 debuggee.redirectStderr(out); 159 log2(debuggeeName + " debuggee launched"); 160 debuggee.resume(); 161 162 String line = pipe.readln(); 163 if ((line == null) || !line.equals("ready")) { 164 log3("signal received is not 'ready' but: " + line); 165 return FAILED; 166 } else { 167 log2("'ready' recieved"); 168 } 169 170 vm = debuggee.VM(); 171 172 //------------------------------------------------------ testing section 173 log1(" TESTING BEGINS"); 174 175 for (int i = 0; ; i++) { 176 177 pipe.println("newcheck"); 178 line = pipe.readln(); 179 180 if (line.equals("checkend")) { 181 log2(" : returned string is 'checkend'"); 182 break ; 183 } else if (!line.equals("checkready")) { 184 log3("ERROR: returned string is not 'checkready'"); 185 testExitCode = FAILED; 186 break ; 187 } 188 189 log1("new checkready: #" + i); 190 191 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part 192 193 int expresult = returnCode0; 194 195 eventRManager = vm.eventRequestManager(); 196 eventQueue = vm.eventQueue(); 197 198 String threadName = "Thread2"; 199 String flagName = "flagCount"; 200 201 String breakpointMethod1 = "runt1"; 202 String breakpointMethod2 = "runt2"; 203 204 String bpLine1 = "breakpointLineNumber1"; 205 String bpLine2 = "breakpointLineNumber2"; 206 207 List allThreads = null; 208 ListIterator listIterator = null; 209 List classes = null; 210 211 BreakpointRequest breakpRequest1 = null; 212 BreakpointRequest breakpRequest2 = null; 213 214 215 label0: { 216 217 log2("getting ThreadReference objects and setting up breakponts"); 218 try { 219 allThreads = vm.allThreads(); 220 classes = vm.classesByName(testedClassName); 221 testedclass = (ReferenceType) classes.get(0); 222 } catch ( Exception e) { 223 log3("ERROR: Exception at very beginning !? : " + e); 224 expresult = returnCode1; 225 break label0; 226 } 227 228 listIterator = allThreads.listIterator(); 229 for (;;) { 230 try { 231 thread2 = (ThreadReference) listIterator.next(); 232 if (thread2.name().equals(threadName)) 233 break ; 234 } catch ( NoSuchElementException e ) { 235 log3("ERROR: NoSuchElementException for listIterator.next()"); 236 log3("ERROR: NO THREAD2 ?????????!!!!!!!"); 237 expresult = returnCode1; 238 break label0; 239 } 240 } 241 listIterator = allThreads.listIterator(); 242 for (;;) { 243 try { 244 mainThread = (ThreadReference) listIterator.next(); 245 if (mainThread.name().equals("main")) 246 break ; 247 } catch ( NoSuchElementException e ) { 248 log3("ERROR: NoSuchElementException for listIterator.next()"); 249 log3("ERROR: NO THREAD2 ?????????!!!!!!!"); 250 expresult = returnCode1; 251 break label0; 252 } 253 } 254 255 log2("setting up breakpoints"); 256 257 breakpRequest1 = settingBreakpoint(breakpointMethod1, bpLine1, "one"); 258 if (breakpRequest1 == null) { 259 expresult = returnCode1; 260 break label0; 261 } 262 breakpRequest2 = settingBreakpoint(breakpointMethod2, bpLine2, "two"); 263 if (breakpRequest2 == null) { 264 expresult = returnCode1; 265 break label0; 266 } 267 } 268 269 label1: { 270 if (expresult != returnCode0) 271 break label1; 272 273 log2(" enabling breakpRequest1"); 274 breakpRequest1.enable(); 275 276 log2(" instructing the main thread to leave synchronized block"); 277 pipe.println("continue"); 278 line = pipe.readln(); 279 if (!line.equals("docontinue")) { 280 log3("ERROR: returned string is not 'docontinue'"); 281 expresult = returnCode4; 282 break label1; 283 } 284 285 log2(" getting BreakpointEvent"); 286 expresult = breakpoint(); 287 if (expresult != returnCode0) 288 break label1; 289 log2(" thread2 is at breakpoint"); 290 291 log2(" copying: EventSet eventSet1 = eventSet;"); 292 EventSet eventSet1 = eventSet; 293 294 log2(" enabling breakpRequest2"); 295 breakpRequest2.enable(); 296 297 log2(" instructing the main thread to leave to continue"); 298 pipe.println("continue"); 299 line = pipe.readln(); 300 if (!line.equals("docontinue")) { 301 log3("ERROR: returned string is not 'docontinue'"); 302 expresult = returnCode4; 303 break label1; 304 } 305 306 log2(" getting BreakpointEvent"); 307 expresult = breakpoint(); 308 if (expresult != returnCode0) 309 break label1; 310 log2(" mainThread is at breakpoint"); 311 312 log2(" debugger turned off pipe pinging"); 313 pipe.setPingTimeout(0); 314 315 log2(" suspending VM"); 316 vm.suspend(); 317 318 log2(" resuming threads individually: eventSet1.resume(); eventSet.resume();"); 319 eventSet1.resume(); 320 eventSet.resume(); 321 322 log2(" before: Thread.sleep(waitTime*1000);"); 323 324 try { 325 Thread.sleep(Utils.adjustTimeout(waitTime*1000)); 326 } catch ( InterruptedException e ) { 327 log3("ERROR: InterruptedException"); 328 expresult = returnCode1; 329 break label1; 330 } 331 332 log2(" checking up debuggee's flagCount value"); 333 int flag = ((IntegerValue) testedclass.getValue(testedclass.fieldByName(flagName))).value(); 334 log2(" value of flagCount == " + flag); 335 if (flag != 0) { 336 log3("ERROR: value of flagCount != 0"); 337 expresult = returnCode1; 338 } 339 } 340 341 log2(" resuming VM"); 342 vm.resume(); 343 344 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 345 log2(" the end of testing"); 346 if (expresult != returnCode0) 347 testExitCode = FAILED; 348 } 349 log1(" TESTING ENDS"); 350 351 //-------------------------------------------------- test summary section 352 //------------------------------------------------- standard end section 353 354 pipe.println("quit"); 355 log2("waiting for the debuggee to finish ..."); 356 debuggee.waitFor(); 357 358 int status = debuggee.getStatus(); 359 if (status != PASSED + PASS_BASE) { 360 log3("debuggee returned UNEXPECTED exit status: " + 361 status + " != PASS_BASE"); 362 testExitCode = FAILED; 363 } else { 364 log2("debuggee returned expected exit status: " + 365 status + " == PASS_BASE"); 366 } 367 368 if (testExitCode != PASSED) { 369 logHandler.complain("TEST FAILED"); 370 } 371 return testExitCode; 372 } 373 374 375 /* 376 * private BreakpointRequest settingBreakpoint(String, String, String) 377 * 378 * It sets up a breakpoint within a given method at given line number 379 * for the thread2 only. 380 * Third parameter is required for any case in future debugging, as if. 381 * 382 * Return codes: 383 * = BreakpointRequest object in case of success 384 * = null in case of an Exception thrown within the method 385 */ 386 settingBreakpoint( String methodName, String bpLine, String property)387 private BreakpointRequest settingBreakpoint ( String methodName, 388 String bpLine, 389 String property) { 390 391 log2("setting up a breakpoint: method: '" + methodName + "' line: " + bpLine ); 392 393 List alllineLocations = null; 394 Location lineLocation = null; 395 BreakpointRequest breakpRequest = null; 396 397 try { 398 Method method = (Method) testedclass.methodsByName(methodName).get(0); 399 400 alllineLocations = method.allLineLocations(); 401 402 int n = 403 ( (IntegerValue) testedclass.getValue(testedclass.fieldByName(bpLine) ) ).value(); 404 if (n > alllineLocations.size()) { 405 log3("ERROR: TEST_ERROR_IN_settingBreakpoint(): number is out of bound of method's lines"); 406 } else { 407 lineLocation = (Location) alllineLocations.get(n); 408 try { 409 breakpRequest = eventRManager.createBreakpointRequest(lineLocation); 410 breakpRequest.putProperty("number", property); 411 // breakpRequest.addThreadFilter(thread2); 412 breakpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); 413 } catch ( Exception e1 ) { 414 log3("ERROR: inner Exception within settingBreakpoint() : " + e1); 415 breakpRequest = null; 416 } 417 } 418 } catch ( Exception e2 ) { 419 log3("ERROR: ATTENTION: outer Exception within settingBreakpoint() : " + e2); 420 breakpRequest = null; 421 } 422 423 if (breakpRequest == null) 424 log2(" A BREAKPOINT HAS NOT BEEN SET UP"); 425 else 426 log2(" a breakpoint has been set up"); 427 428 return breakpRequest; 429 } 430 431 432 /* 433 * private int breakpoint () 434 * 435 * It removes events from EventQueue until gets first BreakpointEvent. 436 * To get next EventSet value, it uses the method 437 * EventQueue.remove(int timeout) 438 * The timeout argument passed to the method, is "waitTime*60000". 439 * Note: the value of waitTime is set up with 440 * the method ArgumentHandler.getWaitTime() at the beginning of the test. 441 * 442 * Return codes: 443 * = returnCode0 - success; 444 * = returnCode2 - Exception when "eventSet = eventQueue.remove()" is executed 445 * = returnCode3 - default case when loop of processing an event, that is, 446 * an unspecified event was taken from the EventQueue 447 */ 448 breakpoint()449 private int breakpoint () { 450 451 int returnCode = returnCode0; 452 453 log2(" waiting for BreakpointEvent"); 454 455 labelBP: 456 for (;;) { 457 458 log2(" new: eventSet = eventQueue.remove();"); 459 try { 460 eventSet = eventQueue.remove (waitTime*60000); 461 if (eventSet == null) { 462 // log2(":::::: timeout when waiting for a BreakpintEvent"); 463 log3("ERROR: timeout for waiting for a BreakpintEvent"); 464 returnCode = returnCode3; 465 break labelBP; 466 } 467 } catch ( Exception e ) { 468 log3("ERROR: Exception for eventSet = eventQueue.remove(); : " + e); 469 returnCode = 1; 470 break labelBP; 471 } 472 473 if (eventSet != null) { 474 475 log2(" : eventSet != null; size == " + eventSet.size()); 476 477 EventIterator eIter = eventSet.eventIterator(); 478 Event ev = null; 479 480 for (; eIter.hasNext(); ) { 481 482 if (returnCode != returnCode0) 483 break; 484 485 ev = eIter.nextEvent(); 486 487 ll: for (int ifor =0; ; ifor++) { 488 489 try { 490 switch (ifor) { 491 492 case 0: AccessWatchpointEvent awe = (AccessWatchpointEvent) ev; 493 log2(" AccessWatchpointEvent removed"); 494 break ll; 495 case 1: BreakpointEvent be = (BreakpointEvent) ev; 496 log2(" BreakpointEvent removed"); 497 break labelBP; 498 case 2: ClassPrepareEvent cpe = (ClassPrepareEvent) ev; 499 log2(" ClassPreparEvent removed"); 500 break ll; 501 case 3: ClassUnloadEvent cue = (ClassUnloadEvent) ev; 502 log2(" ClassUnloadEvent removed"); 503 break ll; 504 case 4: ExceptionEvent ee = (ExceptionEvent) ev; 505 log2(" ExceptionEvent removed"); 506 break ll; 507 case 5: MethodEntryEvent mene = (MethodEntryEvent) ev; 508 log2(" MethodEntryEvent removed"); 509 break ll; 510 case 6: MethodExitEvent mexe = (MethodExitEvent) ev; 511 log2(" MethodExiEvent removed"); 512 break ll; 513 case 7: ModificationWatchpointEvent mwe = (ModificationWatchpointEvent) ev; 514 log2(" ModificationWatchpointEvent removed"); 515 break ll; 516 case 8: StepEvent se = (StepEvent) ev; 517 log2(" StepEvent removed"); 518 break ll; 519 case 9: ThreadDeathEvent tde = (ThreadDeathEvent) ev; 520 log2(" ThreadDeathEvent removed"); 521 break ll; 522 case 10: ThreadStartEvent tse = (ThreadStartEvent) ev; 523 log2(" ThreadStartEvent removed"); 524 break ll; 525 case 11: VMDeathEvent vmde = (VMDeathEvent) ev; 526 log2(" VMDeathEvent removed"); 527 break ll; 528 case 12: VMStartEvent vmse = (VMStartEvent) ev; 529 log2(" VMStartEvent removed"); 530 break ll; 531 case 13: WatchpointEvent we = (WatchpointEvent) ev; 532 log2(" WatchpointEvent removed"); 533 break ll; 534 535 default: log3("ERROR: default case for casting event"); 536 returnCode = returnCode3; 537 break ll; 538 } // switch 539 } catch ( ClassCastException e ) { 540 } // try 541 } // ll: for (int ifor =0; ; ifor++) 542 } // for (; ev.hasNext(); ) 543 } 544 } 545 if (returnCode == returnCode0) 546 log2(" : eventSet == null: EventQueue is empty"); 547 548 return returnCode; 549 } 550 551 } 552