001: /*BEGIN_COPYRIGHT_BLOCK
002: *
003: * Copyright (c) 2001-2007, JavaPLT group at Rice University (javaplt@rice.edu)
004: * All rights reserved.
005: *
006: * Redistribution and use in source and binary forms, with or without
007: * modification, are permitted provided that the following conditions are met:
008: * * Redistributions of source code must retain the above copyright
009: * notice, this list of conditions and the following disclaimer.
010: * * Redistributions in binary form must reproduce the above copyright
011: * notice, this list of conditions and the following disclaimer in the
012: * documentation and/or other materials provided with the distribution.
013: * * Neither the names of DrJava, the JavaPLT group, Rice University, nor the
014: * names of its contributors may be used to endorse or promote products
015: * derived from this software without specific prior written permission.
016: *
017: * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
018: * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
019: * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
020: * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
021: * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
022: * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
023: * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
024: * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
025: * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
026: * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
027: * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
028: *
029: * This software is Open Source Initiative approved Open Source Software.
030: * Open Source Initative Approved is a trademark of the Open Source Initiative.
031: *
032: * This file is part of DrJava. Download the current version of this project
033: * from http://www.drjava.org/ or http://sourceforge.net/projects/drjava/
034: *
035: * END_COPYRIGHT_BLOCK*/
036:
037: package edu.rice.cs.drjava.model.debug;
038:
039: import edu.rice.cs.drjava.model.*;
040: import edu.rice.cs.plt.io.IOUtil;
041: import edu.rice.cs.util.Log;
042:
043: import java.io.*;
044:
045: /** This class contains the basic fields and methods that are necessary for any test file that needs to use the
046: * JPDADebugger.
047: * @version $Id: DebugTestCase.java 4255 2007-08-28 19:17:37Z mgricken $
048: */
049: public abstract class DebugTestCase extends GlobalModelTestCase {
050:
051: // protected final boolean printEvents = true;
052: // protected final boolean printMessages = true;
053: // protected PrintStream printStream = System.err;
054:
055: // _log inherited from GlabalModelTestCase
056:
057: protected volatile int _pendingNotifies = 0;
058: protected final Object _notifierLock = new Object();
059:
060: protected volatile Debugger _debugger;
061:
062: protected static final String DEBUG_CLASS =
063: /* 1 */"class DrJavaDebugClass {\n" +
064: /* 2 */" public void foo() {\n" +
065: /* 3 */" System.out.println(\"Foo Line 1\");\n" +
066: /* 4 */" bar();\n" +
067: /* 5 */" System.out.println(\"Foo Line 3\");\n" +
068: /* 6 */" }\n" +
069: /* 7 */" public void bar() {\n" +
070: /* 8 */" System.out.println(\"Bar Line 1\");\n" +
071: /* 9 */" System.out.println(\"Bar Line 2\");\n" +
072: /* 10 */" }\n" +
073: /* 11 */"}\n" +
074: /* 12 */"class DrJavaDebugClass2 {\n" +
075: /* 13 */" public void baz() {\n" +
076: /* 14 */" System.out.println(\"Baz Line 1\");\n" +
077: /* 15 */" new DrJavaDebugClass().bar();\n" +
078: /* 16 */" }\n" +
079: /* 17 */"}";
080:
081: protected static final String DEBUG_CLASS_WITH_PACKAGE =
082: /* 1 */"package a;\n" +
083: /* 2 */"public class DrJavaDebugClassWithPackage {\n" +
084: /* 3 */" public void foo() {\n" +
085: /* 4 */" System.out.println(\"foo line 1\");\n" +
086: /* 5 */" System.out.println(\"foo line 2\");\n" +
087: /* 6 */" }\n" +
088: /* 7 */"}";
089:
090: protected static final String SUSPEND_CLASS = "class Suspender {\n"
091: + " public static void main(String[] args) {\n"
092: + " Thread t1 = new Thread(){\n"
093: + " public void run(){\n" + " int a = 1;\n"
094: + " while(true);\n" + " }\n" + " };\n"
095: + " t1.start();\n" + " }\n" + "}";
096:
097: protected static final String MONKEY_CLASS =
098: /* 1 */"class Monkey {\n"
099: +
100: /* 2 */" public static void main(String[] args) {\n"
101: +
102: /* 3 */"\n"
103: +
104: /* 4 */" Thread t = new Thread(){\n"
105: +
106: /* 5 */" public void run(){\n"
107: +
108: /* 6 */" try{\n"
109: +
110: /* 7 */" Thread.sleep(1000);\n"
111: +
112: /* 8 */" }\n"
113: +
114: /* 9 */" catch(InterruptedException e){\n"
115: +
116: /* 10 */" }\n"
117: +
118: /* 11 */" System.out.println(\"I\'m a thread! Yeah!\");\n"
119: +
120: /* 12 */" }\n"
121: +
122: /* 13 */" };\n"
123: +
124: /* 14 */" try{\n"
125: +
126: /* 15 */" t.start();\n"
127: +
128: /* 16 */" System.out.println(\"I just woke up. I\'m a big boy now.\");\n"
129: +
130: /* 17 */" System.out.println(\"James likes bananas!\");\n"
131: +
132: /* 18 */" System.out.println(\"Yes they do.\");\n" +
133: /* 19 */" }catch(Exception e){\n" +
134: /* 20 */" e.printStackTrace();\n" +
135: /* 21 */" }\n" +
136: /* 22 */" }\n" +
137: /* 23 */"}\n";
138:
139: protected static final String MONKEY_WITH_INNER_CLASS =
140: /* 1 */"class Monkey {\n"
141: +
142: /* 2 */" static int foo = 6; \n"
143: +
144: /* 3 */" class MonkeyInner { \n"
145: +
146: /* 4 */" int innerFoo = 8;\n"
147: +
148: /* 5 */" class MonkeyInnerInner { \n"
149: +
150: /* 6 */" int innerInnerFoo = 10;\n"
151: +
152: /* 7 */" public void innerMethod() { \n"
153: +
154: /* 8 */" int innerMethodFoo;\n"
155: +
156: /* 9 */" String nullString = null;\n"
157: +
158: /* 10 */" innerMethodFoo = 12;\n"
159: +
160: /* 11 */" foo++;\n"
161: +
162: /* 12 */" innerFoo++;\n"
163: +
164: /* 13 */" innerInnerFoo++;\n"
165: +
166: /* 14 */" innerMethodFoo++;\n"
167: +
168: /* 15 */" staticMethod();\n"
169: +
170: /* 16 */" System.out.println(\"innerMethodFoo: \" + innerMethodFoo);\n"
171: +
172: /* 17 */" }\n"
173: +
174: /* 18 */" }\n"
175: +
176: /* 19 */" }\n"
177: +
178: /* 20 */" public void bar() {\n"
179: +
180: /* 21 */" final MonkeyInner.MonkeyInnerInner mi = \n"
181: +
182: /* 22 */" new MonkeyInner().new MonkeyInnerInner();\n"
183: +
184: /* 23 */" mi.innerMethod();\n"
185: +
186: /* 24 */" final int localVar = 99;\n"
187: +
188: /* 25 */" new Thread() {\n"
189: +
190: /* 26 */" public void run() {\n"
191: +
192: /* 27 */" final int localVar = mi.innerInnerFoo;\n"
193: +
194: /* 28 */" new Thread() {\n"
195: +
196: /* 29 */" public void run() {\n"
197: +
198: /* 30 */" new Thread() {\n"
199: +
200: /* 31 */" public void run() {\n"
201: +
202: /* 32 */" System.out.println(\"localVar = \" + localVar);\n"
203: +
204: /* 33 */" }\n" +
205: /* 34 */" }.run();\n" +
206: /* 35 */" }\n" +
207: /* 36 */" }.run();\n" +
208: /* 37 */" }\n" +
209: /* 38 */" }.run();\n" +
210: /* 39 */" }\n" +
211: /* 40 */" public static void staticMethod() {\n" +
212: /* 41 */" int z = 3;\n" +
213: /* 42 */" }\n" +
214: /* 43 */"}\n";
215:
216: protected static final String INNER_CLASS_WITH_LOCAL_VARS =
217: /* 1 */"class InnerClassWithLocalVariables {\n"
218: +
219: /* 2 */" public static void main(final String[] args) {\n"
220: +
221: /* 3 */" final int numArgs = args.length;\n"
222: +
223: /* 4 */" final int inlined = 0;\n"
224: +
225: /* 5 */" new Runnable() {\n"
226: +
227: /* 6 */" public void run() {\n"
228: +
229: /* 7 */" System.out.println(\"numArgs: \" + numArgs);\n"
230: +
231: /* 8 */" System.out.println(\"inlined: \" + inlined);\n"
232: +
233: /* 9 */" System.out.println(\"args.length: \" + args.length);\n"
234: +
235: /* 10 */" }\n" +
236: /* 11 */" }.run();\n" +
237: /* 12 */" }\n" +
238: /* 13 */"}\n";
239:
240: protected static final String CLASS_WITH_STATIC_FIELD =
241: /* 1 */"public class DrJavaDebugStaticField {\n" +
242: /* 2 */" public static int x = 0;\n" +
243: /* 3 */" public void bar() {\n" +
244: /* 4 */" System.out.println(\"x == \" + x);\n" +
245: /* 5 */" x++;\n" +
246: /* 6 */" }\n" +
247: /* 7 */" public static void main(String[] nu) {\n" +
248: /* 8 */" new Thread(\"stuff\") {\n" +
249: /* 9 */" public void run() {\n" +
250: /* 10 */" new DrJavaDebugStaticField().bar();\n" +
251: /* 11 */" }\n" +
252: /* 12 */" }.start();\n" +
253: /* 13 */" new DrJavaDebugStaticField().bar();\n" +
254: /* 14 */" }\n" +
255: /* 15 */"}";
256:
257: protected static final String MONKEY_STATIC_STUFF =
258: /*1*/"class MonkeyStaticStuff {\n"
259: +
260: /*2*/" static int foo = 6;\n"
261: +
262: /*3*/" static class MonkeyInner {\n"
263: +
264: /*4*/" static int innerFoo = 8;\n"
265: +
266: /*5*/" static public class MonkeyTwoDeep {\n"
267: +
268: /*6*/" static int twoDeepFoo = 13;\n"
269: +
270: /*7*/" static class MonkeyThreeDeep {\n"
271: +
272: /*8*/" public static int threeDeepFoo = 18;\n"
273: +
274: /*9*/" public static void threeDeepMethod() {\n"
275: +
276: /*10*/" System.out.println(MonkeyStaticStuff.MonkeyInner.MonkeyTwoDeep.MonkeyThreeDeep.threeDeepFoo);\n"
277: +
278: /*11*/" System.out.println(MonkeyTwoDeep.twoDeepFoo);\n"
279: +
280: /*12*/" System.out.println(MonkeyStaticStuff.foo);\n"
281: +
282: /*13*/" System.out.println(MonkeyStaticStuff.MonkeyInner.innerFoo);\n"
283: +
284: /*14*/" System.out.println(MonkeyInner.MonkeyTwoDeep.twoDeepFoo);\n"
285: +
286: /*15*/" System.out.println(innerFoo);\n" +
287: /*16*/" }\n" +
288: /*17*/" }\n" +
289: /*18*/" static int getNegativeTwo() { return -2; }\n"
290: +
291: /*19*/" }\n" +
292: /*20*/" }\n" +
293: /*21*/"}";
294:
295: protected static final String THREAD_DEATH_CLASS =
296: /* 1 */"class Jones {\n"
297: +
298: /* 2 */" public static void threadShouldDie() {\n"
299: +
300: /* 3 */" Thread cooper = new Thread() {\n"
301: +
302: /* 4 */" public void run() {\n"
303: +
304: /* 5 */" System.out.println(\"This thread should die.\");\n"
305: +
306: /* 6 */" }\n" +
307: /* 7 */" };\n" +
308: /* 8 */" cooper.start();\n" +
309: /* 9 */" while(cooper.isAlive()) {}\n" +
310: /* 10 */" System.out.println(\"Thread died.\");\n" +
311: /* 11 */" }\n" +
312: /* 12 */"}";
313:
314: /** Sets up the debugger for each test. */
315: public void setUp() throws Exception {
316: _log.log("Setting up (DebugTestCase)" + this );
317: super .setUp();
318: _debugger = _model.getDebugger();
319: assertNotNull("Debug Manager should not be null", _debugger);
320: }
321:
322: /** Cleans up the debugger after each test. */
323: public void tearDown() throws Exception {
324: _log.log("Tearing down (DebugTestCase)" + this );
325: _debugger = null;
326: super .tearDown();
327: }
328:
329: /** Ensures that the given object will wait for n notifications. Callers must call o.wait() AFTER this is
330: * called. Use _notifyLock instead of o.notify() when using this method. Only one object (o) can use this
331: * synchronization protocol at a time, since it uses a field to store the number of pending notifications.
332: * @param n The number of times to be "notified" through _notifyLock
333: */
334: protected void _setPendingNotifies(int n)
335: throws InterruptedException {
336: synchronized (_notifierLock) {
337: _log.log("Waiting for " + n + " notifications ...");
338: _pendingNotifies = n;
339: }
340: }
341:
342: /** Notifies _notifierLock if the after the notify count has expired. See _setPendingNotifies. */
343: protected void _notifyLock() {
344: synchronized (_notifierLock) {
345: _pendingNotifies--;
346: _log.log("notified; count = " + _pendingNotifies);
347: if (_pendingNotifies == 0) {
348: _log.log("Notify count reached 0 -- notifying!");
349: _notifierLock.notifyAll(); // can accommodate multiple threads waiting on this event (NOT USED?)
350: }
351: if (_pendingNotifies < 0)
352: fail("Notified too many times");
353: }
354: }
355:
356: /** Cleanly starts the debugger with a newly compiled file saved in a temporary directory. Assumes that the
357: * file will compile successfully.
358: * @param fileName Name of the file to save in a temp directory
359: * @param classText String containing the code for the class to compile
360: * @return OpenDefinitionsDocument containing the compiled source file
361: */
362: protected OpenDefinitionsDocument _startupDebugger(String fileName,
363: String classText) throws Exception {
364: // Create a file in the temporary directory
365: File file = IOUtil.attemptCanonicalFile(new File(_tempDir,
366: fileName));
367: return _startupDebugger(file, classText);
368: }
369:
370: /** Cleanly starts the debugger with a newly compiled file saved in a temporary directory. Assumes that the
371: * file will compile successfully.
372: * @param file File to save the class in
373: * @param classText String containing the code for the class to compile
374: * @return OpenDefinitionsDocument containing the compiled source file
375: */
376: protected OpenDefinitionsDocument _startupDebugger(File file,
377: String classText) throws Exception {
378: // Compile the file
379: _log.log("Compiling " + file);
380: OpenDefinitionsDocument doc = doCompile(classText, file);
381: _log.log("Staring debugger in " + this );
382: // Start debugger
383: synchronized (_notifierLock) {
384: _setPendingNotifies(1); // startUp
385: _debugger.startUp();
386: while (_pendingNotifies > 0)
387: _notifierLock.wait();
388: }
389: _log.log("Finished starting debugger in " + this );
390: return doc;
391: }
392:
393: /** Cleanly shuts down the debugger, without having to wait for a suspended interaction to complete. */
394: protected void _shutdownWithoutSuspendedInteraction()
395: throws Exception {
396: _log.log("Shutting down debugger in " + this
397: + " without waiting");
398: _model.getBreakpointManager().clearRegions();
399:
400: // Shutdown the debugger
401: _log.log("Shutting down...");
402: synchronized (_notifierLock) {
403: _setPendingNotifies(1); // shutdown
404: _debugger.shutdown();
405: while (_pendingNotifies > 0)
406: _notifierLock.wait();
407: }
408: _log.log("Shut down.");
409: _log.log("Completed debugger shutdown for " + this );
410: }
411:
412: /** Cleanly shuts down the debugger, waiting for a suspended interaction to complete. */
413: protected void _shutdownAndWaitForInteractionEnded()
414: throws Exception {
415: _log.log("Shutting down debugger in " + this + " with waiting");
416: _model.getBreakpointManager().clearRegions();
417:
418: // Shutdown the debugger
419: _log.log("Shutting down...");
420: InterpretListener interpretListener = new InterpretListener() {
421: public void interpreterChanged(boolean inProgress) {
422: // Don't notify: happens in the same thread
423: interpreterChangedCount++;
424: }
425: };
426: _model.addListener(interpretListener);
427: synchronized (_notifierLock) {
428: _setPendingNotifies(2); // interactionEnded, shutdown
429: _debugger.shutdown();
430: while (_pendingNotifies > 0)
431: _notifierLock.wait();
432: }
433: interpretListener.assertInteractionEndCount(1);
434: interpretListener.assertInterpreterChangedCount(1); // fires (don't wait)
435: _model.removeListener(interpretListener);
436:
437: _log.log("Shut down.");
438: _log.log("Completed debugger shutdown for " + this );
439: }
440:
441: /** Sets the current debugger thread to the specified thread t.*/
442: protected void _doSetCurrentThread(final DebugThreadData t)
443: throws DebugException {
444: _debugger.setCurrentThread(t);
445: }
446:
447: /** Resumes the debugger asynchronously so as to avoid getting notified before we start waiting for notifies. */
448: protected void _asyncStep(final Debugger.StepType type) {
449: new Thread("asyncStep Thread") {
450: public void run() {
451: try {
452: _debugger.step(type);
453: } catch (DebugException dbe) {
454: dbe.printStackTrace();
455: listenerFail("Debugger couldn't be resumed!\n"
456: + dbe);
457: }
458: }
459: }.start();
460: }
461:
462: /**
463: * Resumes the debugger asynchronously so as to aovid
464: * getting notified before we start waiting for notifies
465: */
466: protected void _asyncResume() {
467: new Thread("asyncResume Thread") {
468: public void run() {
469: try {
470: _debugger.resume();
471: } catch (DebugException dbe) {
472: dbe.printStackTrace();
473: listenerFail("Debugger couldn't be resumed!\n"
474: + dbe);
475: }
476: }
477: }.start();
478: }
479:
480: /** Sets the current thread in a new thread to avoid being notified of events before we start waiting for them. */
481: protected void _asyncDoSetCurrentThread(final DebugThreadData th) {
482: new Thread("asyncDoSetCurrentThread Thread") {
483: public void run() {
484: try {
485: _doSetCurrentThread(th);
486: } catch (DebugException dbe) {
487: dbe.printStackTrace();
488: listenerFail("Couldn't set current thread in _asyncDoSetCurrentThread\n"
489: + dbe);
490: }
491: }
492: }.start();
493: }
494:
495: /** Listens to events from the debugger to ensure that they happen at the correct times. */
496: protected class DebugTestListener implements DebugListener {
497: protected volatile int debuggerStartedCount = 0;
498: protected volatile int debuggerShutdownCount = 0;
499: protected volatile int threadLocationUpdatedCount = 0;
500: protected volatile int breakpointReachedCount = 0;
501: protected volatile int regionAddedCount = 0;
502: protected volatile int regionChangedCount = 0;
503: protected volatile int regionRemovedCount = 0;
504: protected volatile int watchSetCount = 0;
505: protected volatile int watchRemovedCount = 0;
506: protected volatile int stepRequestedCount = 0;
507: protected volatile int currThreadSuspendedCount = 0;
508: protected volatile int currThreadResumedCount = 0;
509: protected volatile int threadStartedCount = 0;
510: protected volatile int currThreadDiedCount = 0;
511: protected volatile int currThreadSetCount = 0;
512: protected volatile int nonCurrThreadDiedCount = 0;
513:
514: public DebugTestListener() {
515: }
516:
517: public void assertDebuggerStartedCount(int i) {
518: assertEquals("number of times debuggerStarted fired", i,
519: debuggerStartedCount);
520: }
521:
522: public void assertDebuggerShutdownCount(int i) {
523: assertEquals("number of times debuggerShutdown fired", i,
524: debuggerShutdownCount);
525: }
526:
527: public void assertThreadLocationUpdatedCount(int i) {
528: assertEquals("number of times threadLocationUpdated fired",
529: i, threadLocationUpdatedCount);
530: }
531:
532: public void assertBreakpointReachedCount(int i) {
533: assertEquals("number of times breakpointReached fired", i,
534: breakpointReachedCount);
535: }
536:
537: public void assertRegionAddedCount(int i) {
538: assertEquals("number of times regionAdded fired", i,
539: regionAddedCount);
540: }
541:
542: public void assertRegionChangedCount(int i) {
543: assertEquals("number of times regionChanged fired", i,
544: regionChangedCount);
545: }
546:
547: public void assertRegionRemovedCount(int i) {
548: assertEquals("number of times regionRemoved fired", i,
549: regionRemovedCount);
550: }
551:
552: public void assertWatchSetCount(int i) {
553: assertEquals("number of times watchSet fired", i,
554: watchSetCount);
555: }
556:
557: public void assertWatchRemovedCount(int i) {
558: assertEquals("number of times watchRemoved fired", i,
559: watchRemovedCount);
560: }
561:
562: public void assertStepRequestedCount(int i) {
563: assertEquals("number of times stepRequested fired", i,
564: stepRequestedCount);
565: }
566:
567: public void assertStepFinishedCount(int i) {
568: assertEquals("number of times stepRequested fired", i,
569: stepRequestedCount);
570: }
571:
572: public void assertCurrThreadSuspendedCount(int i) {
573: assertEquals("number of times currThreadSuspended fired",
574: i, currThreadSuspendedCount);
575: }
576:
577: public void assertCurrThreadResumedCount(int i) {
578: assertEquals("number of times currThreadResumed fired", i,
579: currThreadResumedCount);
580: }
581:
582: public void assertCurrThreadSetCount(int i) {
583: assertEquals("number of times currThreadSet fired", i,
584: currThreadSetCount);
585: }
586:
587: public void assertThreadStartedCount(int i) {
588: assertEquals("number of times threadStarted fired", i,
589: threadStartedCount);
590: }
591:
592: public void assertCurrThreadDiedCount(int i) {
593: assertEquals("number of times currThreadDied fired", i,
594: currThreadDiedCount);
595: }
596:
597: public void assertNonCurrThreadDiedCount(int i) {
598: assertEquals("number of times nonCurrThreadDied fired", i,
599: nonCurrThreadDiedCount);
600: }
601:
602: public void debuggerStarted() {
603: fail("debuggerStarted fired unexpectedly");
604: }
605:
606: public void debuggerShutdown() {
607: fail("debuggerShutdown fired unexpectedly");
608: }
609:
610: public void threadLocationUpdated(OpenDefinitionsDocument doc,
611: int lineNumber, boolean shouldHighlight) {
612: fail("threadLocationUpdated fired unexpectedly");
613: }
614:
615: public void breakpointReached(Breakpoint bp) {
616: fail("breakpointReached fired unexpectedly");
617: }
618:
619: public void regionAdded(Breakpoint bp, int index) {
620: fail("regionAdded fired unexpectedly");
621: }
622:
623: public void regionChanged(Breakpoint bp, int index) {
624: fail("regionChanged fired unexpectedly");
625: }
626:
627: public void regionRemoved(Breakpoint bp) {
628: fail("regionRemoved fired unexpectedly");
629: }
630:
631: public void watchSet(DebugWatchData w) {
632: fail("watchSet fired unexpectedly");
633: }
634:
635: public void watchRemoved(DebugWatchData w) {
636: fail("watchRemoved fired unexpectedly");
637: }
638:
639: public void stepRequested() {
640: fail("stepRequested fired unexpectedly");
641: }
642:
643: public void currThreadSuspended() {
644: fail("currThreadSuspended fired unexpectedly");
645: }
646:
647: public void currThreadResumed() {
648: fail("currThreadResumed fired unexpectedly");
649: }
650:
651: public void currThreadSet(DebugThreadData dtd) {
652: fail("currThreadSet fired unexpectedly");
653: }
654:
655: /** This won't fail because threads could be starting at any time. We have to expect this to be fired. */
656: public void threadStarted() {
657: threadStartedCount++;
658: }
659:
660: public void currThreadDied() {
661: fail("currThreadDied fired unexpectedly");
662: }
663:
664: /** This won't fail because threads could be dying at any time. We have to expect this to be fired. */
665: public void nonCurrThreadDied() {
666: nonCurrThreadDiedCount++;
667: }
668: }
669:
670: /** DebugTestListener for all tests starting the debugger. */
671: protected class DebugStartAndStopListener extends DebugTestListener {
672:
673: public DebugStartAndStopListener() {
674: }
675:
676: public void debuggerStarted() {
677: // EventHandler's thread: test should wait
678: synchronized (_notifierLock) {
679: debuggerStartedCount++;
680: _log.log("debuggerStarted " + debuggerStartedCount);
681: _notifyLock();
682: }
683: }
684:
685: public void debuggerShutdown() {
686: // EventHandler's thread: test should wait
687: synchronized (_notifierLock) {
688: debuggerShutdownCount++;
689: _log.log("debuggerShutdown " + debuggerShutdownCount);
690: _notifyLock();
691: }
692: }
693: }
694:
695: /** DebugTestListener for all tests setting breakpoints. */
696: protected class BreakpointTestListener extends
697: DebugStartAndStopListener {
698:
699: public BreakpointTestListener() {
700: }
701:
702: public void breakpointReached(Breakpoint bp) {
703: // EventHandler's thread: test should wait
704: synchronized (_notifierLock) {
705: breakpointReachedCount++;
706: _log.log("breakpointReached " + breakpointReachedCount);
707: _notifyLock();
708: }
709: }
710:
711: public void regionAdded(Breakpoint bp, int index) {
712: // Manager's thread: test shouldn't wait
713: regionAddedCount++;
714: }
715:
716: public void regionRemoved(Breakpoint bp) {
717: // Manager's thread: test shouldn't wait
718: regionRemovedCount++;
719: _log.log("regionRemoved " + regionRemovedCount);
720: }
721:
722: public void currThreadSuspended() {
723: // EventHandler's thread: test should wait
724: synchronized (_notifierLock) {
725: currThreadSuspendedCount++;
726: _log.log("threadSuspended " + currThreadSuspendedCount);
727: _notifyLock();
728: }
729: }
730:
731: public void currThreadResumed() {
732: // Manager's thread: test shouldn't wait
733: currThreadResumedCount++;
734: _log.log("threadResumed " + currThreadResumedCount);
735: }
736:
737: public void currThreadSet(DebugThreadData dtd) {
738: // Manager's thread: test shouldn't wait
739: currThreadSetCount++;
740: _log.log("threadSet " + currThreadSetCount);
741: }
742:
743: public void currThreadDied() {
744: // EventHandler's thread: test should wait
745: synchronized (_notifierLock) {
746: currThreadDiedCount++;
747: _log.log("currThreadDied " + currThreadDiedCount);
748: _notifyLock();
749: }
750: }
751:
752: public void threadLocationUpdated(OpenDefinitionsDocument doc,
753: int lineNumber, boolean shouldHighlight) {
754: // EventHandler's thread: test should wait
755: synchronized (_notifierLock) {
756: threadLocationUpdatedCount++;
757: _log.log("threadUpdated " + threadLocationUpdatedCount);
758: _notifyLock();
759: }
760: }
761:
762: public void watchSet(DebugWatchData w) {
763: // Manager's thread: test shouldn't wait
764: watchSetCount++;
765: _log.log("watchSet " + watchSetCount);
766: }
767:
768: public void watchRemoved(DebugWatchData w) {
769: // Manager's thread: test shouldn't wait
770: watchRemovedCount++;
771: _log.log("watchRemoved " + watchRemovedCount);
772: }
773: }
774:
775: /** DebugTestListener for all tests using the stepper. */
776: protected class StepTestListener extends BreakpointTestListener {
777:
778: public StepTestListener() {
779: }
780:
781: public void stepRequested() {
782: // Manager's thread: test shouldn't wait
783: stepRequestedCount++;
784: _log.log("stepRequested " + stepRequestedCount);
785: }
786: }
787:
788: /** TestListener that listens for an interpretation to end, and then notifies anyone waiting on it.
789: * (Necessary to prevent tests from overlapping.) */
790: protected class InterpretListener extends TestListener {
791:
792: public InterpretListener() {
793: }
794:
795: public void interactionStarted() {
796: synchronized (_notifierLock) {
797: interactionStartCount++;
798: _log.log("interactionStarted " + interactionStartCount);
799: _notifyLock();
800: }
801: }
802:
803: public void interactionEnded() {
804: synchronized (_notifierLock) {
805: interactionEndCount++;
806: _log.log("interactionEnded " + interactionEndCount);
807: _notifyLock();
808: }
809: }
810:
811: public void interpreterChanged(boolean inProgress) {
812: synchronized (_notifierLock) {
813: interpreterChangedCount++;
814: _log.log("interpreterChanged "
815: + interpreterChangedCount);
816: _notifyLock();
817: }
818: }
819: }
820: }
|