1 /******************************************************************************* 2 * Copyright (c) 2000, 2015 IBM Corporation and others. 3 * 4 * This program and the accompanying materials 5 * are made available under the terms of the Eclipse Public License 2.0 6 * which accompanies this distribution, and is available at 7 * https://www.eclipse.org/legal/epl-2.0/ 8 * 9 * SPDX-License-Identifier: EPL-2.0 10 * 11 * Contributors: 12 * IBM Corporation - initial API and implementation 13 *******************************************************************************/ 14 package org.eclipse.debug.jdi.tests; 15 16 import java.io.File; 17 import java.io.IOException; 18 import java.io.InputStream; 19 import java.util.Iterator; 20 import java.util.List; 21 import java.util.ListIterator; 22 import java.util.Map; 23 import java.util.StringTokenizer; 24 import java.util.Vector; 25 26 import org.eclipse.jdi.Bootstrap; 27 28 import com.sun.jdi.AbsentInformationException; 29 import com.sun.jdi.ArrayReference; 30 import com.sun.jdi.ArrayType; 31 import com.sun.jdi.ClassLoaderReference; 32 import com.sun.jdi.ClassNotLoadedException; 33 import com.sun.jdi.ClassType; 34 import com.sun.jdi.Field; 35 import com.sun.jdi.IncompatibleThreadStateException; 36 import com.sun.jdi.InterfaceType; 37 import com.sun.jdi.InvalidTypeException; 38 import com.sun.jdi.LocalVariable; 39 import com.sun.jdi.Location; 40 import com.sun.jdi.Method; 41 import com.sun.jdi.ObjectReference; 42 import com.sun.jdi.ReferenceType; 43 import com.sun.jdi.StackFrame; 44 import com.sun.jdi.StringReference; 45 import com.sun.jdi.ThreadReference; 46 import com.sun.jdi.VMDisconnectedException; 47 import com.sun.jdi.Value; 48 import com.sun.jdi.VirtualMachineManager; 49 import com.sun.jdi.connect.AttachingConnector; 50 import com.sun.jdi.connect.Connector.Argument; 51 import com.sun.jdi.connect.IllegalConnectorArgumentsException; 52 import com.sun.jdi.event.Event; 53 import com.sun.jdi.event.ExceptionEvent; 54 import com.sun.jdi.event.StepEvent; 55 import com.sun.jdi.request.AccessWatchpointRequest; 56 import com.sun.jdi.request.BreakpointRequest; 57 import com.sun.jdi.request.EventRequest; 58 import com.sun.jdi.request.ExceptionRequest; 59 import com.sun.jdi.request.ModificationWatchpointRequest; 60 import com.sun.jdi.request.StepRequest; 61 62 import junit.framework.Test; 63 import junit.framework.TestCase; 64 65 /** 66 * Tests for com.sun.jdi.* and JDWP commands. 67 * These tests assume that the target program is 68 * "org.eclipse.debug.jdi.tests.program.MainClass". 69 * 70 * Examples of arguments: 71 * -launcher SunVMLauncher -address c:\jdk1.2.2\ -cp d:\target 72 * -launcher J9VMLauncher -address d:\ive\ -cp d:\target 73 */ 74 public abstract class AbstractJDITest extends TestCase { 75 static int TIMEOUT = 10000; //ms 76 static protected int fBackEndPort = 9900; 77 // We want subsequent connections to use different ports. 78 protected static String fVMLauncherName; 79 protected static String fTargetAddress; 80 protected static String fClassPath; 81 protected static String fBootPath; 82 protected static String fVMType; 83 protected com.sun.jdi.VirtualMachine fVM; 84 protected Process fLaunchedProxy; 85 protected Process fLaunchedVM; 86 protected static int fVMTraceFlags = com.sun.jdi.VirtualMachine.TRACE_NONE; 87 protected EventReader fEventReader; 88 protected AbstractReader fConsoleReader; 89 protected AbstractReader fConsoleErrorReader; 90 protected AbstractReader fProxyReader; 91 protected AbstractReader fProxyErrorReader; 92 protected boolean fInControl = true; 93 // Whether this test should control the VM (ie. starting it and shutting it down) 94 protected static boolean fVerbose; 95 protected static String fStdoutFile; 96 protected static String fStderrFile; 97 protected static String fProxyoutFile; 98 protected static String fProxyerrFile; 99 protected static String fVmCmd; 100 protected static String fVmArgs; 101 protected static String fProxyCmd; 102 103 // Stack offset to the MainClass.run() method 104 protected static final int RUN_FRAME_OFFSET = 1; 105 106 /** 107 * Constructs a test case with a default name. 108 */ AbstractJDITest()109 public AbstractJDITest() { 110 super("JDI Test"); 111 } 112 /** 113 * Returns the names of the tests that are known to not work 114 * By default, none are excluded. 115 */ excludedTests()116 protected String[] excludedTests() { 117 return new String[] { 118 }; 119 } 120 /** 121 * Creates and returns an access watchpoint request 122 * for the field "fBool" in 123 * org.eclipse.debug.jdi.tests.program.MainClass 124 * NOTE: This assumes that the VM can watch field access. 125 */ getAccessWatchpointRequest()126 protected AccessWatchpointRequest getAccessWatchpointRequest() { 127 // Get the field 128 Field field = getField("fBool"); 129 130 // Create an access watchpoint for this field 131 return fVM.eventRequestManager().createAccessWatchpointRequest(field); 132 } 133 /** 134 * Returns all tests that start with the given string. 135 * Returns a vector of String. 136 */ getAllMatchingTests(String match)137 protected Vector<String> getAllMatchingTests(String match) { 138 Class<? extends AbstractJDITest> theClass = this.getClass(); 139 java.lang.reflect.Method[] methods = theClass.getDeclaredMethods(); 140 Vector<String> result = new Vector<>(); 141 for (int i = 0; i < methods.length; i++) { 142 java.lang.reflect.Method m = methods[i]; 143 String name = m.getName(); 144 Class<?>[] parameters = m.getParameterTypes(); 145 if (parameters.length == 0 && name.startsWith(match)) { 146 if (!isExcludedTest(name)) { 147 result.add(name); 148 } else { 149 System.out.println(name + " is excluded."); 150 } 151 } 152 } 153 return result; 154 } 155 156 /** 157 * Returns if the current VM version is greater than or equal to 1.6 158 * @return <code>true</code> if a 1.6 or higher VM 159 * @since 3.8 160 */ is16OrGreater()161 protected boolean is16OrGreater() { 162 String ver = fVM.version(); 163 return ver.indexOf("1.6") > -1 || ver.indexOf("1.7") > -1; 164 } 165 166 /** 167 * Returns an array reference. 168 */ getObjectArrayReference()169 protected ArrayReference getObjectArrayReference() { 170 // Get static field "fArray" 171 Field field = getField("fArray"); 172 173 // Get value of "fArray" 174 return (ArrayReference) getMainClass().getValue(field); 175 } 176 177 /** 178 * Returns another array reference. 179 */ getNonEmptyDoubleArrayReference()180 protected ArrayReference getNonEmptyDoubleArrayReference() { 181 // Get static field "fDoubleArray" 182 Field field = getField("fDoubleArray"); 183 184 // Get value of "fDoubleArray" 185 return (ArrayReference) getMainClass().getValue(field); 186 } 187 188 /** 189 * One-dimensional empty array reference getters 190 */ getByteArrayReference()191 protected ArrayReference getByteArrayReference() { 192 Field field = getField("byteArray"); 193 return (ArrayReference) getMainClass().getValue(field); 194 } getShortArrayReference()195 protected ArrayReference getShortArrayReference() { 196 Field field = getField("shortArray"); 197 return (ArrayReference) getMainClass().getValue(field); 198 } getIntArrayReference()199 protected ArrayReference getIntArrayReference() { 200 Field field = getField("intArray"); 201 return (ArrayReference) getMainClass().getValue(field); 202 } getLongArrayReference()203 protected ArrayReference getLongArrayReference() { 204 Field field = getField("longArray"); 205 return (ArrayReference) getMainClass().getValue(field); 206 } getDoubleArrayReference()207 protected ArrayReference getDoubleArrayReference() { 208 Field field = getField("doubleArray"); 209 return (ArrayReference) getMainClass().getValue(field); 210 } getFloatArrayReference()211 protected ArrayReference getFloatArrayReference() { 212 Field field = getField("floatArray"); 213 return (ArrayReference) getMainClass().getValue(field); 214 } getCharArrayReference()215 protected ArrayReference getCharArrayReference() { 216 Field field = getField("charArray"); 217 return (ArrayReference) getMainClass().getValue(field); 218 } getBooleanArrayReference()219 protected ArrayReference getBooleanArrayReference() { 220 Field field = getField("booleanArray"); 221 return (ArrayReference) getMainClass().getValue(field); 222 } 223 /** 224 * Two-dimensional array reference getters 225 */ getByteDoubleArrayReference()226 protected ArrayReference getByteDoubleArrayReference() { 227 Field field = getField("byteDoubleArray"); 228 return (ArrayReference) getMainClass().getValue(field); 229 } getShortDoubleArrayReference()230 protected ArrayReference getShortDoubleArrayReference() { 231 Field field = getField("shortDoubleArray"); 232 return (ArrayReference) getMainClass().getValue(field); 233 } getIntDoubleArrayReference()234 protected ArrayReference getIntDoubleArrayReference() { 235 Field field = getField("intDoubleArray"); 236 return (ArrayReference) getMainClass().getValue(field); 237 } getLongDoubleArrayReference()238 protected ArrayReference getLongDoubleArrayReference() { 239 Field field = getField("longDoubleArray"); 240 return (ArrayReference) getMainClass().getValue(field); 241 } getFloatDoubleArrayReference()242 protected ArrayReference getFloatDoubleArrayReference() { 243 Field field = getField("floatDoubleArray"); 244 return (ArrayReference) getMainClass().getValue(field); 245 } getDoubleDoubleArrayReference()246 protected ArrayReference getDoubleDoubleArrayReference() { 247 Field field = getField("doubleDoubleArray"); 248 return (ArrayReference) getMainClass().getValue(field); 249 } getCharDoubleArrayReference()250 protected ArrayReference getCharDoubleArrayReference() { 251 Field field = getField("charDoubleArray"); 252 return (ArrayReference) getMainClass().getValue(field); 253 } getBooleanDoubleArrayReference()254 protected ArrayReference getBooleanDoubleArrayReference() { 255 Field field = getField("booleanDoubleArray"); 256 return (ArrayReference) getMainClass().getValue(field); 257 } 258 259 /** 260 * Returns the array type. 261 */ getArrayType()262 protected ArrayType getArrayType() { 263 // Get array reference 264 ArrayReference value = getObjectArrayReference(); 265 266 // Get reference type of "fArray" 267 return (ArrayType) value.referenceType(); 268 } 269 /** 270 * One-dimensional primitive array getters 271 */ getByteArrayType()272 protected ArrayType getByteArrayType() { 273 ArrayReference value = getByteArrayReference(); 274 return (ArrayType) value.referenceType(); 275 } getShortArrayType()276 protected ArrayType getShortArrayType() { 277 ArrayReference value = getShortArrayReference(); 278 return (ArrayType) value.referenceType(); 279 } getIntArrayType()280 protected ArrayType getIntArrayType() { 281 ArrayReference value = getIntArrayReference(); 282 return (ArrayType) value.referenceType(); 283 } getLongArrayType()284 protected ArrayType getLongArrayType() { 285 ArrayReference value = getLongArrayReference(); 286 return (ArrayType) value.referenceType(); 287 } getFloatArrayType()288 protected ArrayType getFloatArrayType() { 289 ArrayReference value = getFloatArrayReference(); 290 return (ArrayType) value.referenceType(); 291 } getDoubleArrayType()292 protected ArrayType getDoubleArrayType() { 293 ArrayReference value = getDoubleArrayReference(); 294 return (ArrayType) value.referenceType(); 295 } getCharArrayType()296 protected ArrayType getCharArrayType() { 297 ArrayReference value = getCharArrayReference(); 298 return (ArrayType) value.referenceType(); 299 } getBooleanArrayType()300 protected ArrayType getBooleanArrayType() { 301 ArrayReference value = getBooleanArrayReference(); 302 return (ArrayType) value.referenceType(); 303 } 304 /** 305 * Two-dimensional primitive array getters 306 */ getByteDoubleArrayType()307 protected ArrayType getByteDoubleArrayType() { 308 ArrayReference value = getByteDoubleArrayReference(); 309 return (ArrayType) value.referenceType(); 310 } getShortDoubleArrayType()311 protected ArrayType getShortDoubleArrayType() { 312 ArrayReference value = getShortDoubleArrayReference(); 313 return (ArrayType) value.referenceType(); 314 } getIntDoubleArrayType()315 protected ArrayType getIntDoubleArrayType() { 316 ArrayReference value = getIntDoubleArrayReference(); 317 return (ArrayType) value.referenceType(); 318 } getLongDoubleArrayType()319 protected ArrayType getLongDoubleArrayType() { 320 ArrayReference value = getLongDoubleArrayReference(); 321 return (ArrayType) value.referenceType(); 322 } getFloatDoubleArrayType()323 protected ArrayType getFloatDoubleArrayType() { 324 ArrayReference value = getFloatDoubleArrayReference(); 325 return (ArrayType) value.referenceType(); 326 } getDoubleDoubleArrayType()327 protected ArrayType getDoubleDoubleArrayType() { 328 ArrayReference value = getDoubleDoubleArrayReference(); 329 return (ArrayType) value.referenceType(); 330 } getCharDoubleArrayType()331 protected ArrayType getCharDoubleArrayType() { 332 ArrayReference value = getCharDoubleArrayReference(); 333 return (ArrayType) value.referenceType(); 334 } getBooleanDoubleArrayType()335 protected ArrayType getBooleanDoubleArrayType() { 336 ArrayReference value = getBooleanDoubleArrayReference(); 337 return (ArrayType) value.referenceType(); 338 } 339 340 /** 341 * Creates and returns a breakpoint request in the first 342 * instruction of the MainClass.triggerBreakpointEvent() method. 343 */ getBreakpointRequest()344 protected BreakpointRequest getBreakpointRequest() { 345 // Create a breakpoint request 346 return fVM.eventRequestManager().createBreakpointRequest(getLocation()); 347 } 348 349 /** 350 * Creates a new breakpoint request for a user specified position 351 * @param loc the location to set the breakpoint on 352 * @return a new breakpoint request or null if the location is invalid 353 * @since 3.3 354 */ getBreakpointRequest(Location loc)355 protected BreakpointRequest getBreakpointRequest(Location loc) { 356 return fVM.eventRequestManager().createBreakpointRequest(loc); 357 } 358 /** 359 * Returns the class with the given name or null if not loaded. 360 */ getClass(String name)361 protected ClassType getClass(String name) { 362 List<?> classes = fVM.classesByName(name); 363 if (classes.size() == 0) { 364 return null; 365 } 366 367 return (ClassType) classes.get(0); 368 } 369 /** 370 * Returns the class loader of 371 * org.eclipse.debug.jdi.tests.program.MainClass 372 */ getClassLoaderReference()373 protected ClassLoaderReference getClassLoaderReference() { 374 // Get main class 375 ClassType type = getMainClass(); 376 377 // Get its class loader 378 return type.classLoader(); 379 } 380 /** 381 * Creates and returns an exception request for uncaught exceptions. 382 */ getExceptionRequest()383 protected ExceptionRequest getExceptionRequest() { 384 return fVM.eventRequestManager().createExceptionRequest(null, false, true); 385 } 386 /** 387 * Returns the static field "fObject" in 388 * org.eclipse.debug.jdi.tests.program.MainClass 389 */ getField()390 protected Field getField() { 391 return getField("fObject"); 392 } 393 /** 394 * Returns the field with the given name in 395 * org.eclipse.debug.jdi.tests.program.MainClass. 396 */ getField(String fieldName)397 protected Field getField(String fieldName) { 398 // Get main class 399 ClassType type = getMainClass(); 400 401 // Get field 402 Field result = type.fieldByName(fieldName); 403 if (result == null) { 404 throw new Error("Unknown field: " + fieldName); 405 } 406 407 return result; 408 } 409 /** 410 * Returns the n frame (starting at the top of the stack) of the thread 411 * contained in the static field "fThread" of org.eclipse.debug.jdi.tests.program.MainClass. 412 */ getFrame(int n)413 protected StackFrame getFrame(int n) { 414 // Make sure the thread is suspended 415 ThreadReference thread = getThread(); 416 assertTrue(thread.isSuspended()); 417 418 // Get the frame 419 StackFrame frame = null; 420 try { 421 List<?> frames = thread.frames(); 422 frame = (StackFrame) frames.get(n); 423 } catch (IncompatibleThreadStateException e) { 424 throw new Error("Thread was not suspended"); 425 } 426 427 return frame; 428 } 429 /** 430 * Returns the interface type org.eclipse.debug.jdi.tests.program.Printable. 431 */ getInterfaceType()432 protected InterfaceType getInterfaceType() { 433 List<?> types = fVM.classesByName("org.eclipse.debug.jdi.tests.program.Printable"); 434 return (InterfaceType) types.get(0); 435 } 436 /** 437 * Returns the variable "t" in the frame running MainClass.run(). 438 */ getLocalVariable()439 protected LocalVariable getLocalVariable() { 440 try { 441 return getFrame(RUN_FRAME_OFFSET).visibleVariableByName("t"); 442 } catch (AbsentInformationException e) { 443 return null; 444 } 445 } 446 /** 447 * Returns the first location in MainClass.print(OutputStream). 448 */ getLocation()449 protected Location getLocation() { 450 return getMethod().location(); 451 } 452 /** 453 * Returns the class org.eclipse.debug.jdi.tests.program.MainClass. 454 */ getMainClass()455 protected ClassType getMainClass() { 456 return getClass( getMainClassName() ); 457 } 458 /** 459 * Returns the method "print(Ljava/io/OutputStream;)V" 460 * in org.eclipse.debug.jdi.tests.program.MainClass 461 */ getMethod()462 protected Method getMethod() { 463 return getMethod("print", "(Ljava/io/OutputStream;)V"); 464 } 465 /** 466 * Returns the method with the given name and signature 467 * in org.eclipse.debug.jdi.tests.program.MainClass 468 */ getMethod(String name, String signature)469 protected Method getMethod(String name, String signature) { 470 return getMethod( 471 getMainClassName(), 472 name, 473 signature); 474 } 475 /** 476 * Returns the method with the given name and signature 477 * in the given class. 478 */ getMethod(String className, String name, String signature)479 protected Method getMethod(String className, String name, String signature) { 480 // Get main class 481 ClassType type = getClass(className); 482 483 // Get method print(OutputStream) 484 Method method = null; 485 List<Method> methods = type.methods(); 486 ListIterator<Method> iterator = methods.listIterator(); 487 while (iterator.hasNext()) { 488 Method m = iterator.next(); 489 if ((m.name().equals(name)) && (m.signature().equals(signature))) { 490 method = m; 491 break; 492 } 493 } 494 if (method == null) { 495 throw new Error("Unknown method: " + name + signature); 496 } 497 498 return method; 499 } 500 /** 501 * Creates and returns a modification watchpoint request 502 * for the field "fBool" in 503 * org.eclipse.debug.jdi.tests.program.MainClass. 504 * NOTE: This assumes that the VM can watch field modification. 505 */ getModificationWatchpointRequest()506 protected ModificationWatchpointRequest getModificationWatchpointRequest() { 507 // Get the field 508 Field field = getField("fBool"); 509 510 // Create a modification watchpoint for this field 511 return fVM.eventRequestManager().createModificationWatchpointRequest(field); 512 } 513 /** 514 * Returns the value of the static field "fObject" in 515 * org.eclipse.debug.jdi.tests.program.MainClass 516 */ getObjectReference()517 protected ObjectReference getObjectReference() { 518 // Get main class 519 ClassType type = getMainClass(); 520 521 // Get field "fObject" 522 Field field = getField(); 523 524 // Get value of "fObject" 525 return (ObjectReference) type.getValue(field); 526 } 527 /** 528 * Creates and returns an access watchpoint request 529 * for the static field "fString" in 530 * org.eclipse.debug.jdi.tests.program.MainClass 531 * NOTE: This assumes that the VM can watch field access. 532 */ getStaticAccessWatchpointRequest()533 protected AccessWatchpointRequest getStaticAccessWatchpointRequest() { 534 // Get the static field 535 Field field = getField("fString"); 536 537 // Create an access watchpoint for this field 538 return fVM.eventRequestManager().createAccessWatchpointRequest(field); 539 } 540 /** 541 * Creates and returns a modification watchpoint request 542 * for the static field "fString" in 543 * org.eclipse.debug.jdi.tests.program.MainClass. 544 * NOTE: This assumes that the VM can watch field modification. 545 */ getStaticModificationWatchpointRequest()546 protected ModificationWatchpointRequest getStaticModificationWatchpointRequest() { 547 // Get the field 548 Field field = getField("fString"); 549 550 // Create a modification watchpoint for this field 551 return fVM.eventRequestManager().createModificationWatchpointRequest(field); 552 } 553 /** 554 * Returns the value of the static field "fString" in 555 * org.eclipse.debug.jdi.tests.program.MainClass 556 */ getStringReference()557 protected StringReference getStringReference() { 558 // Get field "fString" 559 Field field = getField("fString"); 560 561 // Get value of "fString" 562 return (StringReference) getMainClass().getValue(field); 563 } 564 /** 565 * Returns the class java.lang.Object. 566 */ getSystemType()567 protected ClassType getSystemType() { 568 List<ReferenceType> classes = fVM.classesByName("java.lang.Object"); 569 if (classes.size() == 0) { 570 return null; 571 } 572 573 return (ClassType) classes.get(0); 574 } 575 /** 576 * Returns the thread contained in the static field "fThread" in 577 * org.eclipse.debug.jdi.tests.program.MainClass 578 */ getThread()579 protected ThreadReference getThread() { 580 return getThread("fThread"); 581 } 582 getMainThread()583 protected ThreadReference getMainThread() { 584 return getThread("fMainThread"); 585 } 586 getThread(String fieldName)587 private ThreadReference getThread(String fieldName) { 588 ClassType type = getMainClass(); 589 if (type == null) { 590 return null; 591 } 592 593 // Get static field "fThread" 594 List<Field> fields = type.fields(); 595 ListIterator<Field> iterator = fields.listIterator(); 596 Field field = null; 597 while (iterator.hasNext()) { 598 field = iterator.next(); 599 if (field.name().equals(fieldName)) { 600 break; 601 } 602 } 603 604 // Get value of "fThread" 605 Value value = type.getValue(field); 606 if (value == null) { 607 return null; 608 } 609 610 return (ThreadReference) value; 611 } 612 /** 613 * Returns the VM info for this test. 614 */ getVMInfo()615 public VMInformation getVMInfo() { 616 return new VMInformation( 617 fVM, 618 fVMType, 619 fLaunchedVM, 620 fEventReader, 621 fConsoleReader); 622 } 623 /** 624 * Returns whether the given test is excluded for the VM we are testing. 625 */ isExcludedTest(String testName)626 private boolean isExcludedTest(String testName) { 627 String[] excludedTests = excludedTests(); 628 if (excludedTests == null) { 629 return false; 630 } 631 for (int i = 0; i < excludedTests.length; i++) { 632 if (testName.equals(excludedTests[i])) { 633 return true; 634 } 635 } 636 return false; 637 } 638 639 /** 640 * Launches the target VM and connects to VM. 641 */ launchTargetAndConnectToVM()642 protected void launchTargetAndConnectToVM() { 643 launchTarget(); 644 connectToVM(); 645 } 646 vmIsRunning()647 protected boolean vmIsRunning() { 648 boolean isRunning = false; 649 try { 650 if (fLaunchedVM != null) { 651 fLaunchedVM.exitValue(); 652 } 653 } catch (IllegalThreadStateException e) { 654 isRunning = true; 655 } 656 return isRunning; 657 } 658 launchTarget()659 protected void launchTarget() { 660 if (fVmCmd != null) { 661 launchCommandLineTarget(); 662 } else if (fVMLauncherName.equals("SunVMLauncher")) { 663 launchSunTarget(); 664 } else if (fVMLauncherName.equals("IBMVMLauncher")) { 665 launchIBMTarget(); 666 } else { 667 launchJ9Target(); 668 } 669 } 670 671 /** 672 * Launches the target VM specified on the command line. 673 */ launchCommandLineTarget()674 private void launchCommandLineTarget() { 675 try { 676 if (fProxyCmd != null) { 677 fLaunchedProxy = Runtime.getRuntime().exec(parseCommand(fProxyCmd)); 678 } 679 fLaunchedVM = Runtime.getRuntime().exec(parseCommand(fVmCmd)); 680 } catch (IOException e) { 681 throw new Error("Could not launch the VM because " + e.getMessage()); 682 } 683 } 684 685 /** 686 * Parse the command {@link String} to make sure we use 687 * {@link Runtime#exec(String[])}. 688 * 689 * @param command 690 * @return the array of items from the command {@link String} 691 * @since 4.3 692 */ parseCommand(String command)693 String[] parseCommand(String command) { 694 StringTokenizer tokenizer = new StringTokenizer(command); 695 String[] commandArray = new String[tokenizer.countTokens()]; 696 //first token is the command 697 if(tokenizer.hasMoreTokens()) { 698 commandArray[0] = tokenizer.nextToken(); 699 } 700 for (int i= 1; tokenizer.hasMoreTokens(); i++) { 701 commandArray[i] = tokenizer.nextToken(); 702 } 703 return commandArray; 704 } 705 706 /** 707 * Launches the target J9 VM. 708 */ launchJ9Target()709 private void launchJ9Target() { 710 try { 711 // Launch proxy 712 String proxyString[] = new String[3]; 713 int index = 0; 714 String binDirectory = 715 fTargetAddress 716 + File.separatorChar 717 + "bin" 718 + File.separatorChar; 719 720 proxyString[index++] = binDirectory + "j9proxy"; 721 proxyString[index++] = "localhost:" + (fBackEndPort - 1); 722 proxyString[index++] = "" + fBackEndPort; 723 fLaunchedProxy = Runtime.getRuntime().exec(proxyString); 724 725 // Launch target VM 726 Vector<String> commandLine = new Vector<>(); 727 728 String launcher = binDirectory + "j9w.exe"; 729 File vm= new File(launcher); 730 if (!vm.exists()) { 731 launcher = binDirectory + "j9"; 732 } 733 commandLine.add(launcher); 734 735 if (fBootPath.length() > 0) { 736 commandLine.add("-bp:" + fBootPath); 737 } 738 commandLine.add("-cp:" + fClassPath); 739 commandLine.add("-debug:" + (fBackEndPort - 1)); 740 injectVMArgs(commandLine); 741 commandLine.add(getMainClassName()); 742 743 fLaunchedVM = exec(commandLine); 744 745 } catch (IOException e) { 746 throw new Error("Could not launch the VM because " + e.getMessage()); 747 } 748 } 749 750 /** 751 * Launches the target Sun VM. 752 */ launchSunTarget()753 private void launchSunTarget() { 754 try { 755 // Launch target VM 756 StringBuilder binDirectory= new StringBuilder(); 757 if (fTargetAddress.endsWith("jre")) { 758 binDirectory.append(fTargetAddress.substring(0, fTargetAddress.length() - 4)); 759 } else { 760 binDirectory.append(fTargetAddress); 761 } 762 binDirectory.append(File.separatorChar); 763 binDirectory.append("bin").append(File.separatorChar); 764 765 Vector<String> commandLine = new Vector<>(); 766 767 String launcher = binDirectory.toString() + "javaw.exe"; 768 File vm= new File(launcher); 769 if (!vm.exists()) { 770 launcher = binDirectory + "java"; 771 } 772 commandLine.add(launcher); 773 774 if (fBootPath.length() > 0) { 775 commandLine.add("-bootpath"); 776 commandLine.add(fBootPath); 777 } 778 commandLine.add("-classpath"); 779 commandLine.add(fClassPath); 780 commandLine.add("-Xdebug"); 781 commandLine.add("-Xnoagent"); 782 commandLine.add("-Djava.compiler=NONE"); 783 commandLine.add("-Xrunjdwp:transport=dt_socket,address=" + fBackEndPort + ",suspend=y,server=y"); 784 injectVMArgs(commandLine); 785 commandLine.add(getMainClassName()); 786 787 fLaunchedVM = exec(commandLine); 788 789 } catch (IOException e) { 790 throw new Error("Could not launch the VM because " + e.getMessage()); 791 } 792 } 793 /** 794 * Launches the target IBM VM. 795 */ launchIBMTarget()796 private void launchIBMTarget() { 797 try { 798 // Launch target VM 799 String binDirectory = 800 fTargetAddress 801 + File.separatorChar 802 + "bin" 803 + File.separatorChar; 804 805 Vector<String> commandLine = new Vector<>(); 806 807 commandLine.add(binDirectory + "javaw"); 808 if (fBootPath.length() > 0) { 809 commandLine.add("-bootpath"); 810 commandLine.add(fBootPath); 811 } 812 813 commandLine.add("-classpath"); 814 commandLine.add(fClassPath); 815 commandLine.add("-Xdebug"); 816 commandLine.add("-Xnoagent"); 817 commandLine.add("-Djava.compiler=NONE"); 818 commandLine.add("-Xrunjdwp:transport=dt_socket,address=" + fBackEndPort + ",suspend=y,server=y"); 819 injectVMArgs(commandLine); 820 commandLine.add(getMainClassName()); 821 822 fLaunchedVM = exec(commandLine); 823 824 } catch (IOException e) { 825 throw new Error("Could not launch the VM because " + e.getMessage()); 826 } 827 } 828 getMainClassName()829 protected String getMainClassName() { 830 return "org.eclipse.debug.jdi.tests.program.MainClass"; 831 } 832 getTestPrefix()833 protected String getTestPrefix() { 834 return "testJDI"; 835 } 836 837 /** 838 * Injects arguments specified using -vmargs command line option into 839 * the provided commandLine. 840 * @param commandLine A vector of command line argument strings. 841 */ injectVMArgs(Vector<String> commandLine)842 private void injectVMArgs(Vector<String> commandLine) { 843 if (fVmArgs != null) { 844 String[] args = fVmArgs.split(","); 845 for (int i=0; i < args.length; i++) { 846 commandLine.add(args[i]); 847 } 848 } 849 } 850 851 /** 852 * Flattens the variable size command line and calls Runtime.exec(). 853 * @param commandLine A vector of command line argument strings. 854 * @return The Process created by Runtime.exec() 855 * @throws IOException 856 */ exec(Vector<String> commandLine)857 private Process exec(Vector<String> commandLine) throws IOException { 858 String[] vmString = new String[commandLine.size()]; 859 commandLine.toArray(vmString); 860 return Runtime.getRuntime().exec(vmString); 861 } 862 863 864 /** 865 * Connects to the target vm. 866 */ connectToVM()867 protected void connectToVM() { 868 // Start the console reader if possible so that the VM doesn't block when the stdout is full 869 startConsoleReaders(); 870 871 872 // Contact the VM (try 10 times) 873 for (int i = 0; i < 10; i++) { 874 try { 875 VirtualMachineManager manager = Bootstrap.virtualMachineManager(); 876 List<AttachingConnector> connectors = manager.attachingConnectors(); 877 if (connectors.size() == 0) { 878 break; 879 } 880 AttachingConnector connector = connectors.get(0); 881 Map<String, Argument> args = connector.defaultArguments(); 882 args.get("port").setValue(String.valueOf(fBackEndPort)); 883 args.get("hostname").setValue("localhost"); 884 885 fVM = connector.attach(args); 886 if (fVMTraceFlags != com.sun.jdi.VirtualMachine.TRACE_NONE) { 887 fVM.setDebugTraceMode(fVMTraceFlags); 888 } 889 break; 890 } catch (IllegalConnectorArgumentsException e) { 891 } catch (IOException e) { 892 // System.out.println("Got exception: " + e.getMessage()); 893 try { 894 if (i == 9) { 895 System.out.println( 896 "Could not contact the VM at localhost" + ":" + fBackEndPort + "."); 897 } 898 Thread.sleep(200); 899 } catch (InterruptedException e2) { 900 } 901 } 902 } 903 if (fVM == null) { 904 if (fLaunchedVM != null) { 905 // If the VM is not running, output error stream 906 try { 907 if (!vmIsRunning()) { 908 InputStream in = fLaunchedVM.getErrorStream(); 909 int read; 910 do { 911 read = in.read(); 912 if (read != -1) { 913 System.out.print((char) read); 914 } 915 } while (read != -1); 916 } 917 } catch (IOException e) { 918 } 919 920 // Shut it down 921 killVM(); 922 } 923 throw new Error("Could not contact the VM"); 924 } 925 startEventReader(); 926 } 927 /** 928 * Initializes the fields that are used by this test only. 929 */ localSetUp()930 public abstract void localSetUp(); 931 /** 932 * Makes sure the test leaves the VM in the same state it found it. 933 * Default is to do nothing. 934 */ localTearDown()935 public void localTearDown() { 936 } 937 /** 938 * Parses the given arguments and store them in this tests 939 * fields. 940 * Returns whether the parsing was successful. 941 */ parseArgs(String[] args)942 protected static boolean parseArgs(String[] args) { 943 // Default values 944 String vmVendor = System.getProperty("java.vm.vendor"); 945 String vmVersion = System.getProperty("java.vm.version"); 946 String targetAddress = System.getProperty("java.home"); 947 String vmLauncherName; 948 if (vmVendor != null 949 && (vmVendor.indexOf("Sun") > -1 || vmVendor.indexOf("Oracle") > -1 || vmVendor.indexOf("Apple") > -1) 950 && vmVersion != null) { 951 vmLauncherName = "SunVMLauncher"; 952 } else if ( 953 vmVendor != null && vmVendor.indexOf("IBM") > -1 && vmVersion != null) { 954 vmLauncherName = "IBMVMLauncher"; 955 } else { 956 vmLauncherName = "J9VMLauncher"; 957 } 958 String classPath = System.getProperty("java.class.path"); 959 String bootPath = ""; 960 String vmType = "?"; 961 boolean verbose = false; 962 963 // Parse arguments 964 for (int i = 0; i < args.length; ++i) { 965 String arg = args[i]; 966 if (arg.startsWith("-")) { 967 if (arg.equals("-verbose") || arg.equals("-v")) { 968 verbose = true; 969 } else { 970 String next = (i < args.length - 1) ? args[++i] : null; 971 // If specified, passed values override default values 972 switch (arg) { 973 case "-launcher": 974 vmLauncherName = next; 975 break; 976 case "-address": 977 targetAddress = next; 978 break; 979 case "-port": 980 fBackEndPort = Integer.parseInt(next); 981 break; 982 case "-cp": 983 classPath = next; 984 break; 985 case "-bp": 986 bootPath = next; 987 break; 988 case "-vmtype": 989 vmType = next; 990 break; 991 case "-stdout": 992 fStdoutFile = next; 993 break; 994 case "-stderr": 995 fStderrFile = next; 996 break; 997 case "-proxyout": 998 fProxyoutFile = next; 999 break; 1000 case "-proxyerr": 1001 fProxyerrFile = next; 1002 break; 1003 case "-vmcmd": 1004 fVmCmd = next; 1005 break; 1006 case "-vmargs": 1007 fVmArgs = next; 1008 break; 1009 case "-proxycmd": 1010 fProxyCmd = next; 1011 break; 1012 case "-trace": 1013 if (next.equals("all")) { 1014 fVMTraceFlags = com.sun.jdi.VirtualMachine.TRACE_ALL; 1015 } else { 1016 fVMTraceFlags = Integer.decode(next).intValue(); 1017 } 1018 break; 1019 default: 1020 System.out.println("Invalid option: " + arg); 1021 printUsage(); 1022 return false; 1023 } 1024 } 1025 } 1026 } 1027 fVMLauncherName = vmLauncherName; 1028 fTargetAddress = targetAddress; 1029 fClassPath = classPath; 1030 fBootPath = bootPath; 1031 fVMType = vmType; 1032 fVerbose = verbose; 1033 return true; 1034 } 1035 /** 1036 * Prints the various options to pass to the constructor. 1037 */ printUsage()1038 protected static void printUsage() { 1039 System.out.println("Possible options:"); 1040 System.out.println("-launcher <Name of the launcher class>"); 1041 System.out.println("-address <Address of the target VM>"); 1042 System.out.println("-port <Debug port number>"); 1043 System.out.println("-cp <Path to the test program>"); 1044 System.out.println("-bp <Boot classpath for the system class library>"); 1045 System.out.println("-vmtype <The type of VM: JDK, J9, ...>"); 1046 System.out.println("-verbose | -v"); 1047 System.out.println("-stdout <file where VM output is written to>"); 1048 System.out.println("-stderr <file where VM error output is written to>"); 1049 System.out.println("-proxyout <file where proxy output is written to>"); 1050 System.out.println("-proxyerr <file where proxy error output is written to>"); 1051 System.out.println("-vmcmd <exec string to start VM>"); 1052 System.out.println("-vmargs <comma-separated list of VM arguments>"); 1053 System.out.println("-proxycmd <exec string to start proxy>"); 1054 } 1055 /** 1056 * Set the value of the "fBool" field back to its original value 1057 */ resetField()1058 protected void resetField() { 1059 Field field = getField("fBool"); 1060 Value value = null; 1061 value = fVM.mirrorOf(false); 1062 try { 1063 getObjectReference().setValue(field, value); 1064 } catch (ClassNotLoadedException e) { 1065 assertTrue("resetField.2", false); 1066 } catch (InvalidTypeException e) { 1067 assertTrue("resetField.3", false); 1068 } 1069 } 1070 /** 1071 * Set the value of the "fString" field back to its original value 1072 */ resetStaticField()1073 protected void resetStaticField() { 1074 Field field = getField("fString"); 1075 Value value = null; 1076 value = fVM.mirrorOf("Hello World"); 1077 try { 1078 getMainClass().setValue(field, value); 1079 } catch (ClassNotLoadedException e) { 1080 assertTrue("resetField.1", false); 1081 } catch (InvalidTypeException e) { 1082 assertTrue("resetField.2", false); 1083 } 1084 } 1085 /** 1086 * Runs this test's suite with the given arguments. 1087 */ runSuite(String[] args)1088 protected void runSuite(String[] args) { 1089 // Check args 1090 if (!parseArgs(args)) { 1091 return; 1092 } 1093 1094 // Run test 1095 System.out.println(new java.util.Date()); 1096 System.out.println("Begin testing " + getName() + "..."); 1097 junit.textui.TestRunner.run(suite()); 1098 System.out.println("Done testing " + getName() + "."); 1099 } 1100 /** 1101 * Sets the 'in control of the VM' flag for this test. 1102 */ setInControl(boolean inControl)1103 public void setInControl(boolean inControl) { 1104 fInControl = inControl; 1105 } 1106 /** 1107 * Launch target VM and start program in target VM. 1108 */ launchTargetAndStartProgram()1109 protected void launchTargetAndStartProgram() { 1110 launchTargetAndConnectToVM(); 1111 startProgram(); 1112 } 1113 /** 1114 * Init tests 1115 */ 1116 @Override setUp()1117 protected void setUp() { 1118 if (fVM == null || fInControl) { 1119 launchTargetAndStartProgram(); 1120 } 1121 try { 1122 verbose("Setting up the test"); 1123 localSetUp(); 1124 } catch (RuntimeException e) { 1125 System.out.println("Runtime exception during set up:"); 1126 e.printStackTrace(); 1127 } catch (Error e) { 1128 System.out.println("Error during set up:"); 1129 e.printStackTrace(); 1130 } 1131 } 1132 /** 1133 * Sets the VM info for this test. 1134 */ setVMInfo(VMInformation info)1135 public void setVMInfo(VMInformation info) { 1136 if (info != null) { 1137 fVM = info.fVM; 1138 fLaunchedVM = info.fLaunchedVM; 1139 fEventReader = info.fEventReader; 1140 fConsoleReader = info.fConsoleReader; 1141 } 1142 } 1143 /** 1144 * Stop console and event readers. 1145 */ stopReaders()1146 protected void stopReaders() { 1147 stopEventReader(); 1148 stopConsoleReaders(); 1149 } 1150 /** 1151 * Shut down the target. 1152 */ shutDownTarget()1153 public void shutDownTarget() { 1154 stopReaders(); 1155 if (fVM != null) { 1156 try { 1157 fVM.exit(0); 1158 } catch (VMDisconnectedException e) { 1159 } 1160 } 1161 1162 fVM = null; 1163 fLaunchedVM = null; 1164 1165 // We want subsequent connections to use different ports, unless a 1166 // VM exec sting is given. 1167 if (fVmCmd == null) { 1168 fBackEndPort += 2; 1169 } 1170 } 1171 /** 1172 * Starts the threads that reads from the VM and proxy input and error streams 1173 */ startConsoleReaders()1174 private void startConsoleReaders() { 1175 if (fStdoutFile != null) { 1176 fConsoleReader = 1177 new FileConsoleReader( 1178 "JDI Tests Console Reader", 1179 fStdoutFile, 1180 fLaunchedVM.getInputStream()); 1181 } else { 1182 fConsoleReader = 1183 new NullConsoleReader("JDI Tests Console Reader", fLaunchedVM.getInputStream()); 1184 } 1185 fConsoleReader.start(); 1186 1187 if (fStderrFile != null) { 1188 fConsoleErrorReader = 1189 new FileConsoleReader( 1190 "JDI Tests Console Error Reader", 1191 fStderrFile, 1192 fLaunchedVM.getErrorStream()); 1193 } else { 1194 fConsoleErrorReader = 1195 new NullConsoleReader( 1196 "JDI Tests Console Error Reader", 1197 fLaunchedVM.getErrorStream()); 1198 } 1199 fConsoleErrorReader.start(); 1200 1201 if (fLaunchedProxy == null) { 1202 return; 1203 } 1204 1205 if (fProxyoutFile != null) { 1206 fProxyReader = 1207 new FileConsoleReader( 1208 "JDI Tests Proxy Reader", 1209 fProxyoutFile, 1210 fLaunchedProxy.getInputStream()); 1211 } else { 1212 fProxyReader = 1213 new NullConsoleReader( 1214 "JDI Tests Proxy Reader", 1215 fLaunchedProxy.getInputStream()); 1216 } 1217 fProxyReader.start(); 1218 1219 if (fProxyerrFile != null) { 1220 fProxyErrorReader = 1221 new FileConsoleReader( 1222 "JDI Tests Proxy Error Reader", 1223 fProxyerrFile, 1224 fLaunchedProxy.getErrorStream()); 1225 } else { 1226 fProxyErrorReader = 1227 new NullConsoleReader( 1228 "JDI Tests Proxy Error Reader", 1229 fLaunchedProxy.getErrorStream()); 1230 } 1231 fProxyErrorReader.start(); 1232 } 1233 /** 1234 * Stops the console reader. 1235 */ stopConsoleReaders()1236 private void stopConsoleReaders() { 1237 if (fConsoleReader != null) { 1238 fConsoleReader.stop(); 1239 } 1240 if (fConsoleErrorReader != null) { 1241 fConsoleErrorReader.stop(); 1242 } 1243 if (fProxyReader != null) { 1244 fProxyReader.stop(); 1245 } 1246 if (fProxyErrorReader != null) { 1247 fProxyErrorReader.stop(); 1248 } 1249 } 1250 /** 1251 * Starts event reader. 1252 */ startEventReader()1253 private void startEventReader() { 1254 // Create the VM event reader. 1255 fEventReader = new EventReader("JDI Tests Event Reader", fVM.eventQueue()); 1256 } 1257 /** 1258 * Stops the event reader. 1259 */ stopEventReader()1260 private void stopEventReader() { 1261 fEventReader.stop(); 1262 } killVM()1263 protected void killVM() { 1264 if (fLaunchedVM != null) { 1265 fLaunchedVM.destroy(); 1266 } 1267 if (fLaunchedProxy != null) { 1268 fLaunchedProxy.destroy(); 1269 } 1270 } 1271 /** 1272 * Starts the target program. 1273 */ startProgram()1274 protected void startProgram() { 1275 verbose("Starting target program"); 1276 1277 // Request class prepare events 1278 EventRequest classPrepareRequest = 1279 fVM.eventRequestManager().createClassPrepareRequest(); 1280 classPrepareRequest.enable(); 1281 1282 // Prepare to receive the token class prepare event 1283 ClassPrepareEventWaiter waiter = 1284 new ClassPrepareEventWaiter( 1285 classPrepareRequest, 1286 true, 1287 getMainClassName()); 1288 fEventReader.addEventListener(waiter); 1289 1290 // Start the event reader (this will start the VM when the VMStartEvent is picked up) 1291 fEventReader.start(); 1292 1293 // Wait until the program has started 1294 Event event = waitForEvent(waiter, 3 * TIMEOUT); 1295 fEventReader.removeEventListener(waiter); 1296 if (event == null) { 1297 // try { 1298 System.out.println( 1299 "\nThe program doesn't seem to have started after " + (3 * TIMEOUT) + "ms"); 1300 // InputStream errorStream = fLaunchedVM.getErrorStream(); 1301 // int read; 1302 // do { 1303 // read = errorStream.read(); 1304 // if (read != -1) 1305 // System.out.print((char) read); 1306 // } while (read != -1); 1307 // } catch (IOException e) { 1308 // } 1309 } 1310 1311 // Stop class prepare events 1312 fVM.eventRequestManager().deleteEventRequest(classPrepareRequest); 1313 1314 // Wait for the program to be ready to be tested 1315 waitUntilReady(); 1316 } 1317 /** 1318 * Returns all tests 1319 */ suite()1320 protected Test suite() { 1321 JDITestSuite suite = new JDITestSuite(this); 1322 Vector<String> testNames = getAllMatchingTests( getTestPrefix() ); 1323 Iterator<String> iterator = testNames.iterator(); 1324 while (iterator.hasNext()) { 1325 String name = iterator.next(); 1326 suite.addTest(new JDITestCase(this, name)); 1327 } 1328 return suite; 1329 } 1330 /** 1331 * Undo the initialization of the test. 1332 */ 1333 @Override tearDown()1334 protected void tearDown() { 1335 try { 1336 super.tearDown(); 1337 } catch (Exception e) { 1338 System.out.println("Exception during tear down:"); 1339 e.printStackTrace(); 1340 } 1341 try { 1342 verbose("Tearing down the test"); 1343 localTearDown(); 1344 1345 // Ensure that the test didn't leave a modification watchpoint that could change the expected state of the program 1346 if (fVM != null) { 1347 assertTrue(fVM.eventRequestManager().modificationWatchpointRequests().isEmpty()); 1348 if (fInControl) { 1349 shutDownTarget(); 1350 } 1351 } 1352 1353 } catch (RuntimeException e) { 1354 System.out.println("Runtime exception during tear down:"); 1355 e.printStackTrace(); 1356 } catch (Error e) { 1357 System.out.println("Error during tear down:"); 1358 e.printStackTrace(); 1359 } 1360 1361 } 1362 /** 1363 * Triggers and waits for the given event to come in. 1364 * Let the thread go if asked. 1365 * Throws an Error if the event didn't come in after TIMEOUT ms 1366 */ triggerAndWait( EventRequest request, String eventType, boolean shouldGo)1367 protected Event triggerAndWait( 1368 EventRequest request, 1369 String eventType, 1370 boolean shouldGo) { 1371 Event event = triggerAndWait(request, eventType, shouldGo, TIMEOUT); 1372 if (event == null) { 1373 throw new Error( 1374 "Event for " + request + " didn't come in after " + TIMEOUT + "ms"); 1375 } 1376 1377 return event; 1378 } 1379 /** 1380 * Triggers and waits for the given event to come in. 1381 * Let the thread go if asked. 1382 * Returns null if the event didn't come in after the given amount of time (in ms) 1383 * @param time the time to wait 1384 */ triggerAndWait( EventRequest request, String eventType, boolean shouldGo, long time)1385 protected Event triggerAndWait( 1386 EventRequest request, 1387 String eventType, 1388 boolean shouldGo, 1389 long time) { 1390 // Suspend only if asked 1391 if (shouldGo) { 1392 request.setSuspendPolicy(EventRequest.SUSPEND_NONE); 1393 } else { 1394 request.setSuspendPolicy(EventRequest.SUSPEND_EVENT_THREAD); 1395 } 1396 1397 // Enable request 1398 request.enable(); 1399 1400 // Prepare to receive the event 1401 EventWaiter waiter = new EventWaiter(request, shouldGo); 1402 fEventReader.addEventListener(waiter); 1403 1404 // Trigger the event 1405 triggerEvent(eventType); 1406 1407 // Wait for the event to come in 1408 Event event = waitForEvent(waiter, TIMEOUT); 1409 fEventReader.removeEventListener(waiter); 1410 1411 if (shouldGo) { 1412 // Wait for the program to be ready 1413 waitUntilReady(); 1414 } 1415 1416 // Clear request 1417 fVM.eventRequestManager().deleteEventRequest(request); 1418 1419 return event; 1420 } 1421 /** 1422 * Triggers the given type of event. See the MainClass for details on types of event. 1423 */ triggerEvent(String eventType)1424 protected void triggerEvent(String eventType) { 1425 // Set the "fEventType" field to the given eventType 1426 ClassType type = getMainClass(); 1427 Field field = type.fieldByName("fEventType"); 1428 assertTrue("1", field != null); 1429 1430 Value value = null; 1431 value = fVM.mirrorOf(eventType); 1432 try { 1433 type.setValue(field, value); 1434 } catch (ClassNotLoadedException e) { 1435 assertTrue("2", false); 1436 } catch (InvalidTypeException e) { 1437 assertTrue("3", false); 1438 } 1439 1440 // Resume the test thread 1441 ThreadReference thread = getThread(); 1442 int suspendCount = thread.suspendCount(); 1443 for (int i = 0; i < suspendCount; i++) { 1444 thread.resume(); 1445 } 1446 } 1447 /** 1448 * Triggers a step event and waits for it to come in. 1449 */ triggerStepAndWait()1450 protected StepEvent triggerStepAndWait() { 1451 return triggerStepAndWait( 1452 getThread(), 1453 StepRequest.STEP_MIN, 1454 StepRequest.STEP_OVER); 1455 } 1456 triggerStepAndWait( ThreadReference thread, int gran, int depth)1457 protected StepEvent triggerStepAndWait( 1458 ThreadReference thread, 1459 int gran, 1460 int depth) { 1461 // Request for step events 1462 EventRequest eventRequest = 1463 fVM.eventRequestManager().createStepRequest(thread, gran, depth); 1464 eventRequest.addCountFilter(1); 1465 eventRequest.setSuspendPolicy(EventRequest.SUSPEND_NONE); 1466 eventRequest.enable(); 1467 1468 return triggerStepAndWait(thread, eventRequest, TIMEOUT); 1469 } 1470 triggerStepAndWait( ThreadReference thread, EventRequest eventRequest, int timeout)1471 protected StepEvent triggerStepAndWait( 1472 ThreadReference thread, 1473 EventRequest eventRequest, 1474 int timeout) { 1475 // Prepare to receive the event 1476 EventWaiter waiter = new EventWaiter(eventRequest, true); 1477 fEventReader.addEventListener(waiter); 1478 1479 // Trigger step event 1480 int suspendCount = thread.suspendCount(); 1481 for (int i = 0; i < suspendCount; i++) { 1482 thread.resume(); 1483 } 1484 1485 // Wait for the event to come in 1486 StepEvent event = (StepEvent) waitForEvent(waiter, timeout); 1487 fEventReader.removeEventListener(waiter); 1488 if (event == null) { 1489 throw new Error("StepEvent didn't come in after " + timeout + "ms"); 1490 } 1491 1492 // Stop getting step events 1493 fVM.eventRequestManager().deleteEventRequest(eventRequest); 1494 1495 // Wait for the program to be ready 1496 waitUntilReady(); 1497 1498 return event; 1499 } 1500 /** 1501 * Output verbose string if asked for. 1502 */ verbose(String verboseString)1503 protected void verbose(String verboseString) { 1504 if (fVerbose) { 1505 System.out.println(verboseString); 1506 } 1507 } 1508 /** 1509 * Waits for an event to come in using the given waiter. 1510 * Waits for the given time. If it times out, returns null. 1511 */ waitForEvent(EventWaiter waiter, long time)1512 protected Event waitForEvent(EventWaiter waiter, long time) { 1513 Event event; 1514 try { 1515 event = waiter.waitEvent(time); 1516 } catch (InterruptedException e) { 1517 event = null; 1518 } 1519 return event; 1520 } 1521 /** 1522 * Waits until the program is ready to be tested. 1523 * The default behavior is to wait until the "Test Thread" throws and catches 1524 * an exception. 1525 */ waitUntilReady()1526 protected void waitUntilReady() { 1527 // Make sure the program is running 1528 ThreadReference thread = getThread(); 1529 while (thread == null || thread.suspendCount() > 0) { 1530 fVM.resume(); 1531 thread = getThread(); 1532 } 1533 1534 // Create exception request 1535 EventRequest request = 1536 fVM.eventRequestManager().createExceptionRequest(null, true, false); 1537 request.setSuspendPolicy(EventRequest.SUSPEND_EVENT_THREAD); 1538 1539 // Prepare to receive the event 1540 EventWaiter waiter = new EventWaiter(request, false); 1541 fEventReader.addEventListener(waiter); 1542 1543 request.enable(); 1544 1545 while (true) { 1546 // Wait for the event to come in 1547 ExceptionEvent event = (ExceptionEvent) waitForEvent(waiter, TIMEOUT); 1548 1549 // Throw error if event is null 1550 if (event == null) { 1551 throw new Error("Target program was not ready after " + TIMEOUT + "ms"); 1552 } 1553 1554 // Get the method where the exception was thrown 1555 Method meth = event.location().method(); 1556 if (meth == null || !meth.name().equals("printAndSignal")) { 1557 fVM.resume(); 1558 } else { 1559 break; 1560 } 1561 } 1562 1563 // Disable request 1564 fEventReader.removeEventListener(waiter); 1565 fVM.eventRequestManager().deleteEventRequest(request); 1566 } 1567 } 1568