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.cache;
038:
039: import edu.rice.cs.drjava.DrJavaTestCase;
040: import edu.rice.cs.drjava.model.*;
041: import edu.rice.cs.drjava.model.definitions.DefinitionsDocument;
042: import edu.rice.cs.plt.io.IOUtil;
043: import edu.rice.cs.util.FileOpenSelector;
044: import edu.rice.cs.util.OperationCanceledException;
045:
046: import javax.swing.text.BadLocationException;
047: import java.io.File;
048: import java.io.IOException;
049: import java.util.Hashtable;
050: import java.util.List;
051:
052: /** This used to extend GlobalModelTestCase, but now it extends just TestCase. Perhaps it should be changed back. */
053: public class DocumentCacheTest extends DrJavaTestCase {
054:
055: private DefaultGlobalModel _model;
056: private DocumentCache _cache;
057: private Hashtable<OpenDefinitionsDocument, DCacheAdapter> _adapterTable;
058:
059: private int _doc_made;
060: private int _doc_saved;
061:
062: protected File _tempDir;
063:
064: public void setUp() throws Exception {
065: super .setUp();
066: createModel();
067:
068: String user = System.getProperty("user.name");
069: _tempDir = IOUtil.createAndMarkTempDirectory("DrJava-test-"
070: + user, "");
071:
072: _cache = _model.getDocumentCache();
073: _cache.setCacheSize(4);
074: _adapterTable = new Hashtable<OpenDefinitionsDocument, DCacheAdapter>();
075: _cache
076: .addRegistrationListener(new DocumentCache.RegistrationListener() {
077: public void registered(OpenDefinitionsDocument odd,
078: DCacheAdapter a) {
079: _adapterTable.put(odd, a);
080: }
081: });
082: _doc_made = 0;
083: _doc_saved = 0;
084: }
085:
086: public void tearDown() throws Exception {
087: boolean ret = IOUtil.deleteRecursively(_tempDir);
088: assertTrue("delete temp directory " + _tempDir, ret);
089: _model.dispose();
090:
091: _tempDir = null;
092: _model = null;
093: super .tearDown();
094: }
095:
096: /** Instantiates the GlobalModel to be used in the test cases. */
097: protected void createModel() {
098: //_model = new DefaultGlobalModel(_originalModel);
099: _model = new TestGlobalModel();
100:
101: // Wait until it has connected
102: _model.waitForInterpreter();
103: }
104:
105: /** Create a new temporary file in _tempDir. */
106: protected File tempFile() throws IOException {
107: return File.createTempFile("DrJava-test", ".java", _tempDir)
108: .getCanonicalFile();
109: }
110:
111: /** Create a new temporary file in _tempDir. Calls with the same
112: * int will return the same filename, while calls with different
113: * ints will return different filenames.
114: */
115: protected File tempFile(int i) throws IOException {
116: return File
117: .createTempFile("DrJava-test" + i, ".java", _tempDir)
118: .getCanonicalFile();
119: }
120:
121: protected OpenDefinitionsDocument openFile(final File f)
122: throws IOException {
123: try {
124: OpenDefinitionsDocument doc = _model
125: .openFile(new FileOpenSelector() {
126: public File[] getFiles() {
127: return new File[] { f };
128: }
129: });
130: return doc;
131: } catch (AlreadyOpenException e) {
132: throw new IOException(e.getMessage());
133: } catch (OperationCanceledException e) {
134: throw new IOException(e.getMessage());
135: }
136: }
137:
138: /** A good warmup test case. */
139: public void testCacheSize() {
140: _cache.setCacheSize(6);
141: assertEquals("Wrong cache size", 6, _cache.getCacheSize());
142: _cache.setCacheSize(34);
143: assertEquals("Wrong cache size", 34, _cache.getCacheSize());
144:
145: /* test that an IllegalArgumentException is thrown when a
146: * cacheSize <= 0 is provided
147: */
148: try {
149: _cache.setCacheSize(0);
150: fail("IllegalArgumentException expected.");
151: } catch (IllegalArgumentException iae) {
152: //We're good
153: }
154:
155: try {
156: _cache.setCacheSize(-34);
157: fail("IllegalArgumentException expected.");
158: } catch (IllegalArgumentException iae) {
159: //We're good
160: }
161: }
162:
163: public void testNewDocumentsInAndOutOfTheCache()
164: throws BadLocationException, IOException {
165: assertEquals("Wrong Cache Size", 4, _cache.getCacheSize());
166:
167: // The documents are activated soon after creation by a getCurrentLine operation done somewhere
168: // but they are not entered in the cache because they are new
169:
170: OpenDefinitionsDocument doc1 = _model.newFile();
171: assertEquals("There should be 0 documents in the cache", 0,
172: _cache.getNumInCache()); // was 0
173:
174: OpenDefinitionsDocument doc2 = _model.newFile();
175: assertEquals("There should be 0 documents in the cache", 0,
176: _cache.getNumInCache()); // was 0
177:
178: OpenDefinitionsDocument doc3 = _model.newFile();
179: assertEquals("There should be 0 documents in the cache", 0,
180: _cache.getNumInCache()); // was 0
181:
182: OpenDefinitionsDocument doc4 = _model.newFile();
183: assertEquals("There should be 0 documents in the cache", 0,
184: _cache.getNumInCache()); // was 0
185:
186: OpenDefinitionsDocument doc5 = _model.newFile();
187: assertEquals("There should be 0 documents in the cache", 0,
188: _cache.getNumInCache()); // was 0
189:
190: OpenDefinitionsDocument doc6 = _model.newFile();
191: assertEquals("There should be 0 documents in the cache", 0,
192: _cache.getNumInCache()); // was 0
193:
194: // This tests that isModifiedSinceSave does not cause the document to load into the cache,
195: // so the two that should have been kicked out, 1 & 2 should not be loaded uppon calling isModified.
196:
197: assertFalse("Document 1 shouldn't be modified", doc1
198: .isModifiedSinceSave());
199: assertFalse("Document 2 shouldn't be modified", doc2
200: .isModifiedSinceSave());
201: assertFalse("Document 3 shouldn't be modified", doc3
202: .isModifiedSinceSave());
203: assertFalse("Document 4 shouldn't be modified", doc4
204: .isModifiedSinceSave());
205: assertFalse("Document 5 shouldn't be modified", doc5
206: .isModifiedSinceSave());
207: assertFalse("Document 6 shouldn't be modified", doc6
208: .isModifiedSinceSave());
209: assertEquals("There should be 0 documents in the cache", 0,
210: _cache.getNumInCache());
211:
212: assertFalse("Document 1 shouldn't be ready", _adapterTable.get(
213: doc1).isReady());
214: assertFalse("Document 2 shouldn't be ready", _adapterTable.get(
215: doc2).isReady());
216: assertFalse("Document 3 shouldn't be ready", _adapterTable.get(
217: doc3).isReady());
218: assertFalse("Document 4 shouldn't be ready", _adapterTable.get(
219: doc4).isReady());
220: assertFalse("Document 5 shouldn't be ready", _adapterTable.get(
221: doc5).isReady());
222: assertFalse("Document 6 shouldn't be ready", _adapterTable.get(
223: doc6).isReady());
224:
225: // Reactivate all documents
226: doc1.getCurrentLine();
227: doc2.getCurrentLine();
228: doc3.getCurrentLine();
229: doc4.getCurrentLine();
230: doc5.getCurrentLine();
231: doc6.getCurrentLine();
232:
233: // System.err.println("Is doc1 untitled? " + doc1.isUntitled());
234:
235: // System.err.println("Cache contents = " + _cache);
236: // System.err.println("Document 1 is " + doc1);
237: assertTrue("Document 1 should be ready", _adapterTable
238: .get(doc1).isReady());
239: assertTrue("Document 2 should be ready", _adapterTable
240: .get(doc2).isReady());
241: assertTrue("Document 3 should be ready", _adapterTable
242: .get(doc3).isReady());
243: assertTrue("Document 4 should be ready", _adapterTable
244: .get(doc4).isReady());
245: assertTrue("Document 5 should be ready", _adapterTable
246: .get(doc5).isReady());
247: assertTrue("Document 6 should be ready", _adapterTable
248: .get(doc6).isReady());
249:
250: // New documents should not be cached at all
251:
252: assertEquals("Confirm that cache is empty", 0, _cache
253: .getNumInCache());
254:
255: }
256:
257: public void testOldDocumentsInAndOutOfTheCache()
258: throws BadLocationException, IOException {
259:
260: File file1 = tempFile(1);
261: File file2 = tempFile(2);
262: File file3 = tempFile(3);
263: File file4 = tempFile(4);
264: File file5 = tempFile(5);
265: File file6 = tempFile(6);
266:
267: // opening a document makes it active
268: OpenDefinitionsDocument doc1 = openFile(file1);
269: doc1.getCurrentLine(); // forces document to be read into memory
270: assertEquals("There should be 1 document in the cache", 1,
271: _cache.getNumInCache());
272: OpenDefinitionsDocument doc2 = openFile(file2);
273: doc2.getCurrentLine(); // forces document to be read into memory
274: assertEquals("There should be 2 documents in the cache", 2,
275: _cache.getNumInCache());
276: OpenDefinitionsDocument doc3 = openFile(file3);
277: doc3.getCurrentLine(); // forces document to be read into memory
278: assertEquals("There should be 3 documents in the cache", 3,
279: _cache.getNumInCache());
280: OpenDefinitionsDocument doc4 = openFile(file4);
281: doc4.getCurrentLine(); // forces document to be read into memory
282: assertEquals("There should be 4 documents in the cache", 4,
283: _cache.getNumInCache());
284: OpenDefinitionsDocument doc5 = openFile(file5);
285: doc5.getCurrentLine(); // forces document to be read into memory
286: assertEquals("There should be 4 documents in the cache", 4,
287: _cache.getNumInCache());
288: OpenDefinitionsDocument doc6 = openFile(file6);
289: doc6.getCurrentLine(); // forces document to be read into memory
290: assertEquals("There should be 4 documents in the cache", 4,
291: _cache.getNumInCache());
292:
293: assertEquals("Wrong Cache Size", 4, _cache.getCacheSize());
294:
295: // cache = [3 4 5 6]
296: // This tests that isModifiedSinceSave does not cause the document to load into the cache,
297: // so the two that should have been kicked out, 1 & 2 should not be loaded uppon calling isModified.
298:
299: assertFalse("Document 1 shouldn't be modified", doc1
300: .isModifiedSinceSave());
301: assertFalse("Document 2 shouldn't be modified", doc2
302: .isModifiedSinceSave());
303: assertFalse("Document 3 shouldn't be modified", doc3
304: .isModifiedSinceSave());
305: assertFalse("Document 4 shouldn't be modified", doc4
306: .isModifiedSinceSave());
307: assertFalse("Document 5 shouldn't be modified", doc5
308: .isModifiedSinceSave());
309: assertFalse("Document 6 shouldn't be modified", doc6
310: .isModifiedSinceSave());
311:
312: assertEquals("There should be 4 documents in the cache", 4,
313: _cache.getNumInCache());
314:
315: assertFalse("Document 1 shouldn't be ready", _adapterTable.get(
316: doc1).isReady());
317: assertFalse("Document 2 shouldn't be ready", _adapterTable.get(
318: doc2).isReady());
319: assertTrue("Document 3 should be ready", _adapterTable
320: .get(doc3).isReady());
321: assertTrue("Document 4 should be ready", _adapterTable
322: .get(doc4).isReady());
323: assertTrue("Document 5 should be ready", _adapterTable
324: .get(doc5).isReady());
325: assertTrue("Document 6 should be ready", _adapterTable
326: .get(doc6).isReady());
327:
328: // Rectivate all documents and make sure that the right ones get kicked out
329:
330: doc1.getCurrentLine();
331: doc2.getCurrentLine();
332: doc3.getCurrentLine();
333: doc4.getCurrentLine();
334:
335: // cache = [1 2 3 4]
336:
337: assertTrue("Document 1 should be ready", _adapterTable
338: .get(doc1).isReady());
339: assertTrue("Document 2 should be ready", _adapterTable
340: .get(doc2).isReady());
341: assertTrue("Document 3 should be ready", _adapterTable
342: .get(doc3).isReady());
343: assertTrue("Document 4 should be ready", _adapterTable
344: .get(doc4).isReady());
345:
346: doc5.getCurrentLine();
347: // cache -> 2 3 4 5
348: assertFalse("Document 1 is not longer ready", _adapterTable
349: .get(doc1).isReady());
350: assertTrue("Document 5 should be ready", _adapterTable
351: .get(doc5).isReady());
352:
353: doc6.getCurrentLine();
354: // cache -> 3 4 5 6
355: assertFalse("Document 2 is not longer ready", _adapterTable
356: .get(doc2).isReady());
357: assertTrue("Document 6 should be ready", _adapterTable
358: .get(doc6).isReady());
359: assertTrue("Document 3 should be ready", _adapterTable
360: .get(doc3).isReady());
361: assertTrue("Document 4 should be ready", _adapterTable
362: .get(doc4).isReady());
363: assertTrue("Document 5 should be ready", _adapterTable
364: .get(doc5).isReady());
365:
366: doc1.getCurrentLine(); // 4 5 6 1
367: assertTrue("The document 1 should should now be in the cache",
368: _adapterTable.get(doc1).isReady());
369: assertEquals("There should still be 4 documents in the cache",
370: 4, _cache.getNumInCache());
371: assertFalse(
372: "The document 3 should have been kicked out of the cache",
373: _adapterTable.get(doc3).isReady());
374:
375: doc2.getCurrentLine(); // 5 6 1 2
376: assertTrue("The document 2 should should now be in the cache",
377: _adapterTable.get(doc2).isReady());
378: assertEquals("There should still be 4 documents in the cache",
379: 4, _cache.getNumInCache());
380: assertFalse(
381: "The document 4 should have been kicked out of the cache",
382: _adapterTable.get(doc4).isReady());
383:
384: doc3.getCurrentLine(); // 6 1 2 3
385: assertTrue("The document 3 should should now be in the cache",
386: _adapterTable.get(doc3).isReady());
387: assertEquals("There should still be 4 documents in the cache",
388: 4, _cache.getNumInCache());
389: assertFalse(
390: "The document 5 should have been kicked out of the cache",
391: _adapterTable.get(doc5).isReady());
392:
393: doc4.getCurrentLine(); // 1 2 3 4
394: assertTrue("The document 4 should should now be in the cache",
395: _adapterTable.get(doc4).isReady());
396: assertEquals("There should still be 4 documents in the cache",
397: 4, _cache.getNumInCache());
398: assertFalse(
399: "The document 6 should have been kicked out of the cache",
400: _adapterTable.get(doc6).isReady());
401:
402: doc5.getCurrentLine(); // 2 3 4 5
403: assertTrue("The document 5 should should now be in the cache",
404: _adapterTable.get(doc5).isReady());
405: assertEquals("There should still be 4 documents in the cache",
406: 4, _cache.getNumInCache());
407: assertFalse(
408: "The document 1 should have been kicked out of the cache",
409: _adapterTable.get(doc1).isReady());
410:
411: doc6.getCurrentLine(); // 3 4 5 6
412: assertTrue("The document 6 should should now be in the cache",
413: _adapterTable.get(doc6).isReady());
414: assertEquals("There should still be 4 documents in the cache",
415: 4, _cache.getNumInCache());
416: assertFalse(
417: "The document 2 should have been kicked out of the cache",
418: _adapterTable.get(doc2).isReady());
419:
420: // Load documents out of order
421: doc4.getCurrentLine(); // 3 4 5 6
422: assertTrue(
423: "The document 3 should should still be in the cache",
424: _adapterTable.get(doc3).isReady());
425: assertEquals("There should still be 4 documents in the cache",
426: 4, _cache.getNumInCache());
427: doc5.getCurrentLine(); // 3 4 5 6
428: assertTrue(
429: "The document 3 should should still be in the cache",
430: _adapterTable.get(doc3).isReady());
431: assertEquals("There should still be 4 documents in the cache",
432: 4, _cache.getNumInCache());
433: doc3.getCurrentLine(); // 3 4 5 6
434: assertTrue(
435: "The document 6 should should still be in the cache",
436: _adapterTable.get(doc6).isReady());
437: assertEquals("There should still be 4 documents in the cache",
438: 4, _cache.getNumInCache());
439: doc4.getCurrentLine(); // 3 4 5 6
440: assertTrue(
441: "The document 6 should should still be in the cache",
442: _adapterTable.get(doc6).isReady());
443:
444: assertEquals("There should be 4 documents in the cache", 4,
445: _cache.getNumInCache());
446: assertFalse("The document 1 should still be out of the cache",
447: _adapterTable.get(doc1).isReady());
448: assertFalse("The document 2 should still be out of the cache",
449: _adapterTable.get(doc2).isReady());
450:
451: // Test the resize cache method by increasing the size of the cache to 5, which is still less than the number of open documents: 6
452: _cache.setCacheSize(5); // 3 4 5 6
453: assertEquals("The cache size should now be 5", 5, _cache
454: .getCacheSize());
455: assertEquals("There should still only be 4 files in the cache",
456: 4, _cache.getNumInCache());
457:
458: doc2.getCurrentLine(); // 3 4 5 6 2
459: assertTrue("The document 2 should now be in the cache",
460: _adapterTable.get(doc2).isReady());
461: assertFalse("The document 1 should still be out of the cache",
462: _adapterTable.get(doc1).isReady());
463: assertEquals("There should be 5 documents in the cache", 5,
464: _cache.getNumInCache());
465:
466: _cache.setCacheSize(3); // 5 6 2
467:
468: assertEquals("The cache size should now be 3", 3, _cache
469: .getCacheSize());
470: assertEquals("There should be 3 documents in the cache", 3,
471: _cache.getNumInCache());
472: assertTrue("The document 2 should be in the cache",
473: _adapterTable.get(doc2).isReady());
474: assertTrue("The document 6 should be in the cache",
475: _adapterTable.get(doc6).isReady());
476: assertTrue("The document 5 should be in the cache",
477: _adapterTable.get(doc5).isReady());
478: assertFalse("The document 3 should now be out of the cache",
479: _adapterTable.get(doc3).isReady());
480: assertFalse("The document 4 should now be out of the cache",
481: _adapterTable.get(doc4).isReady());
482: assertFalse("The document 1 should still be out of the cache",
483: _adapterTable.get(doc1).isReady());
484: }
485:
486: public void testGetDDocFromCache() throws BadLocationException,
487: IOException, OperationCanceledException {
488: File file1 = tempFile(1);
489: File file2 = tempFile(2);
490: File file3 = tempFile(3);
491: File file4 = tempFile(4);
492: File file5 = tempFile(5);
493: File file6 = tempFile(6);
494:
495: // opening a document should set it as active
496: OpenDefinitionsDocument doc1 = openFile(file1);
497: doc1.getCurrentLine(); // forces document to be read into memory
498: assertTrue("The document should not start out in the cache",
499: _adapterTable.get(doc1).isReady());
500: assertEquals("There should be 1 documents in the cache", 1,
501: _cache.getNumInCache());
502:
503: OpenDefinitionsDocument doc2 = openFile(file2);
504: doc2.getCurrentLine(); // forces document to be read into memory
505: assertTrue("The document should not start out in the cache",
506: _adapterTable.get(doc2).isReady());
507: assertEquals("There should be 2 documents in the cache", 2,
508: _cache.getNumInCache());
509:
510: OpenDefinitionsDocument doc3 = openFile(file3);
511: doc3.getCurrentLine(); // forces document to be read into memory
512: assertTrue("The document should not start out in the cache",
513: _adapterTable.get(doc3).isReady());
514: assertEquals("There should be 3 documents in the cache", 3,
515: _cache.getNumInCache());
516:
517: OpenDefinitionsDocument doc4 = openFile(file4);
518: doc4.getCurrentLine(); // forces document to be read into memory
519: assertTrue("The document should not start out in the cache",
520: _adapterTable.get(doc4).isReady());
521: assertEquals("There should be 4 documents in the cache", 4,
522: _cache.getNumInCache());
523:
524: OpenDefinitionsDocument doc5 = openFile(file5);
525: doc5.getCurrentLine(); // forces document to be read into memory
526: assertTrue("The document should not start out in the cache",
527: _adapterTable.get(doc5).isReady());
528: assertFalse("The document should not start out in the cache",
529: _adapterTable.get(doc1).isReady());
530: assertEquals("There should be 4 documents in the cache", 4,
531: _cache.getNumInCache());
532:
533: OpenDefinitionsDocument doc6 = openFile(file6);
534: doc6.getCurrentLine(); // forces document to be read into memory
535: assertTrue("The document should not start out in the cache",
536: _adapterTable.get(doc6).isReady());
537: assertFalse("The document should not start out in the cache",
538: _adapterTable.get(doc2).isReady());
539: assertEquals("There should be 4 documents in the cache", 4,
540: _cache.getNumInCache());
541: }
542:
543: private DefinitionsDocument _saved; // used for testReconstructor()
544:
545: public void testReconstructor() throws IOException {
546: DDReconstructor d = new DDReconstructor() {
547: public DefinitionsDocument make() {
548: _doc_made++;
549: return _saved;
550: }
551:
552: public void saveDocInfo(DefinitionsDocument doc) {
553: _doc_saved++;
554: }
555:
556: public void addDocumentListener(
557: javax.swing.event.DocumentListener dl) { /* do nothing */
558: }
559:
560: public String getText() {
561: return null;
562: }
563:
564: public String getText(int offset, int length) {
565: return null;
566: }
567: };
568:
569: OpenDefinitionsDocument doc1 = _model.newFile();
570: assertFalse("The document should not be in the cache",
571: _adapterTable.get(doc1).isReady());
572: _saved = _adapterTable.get(doc1).getDocument();
573: assertTrue("The document should be in the cache", _adapterTable
574: .get(doc1).isReady());
575:
576: // _adapterTable.get(doc1).setReconstructor(d);
577: // assertFalse("The document should not be in the cache after an update", _adapterTable.get(doc1).isReady());
578: //
579: // _adapterTable.get(doc1).getDocument(); // force the cache to reconstruct the document.
580: //
581: // assertEquals("The make in the reconstructor was called 1nce", 1, _doc_made);
582: // assertEquals("The save in the reconstructor was not called", 0, _doc_saved);
583: }
584:
585: // not being used. The new definition of the cache allows for a closed document, if it is used again, to bring its document back.
586: // This should be dealt with.
587: public void testNoDDocInCache() {
588: OpenDefinitionsDocument doc1 = _model.newFile();
589: _model.closeFile(doc1);
590: assertFalse("The document should now be closed", _adapterTable
591: .get(doc1).isReady());
592: }
593:
594: public void testNumListeners() {
595: OpenDefinitionsDocument doc1 = _model.newFile();
596: OpenDefinitionsDocument doc2 = _model.newFile();
597: OpenDefinitionsDocument doc3 = _model.newFile();
598: OpenDefinitionsDocument doc4 = _model.newFile();
599: OpenDefinitionsDocument doc5 = _model.newFile();
600:
601: int numDocListeners = doc1.getDocumentListeners().length;
602: int numUndoListeners = doc1.getUndoableEditListeners().length;
603:
604: doc1.getCurrentLine();
605: doc2.getCurrentLine();
606: doc3.getCurrentLine();
607: doc4.getCurrentLine();
608:
609: // this will kick document one out of the cache
610: doc5.getCurrentLine();
611:
612: // this will reconstruct document 1
613: doc1.getCurrentLine();
614:
615: assertEquals(
616: "the number of document listeners is the same after reconstruction",
617: numDocListeners, doc1.getDocumentListeners().length);
618: assertEquals(
619: "the number of undoableEditListeners is the same after reconstruction",
620: numUndoListeners,
621: doc1.getUndoableEditListeners().length);
622:
623: }
624:
625: /**
626: * There used to be a memory leak where various listeners,
627: * LeafElements, and other extraneous references from the model,
628: * definitions pane, and main frame would be preventing the
629: * definitions panes/documents from being GC'd at the correct
630: * times causing the entire program to run out of heap space
631: * when working with large numbers of files. This problem was
632: * agrivated when we added project facility and implemented
633: * the document cache (which was supposed to solve our memory
634: * problem but actually worsened it).
635: * <p>Adam and Jonathan went through great pains to remove
636: * these references, so <b>don't break our work!!!</b></p>
637: */
638: public void testMemoryLeak() throws InterruptedException,
639: IOException {
640: _memLeakCounter = 0;
641: FinalizationListener<DefinitionsDocument> fl = new FinalizationListener<DefinitionsDocument>() {
642: public void finalized(
643: FinalizationEvent<DefinitionsDocument> fe) {
644: _memLeakCounter++;
645: }
646: };
647:
648: // Adding the listeners will load the document into the cache
649:
650: OpenDefinitionsDocument doc1 = openFile(tempFile(1));
651: OpenDefinitionsDocument doc2 = openFile(tempFile(2));
652: OpenDefinitionsDocument doc3 = openFile(tempFile(3));
653: OpenDefinitionsDocument doc4 = openFile(tempFile(4));
654: OpenDefinitionsDocument doc5 = openFile(tempFile(5));
655:
656: doc1.addFinalizationListener(fl);
657: doc2.addFinalizationListener(fl);
658: doc3.addFinalizationListener(fl);
659: doc4.addFinalizationListener(fl);
660: doc5.addFinalizationListener(fl); // kick 1 out
661:
662: assertEquals("There should be 4 in the QUEUE", 4, _cache
663: .getNumInCache());
664: System.gc();
665: Thread.sleep(100);
666:
667: assertFalse("doc1 should be the one that's not ready",
668: _adapterTable.get(doc1).isReady());
669: assertEquals("One doc should have been collected", 1,
670: _memLeakCounter);
671:
672: doc1.getCurrentLine(); // kick 2
673:
674: // make sure doc1 has it's finalization listener still
675: List<FinalizationListener<DefinitionsDocument>> list = doc1
676: .getFinalizationListeners();
677: assertEquals("There should only be one finalization listener",
678: 1, list.size());
679: assertEquals("The finalization listener should be fl", fl, list
680: .get(0));
681:
682: doc2.getCurrentLine(); // kick 3
683: doc3.getCurrentLine(); // kick 4
684: doc4.getCurrentLine(); // kick 5
685: doc5.getCurrentLine(); // kick 1
686:
687: System.gc();
688: Thread.sleep(100);
689: assertEquals("several docs should have been collected", 6,
690: _memLeakCounter);
691:
692: }
693:
694: private int _memLeakCounter;
695:
696: /** This is just so that we can have an instance of a DefaultGlobalModel rather than a single display model. */
697: private class TestGlobalModel extends DefaultGlobalModel {
698: public void aboutToSaveFromSaveAll(OpenDefinitionsDocument doc) { /* dummy method */
699: }
700:
701: public void saveAllFiles(FileSaveSelector fs)
702: throws IOException {
703: saveAllFilesHelper(fs);
704: }
705:
706: public OpenDefinitionsDocument newFile() {
707: return newFile(getMasterWorkingDirectory());
708: }
709:
710: public OpenDefinitionsDocument openFile(FileOpenSelector fs)
711: throws IOException, OperationCanceledException,
712: AlreadyOpenException {
713: return openFileHelper(fs);
714: }
715:
716: public boolean closeFile(OpenDefinitionsDocument doc) {
717: return closeFileHelper(doc);
718: }
719:
720: public OpenDefinitionsDocument[] openFiles(FileOpenSelector com)
721: throws IOException, OperationCanceledException,
722: AlreadyOpenException {
723: return openFilesHelper(com);
724: }
725:
726: public boolean closeAllFiles() {
727: closeAllFilesOnQuit();
728: return true;
729: }
730: }
731: }
|