0001: /*******************************************************************************
0002: * Copyright (c) 2000, 2005 IBM Corporation and others.
0003: * All rights reserved. This program and the accompanying materials
0004: * are made available under the terms of the Eclipse Public License v1.0
0005: * which accompanies this distribution, and is available at
0006: * http://www.eclipse.org/legal/epl-v10.html
0007: *
0008: * Contributors:
0009: * IBM Corporation - initial API and implementation
0010: *******************************************************************************/package org.eclipse.debug.jdi.tests;
0011:
0012: import java.io.File;
0013: import java.io.IOException;
0014: import java.io.InputStream;
0015: import java.util.Iterator;
0016: import java.util.List;
0017: import java.util.ListIterator;
0018: import java.util.Map;
0019: import java.util.Vector;
0020:
0021: import junit.framework.Test;
0022: import junit.framework.TestCase;
0023: import org.eclipse.jdi.Bootstrap;
0024:
0025: import com.sun.jdi.AbsentInformationException;
0026: import com.sun.jdi.ArrayReference;
0027: import com.sun.jdi.ArrayType;
0028: import com.sun.jdi.ClassLoaderReference;
0029: import com.sun.jdi.ClassNotLoadedException;
0030: import com.sun.jdi.ClassType;
0031: import com.sun.jdi.Field;
0032: import com.sun.jdi.IncompatibleThreadStateException;
0033: import com.sun.jdi.InterfaceType;
0034: import com.sun.jdi.InvalidTypeException;
0035: import com.sun.jdi.LocalVariable;
0036: import com.sun.jdi.Location;
0037: import com.sun.jdi.Method;
0038: import com.sun.jdi.ObjectReference;
0039: import com.sun.jdi.StackFrame;
0040: import com.sun.jdi.StringReference;
0041: import com.sun.jdi.ThreadReference;
0042: import com.sun.jdi.VMDisconnectedException;
0043: import com.sun.jdi.Value;
0044: import com.sun.jdi.VirtualMachineManager;
0045: import com.sun.jdi.connect.AttachingConnector;
0046: import com.sun.jdi.connect.Connector;
0047: import com.sun.jdi.connect.IllegalConnectorArgumentsException;
0048: import com.sun.jdi.event.ClassPrepareEvent;
0049: import com.sun.jdi.event.Event;
0050: import com.sun.jdi.event.ExceptionEvent;
0051: import com.sun.jdi.event.StepEvent;
0052: import com.sun.jdi.request.AccessWatchpointRequest;
0053: import com.sun.jdi.request.BreakpointRequest;
0054: import com.sun.jdi.request.EventRequest;
0055: import com.sun.jdi.request.ExceptionRequest;
0056: import com.sun.jdi.request.ModificationWatchpointRequest;
0057: import com.sun.jdi.request.StepRequest;
0058:
0059: /**
0060: * Tests for com.sun.jdi.* and JDWP commands.
0061: * These tests assume that the target program is
0062: * "org.eclipse.debug.jdi.tests.program.MainClass".
0063: *
0064: * Examples of arguments:
0065: * -launcher SunVMLauncher -address c:\jdk1.2.2\ -cp d:\target
0066: * -launcher J9VMLauncher -address d:\ive\ -cp d:\target
0067: */
0068: public abstract class AbstractJDITest extends TestCase {
0069: static int TIMEOUT = 10000; //ms
0070: static protected int fBackEndPort = 9900;
0071: // We want subsequent connections to use different ports.
0072: protected static String fVMLauncherName;
0073: protected static String fTargetAddress;
0074: protected static String fClassPath;
0075: protected static String fBootPath;
0076: protected static String fVMType;
0077: protected com.sun.jdi.VirtualMachine fVM;
0078: protected Process fLaunchedProxy;
0079: protected Process fLaunchedVM;
0080: protected static int fVMTraceFlags = com.sun.jdi.VirtualMachine.TRACE_NONE;
0081: protected EventReader fEventReader;
0082: protected AbstractReader fConsoleReader;
0083: protected AbstractReader fConsoleErrorReader;
0084: protected AbstractReader fProxyReader;
0085: protected AbstractReader fProxyErrorReader;
0086: protected boolean fInControl = true;
0087: // Whether this test should control the VM (ie. starting it and shutting it down)
0088: protected static boolean fVerbose;
0089: protected static String fStdoutFile;
0090: protected static String fStderrFile;
0091: protected static String fProxyoutFile;
0092: protected static String fProxyerrFile;
0093: protected static String fVmCmd;
0094: protected static String fProxyCmd;
0095:
0096: // Stack offset to the MainClass.run() method
0097: protected static final int RUN_FRAME_OFFSET = 1;
0098:
0099: /**
0100: * Constructs a test case with a default name.
0101: */
0102: public AbstractJDITest() {
0103: super ("JDI Test");
0104: }
0105:
0106: /**
0107: * Returns the names of the tests that are known to not work
0108: * By default, none are excluded.
0109: */
0110: protected String[] excludedTests() {
0111: return new String[] {};
0112: }
0113:
0114: /**
0115: * Creates and returns an access watchpoint request
0116: * for the field "fBool" in
0117: * org.eclipse.debug.jdi.tests.program.MainClass
0118: * NOTE: This assumes that the VM can watch field access.
0119: */
0120: protected AccessWatchpointRequest getAccessWatchpointRequest() {
0121: // Get the field
0122: Field field = getField("fBool");
0123:
0124: // Create an access watchpoint for this field
0125: return fVM.eventRequestManager().createAccessWatchpointRequest(
0126: field);
0127: }
0128:
0129: /**
0130: * Returns all tests that start with the given string.
0131: * Returns a vector of String.
0132: */
0133: protected Vector getAllMatchingTests(String match) {
0134: Class theClass = this .getClass();
0135: java.lang.reflect.Method[] methods = theClass
0136: .getDeclaredMethods();
0137: Vector result = new Vector();
0138: for (int i = 0; i < methods.length; i++) {
0139: java.lang.reflect.Method m = methods[i];
0140: String name = m.getName();
0141: Class[] parameters = m.getParameterTypes();
0142: if (parameters.length == 0 && name.startsWith(match)) {
0143: if (!isExcludedTest(name)) {
0144: result.add(name);
0145: } else
0146: System.out.println(name + " is excluded.");
0147: }
0148: }
0149: return result;
0150: }
0151:
0152: /**
0153: * Returns an array reference.
0154: */
0155: protected ArrayReference getObjectArrayReference() {
0156: // Get static field "fArray"
0157: Field field = getField("fArray");
0158:
0159: // Get value of "fArray"
0160: return (ArrayReference) getMainClass().getValue(field);
0161: }
0162:
0163: /**
0164: * Returns another array reference.
0165: */
0166: protected ArrayReference getNonEmptyDoubleArrayReference() {
0167: // Get static field "fDoubleArray"
0168: Field field = getField("fDoubleArray");
0169:
0170: // Get value of "fDoubleArray"
0171: return (ArrayReference) getMainClass().getValue(field);
0172: }
0173:
0174: /**
0175: * One-dimensional empty array reference getters
0176: */
0177: protected ArrayReference getByteArrayReference() {
0178: Field field = getField("byteArray");
0179: return (ArrayReference) getMainClass().getValue(field);
0180: }
0181:
0182: protected ArrayReference getShortArrayReference() {
0183: Field field = getField("shortArray");
0184: return (ArrayReference) getMainClass().getValue(field);
0185: }
0186:
0187: protected ArrayReference getIntArrayReference() {
0188: Field field = getField("intArray");
0189: return (ArrayReference) getMainClass().getValue(field);
0190: }
0191:
0192: protected ArrayReference getLongArrayReference() {
0193: Field field = getField("longArray");
0194: return (ArrayReference) getMainClass().getValue(field);
0195: }
0196:
0197: protected ArrayReference getDoubleArrayReference() {
0198: Field field = getField("doubleArray");
0199: return (ArrayReference) getMainClass().getValue(field);
0200: }
0201:
0202: protected ArrayReference getFloatArrayReference() {
0203: Field field = getField("floatArray");
0204: return (ArrayReference) getMainClass().getValue(field);
0205: }
0206:
0207: protected ArrayReference getCharArrayReference() {
0208: Field field = getField("charArray");
0209: return (ArrayReference) getMainClass().getValue(field);
0210: }
0211:
0212: protected ArrayReference getBooleanArrayReference() {
0213: Field field = getField("booleanArray");
0214: return (ArrayReference) getMainClass().getValue(field);
0215: }
0216:
0217: /**
0218: * Two-dimensional array reference getters
0219: */
0220: protected ArrayReference getByteDoubleArrayReference() {
0221: Field field = getField("byteDoubleArray");
0222: return (ArrayReference) getMainClass().getValue(field);
0223: }
0224:
0225: protected ArrayReference getShortDoubleArrayReference() {
0226: Field field = getField("shortDoubleArray");
0227: return (ArrayReference) getMainClass().getValue(field);
0228: }
0229:
0230: protected ArrayReference getIntDoubleArrayReference() {
0231: Field field = getField("intDoubleArray");
0232: return (ArrayReference) getMainClass().getValue(field);
0233: }
0234:
0235: protected ArrayReference getLongDoubleArrayReference() {
0236: Field field = getField("longDoubleArray");
0237: return (ArrayReference) getMainClass().getValue(field);
0238: }
0239:
0240: protected ArrayReference getFloatDoubleArrayReference() {
0241: Field field = getField("floatDoubleArray");
0242: return (ArrayReference) getMainClass().getValue(field);
0243: }
0244:
0245: protected ArrayReference getDoubleDoubleArrayReference() {
0246: Field field = getField("doubleDoubleArray");
0247: return (ArrayReference) getMainClass().getValue(field);
0248: }
0249:
0250: protected ArrayReference getCharDoubleArrayReference() {
0251: Field field = getField("charDoubleArray");
0252: return (ArrayReference) getMainClass().getValue(field);
0253: }
0254:
0255: protected ArrayReference getBooleanDoubleArrayReference() {
0256: Field field = getField("booleanDoubleArray");
0257: return (ArrayReference) getMainClass().getValue(field);
0258: }
0259:
0260: /**
0261: * Returns the array type.
0262: */
0263: protected ArrayType getArrayType() {
0264: // Get array reference
0265: ArrayReference value = getObjectArrayReference();
0266:
0267: // Get reference type of "fArray"
0268: return (ArrayType) value.referenceType();
0269: }
0270:
0271: /**
0272: * One-dimensional primitive array getters
0273: */
0274: protected ArrayType getByteArrayType() {
0275: ArrayReference value = getByteArrayReference();
0276: return (ArrayType) value.referenceType();
0277: }
0278:
0279: protected ArrayType getShortArrayType() {
0280: ArrayReference value = getShortArrayReference();
0281: return (ArrayType) value.referenceType();
0282: }
0283:
0284: protected ArrayType getIntArrayType() {
0285: ArrayReference value = getIntArrayReference();
0286: return (ArrayType) value.referenceType();
0287: }
0288:
0289: protected ArrayType getLongArrayType() {
0290: ArrayReference value = getLongArrayReference();
0291: return (ArrayType) value.referenceType();
0292: }
0293:
0294: protected ArrayType getFloatArrayType() {
0295: ArrayReference value = getFloatArrayReference();
0296: return (ArrayType) value.referenceType();
0297: }
0298:
0299: protected ArrayType getDoubleArrayType() {
0300: ArrayReference value = getDoubleArrayReference();
0301: return (ArrayType) value.referenceType();
0302: }
0303:
0304: protected ArrayType getCharArrayType() {
0305: ArrayReference value = getCharArrayReference();
0306: return (ArrayType) value.referenceType();
0307: }
0308:
0309: protected ArrayType getBooleanArrayType() {
0310: ArrayReference value = getBooleanArrayReference();
0311: return (ArrayType) value.referenceType();
0312: }
0313:
0314: /**
0315: * Two-dimensional primitive array getters
0316: */
0317: protected ArrayType getByteDoubleArrayType() {
0318: ArrayReference value = getByteDoubleArrayReference();
0319: return (ArrayType) value.referenceType();
0320: }
0321:
0322: protected ArrayType getShortDoubleArrayType() {
0323: ArrayReference value = getShortDoubleArrayReference();
0324: return (ArrayType) value.referenceType();
0325: }
0326:
0327: protected ArrayType getIntDoubleArrayType() {
0328: ArrayReference value = getIntDoubleArrayReference();
0329: return (ArrayType) value.referenceType();
0330: }
0331:
0332: protected ArrayType getLongDoubleArrayType() {
0333: ArrayReference value = getLongDoubleArrayReference();
0334: return (ArrayType) value.referenceType();
0335: }
0336:
0337: protected ArrayType getFloatDoubleArrayType() {
0338: ArrayReference value = getFloatDoubleArrayReference();
0339: return (ArrayType) value.referenceType();
0340: }
0341:
0342: protected ArrayType getDoubleDoubleArrayType() {
0343: ArrayReference value = getDoubleDoubleArrayReference();
0344: return (ArrayType) value.referenceType();
0345: }
0346:
0347: protected ArrayType getCharDoubleArrayType() {
0348: ArrayReference value = getCharDoubleArrayReference();
0349: return (ArrayType) value.referenceType();
0350: }
0351:
0352: protected ArrayType getBooleanDoubleArrayType() {
0353: ArrayReference value = getBooleanDoubleArrayReference();
0354: return (ArrayType) value.referenceType();
0355: }
0356:
0357: /**
0358: * Creates and returns a breakpoint request in the first
0359: * instruction of the MainClass.triggerBreakpointEvent() method.
0360: */
0361: protected BreakpointRequest getBreakpointRequest() {
0362: // Create a breakpoint request
0363: return fVM.eventRequestManager().createBreakpointRequest(
0364: getLocation());
0365: }
0366:
0367: /**
0368: * Creates a new breakpoinmt request for a user specified position
0369: * @param loc thel oc to set the breakpoint on
0370: * @return a new breakpoint request or null if the location is invalid
0371: * @since 3.3
0372: */
0373: protected BreakpointRequest getBreakpointRequest(Location loc) {
0374: return fVM.eventRequestManager().createBreakpointRequest(loc);
0375: }
0376:
0377: /**
0378: * Returns the class with the given name or null if not loaded.
0379: */
0380: protected ClassType getClass(String name) {
0381: List classes = fVM.classesByName(name);
0382: if (classes.size() == 0)
0383: return null;
0384:
0385: return (ClassType) classes.get(0);
0386: }
0387:
0388: /**
0389: * Returns the class loader of
0390: * org.eclipse.debug.jdi.tests.program.MainClass
0391: */
0392: protected ClassLoaderReference getClassLoaderReference() {
0393: // Get main class
0394: ClassType type = getMainClass();
0395:
0396: // Get its class loader
0397: return type.classLoader();
0398: }
0399:
0400: /**
0401: * Creates and returns an exception request for uncaught exceptions.
0402: */
0403: protected ExceptionRequest getExceptionRequest() {
0404: return fVM.eventRequestManager().createExceptionRequest(null,
0405: false, true);
0406: }
0407:
0408: /**
0409: * Returns the static field "fObject" in
0410: * org.eclipse.debug.jdi.tests.program.MainClass
0411: */
0412: protected Field getField() {
0413: return getField("fObject");
0414: }
0415:
0416: /**
0417: * Returns the field with the given name in
0418: * org.eclipse.debug.jdi.tests.program.MainClass.
0419: */
0420: protected Field getField(String fieldName) {
0421: // Get main class
0422: ClassType type = getMainClass();
0423:
0424: // Get field
0425: Field result = type.fieldByName(fieldName);
0426: if (result == null)
0427: throw new Error("Unknown field: " + fieldName);
0428:
0429: return result;
0430: }
0431:
0432: /**
0433: * Returns the n frame (starting at the top of the stack) of the thread
0434: * contained in the static field "fThread" of org.eclipse.debug.jdi.tests.program.MainClass.
0435: */
0436: protected StackFrame getFrame(int n) {
0437: // Make sure the thread is suspended
0438: ThreadReference thread = getThread();
0439: assertTrue(thread.isSuspended());
0440:
0441: // Get the frame
0442: StackFrame frame = null;
0443: try {
0444: List frames = thread.frames();
0445: frame = (StackFrame) frames.get(n);
0446: } catch (IncompatibleThreadStateException e) {
0447: throw new Error("Thread was not suspended");
0448: }
0449:
0450: return frame;
0451: }
0452:
0453: /**
0454: * Returns the interface type org.eclipse.debug.jdi.tests.program.Printable.
0455: */
0456: protected InterfaceType getInterfaceType() {
0457: List types = fVM
0458: .classesByName("org.eclipse.debug.jdi.tests.program.Printable");
0459: return (InterfaceType) types.get(0);
0460: }
0461:
0462: /**
0463: * Returns the variable "t" in the frame running MainClass.run().
0464: */
0465: protected LocalVariable getLocalVariable() {
0466: try {
0467: return getFrame(RUN_FRAME_OFFSET)
0468: .visibleVariableByName("t");
0469: } catch (AbsentInformationException e) {
0470: return null;
0471: }
0472: }
0473:
0474: /**
0475: * Returns the first location in MainClass.print(OutputStream).
0476: */
0477: protected Location getLocation() {
0478: return getMethod().location();
0479: }
0480:
0481: /**
0482: * Returns the class org.eclipse.debug.jdi.tests.program.MainClass.
0483: */
0484: protected ClassType getMainClass() {
0485: return getClass("org.eclipse.debug.jdi.tests.program.MainClass");
0486: }
0487:
0488: /**
0489: * Returns the method "print(Ljava/io/OutputStream;)V"
0490: * in org.eclipse.debug.jdi.tests.program.MainClass
0491: */
0492: protected Method getMethod() {
0493: return getMethod("print", "(Ljava/io/OutputStream;)V");
0494: }
0495:
0496: /**
0497: * Returns the method with the given name and signature
0498: * in org.eclipse.debug.jdi.tests.program.MainClass
0499: */
0500: protected Method getMethod(String name, String signature) {
0501: return getMethod(
0502: "org.eclipse.debug.jdi.tests.program.MainClass", name,
0503: signature);
0504: }
0505:
0506: /**
0507: * Returns the method with the given name and signature
0508: * in the given class.
0509: */
0510: protected Method getMethod(String className, String name,
0511: String signature) {
0512: // Get main class
0513: ClassType type = getClass(className);
0514:
0515: // Get method print(OutputStream)
0516: Method method = null;
0517: List methods = type.methods();
0518: ListIterator iterator = methods.listIterator();
0519: while (iterator.hasNext()) {
0520: Method m = (Method) iterator.next();
0521: if ((m.name().equals(name))
0522: && (m.signature().equals(signature))) {
0523: method = m;
0524: break;
0525: }
0526: }
0527: if (method == null)
0528: throw new Error("Unknown method: " + name + signature);
0529:
0530: return method;
0531: }
0532:
0533: /**
0534: * Creates and returns a modification watchpoint request
0535: * for the field "fBool" in
0536: * org.eclipse.debug.jdi.tests.program.MainClass.
0537: * NOTE: This assumes that the VM can watch field modification.
0538: */
0539: protected ModificationWatchpointRequest getModificationWatchpointRequest() {
0540: // Get the field
0541: Field field = getField("fBool");
0542:
0543: // Create a modification watchpoint for this field
0544: return fVM.eventRequestManager()
0545: .createModificationWatchpointRequest(field);
0546: }
0547:
0548: /**
0549: * Returns the value of the static field "fObject" in
0550: * org.eclipse.debug.jdi.tests.program.MainClass
0551: */
0552: protected ObjectReference getObjectReference() {
0553: // Get main class
0554: ClassType type = getMainClass();
0555:
0556: // Get field "fObject"
0557: Field field = getField();
0558:
0559: // Get value of "fObject"
0560: return (ObjectReference) type.getValue(field);
0561: }
0562:
0563: /**
0564: * Creates and returns an access watchpoint request
0565: * for the static field "fString" in
0566: * org.eclipse.debug.jdi.tests.program.MainClass
0567: * NOTE: This assumes that the VM can watch field access.
0568: */
0569: protected AccessWatchpointRequest getStaticAccessWatchpointRequest() {
0570: // Get the static field
0571: Field field = getField("fString");
0572:
0573: // Create an access watchpoint for this field
0574: return fVM.eventRequestManager().createAccessWatchpointRequest(
0575: field);
0576: }
0577:
0578: /**
0579: * Creates and returns a modification watchpoint request
0580: * for the static field "fString" in
0581: * org.eclipse.debug.jdi.tests.program.MainClass.
0582: * NOTE: This assumes that the VM can watch field modification.
0583: */
0584: protected ModificationWatchpointRequest getStaticModificationWatchpointRequest() {
0585: // Get the field
0586: Field field = getField("fString");
0587:
0588: // Create a modification watchpoint for this field
0589: return fVM.eventRequestManager()
0590: .createModificationWatchpointRequest(field);
0591: }
0592:
0593: /**
0594: * Returns the value of the static field "fString" in
0595: * org.eclipse.debug.jdi.tests.program.MainClass
0596: */
0597: protected StringReference getStringReference() {
0598: // Get field "fString"
0599: Field field = getField("fString");
0600:
0601: // Get value of "fString"
0602: return (StringReference) getMainClass().getValue(field);
0603: }
0604:
0605: /**
0606: * Returns the class java.lang.Object.
0607: */
0608: protected ClassType getSystemType() {
0609: List classes = fVM.classesByName("java.lang.Object");
0610: if (classes.size() == 0)
0611: return null;
0612:
0613: return (ClassType) classes.get(0);
0614: }
0615:
0616: /**
0617: * Returns the thread contained in the static field "fThread" in
0618: * org.eclipse.debug.jdi.tests.program.MainClass
0619: */
0620: protected ThreadReference getThread() {
0621: return getThread("fThread");
0622: }
0623:
0624: protected ThreadReference getMainThread() {
0625: return getThread("fMainThread");
0626: }
0627:
0628: private ThreadReference getThread(String fieldName) {
0629: ClassType type = getMainClass();
0630: if (type == null)
0631: return null;
0632:
0633: // Get static field "fThread"
0634: List fields = type.fields();
0635: ListIterator iterator = fields.listIterator();
0636: Field field = null;
0637: while (iterator.hasNext()) {
0638: field = (Field) iterator.next();
0639: if (field.name().equals(fieldName))
0640: break;
0641: }
0642:
0643: // Get value of "fThread"
0644: Value value = type.getValue(field);
0645: if (value == null)
0646: return null;
0647:
0648: return (ThreadReference) value;
0649: }
0650:
0651: /**
0652: * Returns the VM info for this test.
0653: */
0654: VMInformation getVMInfo() {
0655: return new VMInformation(fVM, fVMType, fLaunchedVM,
0656: fEventReader, fConsoleReader);
0657: }
0658:
0659: /**
0660: * Returns whether the given test is excluded for the VM we are testing.
0661: */
0662: private boolean isExcludedTest(String testName) {
0663: String[] excludedTests = excludedTests();
0664: if (excludedTests == null)
0665: return false;
0666: for (int i = 0; i < excludedTests.length; i++)
0667: if (testName.equals(excludedTests[i]))
0668: return true;
0669: return false;
0670: }
0671:
0672: /**
0673: * Launches the target VM and connects to VM.
0674: */
0675: protected void launchTargetAndConnectToVM() {
0676: launchTarget();
0677: connectToVM();
0678: }
0679:
0680: protected boolean vmIsRunning() {
0681: boolean isRunning = false;
0682: try {
0683: if (fLaunchedVM != null)
0684: fLaunchedVM.exitValue();
0685: } catch (IllegalThreadStateException e) {
0686: isRunning = true;
0687: }
0688: return isRunning;
0689: }
0690:
0691: protected void launchTarget() {
0692: if (fVmCmd != null)
0693: launchCommandLineTarget();
0694: else if (fVMLauncherName.equals("SunVMLauncher"))
0695: launchSunTarget();
0696: else if (fVMLauncherName.equals("IBMVMLauncher"))
0697: launchIBMTarget();
0698: else
0699: launchJ9Target();
0700: }
0701:
0702: /**
0703: * Launches the target VM specified on the command line.
0704: */
0705: private void launchCommandLineTarget() {
0706: try {
0707: if (fProxyCmd != null) {
0708: fLaunchedProxy = Runtime.getRuntime().exec(fProxyCmd);
0709: }
0710: fLaunchedVM = Runtime.getRuntime().exec(fVmCmd);
0711: } catch (IOException e) {
0712: throw new Error("Could not launch the VM because "
0713: + e.getMessage());
0714: }
0715: }
0716:
0717: /**
0718: * Launches the target J9 VM.
0719: */
0720: private void launchJ9Target() {
0721: try {
0722: // Launch proxy
0723: String proxyString[] = new String[3];
0724: int index = 0;
0725: String binDirectory = fTargetAddress
0726: + System.getProperty("file.separator") + "bin"
0727: + System.getProperty("file.separator");
0728: proxyString[index++] = binDirectory + "j9proxy";
0729: proxyString[index++] = "localhost:" + (fBackEndPort - 1);
0730: proxyString[index++] = "" + fBackEndPort;
0731: fLaunchedProxy = Runtime.getRuntime().exec(proxyString);
0732:
0733: // Launch target VM
0734: String[] vmString;
0735: if (fBootPath.length() > 0)
0736: vmString = new String[5];
0737: else
0738: vmString = new String[4];
0739:
0740: index = 0;
0741: vmString[index++] = binDirectory + "j9w";
0742: File vm = new File(vmString[index - 1] + ".exe");
0743: if (!vm.exists()) {
0744: vmString[index - 1] = binDirectory + "j9";
0745: }
0746: if (fBootPath.length() > 0)
0747: vmString[index++] = "-bp:" + fBootPath;
0748: vmString[index++] = "-cp:" + fClassPath;
0749: vmString[index++] = "-debug:" + (fBackEndPort - 1);
0750: vmString[index++] = "org.eclipse.debug.jdi.tests.program.MainClass";
0751: fLaunchedVM = Runtime.getRuntime().exec(vmString);
0752:
0753: } catch (IOException e) {
0754: throw new Error("Could not launch the VM because "
0755: + e.getMessage());
0756: }
0757: }
0758:
0759: /**
0760: * Launches the target Sun VM.
0761: */
0762: private void launchSunTarget() {
0763: try {
0764: // Launch target VM
0765: StringBuffer binDirectory = new StringBuffer();
0766: if (fTargetAddress.endsWith("jre")) {
0767: binDirectory.append(fTargetAddress.substring(0,
0768: fTargetAddress.length() - 4));
0769: } else {
0770: binDirectory.append(fTargetAddress);
0771: }
0772: binDirectory.append(System.getProperty("file.separator"));
0773: binDirectory.append("bin").append(
0774: System.getProperty("file.separator"));
0775: String[] vmString;
0776: if (fBootPath.length() > 0)
0777: vmString = new String[10];
0778: else
0779: vmString = new String[8];
0780:
0781: int index = 0;
0782: vmString[index++] = binDirectory.toString() + "javaw";
0783: File vm = new File(vmString[index - 1] + ".exe");
0784: if (!vm.exists()) {
0785: vmString[index - 1] = binDirectory + "java";
0786: }
0787: if (fBootPath.length() > 0) {
0788: vmString[index++] = "-bootpath";
0789: vmString[index++] = fBootPath;
0790: }
0791: vmString[index++] = "-classpath";
0792: vmString[index++] = fClassPath;
0793: vmString[index++] = "-Xdebug";
0794: vmString[index++] = "-Xnoagent";
0795: vmString[index++] = "-Djava.compiler=NONE";
0796: vmString[index++] = "-Xrunjdwp:transport=dt_socket,address="
0797: + fBackEndPort + ",suspend=y,server=y";
0798: vmString[index++] = "org.eclipse.debug.jdi.tests.program.MainClass";
0799: fLaunchedVM = Runtime.getRuntime().exec(vmString);
0800:
0801: } catch (IOException e) {
0802: throw new Error("Could not launch the VM because "
0803: + e.getMessage());
0804: }
0805: }
0806:
0807: /**
0808: * Launches the target IBM VM.
0809: */
0810: private void launchIBMTarget() {
0811: try {
0812: // Launch target VM
0813: String binDirectory = fTargetAddress
0814: + System.getProperty("file.separator") + "bin"
0815: + System.getProperty("file.separator");
0816: String[] vmString;
0817: if (fBootPath.length() > 0)
0818: vmString = new String[10];
0819: else
0820: vmString = new String[8];
0821:
0822: int index = 0;
0823: vmString[index++] = binDirectory + "javaw";
0824: if (fBootPath.length() > 0) {
0825: vmString[index++] = "-bootpath";
0826: vmString[index++] = fBootPath;
0827: }
0828: vmString[index++] = "-classpath";
0829: vmString[index++] = fClassPath;
0830: vmString[index++] = "-Xdebug";
0831: vmString[index++] = "-Xnoagent";
0832: vmString[index++] = "-Djava.compiler=NONE";
0833: vmString[index++] = "-Xrunjdwp:transport=dt_socket,address="
0834: + fBackEndPort + ",suspend=y,server=y";
0835: vmString[index++] = "org.eclipse.debug.jdi.tests.program.MainClass";
0836: fLaunchedVM = Runtime.getRuntime().exec(vmString);
0837:
0838: } catch (IOException e) {
0839: throw new Error("Could not launch the VM because "
0840: + e.getMessage());
0841: }
0842: }
0843:
0844: /**
0845: * Conects to the target vm.
0846: */
0847: protected void connectToVM() {
0848: // Start the console reader if possible so that the VM doesn't block when the stdout is full
0849: startConsoleReaders();
0850:
0851: // Contact the VM (try 10 times)
0852: for (int i = 0; i < 10; i++) {
0853: try {
0854: VirtualMachineManager manager = Bootstrap
0855: .virtualMachineManager();
0856: List connectors = manager.attachingConnectors();
0857: if (connectors.size() == 0)
0858: break;
0859: AttachingConnector connector = (AttachingConnector) connectors
0860: .get(0);
0861: Map args = connector.defaultArguments();
0862: ((Connector.Argument) args.get("port")).setValue(String
0863: .valueOf(fBackEndPort));
0864: ((Connector.Argument) args.get("hostname"))
0865: .setValue("localhost");
0866:
0867: fVM = connector.attach(args);
0868: if (fVMTraceFlags != com.sun.jdi.VirtualMachine.TRACE_NONE)
0869: fVM.setDebugTraceMode(fVMTraceFlags);
0870: break;
0871: } catch (IllegalConnectorArgumentsException e) {
0872: } catch (IOException e) {
0873: // System.out.println("Got exception: " + e.getMessage());
0874: try {
0875: if (i == 9) {
0876: System.out
0877: .println("Could not contact the VM at localhost"
0878: + ":" + fBackEndPort + ".");
0879: }
0880: Thread.sleep(200);
0881: } catch (InterruptedException e2) {
0882: }
0883: }
0884: }
0885: if (fVM == null) {
0886: if (fLaunchedVM != null) {
0887: // If the VM is not running, output error stream
0888: try {
0889: if (!vmIsRunning()) {
0890: InputStream in = fLaunchedVM.getErrorStream();
0891: int read;
0892: do {
0893: read = in.read();
0894: if (read != -1)
0895: System.out.print((char) read);
0896: } while (read != -1);
0897: }
0898: } catch (IOException e) {
0899: }
0900:
0901: // Shut it down
0902: killVM();
0903: }
0904: throw new Error("Could not contact the VM");
0905: }
0906: startEventReader();
0907: }
0908:
0909: /**
0910: * Initializes the fields that are used by this test only.
0911: */
0912: public abstract void localSetUp();
0913:
0914: /**
0915: * Makes sure the test leaves the VM in the same state it found it.
0916: * Default is to do nothing.
0917: */
0918: public void localTearDown() {
0919: }
0920:
0921: /**
0922: * Parses the given arguments and store them in this tests
0923: * fields.
0924: * Returns whether the parsing was successfull.
0925: */
0926: protected static boolean parseArgs(String[] args) {
0927: // Default values
0928: String vmVendor = System.getProperty("java.vm.vendor");
0929: String vmVersion = System.getProperty("java.vm.version");
0930: String targetAddress = System.getProperty("java.home");
0931: String vmLauncherName;
0932: if (vmVendor != null
0933: && vmVendor.equals("Sun Microsystems Inc.")
0934: && vmVersion != null) {
0935: vmLauncherName = "SunVMLauncher";
0936: } else if (vmVendor != null
0937: && vmVendor.equals("IBM Corporation")
0938: && vmVersion != null) {
0939: vmLauncherName = "IBMVMLauncher";
0940: } else {
0941: vmLauncherName = "J9VMLauncher";
0942: }
0943: String classPath = System.getProperty("java.class.path");
0944: String bootPath = "";
0945: String vmType = "?";
0946: boolean verbose = false;
0947:
0948: // Parse arguments
0949: for (int i = 0; i < args.length; ++i) {
0950: String arg = args[i];
0951: if (arg.startsWith("-")) {
0952: if (arg.equals("-verbose") || arg.equals("-v")) {
0953: verbose = true;
0954: } else {
0955: String next = (i < args.length - 1) ? args[++i]
0956: : null;
0957: // If specified, passed values overide default values
0958: if (arg.equals("-launcher")) {
0959: vmLauncherName = next;
0960: } else if (arg.equals("-address")) {
0961: targetAddress = next;
0962: } else if (arg.equals("-port")) {
0963: fBackEndPort = Integer.parseInt(next);
0964: } else if (arg.equals("-cp")) {
0965: classPath = next;
0966: } else if (arg.equals("-bp")) {
0967: bootPath = next;
0968: } else if (arg.equals("-vmtype")) {
0969: vmType = next;
0970: } else if (arg.equals("-stdout")) {
0971: fStdoutFile = next;
0972: } else if (arg.equals("-stderr")) {
0973: fStderrFile = next;
0974: } else if (arg.equals("-proxyout")) {
0975: fProxyoutFile = next;
0976: } else if (arg.equals("-proxyerr")) {
0977: fProxyerrFile = next;
0978: } else if (arg.equals("-vmcmd")) {
0979: fVmCmd = next;
0980: } else if (arg.equals("-proxycmd")) {
0981: fProxyCmd = next;
0982: } else if (arg.equals("-trace")) {
0983: if (next.equals("all")) {
0984: fVMTraceFlags = com.sun.jdi.VirtualMachine.TRACE_ALL;
0985: } else {
0986: fVMTraceFlags = Integer.decode(next)
0987: .intValue();
0988: }
0989: } else {
0990: System.out.println("Invalid option: " + arg);
0991: printUsage();
0992: return false;
0993: }
0994: }
0995: }
0996: }
0997: fVMLauncherName = vmLauncherName;
0998: fTargetAddress = targetAddress;
0999: fClassPath = classPath;
1000: fBootPath = bootPath;
1001: fVMType = vmType;
1002: fVerbose = verbose;
1003: return true;
1004: }
1005:
1006: /**
1007: * Prints the various options to pass to the constructor.
1008: */
1009: protected static void printUsage() {
1010: System.out.println("Possible options:");
1011: System.out.println("-launcher <Name of the launcher class>");
1012: System.out.println("-address <Address of the target VM>");
1013: System.out.println("-port <Debug port number>");
1014: System.out.println("-cp <Path to the test program>");
1015: System.out
1016: .println("-bp <Boot classpath for the system class library>");
1017: System.out.println("-vmtype <The type of VM: JDK, J9, ...>");
1018: System.out.println("-verbose | -v");
1019: System.out
1020: .println("-stdout <file where VM output is written to>");
1021: System.out
1022: .println("-stderr <file where VM error output is written to>");
1023: System.out
1024: .println("-proxyout <file where proxy output is written to>");
1025: System.out
1026: .println("-proxyerr <file where proxy error output is written to>");
1027: System.out.println("-vmcmd <exec string to start VM>");
1028: System.out.println("-proxycmd <exec string to start proxy>");
1029: }
1030:
1031: /**
1032: * Set the value of the "fBool" field back to its original value
1033: */
1034: protected void resetField() {
1035: Field field = getField("fBool");
1036: Value value = null;
1037: value = fVM.mirrorOf(false);
1038: try {
1039: getObjectReference().setValue(field, value);
1040: } catch (ClassNotLoadedException e) {
1041: assertTrue("resetField.2", false);
1042: } catch (InvalidTypeException e) {
1043: assertTrue("resetField.3", false);
1044: }
1045: }
1046:
1047: /**
1048: * Set the value of the "fString" field back to its original value
1049: */
1050: protected void resetStaticField() {
1051: Field field = getField("fString");
1052: Value value = null;
1053: value = fVM.mirrorOf("Hello World");
1054: try {
1055: getMainClass().setValue(field, value);
1056: } catch (ClassNotLoadedException e) {
1057: assertTrue("resetField.1", false);
1058: } catch (InvalidTypeException e) {
1059: assertTrue("resetField.2", false);
1060: }
1061: }
1062:
1063: /**
1064: * Runs this test's suite with the given arguments.
1065: */
1066: protected void runSuite(String[] args) {
1067: // Check args
1068: if (!parseArgs(args))
1069: return;
1070:
1071: // Run test
1072: System.out.println(new java.util.Date());
1073: System.out.println("Begin testing " + getName() + "...");
1074: junit.textui.TestRunner.run(suite());
1075: System.out.println("Done testing " + getName() + ".");
1076: }
1077:
1078: /**
1079: * Sets the 'in control of the VM' flag for this test.
1080: */
1081: void setInControl(boolean inControl) {
1082: fInControl = inControl;
1083: }
1084:
1085: /**
1086: * Launch target VM and start program in target VM.
1087: */
1088: protected void launchTargetAndStartProgram() {
1089: launchTargetAndConnectToVM();
1090: startProgram();
1091: }
1092:
1093: /**
1094: * Init tests
1095: */
1096: protected void setUp() {
1097: if (fVM == null || fInControl) {
1098: launchTargetAndStartProgram();
1099: }
1100: try {
1101: verbose("Setting up the test");
1102: localSetUp();
1103: } catch (RuntimeException e) {
1104: System.out.println("Runtime exception during set up:");
1105: e.printStackTrace();
1106: } catch (Error e) {
1107: System.out.println("Error during set up:");
1108: e.printStackTrace();
1109: }
1110: }
1111:
1112: /**
1113: * Sets the VM info for this test.
1114: */
1115: void setVMInfo(VMInformation info) {
1116: if (info != null) {
1117: fVM = info.fVM;
1118: fLaunchedVM = info.fLaunchedVM;
1119: fEventReader = info.fEventReader;
1120: fConsoleReader = info.fConsoleReader;
1121: }
1122: }
1123:
1124: /**
1125: * Stop console and event readers.
1126: */
1127: protected void stopReaders() {
1128: stopEventReader();
1129: stopConsoleReaders();
1130: }
1131:
1132: /**
1133: * Shut down the target.
1134: */
1135: protected void shutDownTarget() {
1136: stopReaders();
1137: if (fVM != null) {
1138: try {
1139: fVM.exit(0);
1140: } catch (VMDisconnectedException e) {
1141: }
1142: }
1143:
1144: fVM = null;
1145: fLaunchedVM = null;
1146:
1147: // We want subsequent connections to use different ports, unless a
1148: // VM exec sting is given.
1149: if (fVmCmd == null)
1150: fBackEndPort += 2;
1151: }
1152:
1153: /**
1154: * Starts the threads that reads from the VM and proxy input and error streams
1155: */
1156: private void startConsoleReaders() {
1157: if (fStdoutFile != null) {
1158: fConsoleReader = new FileConsoleReader(
1159: "JDI Tests Console Reader", fStdoutFile,
1160: fLaunchedVM.getInputStream());
1161: } else {
1162: fConsoleReader = new NullConsoleReader(
1163: "JDI Tests Console Reader", fLaunchedVM
1164: .getInputStream());
1165: }
1166: fConsoleReader.start();
1167:
1168: if (fStderrFile != null) {
1169: fConsoleErrorReader = new FileConsoleReader(
1170: "JDI Tests Console Error Reader", fStderrFile,
1171: fLaunchedVM.getErrorStream());
1172: } else {
1173: fConsoleErrorReader = new NullConsoleReader(
1174: "JDI Tests Console Error Reader", fLaunchedVM
1175: .getErrorStream());
1176: }
1177: fConsoleErrorReader.start();
1178:
1179: if (fLaunchedProxy == null)
1180: return;
1181:
1182: if (fProxyoutFile != null) {
1183: fProxyReader = new FileConsoleReader(
1184: "JDI Tests Proxy Reader", fProxyoutFile,
1185: fLaunchedProxy.getInputStream());
1186: } else {
1187: fProxyReader = new NullConsoleReader(
1188: "JDI Tests Proxy Reader", fLaunchedProxy
1189: .getInputStream());
1190: }
1191: fProxyReader.start();
1192:
1193: if (fProxyerrFile != null) {
1194: fProxyErrorReader = new FileConsoleReader(
1195: "JDI Tests Proxy Error Reader", fProxyerrFile,
1196: fLaunchedProxy.getErrorStream());
1197: } else {
1198: fProxyErrorReader = new NullConsoleReader(
1199: "JDI Tests Proxy Error Reader", fLaunchedProxy
1200: .getErrorStream());
1201: }
1202: fProxyErrorReader.start();
1203: }
1204:
1205: /**
1206: * Stops the console reader.
1207: */
1208: private void stopConsoleReaders() {
1209: if (fConsoleReader != null)
1210: fConsoleReader.stop();
1211: if (fConsoleErrorReader != null)
1212: fConsoleErrorReader.stop();
1213: if (fProxyReader != null)
1214: fProxyReader.stop();
1215: if (fProxyErrorReader != null)
1216: fProxyErrorReader.stop();
1217: }
1218:
1219: /**
1220: * Starts event reader.
1221: */
1222: private void startEventReader() {
1223: // Create the VM event reader.
1224: fEventReader = new EventReader("JDI Tests Event Reader", fVM
1225: .eventQueue());
1226: }
1227:
1228: /**
1229: * Stops the event reader.
1230: */
1231: private void stopEventReader() {
1232: fEventReader.stop();
1233: }
1234:
1235: protected void killVM() {
1236: if (fLaunchedVM != null)
1237: fLaunchedVM.destroy();
1238: if (fLaunchedProxy != null)
1239: fLaunchedProxy.destroy();
1240: }
1241:
1242: /**
1243: * Starts the target program.
1244: */
1245: protected void startProgram() {
1246: verbose("Starting target program");
1247:
1248: // Request class prepare events
1249: EventRequest classPrepareRequest = fVM.eventRequestManager()
1250: .createClassPrepareRequest();
1251: classPrepareRequest.enable();
1252:
1253: // Prepare to receive the token class prepare event
1254: ClassPrepareEventWaiter waiter = new ClassPrepareEventWaiter(
1255: classPrepareRequest, true,
1256: "org.eclipse.debug.jdi.tests.program.MainClass");
1257: fEventReader.addEventListener(waiter);
1258:
1259: // Start the event reader (this will start the VM when the VMStartEvent is picked up)
1260: fEventReader.start();
1261:
1262: // Wait until the program has started
1263: Event event = (ClassPrepareEvent) waitForEvent(waiter,
1264: 3 * TIMEOUT);
1265: fEventReader.removeEventListener(waiter);
1266: if (event == null) {
1267: // try {
1268: System.out
1269: .println("\nThe program doesn't seem to have started after "
1270: + (3 * TIMEOUT) + "ms");
1271: // InputStream errorStream = fLaunchedVM.getErrorStream();
1272: // int read;
1273: // do {
1274: // read = errorStream.read();
1275: // if (read != -1)
1276: // System.out.print((char) read);
1277: // } while (read != -1);
1278: // } catch (IOException e) {
1279: // }
1280: }
1281:
1282: // Stop class prepare events
1283: fVM.eventRequestManager().deleteEventRequest(
1284: classPrepareRequest);
1285:
1286: // Wait for the program to be ready to be tested
1287: waitUntilReady();
1288: }
1289:
1290: /**
1291: * Returns all tests
1292: */
1293: protected Test suite() {
1294: JDITestSuite suite = new JDITestSuite(this );
1295: Vector testNames = getAllMatchingTests("testJDI");
1296: Iterator iterator = testNames.iterator();
1297: while (iterator.hasNext()) {
1298: String name = (String) iterator.next();
1299: suite.addTest(new JDITestCase(this , name));
1300: }
1301: return suite;
1302: }
1303:
1304: /**
1305: * Undo the initialization of the test.
1306: */
1307: protected void tearDown() {
1308: try {
1309: super .tearDown();
1310: } catch (Exception e) {
1311: System.out.println("Exception during tear down:");
1312: e.printStackTrace();
1313: }
1314: try {
1315: verbose("Tearing down the test");
1316: localTearDown();
1317:
1318: // Ensure that the test didn't leave a modification watchpoint that could change the expected state of the program
1319: if (fVM != null) {
1320: assertTrue(fVM.eventRequestManager()
1321: .modificationWatchpointRequests().size() == 0);
1322: if (fInControl) {
1323: shutDownTarget();
1324: }
1325: }
1326:
1327: } catch (RuntimeException e) {
1328: System.out.println("Runtime exception during tear down:");
1329: e.printStackTrace();
1330: } catch (Error e) {
1331: System.out.println("Error during tear down:");
1332: e.printStackTrace();
1333: }
1334:
1335: }
1336:
1337: /**
1338: * Triggers and waits for the given event to come in.
1339: * Let the thread go if asked.
1340: * Throws an Error if the event didn't come in after TIMEOUT ms
1341: */
1342: protected Event triggerAndWait(EventRequest request,
1343: String eventType, boolean shouldGo) {
1344: Event event = triggerAndWait(request, eventType, shouldGo,
1345: TIMEOUT);
1346: if (event == null)
1347: throw new Error("Event for " + request
1348: + " didn't come in after " + TIMEOUT + "ms");
1349:
1350: return event;
1351: }
1352:
1353: /**
1354: * Triggers and waits for the given event to come in.
1355: * Let the thread go if asked.
1356: * Returns null if the event didn't come in after the given amount of time (in ms)
1357: */
1358: protected Event triggerAndWait(EventRequest request,
1359: String eventType, boolean shouldGo, long time) {
1360: // Suspend only if asked
1361: if (shouldGo)
1362: request.setSuspendPolicy(EventRequest.SUSPEND_NONE);
1363: else
1364: request.setSuspendPolicy(EventRequest.SUSPEND_EVENT_THREAD);
1365:
1366: // Enable request
1367: request.enable();
1368:
1369: // Prepare to receive the event
1370: EventWaiter waiter = new EventWaiter(request, shouldGo);
1371: fEventReader.addEventListener(waiter);
1372:
1373: // Trigger the event
1374: triggerEvent(eventType);
1375:
1376: // Wait for the event to come in
1377: Event event = waitForEvent(waiter, TIMEOUT);
1378: fEventReader.removeEventListener(waiter);
1379:
1380: if (shouldGo) {
1381: // Wait for the program to be ready
1382: waitUntilReady();
1383: }
1384:
1385: // Clear request
1386: fVM.eventRequestManager().deleteEventRequest(request);
1387:
1388: return event;
1389: }
1390:
1391: /**
1392: * Triggers the given type of event. See the MainClass for details on types of event.
1393: */
1394: protected void triggerEvent(String eventType) {
1395: // Set the "fEventType" field to the given eventType
1396: ClassType type = getMainClass();
1397: Field field = type.fieldByName("fEventType");
1398: assertTrue("1", field != null);
1399:
1400: Value value = null;
1401: value = fVM.mirrorOf(eventType);
1402: try {
1403: type.setValue(field, value);
1404: } catch (ClassNotLoadedException e) {
1405: assertTrue("2", false);
1406: } catch (InvalidTypeException e) {
1407: assertTrue("3", false);
1408: }
1409:
1410: // Resume the test thread
1411: ThreadReference thread = getThread();
1412: int suspendCount = thread.suspendCount();
1413: for (int i = 0; i < suspendCount; i++)
1414: thread.resume();
1415: }
1416:
1417: /**
1418: * Triggers a step event and waits for it to come in.
1419: */
1420: protected StepEvent triggerStepAndWait() {
1421: return triggerStepAndWait(getThread(), StepRequest.STEP_MIN,
1422: StepRequest.STEP_OVER);
1423: }
1424:
1425: protected StepEvent triggerStepAndWait(ThreadReference thread,
1426: int gran, int depth) {
1427: // Request for step events
1428: EventRequest eventRequest = fVM.eventRequestManager()
1429: .createStepRequest(thread, gran, depth);
1430: eventRequest.addCountFilter(1);
1431: eventRequest.setSuspendPolicy(EventRequest.SUSPEND_NONE);
1432: eventRequest.enable();
1433:
1434: return triggerStepAndWait(thread, eventRequest, TIMEOUT);
1435: }
1436:
1437: protected StepEvent triggerStepAndWait(ThreadReference thread,
1438: EventRequest eventRequest, int timeout) {
1439: // Prepare to receive the event
1440: EventWaiter waiter = new EventWaiter(eventRequest, true);
1441: fEventReader.addEventListener(waiter);
1442:
1443: // Trigger step event
1444: int suspendCount = thread.suspendCount();
1445: for (int i = 0; i < suspendCount; i++)
1446: thread.resume();
1447:
1448: // Wait for the event to come in
1449: StepEvent event = (StepEvent) waitForEvent(waiter, timeout);
1450: fEventReader.removeEventListener(waiter);
1451: if (event == null)
1452: throw new Error("StepEvent didn't come in after " + timeout
1453: + "ms");
1454:
1455: // Stop getting step events
1456: fVM.eventRequestManager().deleteEventRequest(eventRequest);
1457:
1458: // Wait for the program to be ready
1459: waitUntilReady();
1460:
1461: return event;
1462: }
1463:
1464: /**
1465: * Output verbose string if asked for.
1466: */
1467: protected void verbose(String verboseString) {
1468: if (fVerbose)
1469: System.out.println(verboseString);
1470: }
1471:
1472: /**
1473: * Waits for an event to come in using the given waiter.
1474: * Waits for the given time. If it times out, returns null.
1475: */
1476: protected Event waitForEvent(EventWaiter waiter, long time) {
1477: Event event;
1478: try {
1479: event = waiter.waitEvent(time);
1480: } catch (InterruptedException e) {
1481: event = null;
1482: }
1483: return event;
1484: }
1485:
1486: /**
1487: * Waits until the program is ready to be tested.
1488: * The default behaviour is to wait until the "Test Thread" throws and catches
1489: * an exception.
1490: */
1491: protected void waitUntilReady() {
1492: // Make sure the program is running
1493: ThreadReference thread = getThread();
1494: while (thread == null || thread.suspendCount() > 0) {
1495: fVM.resume();
1496: thread = getThread();
1497: }
1498:
1499: // Create exception request
1500: EventRequest request = fVM.eventRequestManager()
1501: .createExceptionRequest(null, true, false);
1502: request.setSuspendPolicy(EventRequest.SUSPEND_EVENT_THREAD);
1503:
1504: // Prepare to receive the event
1505: EventWaiter waiter = new EventWaiter(request, false);
1506: fEventReader.addEventListener(waiter);
1507:
1508: request.enable();
1509:
1510: while (true) {
1511: // Wait for the event to come in
1512: ExceptionEvent event = (ExceptionEvent) waitForEvent(
1513: waiter, TIMEOUT);
1514:
1515: // Throw error if event is null
1516: if (event == null)
1517: throw new Error("Target program was not ready after "
1518: + TIMEOUT + "ms");
1519:
1520: // Get the method where the exception was thrown
1521: Method meth = event.location().method();
1522: if (meth == null || !meth.name().equals("printAndSignal"))
1523: fVM.resume();
1524: else
1525: break;
1526: }
1527:
1528: // Disable request
1529: fEventReader.removeEventListener(waiter);
1530: fVM.eventRequestManager().deleteEventRequest(request);
1531: }
1532: }
|