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.jpda;
038:
039: import java.io.*;
040:
041: import edu.rice.cs.drjava.config.*;
042: import edu.rice.cs.drjava.model.*;
043: import edu.rice.cs.drjava.model.debug.*;
044:
045: import edu.rice.cs.util.swing.Utilities;
046:
047: /** Tests the JPDA-based debugger.
048: * @version $Id: DebugTest.java 4255 2007-08-28 19:17:37Z mgricken $
049: */
050: public final class DebugTest extends JPDADebugTestCase implements
051: OptionConstants {
052:
053: /** Tests startUp and shutdown, ensuring that all appropriate fields are initialized. Ensures multiple startups
054: * and shutdowns work, even after a reset, which changes the debug port.
055: */
056: public void testStartupAndShutdown() throws DebugException,
057: InterruptedException {
058: _log.log("----testStartupAndShutdown----");
059: DebugTestListener debugListener = new DebugStartAndStopListener();
060: _debugger.addListener(debugListener);
061:
062: // Start debugger
063: synchronized (_notifierLock) {
064: _debugger.startUp();
065: _setPendingNotifies(1); // startUp
066: while (_pendingNotifies > 0)
067: _notifierLock.wait();
068: }
069: debugListener.assertDebuggerStartedCount(1); //fires
070: debugListener.assertDebuggerShutdownCount(0);
071:
072: // Check fields and status
073: assertTrue("Debug Manager should be ready", _debugger.isReady());
074: assertNotNull(
075: "EventRequestManager should not be null after startUp",
076: _debugger.getEventRequestManager());
077: assertNotNull(
078: "PendingRequestManager should not be null after startUp",
079: _debugger.getPendingRequestManager());
080:
081: // Shutdown the debugger
082: synchronized (_notifierLock) {
083: _debugger.shutdown();
084: _setPendingNotifies(1); // shutdown
085: while (_pendingNotifies > 0)
086: _notifierLock.wait();
087: }
088: debugListener.assertDebuggerStartedCount(1);
089: debugListener.assertDebuggerShutdownCount(1); //fires
090:
091: // Start debugger again without resetting
092: synchronized (_notifierLock) {
093: _debugger.startUp();
094: _setPendingNotifies(1); // startUp
095: while (_pendingNotifies > 0)
096: _notifierLock.wait();
097: }
098: debugListener.assertDebuggerStartedCount(2); //fires
099: debugListener.assertDebuggerShutdownCount(1);
100:
101: // Define listener that will count notification events
102: InterpretListener resetListener = new InterpretListener() {
103: public void interactionStarted() {
104: // Don't notify: happens in the same thread
105: _log.log("interactionStarted called in resetListener");
106: interactionStartCount++;
107: }
108:
109: public void interactionEnded() {
110: // Don't notify: happens in the same thread
111: _log.log("interactionEnded called in resetListener");
112: interactionEndCount++;
113: }
114:
115: public void interpreterChanged(boolean inProgress) {
116: // Don't notify: happens in the same thread
117: _log.log("interpreterChanged called in resetListener");
118: interpreterChangedCount++;
119: }
120:
121: public void interpreterResetting() {
122: // Don't notify: happens in the same thread
123: _log
124: .log("interpreterResetting called in resetListener");
125: interpreterResettingCount++;
126: }
127:
128: public void interpreterReady(File wd) {
129: synchronized (_notifierLock) {
130: interpreterReadyCount++;
131: _log.log("interpreterReady "
132: + interpreterReadyCount);
133: _notifyLock();
134: }
135: }
136:
137: public void consoleReset() {
138: consoleResetCount++;
139: }
140: };
141:
142: // Install listener
143: _model.addListener(resetListener); // shutdown, interpreterReady
144: _setPendingNotifies(2);
145:
146: // Use the interpeter so that resetInteractions restarts the slave JVM
147: // interpret("2+2");
148:
149: _model.resetInteractions(FileOption.NULL_FILE);
150:
151: synchronized (_notifierLock) {
152: while (_pendingNotifies > 0)
153: _notifierLock.wait();
154: }
155:
156: _model.removeListener(resetListener);
157:
158: resetListener.assertInterpreterResettingCount(1); //fires (no waiting)
159: resetListener.assertInterpreterReadyCount(1); //fires
160: debugListener.assertDebuggerStartedCount(2);
161: debugListener.assertDebuggerShutdownCount(2); //fires
162:
163: // Start debugger again after reset
164: synchronized (_notifierLock) {
165: _debugger.startUp();
166: _setPendingNotifies(1); // startUp
167: while (_pendingNotifies > 0)
168: _notifierLock.wait();
169: }
170: debugListener.assertDebuggerStartedCount(3); //fires
171: debugListener.assertDebuggerShutdownCount(2);
172:
173: // Shutdown the debugger
174: synchronized (_notifierLock) {
175: _debugger.shutdown();
176: _setPendingNotifies(1); // shutdown
177: while (_pendingNotifies > 0)
178: _notifierLock.wait();
179: }
180: debugListener.assertDebuggerStartedCount(3);
181: debugListener.assertDebuggerShutdownCount(3); //fires
182:
183: _debugger.removeListener(debugListener);
184: }
185:
186: /**
187: * Test that when two threads are suspended setCurrentThread can be used
188: * to switch between them in the debugger
189: */
190: public synchronized void testMultiThreadedSetCurrentThread()
191: throws Exception {
192: _log.log("----testMultiThreadedSetCurrentThread----");
193: BreakpointTestListener debugListener = new BreakpointTestListener();
194: _debugger.addListener(debugListener);
195:
196: // Start up
197: OpenDefinitionsDocument doc = _startupDebugger("Monkey.java",
198: MONKEY_CLASS);
199:
200: // Set two breakpoints
201: int index = MONKEY_CLASS
202: .indexOf("System.out.println(\"I\'m a thread! Yeah!\");");
203: _debugger.toggleBreakpoint(doc, index, 11, true);
204: index = MONKEY_CLASS
205: .indexOf("System.out.println(\"James likes bananas!\");");
206: _debugger.toggleBreakpoint(doc, index, 17, true);
207:
208: // Run the main() method, hitting both breakpoints in different threads
209: synchronized (_notifierLock) {
210: interpretIgnoreResult("java Monkey");
211: _setPendingNotifies(6); // (suspended, updated, breakpointReached) * 2
212: while (_pendingNotifies > 0)
213: _notifierLock.wait();
214: }
215: DebugThreadData threadA = new JPDAThreadData(_debugger
216: .getCurrentThread());
217: DebugThreadData threadB = new JPDAThreadData(_debugger
218: .getThreadAt(1));
219: synchronized (_notifierLock) {
220: _asyncDoSetCurrentThread(threadB);
221: _setPendingNotifies(2); // updated, suspended
222: while (_pendingNotifies > 0)
223: _notifierLock.wait();
224: }
225:
226: DebugThreadData thread1 = new JPDAThreadData(_debugger
227: .getThreadAt(1));
228: DebugThreadData thread2 = new JPDAThreadData(_debugger
229: .getCurrentThread());
230:
231: // make sure threads have switched places
232: assertTrue(thread1.getUniqueID() == threadA.getUniqueID());
233: assertTrue(thread2.getUniqueID() == threadB.getUniqueID());
234:
235: // Shut down
236: _shutdownAndWaitForInteractionEnded();
237: _debugger.removeListener(debugListener);
238: }
239:
240: /**
241: * Tests that setCurrentThread works for multiple threads
242: *
243: * This test has been commented out because we do not support setting the
244: * current thread to be an unsuspended thread right now
245: *
246: public synchronized void testMultiThreadedSetCurrentThread() throws Exception {
247: _log.log("----testMultiThreadedSetCurrentThread----");
248: BreakpointTestListener debugListener = new BreakpointTestListener();
249: _debugger.addListener(debugListener);
250:
251: // Start up
252: OpenDefinitionsDocument doc = _startupDebugger("Suspender.java",
253: SUSPEND_CLASS);
254:
255: int index = SUSPEND_CLASS.indexOf("int a = 1;");
256: _debugger.toggleBreakpoint(doc,index,5,true);
257:
258: // Run the main() method, hitting breakpoints
259: synchronized(_notifierLock) {
260: interpretIgnoreResult("java Suspender");
261: _setPendingNotifies(3); // suspended, updated, breakpointReached
262: while (_pendingNotifies > 0) _notifierLock.wait();
263: }
264: final DebugThreadData thread = new DebugThreadData(_debugger.getCurrentThread());
265: synchronized(_notifierLock) {
266: // _debugger.setCurrentThread(...);
267: // must be executed in another thread because otherwise the notifies
268: // will be received before the _notifierLock is released
269: new Thread() {
270: public void run() {
271: try {
272: _debugger.resume();
273: _doSetCurrentThread(thread);
274: }
275: catch (DebugException excep) {
276: excep.printStackTrace();
277: fail("_doSetCurrentThread failed in testMultiThreadedSetCurrentThread");
278: }
279: }
280: }.start();
281: _setPendingNotifies(2); // suspended, updated
282: while (_pendingNotifies > 0) _notifierLock.wait();
283: }
284: // Ensure thread suspended
285: debugListener.assertCurrThreadSuspendedCount(2); //fires
286:
287: // Shut down
288: _shutdownWithoutSuspendedInteraction();
289: _debugger.removeListener(debugListener);
290: }*/
291:
292: /** Tests that breakpoints behave correctly for multiple threads. */
293: public synchronized void testMultiThreadedBreakpointsAndStep()
294: throws Exception {
295: _log.log("----testMultiThreadedBreakpointsAndStep----");
296: BreakpointTestListener debugListener = new BreakpointTestListener();
297: _debugger.addListener(debugListener);
298:
299: // Start up
300: OpenDefinitionsDocument doc = _startupDebugger("Monkey.java",
301: MONKEY_CLASS);
302:
303: // Set breakpoints
304: int index = MONKEY_CLASS
305: .indexOf("System.out.println(\"I\'m a thread! Yeah!\");");
306: _debugger.toggleBreakpoint(doc, index, 11, true);
307: index = MONKEY_CLASS
308: .indexOf("System.out.println(\"I just woke up. I\'m a big boy now.\");");
309: _debugger.toggleBreakpoint(doc, index, 16, true);
310:
311: Utilities.clearEventQueue();
312: debugListener.assertRegionAddedCount(2);
313:
314: // Run the main method, hitting breakpoints
315: synchronized (_notifierLock) {
316: interpretIgnoreResult("java Monkey");
317: _setPendingNotifies(6); // (suspended, updated, breakpointReached) x 2
318: while (_pendingNotifies > 0)
319: _notifierLock.wait();
320: }
321:
322: DebugThreadData thread = new JPDAThreadData(_debugger
323: .getCurrentThread());
324: // Resumes one thread, finishing it and switching to the next break point
325: synchronized (_notifierLock) {
326: _asyncResume();
327: _setPendingNotifies(2); // suspended, updated
328: // no longer get a currThreadDied since we immediately
329: // switch to the next thread
330: while (_pendingNotifies > 0)
331: _notifierLock.wait();
332: }
333:
334: DebugThreadData thread2 = new JPDAThreadData(_debugger
335: .getCurrentThread());
336: assertTrue(
337: "testMultiThreadedBreakPoint thread references should not be equal",
338: !thread.getName().equals(thread2.getName()));
339:
340: // Ensure breakpoint is hit
341: debugListener.assertBreakpointReachedCount(2); //fires
342: debugListener.assertThreadLocationUpdatedCount(3); //fires
343: debugListener.assertCurrThreadSuspendedCount(3); //fires
344: debugListener.assertCurrThreadResumedCount(1);
345: _debugger.removeListener(debugListener);
346:
347: _log.log("Testing stepping...");
348:
349: // Step
350: StepTestListener stepTestListener = new StepTestListener();
351: _debugger.addListener(stepTestListener);
352: synchronized (_notifierLock) {
353: _asyncStep(Debugger.StepType.STEP_INTO);
354: _setPendingNotifies(2); // suspended, updated
355: while (_pendingNotifies > 0)
356: _notifierLock.wait();
357: }
358: stepTestListener.assertStepRequestedCount(1);
359: _debugger.removeListener(stepTestListener);
360:
361: DebugThreadData thread3 = new JPDAThreadData(_debugger
362: .getCurrentThread());
363: assertEquals(
364: "testMultiThreadedBreakPoint thread references should be equal",
365: thread2.getName(), thread3.getName());
366:
367: // Resume until finished, waiting for interpret call to end
368: _debugger.addListener(debugListener);
369: InterpretListener interpretListener = new InterpretListener();
370: _model.addListener(interpretListener);
371: synchronized (_notifierLock) {
372: _asyncResume();
373: _setPendingNotifies(3); // interactionEnded, interpreterChanged, currThreadDied
374: // we get a currThreadDied here since it's the last thread
375: while (_pendingNotifies > 0)
376: _notifierLock.wait();
377: }
378: interpretListener.assertInteractionEndCount(1);
379: _model.removeListener(interpretListener);
380:
381: // Shut down
382: _shutdownWithoutSuspendedInteraction();
383: _debugger.removeListener(debugListener);
384: }
385:
386: /**
387: * Tests that breakpoints behave correctly.
388: */
389: public synchronized void testBreakpoints() throws Exception {
390: _log.log("----testBreakpoints----");
391: BreakpointTestListener debugListener = new BreakpointTestListener();
392: _debugger.addListener(debugListener);
393:
394: // Start up
395: OpenDefinitionsDocument doc = _startupDebugger(
396: "DrJavaDebugClass.java", DEBUG_CLASS);
397:
398: // Add breakpoint before class is loaded
399: _debugger.toggleBreakpoint(doc, DEBUG_CLASS.indexOf("bar();"),
400: 4, true);
401:
402: Utilities.clearEventQueue();
403: debugListener.assertRegionAddedCount(1);
404:
405: // Run the foo() method, hitting breakpoint
406: synchronized (_notifierLock) {
407: interpretIgnoreResult("new DrJavaDebugClass().foo()");
408: _setPendingNotifies(3); // suspended, updated, breakpointReached
409: while (_pendingNotifies > 0)
410: _notifierLock.wait();
411: }
412:
413: _log.log("----After breakpoint:\n" + getInteractionsText());
414:
415: // Ensure breakpoint is hit
416: debugListener.assertBreakpointReachedCount(1); //fires
417: debugListener.assertThreadLocationUpdatedCount(1); //fires
418: debugListener.assertCurrThreadSuspendedCount(1); //fires
419: debugListener.assertCurrThreadResumedCount(0);
420: debugListener.assertCurrThreadDiedCount(0);
421: assertInteractionsContains("Foo Line 1");
422: assertInteractionsDoesNotContain("Bar Line 1");
423:
424: _log.log("adding another breakpoint");
425:
426: // Set another breakpoint (after is class loaded)
427: _debugger
428: .toggleBreakpoint(doc, DEBUG_CLASS
429: .indexOf("System.out.println(\"Bar Line 2\")"),
430: 9, true);
431:
432: Utilities.clearEventQueue();
433: debugListener.assertRegionAddedCount(2);
434:
435: // Resume until next breakpoint
436: synchronized (_notifierLock) {
437: _log.log("resuming");
438: _asyncResume();
439: _setPendingNotifies(3); // suspended, updated, breakpointReached
440: while (_pendingNotifies > 0)
441: _notifierLock.wait();
442: }
443: _log.log("----After one resume:\n" + getInteractionsText());
444: debugListener.assertCurrThreadResumedCount(1); //fires (no waiting)
445: debugListener.assertBreakpointReachedCount(2); //fires
446: debugListener.assertThreadLocationUpdatedCount(2); //fires
447: debugListener.assertCurrThreadSuspendedCount(2); //fires
448: debugListener.assertCurrThreadDiedCount(0);
449: assertInteractionsContains("Bar Line 1");
450: assertInteractionsDoesNotContain("Bar Line 2");
451:
452: // Resume until finished, waiting for interpret call to end
453: InterpretListener interpretListener = new InterpretListener();
454: _model.addListener(interpretListener);
455: synchronized (_notifierLock) {
456: _log.log("-------- Resuming --------");
457: _asyncResume();
458: _setPendingNotifies(3); // interactionEnded, interpreterChanged, currThreadDied
459: // here, we get a currThreadDied since it's the last thread
460: while (_pendingNotifies > 0)
461: _notifierLock.wait();
462: }
463: interpretListener.assertInteractionEndCount(1);
464: _model.removeListener(interpretListener);
465:
466: _log.log("----After second resume:\n" + getInteractionsText());
467: debugListener.assertCurrThreadResumedCount(2); //fires (no waiting)
468: debugListener.assertBreakpointReachedCount(2);
469: debugListener.assertThreadLocationUpdatedCount(2);
470: debugListener.assertCurrThreadSuspendedCount(2);
471: assertInteractionsContains("Foo Line 3");
472:
473: // Shut down
474: _shutdownWithoutSuspendedInteraction();
475: _debugger.removeListener(debugListener);
476: }
477:
478: /**
479: * Tests that the debugger will stop at a breakpoint in one class
480: * when the invoking method resides in a class with the same
481: * prefix in its name. (bug #769764)
482: * (ie. Class DrJavaDebugTest2 has a method which calls something
483: * in class DrJavaDebugTest, which has a breakpoint.)
484: */
485: public synchronized void testBreakpointsWithSameNamePrefix()
486: throws Exception {
487: _log.log("----testBreakpointsWithSameNamePrefix----");
488: BreakpointTestListener debugListener = new BreakpointTestListener();
489: _debugger.addListener(debugListener);
490:
491: // Start up
492: OpenDefinitionsDocument doc = _startupDebugger(
493: "DrJavaDebugClass.java", DEBUG_CLASS);
494:
495: // Add breakpoint in DrJavaDebugClass before class is loaded
496: _debugger.toggleBreakpoint(doc, DEBUG_CLASS
497: .indexOf("Bar Line 1"), 8, true);
498:
499: Utilities.clearEventQueue();
500: debugListener.assertRegionAddedCount(1);
501:
502: // Run the baz() method, hitting breakpoint
503: synchronized (_notifierLock) {
504: interpretIgnoreResult("new DrJavaDebugClass2().baz()");
505: _setPendingNotifies(3); // suspended, updated, breakpointReached
506: while (_pendingNotifies > 0)
507: _notifierLock.wait();
508: }
509:
510: _log.log("----After breakpoint:\n" + getInteractionsText());
511:
512: // Ensure breakpoint is hit
513: debugListener.assertBreakpointReachedCount(1); //fires
514: debugListener.assertThreadLocationUpdatedCount(1); //fires
515: debugListener.assertCurrThreadSuspendedCount(1); //fires
516: debugListener.assertCurrThreadResumedCount(0);
517: debugListener.assertCurrThreadDiedCount(0);
518: assertInteractionsContains("Baz Line 1");
519: assertInteractionsDoesNotContain("Bar Line 1");
520:
521: // Resume until finished, waiting for interpret call to end
522: InterpretListener interpretListener = new InterpretListener();
523: _model.addListener(interpretListener);
524: synchronized (_notifierLock) {
525: _log.log("-------- Resuming --------");
526: _asyncResume();
527: _setPendingNotifies(3); // interactionEnded, interpreterChanged, currThreadDied
528: // here, we get a currThreadDied since it's the last thread
529: while (_pendingNotifies > 0)
530: _notifierLock.wait();
531: }
532: interpretListener.assertInteractionEndCount(1);
533: _model.removeListener(interpretListener);
534:
535: _log.log("----After second resume:\n" + getInteractionsText());
536: debugListener.assertCurrThreadResumedCount(1); //fires (no waiting)
537: debugListener.assertBreakpointReachedCount(1);
538: debugListener.assertThreadLocationUpdatedCount(1);
539: debugListener.assertCurrThreadSuspendedCount(1);
540: assertInteractionsContains("Bar Line 2");
541:
542: // Shut down
543: _shutdownWithoutSuspendedInteraction();
544: _debugger.removeListener(debugListener);
545: }
546:
547: /**
548: * Tests that breakpoints and steps behave correctly.
549: */
550: public void testStepInto() throws Exception {
551: _log.log("----testStepInto----");
552: StepTestListener debugListener = new StepTestListener();
553: _debugger.addListener(debugListener);
554:
555: // Start up
556: OpenDefinitionsDocument doc = _startupDebugger(
557: "DrJavaDebugClass.java", DEBUG_CLASS);
558:
559: // Add a breakpoint
560: _debugger.toggleBreakpoint(doc, DEBUG_CLASS.indexOf("bar();"),
561: 4, true);
562:
563: Utilities.clearEventQueue();
564: debugListener.assertRegionAddedCount(1);
565:
566: // Run the foo() method, hitting breakpoint
567: synchronized (_notifierLock) {
568: interpretIgnoreResult("new DrJavaDebugClass().foo()");
569: _setPendingNotifies(3); // suspended, updated, breakpointReached
570: while (_pendingNotifies > 0)
571: _notifierLock.wait();
572: }
573:
574: _log.log("----After breakpoint:\n" + getInteractionsText());
575:
576: // Ensure breakpoint is hit
577: debugListener.assertBreakpointReachedCount(1); //fires
578: debugListener.assertThreadLocationUpdatedCount(1); //fires
579: debugListener.assertCurrThreadSuspendedCount(1); //fires
580: debugListener.assertCurrThreadResumedCount(0);
581: debugListener.assertCurrThreadDiedCount(0);
582: assertInteractionsContains("Foo Line 1");
583: assertInteractionsDoesNotContain("Bar Line 1");
584:
585: // Step into bar() method
586: synchronized (_notifierLock) {
587: _asyncStep(Debugger.StepType.STEP_INTO);
588: _setPendingNotifies(2); // suspended, updated
589: while (_pendingNotifies > 0)
590: _notifierLock.wait();
591: }
592: debugListener.assertStepRequestedCount(1); // fires (don't wait)
593: debugListener.assertCurrThreadResumedCount(1); // fires (don't wait)
594: debugListener.assertThreadLocationUpdatedCount(2); // fires
595: debugListener.assertCurrThreadSuspendedCount(2); // fires
596: debugListener.assertBreakpointReachedCount(1);
597: debugListener.assertCurrThreadDiedCount(0);
598: assertInteractionsDoesNotContain("Bar Line 1");
599:
600: // Step to next line
601: synchronized (_notifierLock) {
602: _asyncStep(Debugger.StepType.STEP_OVER);
603: _setPendingNotifies(2); // suspended, updated
604: while (_pendingNotifies > 0)
605: _notifierLock.wait();
606: }
607:
608: _log.log("****" + getInteractionsText());
609: debugListener.assertStepRequestedCount(2); // fires (don't wait)
610: debugListener.assertCurrThreadResumedCount(2); // fires (don't wait)
611: debugListener.assertThreadLocationUpdatedCount(3); // fires
612: debugListener.assertCurrThreadDiedCount(0);
613: debugListener.assertCurrThreadSuspendedCount(3); // fires
614: debugListener.assertBreakpointReachedCount(1);
615: assertInteractionsContains("Bar Line 1");
616: assertInteractionsDoesNotContain("Bar Line 2");
617:
618: // Step to next line
619: synchronized (_notifierLock) {
620: _asyncStep(Debugger.StepType.STEP_OVER);
621: _setPendingNotifies(2); // suspended, updated
622: while (_pendingNotifies > 0)
623: _notifierLock.wait();
624: }
625: debugListener.assertStepRequestedCount(3); // fires (don't wait)
626: debugListener.assertCurrThreadResumedCount(3); // fires (don't wait)
627: debugListener.assertThreadLocationUpdatedCount(4); // fires
628: debugListener.assertCurrThreadDiedCount(0);
629: debugListener.assertCurrThreadSuspendedCount(4); // fires
630: debugListener.assertBreakpointReachedCount(1);
631: assertInteractionsContains("Bar Line 2");
632: assertInteractionsDoesNotContain("Foo Line 3");
633:
634: // Step twice to print last line in Foo
635: synchronized (_notifierLock) {
636: _asyncStep(Debugger.StepType.STEP_OVER);
637: _setPendingNotifies(2); // suspended, updated
638: while (_pendingNotifies > 0)
639: _notifierLock.wait();
640: }
641: synchronized (_notifierLock) {
642: _asyncStep(Debugger.StepType.STEP_OVER);
643: _setPendingNotifies(2); // suspended, updated
644: while (_pendingNotifies > 0)
645: _notifierLock.wait();
646: }
647: debugListener.assertStepRequestedCount(5); // fires (don't wait)
648: debugListener.assertCurrThreadResumedCount(5); // fires (don't wait)
649: debugListener.assertThreadLocationUpdatedCount(6); // fires
650: debugListener.assertCurrThreadDiedCount(0);
651: debugListener.assertCurrThreadSuspendedCount(6); //fires
652: debugListener.assertBreakpointReachedCount(1);
653: assertInteractionsContains("Foo Line 3");
654:
655: // Step again to finish, waiting for interpret call to end
656: InterpretListener interpretListener = new InterpretListener();
657: _model.addListener(interpretListener);
658: synchronized (_notifierLock) {
659: _asyncStep(Debugger.StepType.STEP_OVER);
660: _setPendingNotifies(3); // interactionEnded, interpreterChanged, currThreadDied
661: // here, we get a currThreadDied since it's the last thread
662: while (_pendingNotifies > 0)
663: _notifierLock.wait();
664: }
665: interpretListener.assertInteractionEndCount(1);
666: _model.removeListener(interpretListener);
667:
668: debugListener.assertStepRequestedCount(6); // fires (don't wait)
669: debugListener.assertCurrThreadDiedCount(1);
670:
671: // Shut down
672: _shutdownWithoutSuspendedInteraction();
673: _debugger.removeListener(debugListener);
674: }
675:
676: /** Tests that stepping out of a method behaves correctly. */
677: public synchronized void testStepOut() throws Exception {
678: _log.log("----testStepOut----");
679: StepTestListener debugListener = new StepTestListener();
680: _debugger.addListener(debugListener);
681:
682: // Start up
683: OpenDefinitionsDocument doc = _startupDebugger(
684: "DrJavaDebugClass.java", DEBUG_CLASS);
685:
686: // Set breakpoint
687: _debugger.toggleBreakpoint(doc, DEBUG_CLASS.indexOf("bar();"),
688: 4, true);
689:
690: Utilities.clearEventQueue();
691: debugListener.assertRegionAddedCount(1);
692:
693: // Run the foo() method, hitting breakpoint
694: synchronized (_notifierLock) {
695: interpretIgnoreResult("new DrJavaDebugClass().foo()");
696: _setPendingNotifies(3); // suspended, updated, breakpointReached
697: while (_pendingNotifies > 0)
698: _notifierLock.wait();
699: }
700:
701: _log.log("----After breakpoint:\n" + getInteractionsText());
702:
703: // Ensure breakpoint is hit
704: debugListener.assertBreakpointReachedCount(1); // fires
705: debugListener.assertThreadLocationUpdatedCount(1); // fires
706: debugListener.assertCurrThreadSuspendedCount(1); // fires
707: debugListener.assertCurrThreadResumedCount(0);
708: debugListener.assertCurrThreadDiedCount(0);
709: assertInteractionsContains("Foo Line 1");
710: assertInteractionsDoesNotContain("Bar Line 1");
711:
712: // Step into bar() method
713: synchronized (_notifierLock) {
714: _asyncStep(Debugger.StepType.STEP_INTO);
715: _setPendingNotifies(2); // suspended, updated
716: while (_pendingNotifies > 0)
717: _notifierLock.wait();
718: }
719: debugListener.assertStepRequestedCount(1); // fires (don't wait)
720: debugListener.assertCurrThreadResumedCount(1); // fires (don't wait)
721: debugListener.assertThreadLocationUpdatedCount(2); //fires
722: debugListener.assertCurrThreadSuspendedCount(2); //fires
723: debugListener.assertBreakpointReachedCount(1);
724: debugListener.assertCurrThreadDiedCount(0);
725: assertInteractionsDoesNotContain("Bar Line 1");
726:
727: // Step out of method
728: synchronized (_notifierLock) {
729: _asyncStep(Debugger.StepType.STEP_OUT);
730: _setPendingNotifies(2); // suspended, updated
731: while (_pendingNotifies > 0)
732: _notifierLock.wait();
733: }
734:
735: _log.log("****" + getInteractionsText());
736: debugListener.assertStepRequestedCount(2); // fires (don't wait)
737: debugListener.assertCurrThreadResumedCount(2); // fires (don't wait)
738: debugListener.assertThreadLocationUpdatedCount(3); // fires
739: debugListener.assertCurrThreadDiedCount(0);
740: debugListener.assertCurrThreadSuspendedCount(3); //fires
741: debugListener.assertBreakpointReachedCount(1);
742: assertInteractionsContains("Bar Line 2");
743: assertInteractionsDoesNotContain("Foo Line 3");
744:
745: // Shut down
746: _shutdownAndWaitForInteractionEnded();
747: _debugger.removeListener(debugListener);
748: }
749:
750: /**
751: * Tests that stepping works in a public class with a package
752: */
753: public synchronized void testStepOverWithPackage() throws Exception {
754: _log.log("----testStepOverWithPackage----");
755: StepTestListener debugListener = new StepTestListener();
756: _debugger.addListener(debugListener);
757:
758: // Create the file in an "a" sub-directory
759: File aDir = new File(_tempDir, "a");
760: aDir.mkdir();
761: File file = new File(aDir, "DrJavaDebugClassWithPackage.java");
762:
763: // Start up
764: OpenDefinitionsDocument doc = _startupDebugger(file,
765: DEBUG_CLASS_WITH_PACKAGE);
766:
767: // Add a breakpoint
768: _debugger.toggleBreakpoint(doc, DEBUG_CLASS_WITH_PACKAGE
769: .indexOf("foo line 1"), 4, true);
770:
771: Utilities.clearEventQueue();
772: debugListener.assertRegionAddedCount(1);
773:
774: // Run the foo() method, hitting breakpoint
775: synchronized (_notifierLock) {
776: interpretIgnoreResult("new a.DrJavaDebugClassWithPackage().foo()");
777: _setPendingNotifies(3); // suspended, updated, breakpointReached
778: while (_pendingNotifies > 0)
779: _notifierLock.wait();
780: }
781:
782: _log.log("----After breakpoint:\n" + getInteractionsText());
783:
784: // Ensure breakpoint is hit
785: debugListener.assertBreakpointReachedCount(1); //fires
786: debugListener.assertThreadLocationUpdatedCount(1); //fires
787: debugListener.assertCurrThreadSuspendedCount(1); //fires
788: debugListener.assertCurrThreadResumedCount(0);
789: debugListener.assertCurrThreadDiedCount(0);
790: assertInteractionsDoesNotContain("foo line 1");
791:
792: // Step over once
793: synchronized (_notifierLock) {
794: _asyncStep(Debugger.StepType.STEP_OVER);
795: _setPendingNotifies(2); // suspended, updated
796: while (_pendingNotifies > 0)
797: _notifierLock.wait();
798: }
799: debugListener.assertStepRequestedCount(1); // fires (don't wait)
800: debugListener.assertCurrThreadResumedCount(1); // fires (don't wait)
801: debugListener.assertThreadLocationUpdatedCount(2); // fires
802: debugListener.assertCurrThreadSuspendedCount(2); // fires
803: debugListener.assertBreakpointReachedCount(1);
804: debugListener.assertCurrThreadDiedCount(0);
805: assertInteractionsContains("foo line 1");
806: assertInteractionsDoesNotContain("foo line 2");
807:
808: // Step over again
809: synchronized (_notifierLock) {
810: _asyncStep(Debugger.StepType.STEP_OVER);
811: _setPendingNotifies(2); // suspended, updated
812: while (_pendingNotifies > 0)
813: _notifierLock.wait();
814: }
815:
816: _log.log("****" + getInteractionsText());
817: debugListener.assertStepRequestedCount(2); // fires (don't wait)
818: debugListener.assertCurrThreadResumedCount(2); // fires (don't wait)
819: debugListener.assertThreadLocationUpdatedCount(3); // fires
820: debugListener.assertCurrThreadDiedCount(0);
821: debugListener.assertCurrThreadSuspendedCount(3); // fires
822: debugListener.assertBreakpointReachedCount(1);
823: assertInteractionsContains("foo line 2");
824:
825: // Resume until finished, waiting for interpret call to finish
826: InterpretListener interpretListener = new InterpretListener();
827: _model.addListener(interpretListener);
828: synchronized (_notifierLock) {
829: _asyncResume();
830: _setPendingNotifies(3); // interactionEnded, interpreterChanged, currThreadDied
831: // here, we get a currThreadDied since it's the last thread
832: while (_pendingNotifies > 0)
833: _notifierLock.wait();
834: }
835: interpretListener.assertInteractionEndCount(1);
836: _model.removeListener(interpretListener);
837:
838: _log.log("----After resume:\n" + getInteractionsText());
839: debugListener.assertCurrThreadResumedCount(3); //fires (no waiting)
840: debugListener.assertBreakpointReachedCount(1);
841: debugListener.assertThreadLocationUpdatedCount(3);
842: debugListener.assertCurrThreadSuspendedCount(3);
843:
844: // Shut down
845: _shutdownWithoutSuspendedInteraction();
846: _debugger.removeListener(debugListener);
847: }
848:
849: /**
850: * Tests the utility function to get a relative directory for a package.
851: */
852: public void testGetPackageDir() {
853: String class1 = "edu.rice.cs.drjava.model.MyTest";
854: String class2 = "MyTest";
855: String sep = System.getProperty("file.separator");
856:
857: assertEquals("package dir with package", "edu" + sep + "rice"
858: + sep + "cs" + sep + "drjava" + sep + "model" + sep,
859: _debugger.getPackageDir(class1));
860: assertEquals("package dir without package", "", _debugger
861: .getPackageDir(class2));
862: }
863: }
|