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