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.ui;
038:
039: import edu.rice.cs.drjava.DrJava;
040: import edu.rice.cs.drjava.config.OptionConstants;
041: import edu.rice.cs.drjava.model.MultiThreadedTestCase;
042: import edu.rice.cs.drjava.model.*;
043: import edu.rice.cs.drjava.model.definitions.DefinitionsDocument;
044: import edu.rice.cs.util.Log;
045: import edu.rice.cs.util.UnexpectedException;
046: import edu.rice.cs.util.swing.Utilities;
047:
048: import javax.swing.*;
049: import javax.swing.text.BadLocationException;
050: import java.awt.event.InputEvent;
051: import java.awt.event.KeyEvent;
052: import java.awt.event.KeyListener;
053: import java.io.IOException;
054: import java.lang.reflect.InvocationTargetException;
055: import java.util.Date;
056:
057: /** Tests the Definitions Pane
058: * @version $Id: DefinitionsPaneTest.java 4255 2007-08-28 19:17:37Z mgricken $
059: */
060: public final class DefinitionsPaneTest extends MultiThreadedTestCase {
061:
062: private volatile MainFrame _frame;
063:
064: public static final Log _log = new Log("DefinitionsPaneTest.txt",
065: false); // used in other tests
066:
067: private static final char UNDEFINED = KeyEvent.CHAR_UNDEFINED;
068: private static final int PRESSED = KeyEvent.KEY_PRESSED;
069: private static final int RELEASED = KeyEvent.KEY_RELEASED;
070: private static final int SHIFT = InputEvent.SHIFT_MASK;
071: private static final int TYPED = KeyEvent.KEY_TYPED;
072: private static final int VK_UNDEF = KeyEvent.VK_UNDEFINED;
073: private static final int META = KeyEvent.VK_META;
074: private static final int W = KeyEvent.VK_W;
075: private static final int M_MASK = InputEvent.META_MASK;
076: private static final int BANG = KeyEvent.VK_EXCLAMATION_MARK;
077: private static final int ALT = InputEvent.ALT_MASK;
078:
079: private static final int DEL_NEXT = OptionConstants.KEY_DELETE_NEXT
080: .getDefault().getKeyCode();
081: private static final int DEL_PREV = OptionConstants.KEY_DELETE_PREVIOUS
082: .getDefault().getKeyCode();
083:
084: /** Setup method for each JUnit test case. */
085: public void setUp() throws Exception {
086: super .setUp();
087: DrJava.getConfig().resetToDefaults();
088: _frame = new MainFrame();
089:
090: // super.setUp();
091: // Utilities.invokeAndWait(new Runnable() {
092: // public void run() {
093: // DrJava.getConfig().resetToDefaults();
094: // _frame = new MainFrame();
095: // }
096: // });
097: // Utilities.clearEventQueue();
098: }
099:
100: public void tearDown() throws Exception {
101: Utilities.invokeLater(new Runnable() {
102: public void run() {
103: _frame.dispose();
104: _log.log("Main Frame disposed");
105: _frame = null;
106: }
107: });
108: Utilities.clearEventQueue();
109: super .tearDown();
110: }
111:
112: /** Tests that shift backspace works the same as backspace. (Ease of use issue 693253). Ideally, this test should
113: * be lighter weight, and not require the creation of an entire MainFrame+GlobalModel. Refactor?
114: * NOTE: This test doesn't work yet, since we can't currently bind two keys to the same action. This should be
115: * implemented as part of feature request 683300.
116: */
117: public void testShiftBackspace() throws BadLocationException {
118: // _log.log("Starting testShiftBackSpace");
119: final DefinitionsPane defPane = _frame.getCurrentDefPane();
120: final OpenDefinitionsDocument doc = defPane
121: .getOpenDefDocument();
122:
123: _assertDocumentEmpty(doc, "before testing");
124:
125: Utilities.invokeAndWait(new Runnable() {
126: public void run() {
127: doc.append("test", null);
128: defPane.setCaretPosition(4);
129:
130: // The following is the sequence of key events for shift+backspace
131: defPane.processKeyEvent(new KeyEvent(defPane, PRESSED,
132: (new Date()).getTime(), SHIFT, DEL_PREV,
133: UNDEFINED));
134: _log.log("first key event processed");
135: defPane.processKeyEvent(new KeyEvent(defPane, RELEASED,
136: (new Date()).getTime(), SHIFT, DEL_PREV,
137: UNDEFINED));
138: _frame.validate();
139: }
140: });
141: Utilities.clearEventQueue();
142:
143: _log.log("second key event processed");
144: _assertDocumentContents(doc, "tes",
145: "Did not delete on shift+backspace");
146: _log.log("Halfway through testShiftBackspace");
147:
148: Utilities.invokeAndWait(new Runnable() {
149: public void run() {
150:
151: defPane.setCaretPosition(1);
152: // The following is the sequence of key events for shift+delete
153: defPane.processKeyEvent(new KeyEvent(defPane, PRESSED,
154: (new Date()).getTime(), SHIFT, DEL_NEXT,
155: UNDEFINED));
156: defPane.processKeyEvent(new KeyEvent(defPane, RELEASED,
157: (new Date()).getTime(), SHIFT, DEL_NEXT,
158: UNDEFINED));
159: _frame.validate();
160: }
161: });
162: Utilities.clearEventQueue();
163: _assertDocumentContents(doc, "ts",
164: "Did not delete on shift+delete");
165: _log.log("testShiftBackSpace completed");
166:
167: }
168:
169: /** Tests that typing a brace in a string/comment does not cause an indent. */
170: public void testTypeBraceNotInCode() throws BadLocationException {
171: final DefinitionsPane defPane = _frame.getCurrentDefPane();
172: final OpenDefinitionsDocument doc = defPane
173: .getOpenDefDocument();
174: _assertDocumentEmpty(doc, "before testing");
175: _log.log("calling invokeAndWait in testTypeBraceNotInCode");
176: Utilities.invokeAndWait(new Runnable() {
177: public void run() {
178: doc.append(" \"", null);
179: defPane.setCaretPosition(3);
180: // The following is the sequence of key events for a left brace
181: defPane.processKeyEvent(new KeyEvent(defPane, TYPED,
182: (new Date()).getTime(), 0, VK_UNDEF, '{'));
183: }
184: });
185: Utilities.clearEventQueue();
186:
187: _assertDocumentContents(doc, " \"{",
188: "Brace should not indent in a string");
189: _log.log("testTypeBraceNotInCode completed");
190: }
191:
192: /** Tests that typing Enter in a string/comment does cause an indent. This behavior works in practice, but I can't
193: * get the test to work. If we use definitions.processKeyEvent, the caret position is not updated, so the " * "
194: * is not inserted. If we try to dispatchEvent from the EventDispatchingThread, it hangs...?
195: */
196: public void testTypeEnterNotInCode() throws BadLocationException,
197: InterruptedException, InvocationTargetException {
198: final DefinitionsPane defPane = _frame.getCurrentDefPane();
199: // _frame.setVisible(true);
200: final OpenDefinitionsDocument doc = defPane
201: .getOpenDefDocument();
202: _assertDocumentEmpty(doc, "before testing");
203: Utilities.invokeAndWait(new Runnable() {
204: public void run() {
205:
206: try {
207: doc.insertString(0, "/**", null);
208: defPane.setCaretPosition(3);
209: // The following is the sequence of key events for Enter
210: int enter = KeyEvent.VK_ENTER;
211: defPane.processKeyEvent(new KeyEvent(defPane,
212: PRESSED, (new Date()).getTime(), 0, enter,
213: UNDEFINED));
214: defPane.processKeyEvent(new KeyEvent(defPane,
215: RELEASED, (new Date()).getTime(), 0, enter,
216: UNDEFINED));
217: _frame.validate();
218: } catch (Throwable t) {
219: listenerFail(t.getMessage());
220: }
221: _log.log("Completed processing of keyEvents");
222: }
223: });
224: Utilities.clearEventQueue();
225: _assertDocumentContents(doc, "/**\n * ",
226: "Enter should indent in a comment");
227: _log.log("testTypeEnterNotInCode completed");
228: }
229:
230: /** Tests that a simulated key press with the meta modifier is correct. Reveals bug 676586. */
231: public void testMetaKeyPress() throws BadLocationException {
232: final DefinitionsPane defPane = _frame.getCurrentDefPane();
233: final OpenDefinitionsDocument doc = defPane
234: .getOpenDefDocument();
235: _assertDocumentEmpty(doc, "point 0");
236:
237: Utilities.invokeAndWait(new Runnable() {
238: public void run() {
239: // The following is the sequence of key events that happen when the user presses Meta-a
240: defPane
241: .processKeyEvent(new KeyEvent(defPane, PRESSED,
242: (new Date()).getTime(), M_MASK, META,
243: UNDEFINED));
244: _frame.validate();
245: }
246: });
247: Utilities.clearEventQueue();
248:
249: _assertDocumentEmpty(doc, "point 1");
250:
251: Utilities.invokeAndWait(new Runnable() {
252: public void run() {
253: defPane.processKeyEvent(new KeyEvent(defPane, PRESSED,
254: (new Date()).getTime(), M_MASK, W, UNDEFINED));
255: _frame.validate();
256: }
257: });
258: Utilities.clearEventQueue();
259:
260: _assertDocumentEmpty(doc, "point 2");
261:
262: Utilities.invokeAndWait(new Runnable() {
263: public void run() {
264: defPane.processKeyEvent(new KeyEvent(defPane, TYPED,
265: (new Date()).getTime(), M_MASK, VK_UNDEF, 'w'));
266: _frame.validate();
267: }
268: });
269: Utilities.clearEventQueue();
270:
271: _assertDocumentEmpty(doc, "point 3");
272:
273: Utilities.invokeAndWait(new Runnable() {
274: public void run() {
275: defPane.processKeyEvent(new KeyEvent(defPane, RELEASED,
276: (new Date()).getTime(), M_MASK, W, UNDEFINED));
277: _frame.validate();
278: }
279: });
280: Utilities.clearEventQueue();
281:
282: _assertDocumentEmpty(doc, "point 4");
283:
284: Utilities.invokeAndWait(new Runnable() {
285: public void run() {
286: defPane.processKeyEvent(new KeyEvent(defPane, RELEASED,
287: (new Date()).getTime(), 0, META, UNDEFINED));
288: _frame.validate();
289: }
290: });
291: Utilities.clearEventQueue();
292:
293: _assertDocumentEmpty(doc, "point 5");
294:
295: _log.log("testMetaKeyPress completed");
296: }
297:
298: /** Tests that undoing/redoing a multi-line comment/uncomment will restore the caret position */
299: public void testMultilineCommentOrUncommentAfterScroll()
300: throws BadLocationException {
301:
302: final DefinitionsPane pane = _frame.getCurrentDefPane();
303: final OpenDefinitionsDocument doc = pane.getOpenDefDocument();
304: final String text = "public class stuff {\n"
305: + " private int _int;\n" + " private Bar _bar;\n"
306: + " public void foo() {\n" + " _bar.baz(_int);\n"
307: + " }\n" + "}\n";
308:
309: String commented = "//public class stuff {\n"
310: + "// private int _int;\n" + "// private Bar _bar;\n"
311: + "// public void foo() {\n"
312: + "// _bar.baz(_int);\n" + "// }\n" + "//}\n";
313:
314: final int newPos = 20;
315:
316: // The following statement hung when run in the main test thread. There must be a pending access to doc in a
317: // task on the event queue that sometimes has not yet executed.
318:
319: Utilities.invokeAndWait(new Runnable() {
320: public void run() {
321: doc.append(text, null);
322: }
323: });
324: Utilities.clearEventQueue();
325:
326: assertEquals("insertion", text, doc.getText());
327:
328: // Need to do this here since the commentLines action in MainFrame usually takes care of this.
329: // I can't run the test here because I'm not sure how to select the text so that we can comment it.
330:
331: Utilities.invokeAndWait(new Runnable() {
332: public void run() {
333: pane.endCompoundEdit();
334: }
335: });
336:
337: doc.acquireWriteLock();
338: try {
339: doc.commentLines(0, doc.getLength());
340: } finally {
341: doc.releaseWriteLock();
342: }
343:
344: // pane.endCompoundEdit();
345: assertEquals("commenting", commented, doc.getText());
346:
347: int oldPos = pane.getCaretPosition();
348:
349: Utilities.invokeAndWait(new Runnable() {
350: public void run() {
351: pane.setCaretPosition(newPos);
352: _frame.validate();
353: }
354: });
355: Utilities.clearEventQueue();
356:
357: doc.getUndoManager().undo();
358: assertEquals("undo commenting", text, doc.getText());
359: assertEquals("undoing commenting restores caret position",
360: oldPos, pane.getCaretPosition());
361:
362: // Perturb the caret position and redo
363: Utilities.invokeAndWait(new Runnable() {
364: public void run() {
365: pane.setCaretPosition(newPos);
366: }
367: });
368: Utilities.clearEventQueue();
369:
370: doc.getUndoManager().redo();
371: assertEquals("redo commenting", commented, doc.getText());
372: assertEquals("redoing commenting restores caret position",
373: oldPos, pane.getCaretPosition());
374:
375: // Need to do this here since the commentLines action in MainFrame usually takes care of this.
376: // I can't simulate a keystroke here because I'm not sure how to select the text so that we can comment it.
377: Utilities.invokeAndWait(new Runnable() {
378: public void run() {
379: pane.endCompoundEdit();
380: }
381: });
382: Utilities.clearEventQueue();
383:
384: doc.acquireWriteLock();
385: try {
386: doc.uncommentLines(0, doc.getLength());
387: } finally {
388: doc.releaseWriteLock();
389: }
390:
391: // pane.endCompoundEdit();
392: assertEquals("uncommenting", text, doc.getText());
393:
394: oldPos = pane.getCaretPosition(); // executing this method call outside of the event thread is borderline
395:
396: Utilities.invokeAndWait(new Runnable() {
397: public void run() {
398: pane.setCaretPosition(newPos);
399: }
400: });
401: Utilities.clearEventQueue();
402:
403: doc.getUndoManager().undo();
404:
405: assertEquals("undo uncommenting", commented, doc.getText());
406: assertEquals("undoing uncommenting restores caret position",
407: oldPos, pane.getCaretPosition());
408:
409: Utilities.invokeAndWait(new Runnable() {
410: public void run() {
411: pane.setCaretPosition(newPos);
412: }
413: });
414: Utilities.clearEventQueue();
415:
416: doc.getUndoManager().redo();
417: assertEquals("redo uncommenting", text, doc.getText());
418: assertEquals("redoing uncommenting restores caret position",
419: oldPos, pane.getCaretPosition());
420:
421: _log
422: .log("testMultiLineCommentOrUncommentAfterScroll completed");
423: }
424:
425: protected void _assertDocumentEmpty(DJDocument doc, String message) {
426: _assertDocumentContents(doc, "", message);
427: }
428:
429: protected void _assertDocumentContents(DJDocument doc,
430: String contents, String message) {
431: assertEquals(message, contents, doc.getText());
432: }
433:
434: public void testGranularUndo() throws BadLocationException {
435: final DefinitionsPane defPane = _frame.getCurrentDefPane();
436: final OpenDefinitionsDocument doc = defPane
437: .getOpenDefDocument();
438: // doc.addUndoableEditListener(doc.getUndoManager());
439:
440: // 1
441: assertEquals("Should start out empty.", "", doc.getText());
442:
443: // Type in consecutive characters and see if they are all undone at once.
444: // Type 'a'
445: Utilities.invokeAndWait(new Runnable() {
446: public void run() {
447: defPane.processKeyEvent(new KeyEvent(defPane, PRESSED,
448: (new Date()).getTime(), 0, KeyEvent.VK_A,
449: UNDEFINED));
450: defPane.processKeyEvent(new KeyEvent(defPane, TYPED,
451: (new Date()).getTime(), 0, VK_UNDEF, 'a'));
452: defPane.processKeyEvent(new KeyEvent(defPane, RELEASED,
453: (new Date()).getTime(), 0, KeyEvent.VK_A,
454: UNDEFINED));
455: // defPane.setCaretPosition(doc.getLength());
456: assertEquals("caret at line end", doc.getLength(),
457: defPane.getCaretPosition());
458:
459: // Type '!'
460: defPane.processKeyEvent(new KeyEvent(defPane, PRESSED,
461: (new Date()).getTime(), 0, BANG, UNDEFINED));
462: defPane.processKeyEvent(new KeyEvent(defPane, TYPED,
463: (new Date()).getTime(), 0, VK_UNDEF, '!'));
464: defPane.processKeyEvent(new KeyEvent(defPane, RELEASED,
465: (new Date()).getTime(), 0, BANG, UNDEFINED));
466: // defPane.setCaretPosition(doc.getLength());
467: assertEquals("caret at line end", doc.getLength(),
468: defPane.getCaretPosition());
469:
470: // Type 'B'
471: defPane.processKeyEvent(new KeyEvent(defPane, PRESSED,
472: (new Date()).getTime(), SHIFT, KeyEvent.VK_B,
473: UNDEFINED));
474: defPane.processKeyEvent(new KeyEvent(defPane, TYPED,
475: (new Date()).getTime(), 0, VK_UNDEF, 'B'));
476: defPane.processKeyEvent(new KeyEvent(defPane, RELEASED,
477: (new Date()).getTime(), SHIFT, KeyEvent.VK_B,
478: UNDEFINED));
479: // defPane.setCaretPosition(doc.getLength());
480: assertEquals("caret at line end", doc.getLength(),
481: defPane.getCaretPosition());
482:
483: // Type '9'
484: defPane.processKeyEvent(new KeyEvent(defPane, PRESSED,
485: (new Date()).getTime(), 0, KeyEvent.VK_9,
486: UNDEFINED));
487: defPane.processKeyEvent(new KeyEvent(defPane, TYPED,
488: (new Date()).getTime(), 0, VK_UNDEF, '9'));
489: defPane.processKeyEvent(new KeyEvent(defPane, RELEASED,
490: (new Date()).getTime(), 0, KeyEvent.VK_9,
491: UNDEFINED));
492: // defPane.setCaretPosition(doc.getLength());
493: assertEquals("caret at line end", doc.getLength(),
494: defPane.getCaretPosition());
495: _frame.validate();
496: }
497: });
498: Utilities.clearEventQueue();
499:
500: assertEquals("The text should have been inserted", "a!B9", doc
501: .getText());
502:
503: // Call the undoAction in MainFrame through the KeyBindingManager.
504: final KeyStroke ks = DrJava.getConfig().getSetting(
505: OptionConstants.KEY_UNDO);
506: final Action a = KeyBindingManager.Singleton.get(ks);
507:
508: final KeyEvent e = new KeyEvent(defPane, PRESSED, 0, ks
509: .getModifiers(), ks.getKeyCode(), UNDEFINED);
510:
511: Utilities.invokeAndWait(new Runnable() {
512: public void run() {
513: defPane.processKeyEvent(e);
514: _frame.validate();
515: }
516: });
517: Utilities.clearEventQueue();
518:
519: assertEquals("Should have undone correctly.", "", doc.getText());
520:
521: // 2
522: /* Test bug #905405 Undo Alt+Anything Causes Exception */
523:
524: // What does the following code test? There are no assertions! -- Corky 5/9/06
525: // Type 'Alt-B'
526: Utilities.invokeAndWait(new Runnable() {
527: public void run() {
528: defPane.processKeyEvent(new KeyEvent(defPane, PRESSED,
529: (new Date()).getTime(), ALT, KeyEvent.VK_Q,
530: UNDEFINED));
531: defPane.processKeyEvent(new KeyEvent(defPane, TYPED,
532: (new Date()).getTime(), ALT, VK_UNDEF, 'Q'));
533: defPane.processKeyEvent(new KeyEvent(defPane, RELEASED,
534: (new Date()).getTime(), ALT, KeyEvent.VK_Q,
535: UNDEFINED));
536:
537: /*
538: * If the bug is not fixed in DefinitionsPane.processKeyEvent, this test
539: * will not fail because the exception is thrown in another thread.
540: * However, the stack trace will get printed onto the console. I don't
541: * know how to fix this problem in case someone unfixes the bug.
542: */
543: SwingUtilities.notifyAction(a, ks, e, e.getSource(), e
544: .getModifiers());
545: _frame.validate();
546: // definitions.setCaretPosition(doc.getLength());
547: }
548: });
549: Utilities.clearEventQueue();
550:
551: // 2
552: /* This part doesn't work right now because by just calling processKeyEvent we
553: * have to manually move the caret, and the UndoWithPosition is off by one. This
554: * bites us since when the backspace is done, the backspace undo position is
555: * still at position 1 which doesn't exist in the document anymore.
556: *
557: *
558: // Test undoing backspace.
559: definitions.processKeyEvent(new KeyEvent(definitions,
560: PRESSED,
561: (new Date()).getTime(),
562: 0,
563: VK_UNDEF, UNDEFINED));
564: definitions.processKeyEvent(new KeyEvent(definitions,
565: TYPED,
566: (new Date()).getTime(),
567: 0,
568: VK_UNDEF, 'a'));
569: definitions.processKeyEvent(new KeyEvent(definitions,
570: RELEASED,
571: (new Date()).getTime(),
572: 0,
573: VK_UNDEF, UNDEFINED));
574: definitions.setCaretPosition(doc.getLength());
575:
576: assertEquals("The text should have been inserted", "a",
577: doc.getText());
578:
579: definitions.processKeyEvent(new KeyEvent(definitions,
580: PRESSED,
581: (new Date()).getTime(),
582: 0,
583: KeyEvent.VK_BACK_SPACE, UNDEFINED));
584: definitions.processKeyEvent(new KeyEvent(definitions,
585: TYPED,
586: (new Date()).getTime(),
587: 0,
588: VK_UNDEF, '\010'));
589: definitions.processKeyEvent(new KeyEvent(definitions,
590: RELEASED,
591: (new Date()).getTime(),
592: 0,
593: KeyEvent.VK_BACK_SPACE, UNDEFINED));
594: System.out.println(definitions.getCaretPosition());
595: definitions.setCaretPosition(doc.getLength());
596:
597: assertEquals("The text should have been deleted", "",
598: doc.getText());
599:
600: // Call the undoAction in MainFrame through the KeyBindingManager.
601: // KeyStroke ks = DrJava.getConfig().getSetting(OptionConstants.KEY_UNDO);
602: // Action a = KeyBindingManager.Singleton.get(ks);
603: // KeyEvent e = new KeyEvent(definitions,
604: // PRESSED,
605: // 0,
606: // ks.getModifiers(),
607: // ks.getKeyCode(),
608: // ks.getKeyChar());
609: // Performs the action a
610: definitions.processKeyEvent(new KeyEvent(definitions,
611: PRESSED,
612: (new Date()).getTime(),
613: ks.getModifiers(),
614: ks.getKeyCode(), UNDEFINED));
615: // doc.getUndoManager().undo();
616: assertEquals("Should have undone correctly.", "a",
617: doc.getText());*/
618:
619: _log.log("testGranularUndo completed");
620: }
621:
622: public void testActiveAndInactive() {
623: SingleDisplayModel _model = _frame.getModel(); // creates a frame with a new untitled document and makes it active
624:
625: DefinitionsPane pane1, pane2;
626: DJDocument doc1, doc2;
627:
628: pane1 = _frame.getCurrentDefPane();
629: doc1 = pane1.getDJDocument();
630: assertTrue(
631: "the active pane should have an open definitions document",
632: doc1 instanceof OpenDefinitionsDocument);
633:
634: _model.newFile(); // creates a new untitled document and makes it active
635: pane2 = _frame.getCurrentDefPane();
636: doc2 = pane2.getDJDocument();
637:
638: assertTrue(
639: "the active pane should have an open definitions document",
640: doc2 instanceof OpenDefinitionsDocument);
641:
642: _model.setActiveNextDocument(); // makes doc1 active
643: DefinitionsPane pane = _frame.getCurrentDefPane();
644: assertEquals("Confirm that next pane is the other pane", pane1,
645: pane);
646:
647: assertTrue("pane2 should have an open definitions document",
648: doc2 instanceof OpenDefinitionsDocument);
649: assertTrue("pane1 should have an open definitions document",
650: doc1 instanceof OpenDefinitionsDocument);
651:
652: _log.log("testActiveAndInactive completed");
653: }
654:
655: private volatile int _finalPaneCt;
656: private volatile int _finalDocCt;
657:
658: public void testDocumentPaneMemoryLeak()
659: throws InterruptedException, java.io.IOException {
660: _finalPaneCt = 0;
661: _finalDocCt = 0;
662:
663: FinalizationListener<DefinitionsPane> fl = new FinalizationListener<DefinitionsPane>() {
664: public void finalized(FinalizationEvent<DefinitionsPane> e) {
665: _finalPaneCt++;
666: // System.out.println("Finalizing: " + e.getObject().hashCode());
667: }
668: };
669:
670: FinalizationListener<DefinitionsDocument> fldoc = new FinalizationListener<DefinitionsDocument>() {
671: public void finalized(
672: FinalizationEvent<DefinitionsDocument> e) {
673: _finalDocCt++;
674: }
675: };
676:
677: SingleDisplayModel _model = _frame.getModel();
678: _model.newFile().addFinalizationListener(fldoc);
679: _frame.getCurrentDefPane().addFinalizationListener(fl);
680: // System.out.println("Created File: " + _frame.getCurrentDefPane().hashCode());
681: _model.newFile().addFinalizationListener(fldoc);
682: _frame.getCurrentDefPane().addFinalizationListener(fl);
683: // System.out.println("Created File: " + _frame.getCurrentDefPane().hashCode());
684: _model.newFile().addFinalizationListener(fldoc);
685: _frame.getCurrentDefPane().addFinalizationListener(fl);
686: // System.out.println("Created File: " + _frame.getCurrentDefPane().hashCode());
687: _model.newFile().addFinalizationListener(fldoc);
688: _frame.getCurrentDefPane().addFinalizationListener(fl);
689: // System.out.println("Created File: " + _frame.getCurrentDefPane().hashCode());
690: _model.newFile().addFinalizationListener(fldoc);
691: _frame.getCurrentDefPane().addFinalizationListener(fl);
692: // System.out.println("Created File: " + _frame.getCurrentDefPane().hashCode());
693: _model.newFile().addFinalizationListener(fldoc);
694: _frame.getCurrentDefPane().addFinalizationListener(fl);
695: // System.out.println("Created File: " + _frame.getCurrentDefPane().hashCode());
696:
697: // all the panes have a listener, so lets close all files
698:
699: _model.closeAllFiles();
700:
701: int ct = 0;
702: do {
703: // make sure that the event queue is empty
704: Utilities.clearEventQueue();
705: Utilities.clearEventQueue();
706:
707: System.gc();
708: System.runFinalization();
709: System.gc();
710: ct++;
711: } while (ct < 10 && (_finalDocCt != 6 || _finalPaneCt != 6));
712:
713: if (ct == 10)
714: fail("Failed to reclaim all documents; panes left = "
715: + (6 - _finalPaneCt) + "; docs left = "
716: + (6 - _finalDocCt));
717:
718: if (ct > 1)
719: System.out.println("testDocumentPaneMemoryLeak required "
720: + ct + " iterations");
721:
722: // System.out.println("Current: " + _frame.getCurrentDefPane().hashCode());
723:
724: // System.out.println("Foo");
725: // System.in.read();
726: assertEquals(
727: "all the defdocs should have been garbage collected",
728: 6, _finalDocCt);
729: assertEquals(
730: "all the panes should have been garbage collected", 6,
731: _finalPaneCt);
732: // System.err.println("_finalPaneCt = " + _finalPaneCt);
733:
734: _log.log("testDocumentPaneMemoryLeak completed");
735: }
736:
737: // This testcase checks that we do no longer discard Alt keys that would be used to make the {,},[,] chars that the french keyboards has.
738: // Using the Locale did not work, and checking if the key was consumed by the document would only pass on the specific keyboards.
739: // It was therefore unavoidable to add a few lines of code in the original code that is only used for this test case.
740: // These lines were added to the DefinitionsPane.java file.
741: public void testFrenchKeyStrokes() throws IOException,
742: InterruptedException {
743:
744: final DefinitionsPane pane = _frame.getCurrentDefPane(); // pane is NOT null.
745: //KeyEvent ke = new KeyEvent(pane, TYPED, 0, ALT, VK_UNDEF, '{');
746: final KeyEvent ke1 = new KeyEvent(pane, TYPED, 0, 0, VK_UNDEF,
747: 'T');
748:
749: Utilities.invokeAndWait(new Runnable() {
750: public void run() {
751: pane.processKeyEvent(ke1);
752: _frame.validate();
753: }
754: });
755: Utilities.clearEventQueue();
756:
757: assertFalse(
758: "The KeyEvent for pressing \"T\" should not involve an Alt Key if this fails we are in trouble!",
759: pane.checkAltKey());
760:
761: final KeyEvent ke2 = new KeyEvent(pane, TYPED, 0, ALT,
762: VK_UNDEF, '{');
763: Utilities.invokeAndWait(new Runnable() {
764: public void run() {
765: pane.processKeyEvent(ke2);
766: _frame.validate();
767: }
768: });
769: Utilities.clearEventQueue();
770:
771: assertTrue(
772: "Alt should have been registered and allowed to pass!",
773: pane.checkAltKey());
774:
775: final KeyEvent ke3 = new KeyEvent(pane, TYPED, 0, ALT,
776: VK_UNDEF, '}');
777: Utilities.invokeAndWait(new Runnable() {
778: public void run() {
779: pane.processKeyEvent(ke3);
780: _frame.validate();
781: }
782: });
783: Utilities.clearEventQueue();
784:
785: assertTrue(
786: "Alt should have been registered and allowed to pass!",
787: pane.checkAltKey());
788:
789: final KeyEvent ke4 = new KeyEvent(pane, TYPED, 0, ALT,
790: VK_UNDEF, '[');
791: Utilities.invokeAndWait(new Runnable() {
792: public void run() {
793: pane.processKeyEvent(ke4);
794: _frame.validate();
795: }
796: });
797: Utilities.clearEventQueue();
798:
799: assertTrue(
800: "Alt should have been registered and allowed to pass!",
801: pane.checkAltKey());
802:
803: final KeyEvent ke5 = new KeyEvent(pane, TYPED, 0, ALT,
804: VK_UNDEF, ']');
805: Utilities.invokeAndWait(new Runnable() {
806: public void run() {
807: pane.processKeyEvent(ke5);
808: _frame.validate();
809: }
810: });
811: Utilities.clearEventQueue();
812:
813: assertTrue(
814: "Alt should have been registered and allowed to pass!",
815: pane.checkAltKey());
816:
817: _log.log("testFrenchKeyStrokes completed");
818: }
819:
820: /* We had several problems with the backspace deleting 2 chars instead of one.
821: * Recently the problem reoccured in Java version 1.4, but not in 1.5
822: * This shows that we clearly needs a test for this.
823: */
824: public void testBackspace() {
825: final DefinitionsPane defPane = _frame.getCurrentDefPane();
826: final OpenDefinitionsDocument doc = defPane
827: .getOpenDefDocument();
828: _assertDocumentEmpty(doc, "before testing");
829:
830: Utilities.invokeAndWait(new Runnable() {
831: public void run() {
832: doc.append("test", null);
833: defPane.setCaretPosition(4);
834: final int VK_BKSP = KeyEvent.VK_BACK_SPACE;
835: // The following is the sequence of key events for backspace
836: defPane.processKeyEvent(new KeyEvent(defPane, PRESSED,
837: (new Date()).getTime(), 0, VK_BKSP, UNDEFINED));
838: defPane.processKeyEvent(new KeyEvent(defPane, RELEASED,
839: (new Date()).getTime(), 0, VK_BKSP, UNDEFINED));
840: defPane.processKeyEvent(new KeyEvent(defPane, TYPED,
841: (new Date()).getTime(), 0, VK_UNDEF, '\b'));
842: _frame.validate();
843: }
844: });
845: Utilities.clearEventQueue();
846:
847: _assertDocumentContents(doc, "tes",
848: "Deleting with Backspace went wrong");
849:
850: _log.log("testBackSpace completed");
851: }
852:
853: private volatile String _result;
854:
855: /** Tests the functionality that allows brace matching that displays the line matched in the status bar */
856: public void testMatchBraceText() {
857:
858: final DefinitionsPane defPane = _frame.getCurrentDefPane();
859: final OpenDefinitionsDocument doc = defPane
860: .getOpenDefDocument();
861: Utilities.clearEventQueue();
862:
863: _assertDocumentEmpty(doc, "before testing");
864:
865: Utilities.invokeAndWait(new Runnable() {
866: public void run() {
867: doc.append("{\n" + "public class Foo {\n" + //21
868: " private int whatev\n" + //42
869: " private void _method()\n" + //67
870: " {\n" + //71
871: " do stuff\n" + //85
872: " new Object() {\n" + //105
873: " }\n" + //116
874: " }\n" + "}" + "}", null);
875:
876: defPane.setCaretPosition(4);
877: }
878: });
879:
880: /* Ensure that DocumentListeners complete. */
881: Utilities.invokeAndWait(new Runnable() {
882: public void run() {
883: _result = _frame.getFileNameField();
884: }
885: });
886:
887: final String taggedFileName = "Editing "
888: + doc.getCompletePath();
889: assertEquals("Should display the document path",
890: taggedFileName, _result);
891:
892: Utilities.invokeAndWait(new Runnable() {
893: public void run() {
894: defPane.setCaretPosition(115);
895: }
896: });
897: // Complete the actions spawned by the preceding command before executing the following command
898: Utilities.invokeAndWait(new Runnable() {
899: public void run() {
900: _result = _frame.getFileNameField();
901: }
902: });
903: assertEquals("Should display the line matched",
904: "Bracket matches: new Object() {", _result);
905:
906: Utilities.invokeAndWait(new Runnable() {
907: public void run() {
908: defPane.setCaretPosition(102);
909: }
910: });
911: // Complete the actions spawned by the preceding command before executing the following command
912: Utilities.invokeAndWait(new Runnable() {
913: public void run() {
914: _result = _frame.getFileNameField();
915: }
916: });
917: assertEquals("Should display the document matched",
918: taggedFileName, _result);
919:
920: Utilities.invokeAndWait(new Runnable() {
921: public void run() {
922: defPane.setCaretPosition(119);
923: }
924: });
925: // Complete the actions spawned by the preceding command before executing the following command
926: Utilities.invokeAndWait(new Runnable() {
927: public void run() {
928: _result = _frame.getFileNameField();
929: }
930: });
931: assertEquals("Should display the line matched",
932: "Bracket matches: private void _method()...{",
933: _result);
934:
935: Utilities.invokeAndWait(new Runnable() {
936: public void run() {
937: defPane.setCaretPosition(121);
938: }
939: });
940: // Complete the actions spawned by the preceding command before executing the following command
941: Utilities.invokeAndWait(new Runnable() {
942: public void run() {
943: _result = _frame.getFileNameField();
944: }
945: });
946: assertEquals("Should display the line matched",
947: "Bracket matches: public class Foo {", _frame
948: .getFileNameField());
949:
950: Utilities.invokeAndWait(new Runnable() {
951: public void run() {
952: defPane.setCaretPosition(122);
953: }
954: });
955: // Complete the actions spawned by the preceding command before executing the following command
956: Utilities.invokeAndWait(new Runnable() {
957: public void run() {
958: _result = _frame.getFileNameField();
959: }
960: });
961: assertEquals(
962: "Should display only one brace when matching an open brace that is the first character in a line",
963: "Bracket matches: {", _result);
964:
965: _log.log("testMatchBraceTest completed");
966: }
967:
968: class KeyTestListener implements KeyListener {
969:
970: public void keyPressed(KeyEvent e) {
971: DefinitionsPaneTest.fail("Unexpected keypress " + e);
972: }
973:
974: public void keyReleased(KeyEvent e) {
975: DefinitionsPaneTest.fail("Unexpected keyrelease " + e);
976: }
977:
978: public void keyTyped(KeyEvent e) {
979: DefinitionsPaneTest.fail("Unexpected keytyped " + e);
980: }
981:
982: public boolean done() {
983: return true;
984: }
985: }
986: }
|