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