1 33 34 package edu.rice.cs.drjava.model.repl; 35 36 import edu.rice.cs.drjava.model.debug.*; 37 import edu.rice.cs.drjava.model.*; 38 import edu.rice.cs.util.text.EditDocumentException; 39 import edu.rice.cs.util.swing.Utilities; 40 41 import java.util.LinkedList ; 42 import java.io.*; 43 import javax.swing.text.*; 44 45 import koala.dynamicjava.util.*; 46 import koala.dynamicjava.tree.*; 47 import koala.dynamicjava.interpreter.context.*; 48 49 56 public final class JavaDebugInterpreterTest extends DebugTestCase { 57 private static final String _newLine = System.getProperty("line.separator"); 58 private JavaDebugInterpreter _debugInterpreter; 59 60 62 protected static final String MONKEY_STUFF = 63 "class MonkeyStuff {\n" + 64 " int foo = 6;\n" + 65 " class MonkeyInner {\n" + 66 " int innerFoo = 8;\n" + 67 " public class MonkeyTwoDeep {\n" + 68 " int twoDeepFoo = 13;\n" + 69 " class MonkeyThreeDeep {\n" + 70 " public int threeDeepFoo = 18;\n" + 71 " public void threeDeepMethod() {\n" + 72 " int blah;\n" + 73 " System.out.println(MonkeyStuff.MonkeyInner.MonkeyTwoDeep.MonkeyThreeDeep.this.threeDeepFoo);\n" + 74 " }\n" + 75 " }\n" + 76 " int getNegativeTwo() { return -2; }\n" + 77 " }\n" + 78 " }\n" + 79 "\n" + 80 " public static void main(String[] args) {\n" + 81 " new MonkeyStuff().new MonkeyInner().new MonkeyTwoDeep().new MonkeyThreeDeep().threeDeepMethod();\n" + 82 " }\n" + 83 "}"; 84 85 protected static final String MONKEY_STATIC_STUFF = 86 "package monkey;\n" + 87 "public class MonkeyStaticStuff {\n" + 88 " static int foo = 6;\n" + 89 " static class MonkeyInner {\n" + 90 " static int innerFoo = 8;\n" + 91 " static public class MonkeyTwoDeep {\n" + 92 " static int twoDeepFoo = 13;\n" + 93 " public static class MonkeyThreeDeep {\n" + 94 " public static int threeDeepFoo = 18;\n" + 95 " public static void threeDeepMethod() {\n" + 96 " System.out.println(MonkeyStaticStuff.MonkeyInner.MonkeyTwoDeep.MonkeyThreeDeep.threeDeepFoo);\n" + 97 " System.out.println(MonkeyTwoDeep.twoDeepFoo);\n" + 98 " System.out.println(twoDeepFoo);\n" + 99 " }\n" + 100 " }\n" + 101 " static int getNegativeTwo() { return -2; }\n" + 102 " }\n" + 103 " }\n" + 104 "}"; 105 106 protected static final String MONKEY_WITH_INNER_CLASS = 107 "class Monkey {\n" + 108 " static int foo = 6; \n" + 109 " class MonkeyInner { \n" + 110 " int innerFoo = 8;\n" + 111 " class MonkeyInnerInner { \n" + 112 " int innerInnerFoo = 10;\n" + 113 " public void innerMethod() { \n" + 114 " int innerMethodFoo;\n" + 115 " String nullString = null;\n" + 116 " innerMethodFoo = 12;\n" + 117 " foo++;\n" + 118 " innerFoo++;\n" + 119 " innerInnerFoo++;\n" + 120 " innerMethodFoo++;\n" + 121 " staticMethod();\n" + 122 " System.out.println(\"innerMethodFoo: \" + innerMethodFoo);\n" + 123 " }\n" + 124 " }\n" + 125 " }\n" + 126 " public void bar() {\n" + 127 " final MonkeyInner.MonkeyInnerInner mi = \n" + 128 " new MonkeyInner().new MonkeyInnerInner();\n" + 129 " mi.innerMethod();\n" + 130 " final int localVar = 99;\n" + 131 " new Thread() {\n" + 132 " public void run() {\n" + 133 " final int localVar = mi.innerInnerFoo;\n" + 134 " new Thread() {\n" + 135 " public void run() {\n" + 136 " new Thread() {\n" + 137 " public void run() {\n" + 138 " System.out.println(\"localVar = \" + localVar);\n" + 139 " }\n" + 140 " }.run();\n" + 141 " }\n" + 142 " }.run();\n" + 143 " }\n" + 144 " }.run();\n" + 145 " }\n" + 146 " public static void staticMethod() {\n" + 147 " int z = 3;\n" + 148 " }\n" + 149 "}\n"; 150 151 152 public void setUp() throws Exception { 153 super.setUp(); 154 _debugInterpreter = new JavaDebugInterpreter("test", "") { 156 public EvaluationVisitorExtension makeEvaluationVisitor(Context context) { 157 return new DebugEvaluationVisitor(context, _name); 158 } 164 }; 165 } 167 168 public void notifyInterpreterAssignment(String name) { 169 } 171 172 public void testVerifyClassName() { 173 _debugInterpreter.setClassName("bar.baz.Foo$FooInner$FooInnerInner"); 174 assertEquals("verify failed", 0, _debugInterpreter.verifyClassName("bar.baz.Foo.FooInner.FooInnerInner")); 175 assertEquals("verify failed", 1, _debugInterpreter.verifyClassName("bar.baz.Foo.FooInner")); 176 assertEquals("verify failed", 2, _debugInterpreter.verifyClassName("bar.baz.Foo")); 177 assertEquals("verify failed", -1, _debugInterpreter.verifyClassName("bar.baz")); 178 assertEquals("verify failed", 0, _debugInterpreter.verifyClassName("Foo.FooInner.FooInnerInner")); 179 assertEquals("verify failed", 2, _debugInterpreter.verifyClassName("Foo")); 180 assertEquals("verify failed", 1, _debugInterpreter.verifyClassName("FooInner")); 181 assertEquals("verify failed", 0, _debugInterpreter.verifyClassName("FooInnerInner")); 182 assertEquals("verify failed", 1, _debugInterpreter.verifyClassName("Foo.FooInner")); 183 assertEquals("verify failed", 0, _debugInterpreter.verifyClassName("FooInner.FooInnerInner")); 184 assertEquals("verify failed", -1, _debugInterpreter.verifyClassName("FooInner.FooInnerInner.Foo")); 185 assertEquals("verify failed", -1, _debugInterpreter.verifyClassName("FooInner.FooInnerInner.foo")); 186 assertEquals("verify failed", -1, _debugInterpreter.verifyClassName("o.FooInner")); 187 _debugInterpreter.setClassName("Foo$FooInner$FooInnerInner"); 188 assertEquals("verify failed", 0, _debugInterpreter.verifyClassName("Foo.FooInner.FooInnerInner")); 189 assertEquals("verify failed", 2, _debugInterpreter.verifyClassName("Foo")); 190 assertEquals("verify failed", 1, _debugInterpreter.verifyClassName("FooInner")); 191 assertEquals("verify failed", 0, _debugInterpreter.verifyClassName("FooInnerInner")); 192 assertEquals("verify failed", 1, _debugInterpreter.verifyClassName("Foo.FooInner")); 193 assertEquals("verify failed", 0, _debugInterpreter.verifyClassName("FooInner.FooInnerInner")); 194 assertEquals("verify failed", -1, _debugInterpreter.verifyClassName("FooInner.FooInnerInner.Foo")); 195 assertEquals("verify failed", -1, _debugInterpreter.verifyClassName("FooInner.FooInnerInner.foo")); 196 assertEquals("verify failed", -1, _debugInterpreter.verifyClassName("o.FooInner")); 197 } 198 199 private void assertEqualsNodes(String message, Node expected, Node actual) { 200 ByteArrayOutputStream baos = new ByteArrayOutputStream(); 201 DisplayVisitor dve = new DisplayVisitor(baos); 202 expected.acceptVisitor(dve); 203 String s1 = baos.toString(); 204 baos.reset(); 205 actual.acceptVisitor(dve); 206 String s2 = baos.toString(); 207 assertEquals(message, s1, s2); 209 } 210 211 212 public void testConvertToName() { 213 ThisExpression thisExp = _debugInterpreter.buildUnqualifiedThis(); 214 Node n = _debugInterpreter.visitThis(thisExp); 215 LinkedList <IdentifierToken> thisList = new LinkedList <IdentifierToken>(); thisList.add(new Identifier("this")); 217 QualifiedName expected = new QualifiedName(thisList); 218 assertEqualsNodes("convertThisToName did not return the correct QualifiedName", expected, n); 219 } 220 221 222 public void testConvertToObjectFieldAccess() { 223 _debugInterpreter.setClassName("bar.baz.Foo$FooInner$FooInnerInner"); 224 LinkedList <IdentifierToken> ids = new LinkedList <IdentifierToken>(); ids.add(new Identifier("Foo")); 226 ThisExpression thisExp = new ThisExpression(ids, "", 0, 0, 0, 0); 227 Node n = _debugInterpreter.visitThis(thisExp); 228 Node expected = 229 new ObjectFieldAccess( 230 new ObjectFieldAccess(_debugInterpreter._convertThisToName(_debugInterpreter.buildUnqualifiedThis()), "this$1"), 231 "this$0"); 232 233 assertEqualsNodes("convertThisToObjectFieldAccess did not return the correct ObjectFieldAccess", 234 expected, 235 n); 236 } 237 238 242 public void testAccessFieldsAndMethodsOfOuterClasses() 243 throws DebugException, BadLocationException, EditDocumentException, IOException, InterruptedException { 244 File file = new File(_tempDir, "MonkeyStuff.java"); 245 OpenDefinitionsDocument doc = doCompile(MONKEY_STUFF, file); 246 BreakpointTestListener debugListener = new BreakpointTestListener(); 247 _debugger.addListener(debugListener); 248 synchronized(_notifierLock) { 250 _debugger.startUp(); 251 _setPendingNotifies(1); while (_pendingNotifies > 0) _notifierLock.wait(); 253 } 254 255 int index = MONKEY_STUFF.indexOf("System.out.println"); 257 _debugger.toggleBreakpoint(doc, index, 11, true); 258 259 synchronized(_notifierLock) { 261 interpretIgnoreResult("java MonkeyStuff"); 262 _setPendingNotifies(3); while (_pendingNotifies > 0) _notifierLock.wait(); 264 } 265 266 268 interpret("try {\n" + 271 " for (int i = MonkeyStuff.this.foo; i < 7; i++) {\n"+ 272 " do{System.out.println(MonkeyInner.this.innerFoo);}\n" + 273 " while(MonkeyStuff.MonkeyInner.this.innerFoo == MonkeyThreeDeep.this.threeDeepFoo);\n" + 274 " switch(MonkeyStuff.MonkeyInner.MonkeyTwoDeep.this.twoDeepFoo) {\n" + 275 " case 13: if (this.threeDeepFoo == 5) {\n" + 276 " System.out.println(MonkeyThreeDeep.this.threeDeepFoo);\n" + 277 " }\n" + 278 " else {\n" + 279 " MonkeyThreeDeep.this.threeDeepFoo = MonkeyThreeDeep.this.threeDeepFoo + MonkeyStuff.this.foo;\n" + 280 " }\n" + 281 " }\n" + 282 " }\n" + 283 "}\n" + 284 "catch(Exception e) { System.out.println(MonkeyThreeDeep.this.threeDeepFoo);}\n" + 285 "finally {System.out.println(MonkeyInner.MonkeyTwoDeep.this.twoDeepFoo);}"); 286 assertInteractionsDoesNotMatch(".*^18$.*"); 287 assertInteractionsDoesNotMatch(".*^6$.*"); 288 assertInteractionsMatches(".*^8" + _newLine + "13$.*"); 289 290 interpret("foo"); 292 293 295 assertInteractionsMatches(".*^6$.*"); 296 297 interpret("foo = 123"); 298 assertEquals("foo should have been modified" , "123", interpret("MonkeyStuff.this.foo")); 299 interpret("int foo = 999;"); 300 assertEquals("foo should refer to defined foo", "999", interpret("foo")); 301 assertEquals("declaring foo should not change MonkeyStuff.this.foo", "123", interpret("MonkeyStuff.this.foo")); 302 303 assertEquals("call method of outer class #1", "-2", interpret("getNegativeTwo()")); 304 assertEquals("call method of outer class #2", "-2", interpret("MonkeyTwoDeep.this.getNegativeTwo()")); 305 assertEquals("call method of outer class #3", "-2", 306 interpret("MonkeyInner.MonkeyTwoDeep.this.getNegativeTwo()")); 307 assertEquals("call method of outer class #4", "-2", 308 interpret("MonkeyStuff.MonkeyInner.MonkeyTwoDeep.this.getNegativeTwo()")); 309 310 _model.closeFile(doc); 312 313 Utilities.clearEventQueue(); 314 debugListener.assertRegionRemovedCount(1); 316 _log.log("Shutting down..."); 318 synchronized(_notifierLock) { 319 _debugger.shutdown(); 320 _setPendingNotifies(1); while (_pendingNotifies > 0) _notifierLock.wait(); 322 } 323 324 debugListener.assertDebuggerShutdownCount(1); _log.log("Shut down."); 326 _debugger.removeListener(debugListener); 327 } 328 329 330 public void testAccessStaticFieldsAndMethodsOfOuterClasses() 331 throws DebugException, BadLocationException, EditDocumentException, IOException, InterruptedException { 332 File dir = new File(_tempDir, "monkey"); 333 dir.mkdir(); 334 File file = new File(dir, "MonkeyStaticStuff.java"); 335 OpenDefinitionsDocument doc = doCompile(MONKEY_STATIC_STUFF, file); 336 BreakpointTestListener debugListener = new BreakpointTestListener(); 337 _debugger.addListener(debugListener); 338 synchronized(_notifierLock) { 340 _debugger.startUp(); 341 _setPendingNotifies(1); while (_pendingNotifies > 0) _notifierLock.wait(); 343 } 344 345 int index = MONKEY_STATIC_STUFF.indexOf("System.out.println"); 347 _debugger.toggleBreakpoint(doc,index,11,true); 348 349 synchronized(_notifierLock) { 351 interpretIgnoreResult("monkey.MonkeyStaticStuff.MonkeyInner.MonkeyTwoDeep.MonkeyThreeDeep.threeDeepMethod();"); 353 _setPendingNotifies(3); while (_pendingNotifies > 0) _notifierLock.wait(); 355 } 356 357 assertEquals("should find field of static outer class", 358 "13", 359 interpret("twoDeepFoo")); 360 assertEquals("should find field of static outer class", 361 "13", 362 interpret("MonkeyInner.MonkeyTwoDeep.twoDeepFoo")); 363 364 interpret("twoDeepFoo = 100;"); 365 assertEquals("should have assigned field of static outer class", 366 "100", 367 interpret("twoDeepFoo")); 368 assertEquals("should have assigned the field of static outer class", 369 "100", 370 interpret("MonkeyStaticStuff.MonkeyInner.MonkeyTwoDeep.twoDeepFoo")); 371 assertEquals("should have assigned the field of static outer class", 372 "100", 373 interpret("monkey.MonkeyStaticStuff.MonkeyInner.MonkeyTwoDeep.twoDeepFoo")); 374 375 interpret("int twoDeepFoo = -10;"); 376 assertEquals("Should have successfully shadowed field of static outer class", "-10", interpret("twoDeepFoo")); 377 378 assertEquals("should have assigned the field of static outer class", "100", 379 interpret("MonkeyTwoDeep.twoDeepFoo")); 380 381 assertEquals("should have assigned the field of static outer class", "100", 382 interpret("MonkeyStaticStuff.MonkeyInner.MonkeyTwoDeep.twoDeepFoo")); 383 384 assertEquals("Should be able to access a static field of a non-static outer class", "6", interpret("foo")); 385 assertEquals("Should be able to access a static field of a non-static outer class", "6", 386 interpret("MonkeyStaticStuff.foo")); 387 388 interpret("foo = 987;"); 389 assertEquals("Should have changed the value of a static field of a non-static outer class", "987", 390 interpret("foo")); 391 392 assertEquals("Should have changed the value of a static field of a non-static outer class", "987", 393 interpret("MonkeyStaticStuff.foo")); 394 395 interpret("int foo = 56;"); 396 assertEquals("Should have defined a new variable", "56", interpret("foo")); 397 assertEquals("Should have shadowed the value of a static field of a non-static outer class", "987", 398 interpret("MonkeyStaticStuff.foo")); 399 400 assertEquals("should be able to call method of outer class", "-2", interpret("getNegativeTwo()")); 401 assertEquals("should be able to call method of outer class", "-2", interpret("MonkeyTwoDeep.getNegativeTwo()")); 402 assertEquals("should be able to call method of outer class", "-2", 403 interpret("MonkeyInner.MonkeyTwoDeep.getNegativeTwo()")); 404 assertEquals("should be able to call method of outer class", "-2", 405 interpret("MonkeyStaticStuff.MonkeyInner.MonkeyTwoDeep.getNegativeTwo()")); 406 407 _log.log("Shutting down..."); 409 410 synchronized(_notifierLock) { 411 _debugger.shutdown(); 412 _setPendingNotifies(1); while (_pendingNotifies > 0) _notifierLock.wait(); 414 } 415 416 debugListener.assertDebuggerShutdownCount(1); _log.log("Shut down."); 418 419 _debugger.removeListener(debugListener); 420 } 421 422 public void testAccessNullFieldsAndFinalLocalVariables() 423 throws DebugException, BadLocationException, EditDocumentException, IOException, InterruptedException { 424 File file = new File(_tempDir, "Monkey.java"); 425 OpenDefinitionsDocument doc = doCompile(MONKEY_WITH_INNER_CLASS, file); 426 BreakpointTestListener debugListener = new BreakpointTestListener(); 427 _debugger.addListener(debugListener); 428 synchronized(_notifierLock) { 430 _debugger.startUp(); 431 _setPendingNotifies(1); while (_pendingNotifies > 0) _notifierLock.wait(); 433 } 434 435 int index = MONKEY_WITH_INNER_CLASS.indexOf("innerMethodFoo = 12;"); 437 _debugger.toggleBreakpoint(doc,index,10,true); 438 index = MONKEY_WITH_INNER_CLASS.indexOf("System.out.println(\"localVar = \" + localVar);"); 439 _debugger.toggleBreakpoint(doc,index,32,true); 440 441 synchronized(_notifierLock) { 443 interpretIgnoreResult("new Monkey().bar()"); 444 _setPendingNotifies(3); while (_pendingNotifies > 0) _notifierLock.wait(); 446 } 447 448 assertEquals("nullString should be null", "null", interpret("nullString")); 450 interpret("nullString = new Integer(3)"); 451 assertInteractionsContains("Error: Bad types in assignment"); 452 assertEquals("nullString should still be null", "null", interpret("nullString")); 453 assertEquals("Should be able to assign a string to nullString", "\"asdf\"", interpret("nullString = \"asdf\"")); 454 assertEquals("Should equal \"asdf\"", "true", interpret("nullString.equals(\"asdf\")")); 455 456 synchronized(_notifierLock) { 458 _asyncResume(); 459 _setPendingNotifies(3); while (_pendingNotifies > 0) _notifierLock.wait(); 461 } 462 assertEquals("Should be able to access localVar", "11", interpret("localVar")); 464 interpret("localVar = 5"); 465 466 467 469 _log.log(this + " is Shutting Down..."); 471 synchronized(_notifierLock) { 472 _debugger.shutdown(); 473 _setPendingNotifies(1); while (_pendingNotifies > 0) _notifierLock.wait(); 475 } 476 477 debugListener.assertDebuggerShutdownCount(1); _log.log(this + " is Shutting Down."); 479 _debugger.removeListener(debugListener); 480 } 481 482 500 501 520 } 521 | Popular Tags |