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.repl;
038:
039: import edu.rice.cs.drjava.model.debug.*;
040: import edu.rice.cs.drjava.model.*;
041: import edu.rice.cs.util.StringOps;
042: import edu.rice.cs.util.text.EditDocumentException;
043: import edu.rice.cs.util.swing.Utilities;
044:
045: import java.util.LinkedList;
046: import java.io.*;
047: import javax.swing.text.*;
048:
049: import koala.dynamicjava.util.*;
050: import koala.dynamicjava.tree.*;
051: import koala.dynamicjava.interpreter.context.*;
052:
053: /** Class to test JavaDebugInterpreters by ensuring that appropriate events are generated on each assignment.
054: *
055: * NOTE: The tests at the bottom are disabled for now, since nothing needs to be done on an assignment. (We
056: * just copy back when the thread is resumed.)
057: *
058: * @version $Id: JavaDebugInterpreterTest.java 4255 2007-08-28 19:17:37Z mgricken $
059: */
060: public final class JavaDebugInterpreterTest extends DebugTestCase {
061: private static final String _newLine = "\n"; // was StringOps.EOL;
062: private JavaDebugInterpreter _debugInterpreter;
063:
064: // private String _assignedInterpreterName;
065:
066: protected static final String MONKEY_STUFF =
067: /*1*/"class MonkeyStuff {\n"
068: +
069: /*2*/" int foo = 6;\n"
070: +
071: /*3*/" class MonkeyInner {\n"
072: +
073: /*4*/" int innerFoo = 8;\n"
074: +
075: /*5*/" public class MonkeyTwoDeep {\n"
076: +
077: /*6*/" int twoDeepFoo = 13;\n"
078: +
079: /*7*/" class MonkeyThreeDeep {\n"
080: +
081: /*8*/" public int threeDeepFoo = 18;\n"
082: +
083: /*9*/" public void threeDeepMethod() {\n"
084: +
085: /*10*/" int blah;\n"
086: +
087: /*11*/" System.out.println(MonkeyStuff.MonkeyInner.MonkeyTwoDeep.MonkeyThreeDeep.this .threeDeepFoo);\n"
088: +
089: /*12*/" }\n"
090: +
091: /*13*/" }\n"
092: +
093: /*14*/" int getNegativeTwo() { return -2; }\n"
094: +
095: /*15*/" }\n"
096: +
097: /*16*/" }\n"
098: +
099: /*17*/"\n"
100: +
101: /*18*/" public static void main(String[] args) {\n"
102: +
103: /*19*/" new MonkeyStuff().new MonkeyInner().new MonkeyTwoDeep().new MonkeyThreeDeep().threeDeepMethod();\n"
104: +
105: /*20*/" }\n" +
106: /*21*/"}";
107:
108: protected static final String MONKEY_STATIC_STUFF =
109: /*1*/"package monkey;\n"
110: +
111: /*2*/"public class MonkeyStaticStuff {\n"
112: +
113: /*3*/" static int foo = 6;\n"
114: +
115: /*4*/" static class MonkeyInner {\n"
116: +
117: /*5*/" static int innerFoo = 8;\n"
118: +
119: /*6*/" static public class MonkeyTwoDeep {\n"
120: +
121: /*7*/" static int twoDeepFoo = 13;\n"
122: +
123: /*8*/" public static class MonkeyThreeDeep {\n"
124: +
125: /*9*/" public static int threeDeepFoo = 18;\n"
126: +
127: /*10*/" public static void threeDeepMethod() {\n"
128: +
129: /*11*/" System.out.println(MonkeyStaticStuff.MonkeyInner.MonkeyTwoDeep.MonkeyThreeDeep.threeDeepFoo);\n"
130: +
131: /*12*/" System.out.println(MonkeyTwoDeep.twoDeepFoo);\n"
132: +
133: /*13*/" System.out.println(twoDeepFoo);\n" +
134: /*14*/" }\n" +
135: /*15*/" }\n" +
136: /*16*/" static int getNegativeTwo() { return -2; }\n"
137: +
138: /*17*/" }\n" +
139: /*18*/" }\n" +
140: /*19*/"}";
141:
142: protected static final String MONKEY_WITH_INNER_CLASS =
143: /* 1 */"class Monkey {\n"
144: +
145: /* 2 */" static int foo = 6; \n"
146: +
147: /* 3 */" class MonkeyInner { \n"
148: +
149: /* 4 */" int innerFoo = 8;\n"
150: +
151: /* 5 */" class MonkeyInnerInner { \n"
152: +
153: /* 6 */" int innerInnerFoo = 10;\n"
154: +
155: /* 7 */" public void innerMethod() { \n"
156: +
157: /* 8 */" int innerMethodFoo;\n"
158: +
159: /* 9 */" String nullString = null;\n"
160: +
161: /* 10 */" innerMethodFoo = 12;\n"
162: +
163: /* 11 */" foo++;\n"
164: +
165: /* 12 */" innerFoo++;\n"
166: +
167: /* 13 */" innerInnerFoo++;\n"
168: +
169: /* 14 */" innerMethodFoo++;\n"
170: +
171: /* 15 */" staticMethod();\n"
172: +
173: /* 16 */" System.out.println(\"innerMethodFoo: \" + innerMethodFoo);\n"
174: +
175: /* 17 */" }\n"
176: +
177: /* 18 */" }\n"
178: +
179: /* 19 */" }\n"
180: +
181: /* 20 */" public void bar() {\n"
182: +
183: /* 21 */" final MonkeyInner.MonkeyInnerInner mi = \n"
184: +
185: /* 22 */" new MonkeyInner().new MonkeyInnerInner();\n"
186: +
187: /* 23 */" mi.innerMethod();\n"
188: +
189: /* 24 */" final int localVar = 99;\n"
190: +
191: /* 25 */" new Thread() {\n"
192: +
193: /* 26 */" public void run() {\n"
194: +
195: /* 27 */" final int localVar = mi.innerInnerFoo;\n"
196: +
197: /* 28 */" new Thread() {\n"
198: +
199: /* 29 */" public void run() {\n"
200: +
201: /* 30 */" new Thread() {\n"
202: +
203: /* 31 */" public void run() {\n"
204: +
205: /* 32 */" System.out.println(\"localVar = \" + localVar);\n"
206: +
207: /* 33 */" }\n" +
208: /* 34 */" }.run();\n" +
209: /* 35 */" }\n" +
210: /* 36 */" }.run();\n" +
211: /* 37 */" }\n" +
212: /* 38 */" }.run();\n" +
213: /* 39 */" }\n" +
214: /* 40 */" public static void staticMethod() {\n" +
215: /* 41 */" int z = 3;\n" +
216: /* 42 */" }\n" +
217: /* 43 */"}\n";
218:
219: public void setUp() throws Exception {
220: super .setUp();
221: // Creating a JavaDebugInterpreter with a custom notifyInterpreterAssignment() method
222: _debugInterpreter = new JavaDebugInterpreter("test", "") {
223: public EvaluationVisitorExtension makeEvaluationVisitor(
224: Context context) {
225: return new DebugEvaluationVisitor(context, _name);
226: // return new DebugEvaluationVisitor(context, _name) {
227: // protected void _notifyAssigned(Expression e) {
228: // notifyInterpreterAssignment(_name);
229: // }
230: // };
231: }
232: };
233: // _assignedInterpreterName = "";
234: }
235:
236: public void notifyInterpreterAssignment(String name) {
237: // _assignedInterpreterName = name;
238: }
239:
240: public void testVerifyClassName() {
241: _debugInterpreter
242: .setClassName("bar.baz.Foo$FooInner$FooInnerInner");
243: assertEquals("verify failed", 0, _debugInterpreter
244: .verifyClassName("bar.baz.Foo.FooInner.FooInnerInner"));
245: assertEquals("verify failed", 1, _debugInterpreter
246: .verifyClassName("bar.baz.Foo.FooInner"));
247: assertEquals("verify failed", 2, _debugInterpreter
248: .verifyClassName("bar.baz.Foo"));
249: assertEquals("verify failed", -1, _debugInterpreter
250: .verifyClassName("bar.baz"));
251: assertEquals("verify failed", 0, _debugInterpreter
252: .verifyClassName("Foo.FooInner.FooInnerInner"));
253: assertEquals("verify failed", 2, _debugInterpreter
254: .verifyClassName("Foo"));
255: assertEquals("verify failed", 1, _debugInterpreter
256: .verifyClassName("FooInner"));
257: assertEquals("verify failed", 0, _debugInterpreter
258: .verifyClassName("FooInnerInner"));
259: assertEquals("verify failed", 1, _debugInterpreter
260: .verifyClassName("Foo.FooInner"));
261: assertEquals("verify failed", 0, _debugInterpreter
262: .verifyClassName("FooInner.FooInnerInner"));
263: assertEquals("verify failed", -1, _debugInterpreter
264: .verifyClassName("FooInner.FooInnerInner.Foo"));
265: assertEquals("verify failed", -1, _debugInterpreter
266: .verifyClassName("FooInner.FooInnerInner.foo"));
267: assertEquals("verify failed", -1, _debugInterpreter
268: .verifyClassName("o.FooInner"));
269: _debugInterpreter.setClassName("Foo$FooInner$FooInnerInner");
270: assertEquals("verify failed", 0, _debugInterpreter
271: .verifyClassName("Foo.FooInner.FooInnerInner"));
272: assertEquals("verify failed", 2, _debugInterpreter
273: .verifyClassName("Foo"));
274: assertEquals("verify failed", 1, _debugInterpreter
275: .verifyClassName("FooInner"));
276: assertEquals("verify failed", 0, _debugInterpreter
277: .verifyClassName("FooInnerInner"));
278: assertEquals("verify failed", 1, _debugInterpreter
279: .verifyClassName("Foo.FooInner"));
280: assertEquals("verify failed", 0, _debugInterpreter
281: .verifyClassName("FooInner.FooInnerInner"));
282: assertEquals("verify failed", -1, _debugInterpreter
283: .verifyClassName("FooInner.FooInnerInner.Foo"));
284: assertEquals("verify failed", -1, _debugInterpreter
285: .verifyClassName("FooInner.FooInnerInner.foo"));
286: assertEquals("verify failed", -1, _debugInterpreter
287: .verifyClassName("o.FooInner"));
288: }
289:
290: private void assertEqualsNodes(String message, Node expected,
291: Node actual) {
292: ByteArrayOutputStream baos = new ByteArrayOutputStream();
293: DisplayVisitor dve = new DisplayVisitor(baos);
294: expected.acceptVisitor(dve);
295: String s1 = baos.toString();
296: baos.reset();
297: actual.acceptVisitor(dve);
298: String s2 = baos.toString();
299: //System.out.println("s1 = " + s1 + "\ns2 = " + s2);
300: assertEquals(message, s1, s2);
301: }
302:
303: /** Tests that a this expression with no classname will be correctly converted to a QualifiedName. */
304: public void testConvertToName() {
305: ThisExpression this Exp = _debugInterpreter
306: .buildUnqualifiedThis();
307: Node n = _debugInterpreter.visitThis(this Exp);
308: LinkedList<IdentifierToken> this List = new LinkedList<IdentifierToken>(); // Add parameterization <Identifier>.
309: this List.add(new Identifier("this"));
310: QualifiedName expected = new QualifiedName(this List);
311: assertEqualsNodes(
312: "convertThisToName did not return the correct QualifiedName",
313: expected, n);
314: }
315:
316: /** Tests that a this expression with a classname will be correctly converted to an ObjectFieldAccess. */
317: public void testConvertToObjectFieldAccess() {
318: _debugInterpreter
319: .setClassName("bar.baz.Foo$FooInner$FooInnerInner");
320: LinkedList<IdentifierToken> ids = new LinkedList<IdentifierToken>(); // Add parameterization <Identifier>.
321: ids.add(new Identifier("Foo"));
322: ThisExpression this Exp = new ThisExpression(ids, "", 0, 0, 0, 0);
323: Node n = _debugInterpreter.visitThis(this Exp);
324: Node expected = new ObjectFieldAccess(new ObjectFieldAccess(
325: _debugInterpreter._convertThisToName(_debugInterpreter
326: .buildUnqualifiedThis()), "this$1"), "this$0");
327:
328: assertEqualsNodes(
329: "convertThisToObjectFieldAccess did not return the correct ObjectFieldAccess",
330: expected, n);
331: }
332:
333: /** Tests that the user can access fields of outer classes in the debug interpreter. */
334: public void testAccessFieldsAndMethodsOfOuterClasses()
335: throws DebugException, BadLocationException,
336: EditDocumentException, IOException, InterruptedException {
337: File file = new File(_tempDir, "MonkeyStuff.java");
338: OpenDefinitionsDocument doc = doCompile(MONKEY_STUFF, file);
339: BreakpointTestListener debugListener = new BreakpointTestListener();
340: _debugger.addListener(debugListener);
341: // Start debugger
342: synchronized (_notifierLock) {
343: _debugger.startUp();
344: _setPendingNotifies(1); // startUp
345: while (_pendingNotifies > 0)
346: _notifierLock.wait();
347: }
348:
349: // Set one breakpoint
350: int index = MONKEY_STUFF.indexOf("System.out.println");
351: _debugger.toggleBreakpoint(doc, index, 11, true);
352:
353: // Run the main() method, hitting the breakpoint
354: synchronized (_notifierLock) {
355: interpretIgnoreResult("java MonkeyStuff");
356: _setPendingNotifies(3); // suspended, updated, breakpointReached
357: while (_pendingNotifies > 0)
358: _notifierLock.wait();
359: }
360:
361: // Calling interpret instead of interpretIgnoreResult because we want to wait until the interaction has ended.
362:
363: // Test that IdentityVisitor really does visit all nodes and their subnodes
364: // by giving it a statement consisting of lots of different syntax components.
365: interpret("try {\n"
366: + " for (int i = MonkeyStuff.this.foo; i < 7; i++) {\n"
367: + " do{System.out.println(MonkeyInner.this.innerFoo);}\n"
368: + " while(MonkeyStuff.MonkeyInner.this.innerFoo == MonkeyThreeDeep.this.threeDeepFoo);\n"
369: + " switch(MonkeyStuff.MonkeyInner.MonkeyTwoDeep.this.twoDeepFoo) {\n"
370: + " case 13: if (this.threeDeepFoo == 5) {\n"
371: + " System.out.println(MonkeyThreeDeep.this.threeDeepFoo);\n"
372: + " }\n"
373: + " else {\n"
374: + " MonkeyThreeDeep.this.threeDeepFoo = MonkeyThreeDeep.this.threeDeepFoo + MonkeyStuff.this.foo;\n"
375: + " }\n"
376: + " }\n"
377: + " }\n"
378: + "}\n"
379: + "catch(Exception e) { System.out.println(MonkeyThreeDeep.this.threeDeepFoo);}\n"
380: + "finally {System.out.println(MonkeyInner.MonkeyTwoDeep.this.twoDeepFoo);}");
381: assertInteractionsDoesNotMatch(".*^18$.*");
382: assertInteractionsDoesNotMatch(".*^6$.*");
383: assertInteractionsMatches(".*^8" + StringOps.EOL + "13$.*"); // EOL by System.out.println is platform-dependent
384:
385: // Tests that the debugger has the correct notion of
386: interpret("foo");
387:
388: // System.err.println(getInteractionsText());
389:
390: assertInteractionsMatches(".*^6$.*");
391:
392: interpret("foo = 123");
393: assertEquals("foo should have been modified", "123",
394: interpret("MonkeyStuff.this.foo"));
395: interpret("int foo = 999;");
396: assertEquals("foo should refer to defined foo", "999",
397: interpret("foo"));
398: assertEquals(
399: "declaring foo should not change MonkeyStuff.this.foo",
400: "123", interpret("MonkeyStuff.this.foo"));
401:
402: assertEquals("call method of outer class #1", "-2",
403: interpret("getNegativeTwo()"));
404: assertEquals("call method of outer class #2", "-2",
405: interpret("MonkeyTwoDeep.this.getNegativeTwo()"));
406: assertEquals(
407: "call method of outer class #3",
408: "-2",
409: interpret("MonkeyInner.MonkeyTwoDeep.this.getNegativeTwo()"));
410: assertEquals(
411: "call method of outer class #4",
412: "-2",
413: interpret("MonkeyStuff.MonkeyInner.MonkeyTwoDeep.this.getNegativeTwo()"));
414:
415: // Close doc and make sure breakpoints are removed
416: _model.closeFile(doc);
417:
418: Utilities.clearEventQueue();
419: debugListener.assertRegionRemovedCount(1); //fires once
420:
421: // Shutdown the debugger
422: _log.log("Shutting down...");
423: synchronized (_notifierLock) {
424: _debugger.shutdown();
425: _setPendingNotifies(1); // shutdown
426: while (_pendingNotifies > 0)
427: _notifierLock.wait();
428: }
429:
430: debugListener.assertDebuggerShutdownCount(1); //fires
431: _log.log("Shut down.");
432: _debugger.removeListener(debugListener);
433: }
434:
435: /** Tests that the user can access static fields of outer classes in the debug interpreter. */
436: public void testAccessStaticFieldsAndMethodsOfOuterClasses()
437: throws DebugException, BadLocationException,
438: EditDocumentException, IOException, InterruptedException {
439: File dir = new File(_tempDir, "monkey");
440: dir.mkdir();
441: File file = new File(dir, "MonkeyStaticStuff.java");
442: OpenDefinitionsDocument doc = doCompile(MONKEY_STATIC_STUFF,
443: file);
444: BreakpointTestListener debugListener = new BreakpointTestListener();
445: _debugger.addListener(debugListener);
446: // Start debugger
447: synchronized (_notifierLock) {
448: _debugger.startUp();
449: _setPendingNotifies(1); // startUp
450: while (_pendingNotifies > 0)
451: _notifierLock.wait();
452: }
453:
454: // Set one breakpoint
455: int index = MONKEY_STATIC_STUFF.indexOf("System.out.println");
456: _debugger.toggleBreakpoint(doc, index, 11, true);
457:
458: // Run the main() method, hitting both breakpoints in different threads
459: synchronized (_notifierLock) {
460: //interpret("package monkey;");
461: interpretIgnoreResult("monkey.MonkeyStaticStuff.MonkeyInner.MonkeyTwoDeep.MonkeyThreeDeep.threeDeepMethod();");
462: _setPendingNotifies(3); // suspended, updated, breakpointReached
463: while (_pendingNotifies > 0)
464: _notifierLock.wait();
465: }
466:
467: assertEquals("should find field of static outer class", "13",
468: interpret("twoDeepFoo"));
469: assertEquals("should find field of static outer class", "13",
470: interpret("MonkeyInner.MonkeyTwoDeep.twoDeepFoo"));
471:
472: interpret("twoDeepFoo = 100;");
473: assertEquals(
474: "should have assigned field of static outer class",
475: "100", interpret("twoDeepFoo"));
476: assertEquals(
477: "should have assigned the field of static outer class",
478: "100",
479: interpret("MonkeyStaticStuff.MonkeyInner.MonkeyTwoDeep.twoDeepFoo"));
480: assertEquals(
481: "should have assigned the field of static outer class",
482: "100",
483: interpret("monkey.MonkeyStaticStuff.MonkeyInner.MonkeyTwoDeep.twoDeepFoo"));
484:
485: interpret("int twoDeepFoo = -10;");
486: assertEquals(
487: "Should have successfully shadowed field of static outer class",
488: "-10", interpret("twoDeepFoo"));
489:
490: assertEquals(
491: "should have assigned the field of static outer class",
492: "100", interpret("MonkeyTwoDeep.twoDeepFoo"));
493:
494: assertEquals(
495: "should have assigned the field of static outer class",
496: "100",
497: interpret("MonkeyStaticStuff.MonkeyInner.MonkeyTwoDeep.twoDeepFoo"));
498:
499: assertEquals(
500: "Should be able to access a static field of a non-static outer class",
501: "6", interpret("foo"));
502: assertEquals(
503: "Should be able to access a static field of a non-static outer class",
504: "6", interpret("MonkeyStaticStuff.foo"));
505:
506: interpret("foo = 987;");
507: assertEquals(
508: "Should have changed the value of a static field of a non-static outer class",
509: "987", interpret("foo"));
510:
511: assertEquals(
512: "Should have changed the value of a static field of a non-static outer class",
513: "987", interpret("MonkeyStaticStuff.foo"));
514:
515: interpret("int foo = 56;");
516: assertEquals("Should have defined a new variable", "56",
517: interpret("foo"));
518: assertEquals(
519: "Should have shadowed the value of a static field of a non-static outer class",
520: "987", interpret("MonkeyStaticStuff.foo"));
521:
522: assertEquals("should be able to call method of outer class",
523: "-2", interpret("getNegativeTwo()"));
524: assertEquals("should be able to call method of outer class",
525: "-2", interpret("MonkeyTwoDeep.getNegativeTwo()"));
526: assertEquals("should be able to call method of outer class",
527: "-2",
528: interpret("MonkeyInner.MonkeyTwoDeep.getNegativeTwo()"));
529: assertEquals(
530: "should be able to call method of outer class",
531: "-2",
532: interpret("MonkeyStaticStuff.MonkeyInner.MonkeyTwoDeep.getNegativeTwo()"));
533:
534: // Shutdown the debugger
535: _log.log("Shutting down...");
536:
537: synchronized (_notifierLock) {
538: _debugger.shutdown();
539: _setPendingNotifies(1); // shutdown
540: while (_pendingNotifies > 0)
541: _notifierLock.wait();
542: }
543:
544: debugListener.assertDebuggerShutdownCount(1); //fires
545: _log.log("Shut down.");
546:
547: _debugger.removeListener(debugListener);
548: }
549:
550: public void testAccessNullFieldsAndFinalLocalVariables()
551: throws DebugException, BadLocationException,
552: EditDocumentException, IOException, InterruptedException {
553: File file = new File(_tempDir, "Monkey.java");
554: OpenDefinitionsDocument doc = doCompile(
555: MONKEY_WITH_INNER_CLASS, file);
556: BreakpointTestListener debugListener = new BreakpointTestListener();
557: _debugger.addListener(debugListener);
558: // Start debugger
559: synchronized (_notifierLock) {
560: _debugger.startUp();
561: _setPendingNotifies(1); // startUp
562: while (_pendingNotifies > 0)
563: _notifierLock.wait();
564: }
565:
566: // System.err.println("Passed first set of notifications");
567: // Set one breakpoint
568: int index = MONKEY_WITH_INNER_CLASS
569: .indexOf("innerMethodFoo = 12;");
570: _debugger.toggleBreakpoint(doc, index, 10, true);
571: index = MONKEY_WITH_INNER_CLASS
572: .indexOf("System.out.println(\"localVar = \" + localVar);");
573: _debugger.toggleBreakpoint(doc, index, 32, true);
574:
575: // Run the main() method, hitting both breakpoints in different threads
576: synchronized (_notifierLock) {
577: interpretIgnoreResult("new Monkey().bar()");
578: _setPendingNotifies(3); // suspended, updated, breakpointReached
579: while (_pendingNotifies > 0)
580: _notifierLock.wait();
581: }
582:
583: // System.err.println("Passed second set of notifications");
584:
585: // Test accessing a field initialized to null
586: assertEquals("nullString should be null", "null",
587: interpret("nullString"));
588: interpret("nullString = new Integer(3)");
589: assertInteractionsContains("Error: Bad types in assignment");
590: assertEquals("nullString should still be null", "null",
591: interpret("nullString"));
592: assertEquals("Should be able to assign a string to nullString",
593: "\"asdf\"", interpret("nullString = \"asdf\""));
594: assertEquals("Should equal \"asdf\"", "true",
595: interpret("nullString.equals(\"asdf\")"));
596:
597: // Resumes this thread, switching to the next break point
598: synchronized (_notifierLock) {
599: _asyncResume();
600: _setPendingNotifies(3); // breakpointReached, suspended, updated
601: while (_pendingNotifies > 0)
602: _notifierLock.wait();
603: }
604:
605: // System.err.println("Passed third set of notifications");
606: // Test accessing final local variables
607: assertEquals("Should be able to access localVar", "11",
608: interpret("localVar"));
609: interpret("localVar = 5");
610: /* The Following test is commented out TEMPORARILY to work around bug in JDK 1.5 Beta2 JVM */
611: /* Update (10/12/2005): The test still fails under a current JDK 1.5 JVM. I'm not sure it's the JDK's fault */
612: // assertEquals("The value of localVar should not have changed", "11", interpret("localVar"));
613: // Shutdown the debugger
614: _log.log(this + " is Shutting Down...");
615: synchronized (_notifierLock) {
616: _debugger.shutdown();
617: _setPendingNotifies(1); // shutdown
618: while (_pendingNotifies > 0)
619: _notifierLock.wait();
620: }
621:
622: debugListener.assertDebuggerShutdownCount(1); //fires
623: _log.log(this + " is Shutting Down.");
624: _debugger.removeListener(debugListener);
625: }
626:
627: /**
628: * Disabled...
629: *
630: public void testNoAssignment() throws ExceptionReturnedException {
631:
632: // 1
633: _debugInterpreter.interpret("1 + 1");
634: assertEquals("Should not have made an assignment.", "", _assignedInterpreterName);
635:
636: // 2
637: _debugInterpreter.interpret("public void foo() {}; foo()");
638: assertEquals("Should not have made an assignment.", "", _assignedInterpreterName);
639:
640: // 3
641: _debugInterpreter.interpret("int x");
642: assertEquals("Should not have made an assignment.", "", _assignedInterpreterName);
643:
644: }*/
645:
646: /**
647: * Disabled...
648: *
649: public void testWithAssignment() throws ExceptionReturnedException {
650: // 1
651: _debugInterpreter.interpret("x = 0");
652: assertEquals("Should have made an assignment.", "test", _assignedInterpreterName);
653: _assignedInterpreterName = "";
654:
655: // 2
656: _debugInterpreter.interpret("y = null");
657: assertEquals("Should have made an assignment.", "test", _assignedInterpreterName);
658: _assignedInterpreterName = "";
659:
660: // 3
661: _debugInterpreter.interpret("int z; z = 2");
662: assertEquals("Should have made an assignment.", "test", _assignedInterpreterName);
663: _assignedInterpreterName = "";
664: } */
665: }
|