KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > edu > rice > cs > drjava > model > cache > DocumentCacheTest


1 /*BEGIN_COPYRIGHT_BLOCK
2  *
3  * This file is part of DrJava. Download the current version of this project from http://www.drjava.org/
4  * or http://sourceforge.net/projects/drjava/
5  *
6  * DrJava Open Source License
7  *
8  * Copyright (C) 2001-2005 JavaPLT group at Rice University (javaplt@rice.edu). All rights reserved.
9  *
10  * Developed by: Java Programming Languages Team, Rice University, http://www.cs.rice.edu/~javaplt/
11  *
12  * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
13  * documentation files (the "Software"), to deal with the Software without restriction, including without limitation
14  * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and
15  * to permit persons to whom the Software is furnished to do so, subject to the following conditions:
16  *
17  * - Redistributions of source code must retain the above copyright notice, this list of conditions and the
18  * following disclaimers.
19  * - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the
20  * following disclaimers in the documentation and/or other materials provided with the distribution.
21  * - Neither the names of DrJava, the JavaPLT, Rice University, nor the names of its contributors may be used to
22  * endorse or promote products derived from this Software without specific prior written permission.
23  * - Products derived from this software may not be called "DrJava" nor use the term "DrJava" as part of their
24  * names without prior written permission from the JavaPLT group. For permission, write to javaplt@rice.edu.
25  *
26  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO
27  * THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
28  * CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
29  * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
30  * WITH THE SOFTWARE.
31  *
32  *END_COPYRIGHT_BLOCK*/

33
34 package edu.rice.cs.drjava.model.cache;
35
36 import edu.rice.cs.drjava.DrJavaTestCase;
37 import edu.rice.cs.drjava.model.*;
38 import edu.rice.cs.drjava.model.definitions.DefinitionsDocument;
39 import edu.rice.cs.plt.io.IOUtil;
40 import edu.rice.cs.util.FileOpenSelector;
41 import edu.rice.cs.util.OperationCanceledException;
42
43 import javax.swing.text.BadLocationException JavaDoc;
44 import java.io.File JavaDoc;
45 import java.io.IOException JavaDoc;
46 import java.util.Hashtable JavaDoc;
47 import java.util.List JavaDoc;
48
49 /** This used to extend GlobalModelTestCase, but now it extends just TestCase. Perhaps it should be changed back. */
50 public class DocumentCacheTest extends DrJavaTestCase {
51   
52   private DefaultGlobalModel _model;
53   private DocumentCache _cache;
54   private Hashtable JavaDoc<OpenDefinitionsDocument, DCacheAdapter> _adapterTable;
55   
56   private int _doc_made;
57   private int _doc_saved;
58   
59   protected File JavaDoc _tempDir;
60
61   public void setUp() throws Exception JavaDoc {
62     super.setUp();
63     createModel();
64     
65     String JavaDoc user = System.getProperty("user.name");
66     _tempDir = IOUtil.createAndMarkTempDirectory("DrJava-test-" + user, "");
67     
68     _cache = _model.getDocumentCache();
69     _cache.setCacheSize(4);
70     _adapterTable = new Hashtable JavaDoc<OpenDefinitionsDocument, DCacheAdapter> ();
71     _cache.addRegistrationListener(new DocumentCache.RegistrationListener() {
72       public void registered(OpenDefinitionsDocument odd, DCacheAdapter a) {
73         _adapterTable.put(odd, a);
74       }
75     });
76     _doc_made = 0;
77     _doc_saved = 0;
78   }
79   
80   public void tearDown() throws Exception JavaDoc {
81     boolean ret = IOUtil.deleteRecursively(_tempDir);
82     assertTrue("delete temp directory " + _tempDir, ret);
83     _model.dispose();
84
85     _tempDir = null;
86     _model = null;
87     super.tearDown();
88   }
89   
90   /** Instantiates the GlobalModel to be used in the test cases. */
91   protected void createModel() {
92     //_model = new DefaultGlobalModel(_originalModel);
93
_model = new TestGlobalModel();
94
95     // Wait until it has connected
96
_model.waitForInterpreter();
97   }
98
99   /** Create a new temporary file in _tempDir. */
100   protected File JavaDoc tempFile() throws IOException JavaDoc {
101     return File.createTempFile("DrJava-test", ".java", _tempDir).getCanonicalFile();
102   }
103   
104   /** Create a new temporary file in _tempDir. Calls with the same
105    * int will return the same filename, while calls with different
106    * ints will return different filenames.
107    */

108   protected File JavaDoc tempFile(int i) throws IOException JavaDoc {
109     return File.createTempFile("DrJava-test" + i, ".java", _tempDir).getCanonicalFile();
110   }
111   
112   protected OpenDefinitionsDocument openFile(final File JavaDoc f) throws IOException JavaDoc {
113     try{
114       OpenDefinitionsDocument doc = _model.openFile(new FileOpenSelector() {
115         public File JavaDoc[] getFiles() { return new File JavaDoc[] {f}; }
116       });
117       return doc;
118     }
119     catch(AlreadyOpenException e) { throw new IOException JavaDoc(e.getMessage()); }
120     catch(OperationCanceledException e) { throw new IOException JavaDoc(e.getMessage());}
121   }
122   
123   /** A good warmup test case. */
124   public void testCacheSize() {
125     _cache.setCacheSize(6);
126     assertEquals("Wrong cache size", 6, _cache.getCacheSize());
127     _cache.setCacheSize(34);
128     assertEquals("Wrong cache size", 34, _cache.getCacheSize());
129     
130     /* test that an IllegalArgumentException is thrown when a
131      * cacheSize <= 0 is provided
132      */

133     try {
134      _cache.setCacheSize(0);
135      fail("IllegalArgumentException expected.");
136     }
137     catch (IllegalArgumentException JavaDoc iae) {
138       //We're good
139
}
140     
141     try {
142      _cache.setCacheSize(-34);
143      fail("IllegalArgumentException expected.");
144     }
145     catch (IllegalArgumentException JavaDoc iae) {
146       //We're good
147
}
148   }
149   
150   public void testNewDocumentsInAndOutOfTheCache() throws BadLocationException JavaDoc, IOException JavaDoc {
151     assertEquals("Wrong Cache Size", 4, _cache.getCacheSize());
152     
153     // The documents are activated soon after creation by a getLength operation done somewhere
154
// but they are not entered in the cache because they are new
155

156     OpenDefinitionsDocument doc1 = _model.newFile();
157     assertEquals("There should be 0 documents in the cache", 0, _cache.getNumInCache()); // was 0
158

159     OpenDefinitionsDocument doc2 = _model.newFile();
160     assertEquals("There should be 0 documents in the cache", 0, _cache.getNumInCache()); // was 0
161

162     OpenDefinitionsDocument doc3 = _model.newFile();
163     assertEquals("There should be 0 documents in the cache", 0, _cache.getNumInCache()); // was 0
164

165     OpenDefinitionsDocument doc4 = _model.newFile();
166     assertEquals("There should be 0 documents in the cache", 0, _cache.getNumInCache()); // was 0
167

168     OpenDefinitionsDocument doc5 = _model.newFile();
169     assertEquals("There should be 0 documents in the cache", 0, _cache.getNumInCache()); // was 0
170

171     OpenDefinitionsDocument doc6 = _model.newFile();
172     assertEquals("There should be 0 documents in the cache", 0, _cache.getNumInCache()); // was 0
173

174     // This tests that isModifiedSinceSave does not cause the document to load into the cache,
175
// so the two that should have been kicked out, 1 & 2 should not be loaded uppon calling isModified.
176

177     assertFalse("Document 1 shouldn't be modified", doc1.isModifiedSinceSave());
178     assertFalse("Document 2 shouldn't be modified", doc2.isModifiedSinceSave());
179     assertFalse("Document 3 shouldn't be modified", doc3.isModifiedSinceSave());
180     assertFalse("Document 4 shouldn't be modified", doc4.isModifiedSinceSave());
181     assertFalse("Document 5 shouldn't be modified", doc5.isModifiedSinceSave());
182     assertFalse("Document 6 shouldn't be modified", doc6.isModifiedSinceSave());
183     assertEquals("There should be 0 documents in the cache", 0, _cache.getNumInCache());
184     
185     assertFalse("Document 1 shouldn't be ready", _adapterTable.get(doc1).isReady());
186     assertFalse("Document 2 shouldn't be ready", _adapterTable.get(doc2).isReady());
187     assertFalse("Document 3 shouldn't be ready", _adapterTable.get(doc3).isReady());
188     assertFalse("Document 4 shouldn't be ready", _adapterTable.get(doc4).isReady());
189     assertFalse("Document 5 shouldn't be ready", _adapterTable.get(doc5).isReady());
190     assertFalse("Document 6 shouldn't be ready", _adapterTable.get(doc6).isReady());
191     
192     
193     // Reactivate all documents
194
doc1.getLength();
195     doc2.getLength();
196     doc3.getLength();
197     doc4.getLength();
198     doc5.getLength();
199     doc6.getLength();
200     
201     assertTrue("Document 1 should be ready", _adapterTable.get(doc1).isReady());
202     assertTrue("Document 2 should be ready", _adapterTable.get(doc2).isReady());
203     assertTrue("Document 3 should be ready", _adapterTable.get(doc3).isReady());
204     assertTrue("Document 4 should be ready", _adapterTable.get(doc4).isReady());
205     assertTrue("Document 5 should be ready", _adapterTable.get(doc5).isReady());
206     assertTrue("Document 6 should be ready", _adapterTable.get(doc6).isReady());
207     
208     // New documents should not be cached at all
209

210     assertEquals("Confirm that cache is empty", 0, _cache.getNumInCache());
211     
212   }
213   
214   public void testOldDocumentsInAndOutOfTheCache() throws BadLocationException JavaDoc, IOException JavaDoc {
215     
216     File JavaDoc file1 = tempFile(1);
217     File JavaDoc file2 = tempFile(2);
218     File JavaDoc file3 = tempFile(3);
219     File JavaDoc file4 = tempFile(4);
220     File JavaDoc file5 = tempFile(5);
221     File JavaDoc file6 = tempFile(6);
222     
223     // opening a document makes it active
224
OpenDefinitionsDocument doc1 = openFile(file1);
225     doc1.getLength(); // forces document to be read into memory
226
assertEquals("There should be 1 document in the cache", 1, _cache.getNumInCache());
227     OpenDefinitionsDocument doc2 = openFile(file2);
228     doc2.getLength(); // forces document to be read into memory
229
assertEquals("There should be 2 documents in the cache", 2, _cache.getNumInCache());
230     OpenDefinitionsDocument doc3 = openFile(file3);
231     doc3.getLength(); // forces document to be read into memory
232
assertEquals("There should be 3 documents in the cache", 3, _cache.getNumInCache());
233     OpenDefinitionsDocument doc4 = openFile(file4);
234     doc4.getLength(); // forces document to be read into memory
235
assertEquals("There should be 4 documents in the cache", 4, _cache.getNumInCache());
236     OpenDefinitionsDocument doc5 = openFile(file5);
237     doc5.getLength(); // forces document to be read into memory
238
assertEquals("There should be 4 documents in the cache", 4, _cache.getNumInCache());
239     OpenDefinitionsDocument doc6 = openFile(file6);
240     doc6.getLength(); // forces document to be read into memory
241
assertEquals("There should be 4 documents in the cache", 4, _cache.getNumInCache());
242     
243     assertEquals("Wrong Cache Size", 4, _cache.getCacheSize());
244
245     // cache = [3 4 5 6]
246
// This tests that isModifiedSinceSave does not cause the document to load into the cache,
247
// so the two that should have been kicked out, 1 & 2 should not be loaded uppon calling isModified.
248

249     assertFalse("Document 1 shouldn't be modified", doc1.isModifiedSinceSave());
250     assertFalse("Document 2 shouldn't be modified", doc2.isModifiedSinceSave());
251     assertFalse("Document 3 shouldn't be modified", doc3.isModifiedSinceSave());
252     assertFalse("Document 4 shouldn't be modified", doc4.isModifiedSinceSave());
253     assertFalse("Document 5 shouldn't be modified", doc5.isModifiedSinceSave());
254     assertFalse("Document 6 shouldn't be modified", doc6.isModifiedSinceSave());
255     
256     assertEquals("There should be 4 documents in the cache", 4, _cache.getNumInCache());
257     
258     assertFalse("Document 1 shouldn't be ready", _adapterTable.get(doc1).isReady());
259     assertFalse("Document 2 shouldn't be ready", _adapterTable.get(doc2).isReady());
260     assertTrue("Document 3 should be ready", _adapterTable.get(doc3).isReady());
261     assertTrue("Document 4 should be ready", _adapterTable.get(doc4).isReady());
262     assertTrue("Document 5 should be ready", _adapterTable.get(doc5).isReady());
263     assertTrue("Document 6 should be ready", _adapterTable.get(doc6).isReady());
264     
265     
266     // Rectivate all documents and make sure that the right ones get kicked out
267

268     doc1.getLength();
269     doc2.getLength();
270     doc3.getLength();
271     doc4.getLength();
272     
273    // cache = [1 2 3 4]
274

275     assertTrue("Document 1 should be ready", _adapterTable.get(doc1).isReady());
276     assertTrue("Document 2 should be ready", _adapterTable.get(doc2).isReady());
277     assertTrue("Document 3 should be ready", _adapterTable.get(doc3).isReady());
278     assertTrue("Document 4 should be ready", _adapterTable.get(doc4).isReady());
279     
280     doc5.getLength();
281     // cache -> 2 3 4 5
282
assertFalse("Document 1 is not longer ready", _adapterTable.get(doc1).isReady());
283     assertTrue("Document 5 should be ready", _adapterTable.get(doc5).isReady());
284     
285     doc6.getLength();
286     // cache -> 3 4 5 6
287
assertFalse("Document 2 is not longer ready", _adapterTable.get(doc2).isReady());
288     assertTrue("Document 6 should be ready", _adapterTable.get(doc6).isReady());
289     assertTrue("Document 3 should be ready", _adapterTable.get(doc3).isReady());
290     assertTrue("Document 4 should be ready", _adapterTable.get(doc4).isReady());
291     assertTrue("Document 5 should be ready", _adapterTable.get(doc5).isReady());
292     
293     doc1.getLength(); // 4 5 6 1
294
assertTrue("The document 1 should should now be in the cache", _adapterTable.get(doc1).isReady());
295     assertEquals("There should still be 4 documents in the cache", 4, _cache.getNumInCache());
296     assertFalse("The document 3 should have been kicked out of the cache", _adapterTable.get(doc3).isReady());
297     
298     doc2.getLength(); // 5 6 1 2
299
assertTrue("The document 2 should should now be in the cache", _adapterTable.get(doc2).isReady());
300     assertEquals("There should still be 4 documents in the cache", 4, _cache.getNumInCache());
301     assertFalse("The document 4 should have been kicked out of the cache", _adapterTable.get(doc4).isReady());
302     
303     doc3.getLength(); // 6 1 2 3
304
assertTrue("The document 3 should should now be in the cache", _adapterTable.get(doc3).isReady());
305     assertEquals("There should still be 4 documents in the cache", 4, _cache.getNumInCache());
306     assertFalse("The document 5 should have been kicked out of the cache", _adapterTable.get(doc5).isReady());
307     
308     doc4.getLength(); // 1 2 3 4
309
assertTrue("The document 4 should should now be in the cache", _adapterTable.get(doc4).isReady());
310     assertEquals("There should still be 4 documents in the cache", 4, _cache.getNumInCache());
311     assertFalse("The document 6 should have been kicked out of the cache", _adapterTable.get(doc6).isReady());
312     
313     doc5.getLength(); // 2 3 4 5
314
assertTrue("The document 5 should should now be in the cache", _adapterTable.get(doc5).isReady());
315     assertEquals("There should still be 4 documents in the cache", 4, _cache.getNumInCache());
316     assertFalse("The document 1 should have been kicked out of the cache", _adapterTable.get(doc1).isReady());
317     
318     doc6.getLength(); // 3 4 5 6
319
assertTrue("The document 6 should should now be in the cache", _adapterTable.get(doc6).isReady());
320     assertEquals("There should still be 4 documents in the cache", 4, _cache.getNumInCache());
321     assertFalse("The document 2 should have been kicked out of the cache", _adapterTable.get(doc2).isReady());
322     
323     // Load documents out of order
324
doc4.getLength(); // 3 4 5 6
325
assertTrue("The document 3 should should still be in the cache", _adapterTable.get(doc3).isReady());
326     assertEquals("There should still be 4 documents in the cache", 4, _cache.getNumInCache());
327     doc5.getLength(); // 3 4 5 6
328
assertTrue("The document 3 should should still be in the cache", _adapterTable.get(doc3).isReady());
329     assertEquals("There should still be 4 documents in the cache", 4, _cache.getNumInCache());
330     doc3.getLength(); // 3 4 5 6
331
assertTrue("The document 6 should should still be in the cache", _adapterTable.get(doc6).isReady());
332     assertEquals("There should still be 4 documents in the cache", 4, _cache.getNumInCache());
333     doc4.getLength(); // 3 4 5 6
334
assertTrue("The document 6 should should still be in the cache", _adapterTable.get(doc6).isReady());
335     
336     assertEquals("There should be 4 documents in the cache", 4, _cache.getNumInCache());
337     assertFalse("The document 1 should still be out of the cache", _adapterTable.get(doc1).isReady());
338     assertFalse("The document 2 should still be out of the cache", _adapterTable.get(doc2).isReady());
339     
340     // 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
341
_cache.setCacheSize(5); // 3 4 5 6
342
assertEquals("The cache size should now be 5", 5, _cache.getCacheSize());
343     assertEquals("There should still only be 4 files in the cache", 4, _cache.getNumInCache());
344     
345     doc2.getLength(); // 3 4 5 6 2
346
assertTrue("The document 2 should now be in the cache", _adapterTable.get(doc2).isReady());
347     assertFalse("The document 1 should still be out of the cache", _adapterTable.get(doc1).isReady());
348     assertEquals("There should be 5 documents in the cache", 5, _cache.getNumInCache());
349     
350     _cache.setCacheSize(3); // 5 6 2
351

352     assertEquals("The cache size should now be 3", 3, _cache.getCacheSize());
353     assertEquals("There should be 3 documents in the cache", 3, _cache.getNumInCache());
354     assertTrue("The document 2 should be in the cache", _adapterTable.get(doc2).isReady());
355     assertTrue("The document 6 should be in the cache", _adapterTable.get(doc6).isReady());
356     assertTrue("The document 5 should be in the cache", _adapterTable.get(doc5).isReady());
357     assertFalse("The document 3 should now be out of the cache", _adapterTable.get(doc3).isReady());
358     assertFalse("The document 4 should now be out of the cache", _adapterTable.get(doc4).isReady());
359     assertFalse("The document 1 should still be out of the cache", _adapterTable.get(doc1).isReady());
360   }
361   
362   public void testGetDDocFromCache() throws BadLocationException JavaDoc, IOException JavaDoc, OperationCanceledException {
363     File JavaDoc file1 = tempFile(1);
364     File JavaDoc file2 = tempFile(2);
365     File JavaDoc file3 = tempFile(3);
366     File JavaDoc file4 = tempFile(4);
367     File JavaDoc file5 = tempFile(5);
368     File JavaDoc file6 = tempFile(6);
369     
370     // opening a document should set it as active
371
OpenDefinitionsDocument doc1 = openFile(file1);
372     doc1.getLength(); // forces document to be read into memory
373
assertTrue("The document should not start out in the cache", _adapterTable.get(doc1).isReady());
374     assertEquals("There should be 1 documents in the cache", 1, _cache.getNumInCache());
375     
376     OpenDefinitionsDocument doc2 = openFile(file2);
377     doc2.getLength(); // forces document to be read into memory
378
assertTrue("The document should not start out in the cache", _adapterTable.get(doc2).isReady());
379     assertEquals("There should be 2 documents in the cache", 2, _cache.getNumInCache());
380     
381     OpenDefinitionsDocument doc3 = openFile(file3);
382     doc3.getLength(); // forces document to be read into memory
383
assertTrue("The document should not start out in the cache", _adapterTable.get(doc3).isReady());
384     assertEquals("There should be 3 documents in the cache", 3, _cache.getNumInCache());
385     
386     OpenDefinitionsDocument doc4 = openFile(file4);
387     doc4.getLength(); // forces document to be read into memory
388
assertTrue("The document should not start out in the cache", _adapterTable.get(doc4).isReady());
389     assertEquals("There should be 4 documents in the cache", 4, _cache.getNumInCache());
390     
391     OpenDefinitionsDocument doc5 = openFile(file5);
392     doc5.getLength(); // forces document to be read into memory
393
assertTrue("The document should not start out in the cache", _adapterTable.get(doc5).isReady());
394     assertFalse("The document should not start out in the cache", _adapterTable.get(doc1).isReady());
395     assertEquals("There should be 4 documents in the cache", 4, _cache.getNumInCache());
396     
397     OpenDefinitionsDocument doc6 = openFile(file6);
398     doc6.getLength(); // forces document to be read into memory
399
assertTrue("The document should not start out in the cache", _adapterTable.get(doc6).isReady());
400     assertFalse("The document should not start out in the cache", _adapterTable.get(doc2).isReady());
401     assertEquals("There should be 4 documents in the cache", 4, _cache.getNumInCache());
402   }
403   
404   
405   private DefinitionsDocument _saved; // used for testReconstructor()
406

407   public void testReconstructor() throws IOException JavaDoc{
408     DDReconstructor d = new DDReconstructor() {
409       public DefinitionsDocument make() {
410         _doc_made++;
411         return _saved;
412       }
413       public void saveDocInfo(DefinitionsDocument doc) { _doc_saved++; }
414       public void addDocumentListener(javax.swing.event.DocumentListener JavaDoc dl) { /* do nothing */ }
415     };
416     
417     OpenDefinitionsDocument doc1 = _model.newFile();
418     assertFalse("The document should not be in the cache", _adapterTable.get(doc1).isReady());
419     _saved = _adapterTable.get(doc1).getDocument();
420     assertTrue("The document should be in the cache", _adapterTable.get(doc1).isReady());
421     
422 // _adapterTable.get(doc1).setReconstructor(d);
423
// assertFalse("The document should not be in the cache after an update", _adapterTable.get(doc1).isReady());
424
//
425
// _adapterTable.get(doc1).getDocument(); // force the cache to reconstruct the document.
426
//
427
// assertEquals("The make in the reconstructor was called 1nce", 1, _doc_made);
428
// assertEquals("The save in the reconstructor was not called", 0, _doc_saved);
429
}
430   
431   // not being used. The new definition of the cache allows for a closed document, if it is used again, to bring its document back.
432
// This should be dealt with.
433
public void testNoDDocInCache() {
434    OpenDefinitionsDocument doc1 = _model.newFile();
435    _model.closeFile(doc1);
436    assertFalse("The document should now be closed", _adapterTable.get(doc1).isReady());
437   }
438
439
440   public void testNumListeners() {
441    OpenDefinitionsDocument doc1 = _model.newFile();
442    OpenDefinitionsDocument doc2 = _model.newFile();
443    OpenDefinitionsDocument doc3 = _model.newFile();
444    OpenDefinitionsDocument doc4 = _model.newFile();
445    OpenDefinitionsDocument doc5 = _model.newFile();
446
447    int numDocListeners = doc1.getDocumentListeners().length;
448    int numUndoListeners = doc1.getUndoableEditListeners().length;
449    
450    doc1.getLength();
451    doc2.getLength();
452    doc3.getLength();
453    doc4.getLength();
454
455    // this will kick document one out of the cache
456
doc5.getLength();
457  
458    // this will reconstruct document 1
459
doc1.getLength();
460    
461    assertEquals("the number of document listeners is the same after reconstruction", numDocListeners,
462                 doc1.getDocumentListeners().length);
463    assertEquals("the number of undoableEditListeners is the same after reconstruction", numUndoListeners,
464                 doc1.getUndoableEditListeners().length);
465
466   }
467   
468   /**
469    * There used to be a memory leak where various listeners,
470    * LeafElements, and other extraneous references from the model,
471    * definitions pane, and main frame would be preventing the
472    * definitions panes/documents from being GC'd at the correct
473    * times causing the entire program to run out of heap space
474    * when working with large numbers of files. This problem was
475    * agrivated when we added project facility and implemented
476    * the document cache (which was supposed to solve our memory
477    * problem but actually worsened it).
478    * <p>Adam and Jonathan went through great pains to remove
479    * these references, so <b>don't break our work!!!</b></p>
480    */

481   public void testMemoryLeak() throws InterruptedException JavaDoc, IOException JavaDoc {
482     _memLeakCounter=0;
483     FinalizationListener<DefinitionsDocument> fl = new FinalizationListener<DefinitionsDocument>() {
484       public void finalized(FinalizationEvent<DefinitionsDocument> fe) {
485         _memLeakCounter++;
486       }
487     };
488     
489     // Adding the listeners will load the document into the cache
490

491    
492     OpenDefinitionsDocument doc1 = openFile(tempFile(1));
493     OpenDefinitionsDocument doc2 = openFile(tempFile(2));
494     OpenDefinitionsDocument doc3 = openFile(tempFile(3));
495     OpenDefinitionsDocument doc4 = openFile(tempFile(4));
496     OpenDefinitionsDocument doc5 = openFile(tempFile(5));
497         
498     doc1.addFinalizationListener(fl);
499     doc2.addFinalizationListener(fl);
500     doc3.addFinalizationListener(fl);
501     doc4.addFinalizationListener(fl);
502     doc5.addFinalizationListener(fl); // kick 1 out
503

504     assertEquals("There should be 4 in the QUEUE", 4, _cache.getNumInCache());
505     System.gc();
506     Thread.sleep(100);
507     
508     
509     assertFalse("doc1 should be the one that's not ready", _adapterTable.get(doc1).isReady());
510     assertEquals("One doc should have been collected", 1, _memLeakCounter);
511     
512     doc1.getLength(); // kick 2
513

514     // make sure doc1 has it's finalization listener still
515
List JavaDoc<FinalizationListener<DefinitionsDocument>> list = doc1.getFinalizationListeners();
516     assertEquals("There should only be one finalization listener", 1, list.size());
517     assertEquals("The finalization listener should be fl", fl, list.get(0));
518     
519     doc2.getLength(); // kick 3
520
doc3.getLength(); // kick 4
521
doc4.getLength(); // kick 5
522
doc5.getLength(); // kick 1
523

524     System.gc();
525     Thread.sleep(100);
526     assertEquals("several docs should have been collected", 6, _memLeakCounter);
527     
528   }
529   private int _memLeakCounter;
530   
531   /** This is just so that we can have an instance of a DefaultGlobalModel rather than a single display model. */
532   private class TestGlobalModel extends DefaultGlobalModel {
533     public void aboutToSaveFromSaveAll(OpenDefinitionsDocument doc) { /* dummy method */ }
534     public void saveAllFiles(FileSaveSelector fs) throws IOException JavaDoc { saveAllFilesHelper(fs); }
535     
536     public OpenDefinitionsDocument newFile() { return newFile(getMasterWorkingDirectory()); }
537     public OpenDefinitionsDocument openFile(FileOpenSelector fs)
538       throws IOException JavaDoc, OperationCanceledException, AlreadyOpenException {
539       return openFileHelper(fs);
540     }
541     public boolean closeFile(OpenDefinitionsDocument doc) { return closeFileHelper(doc); }
542     public OpenDefinitionsDocument[] openFiles(FileOpenSelector com)
543       throws IOException JavaDoc, OperationCanceledException, AlreadyOpenException {
544       return openFilesHelper(com);
545     }
546     public boolean closeAllFiles() {
547       closeAllFilesOnQuit();
548       return true;
549     }
550   }
551 }
552
Popular Tags