Clover icon

Coverage Report

  1. Project Clover database Thu Aug 13 2020 12:04:21 BST
  2. Package jalview.gui

File FreeUpMemoryTest.java

 

Code metrics

8
59
7
1
242
124
13
0.22
8.43
7
1.86

Classes

Class Line # Actions
FreeUpMemoryTest 25 59 13
0.00%
 

Contributing tests

No tests hitting this source file were found.

Source view

1    package jalview.gui;
2   
3    import static org.testng.Assert.assertEquals;
4    import static org.testng.Assert.assertNotNull;
5    import static org.testng.Assert.assertTrue;
6   
7    import jalview.analysis.AlignmentGenerator;
8    import jalview.bin.Cache;
9    import jalview.bin.Jalview;
10    import jalview.datamodel.AlignmentI;
11    import jalview.datamodel.SequenceGroup;
12    import jalview.io.DataSourceType;
13    import jalview.io.FileLoader;
14   
15    import java.awt.event.MouseEvent;
16    import java.io.File;
17    import java.io.IOException;
18    import java.io.PrintStream;
19   
20    import org.testng.annotations.BeforeClass;
21    import org.testng.annotations.Test;
22   
23    import junit.extensions.PA;
24   
 
25    public class FreeUpMemoryTest
26    {
27    private static final int ONE_MB = 1000 * 1000;
28   
29    /**
30    * Configure (read-only) Jalview property settings for test
31    */
 
32  0 toggle @BeforeClass(alwaysRun = true)
33    public void setUp()
34    {
35  0 Jalview.main(new String[] { "-nonews", "-props",
36    "test/jalview/testProps.jvprops" });
37  0 String True = Boolean.TRUE.toString();
38  0 Cache.applicationProperties.setProperty("SHOW_ANNOTATIONS", True);
39  0 Cache.applicationProperties.setProperty("SHOW_QUALITY", True);
40  0 Cache.applicationProperties.setProperty("SHOW_CONSERVATION", True);
41  0 Cache.applicationProperties.setProperty("SHOW_OCCUPANCY", True);
42  0 Cache.applicationProperties.setProperty("SHOW_IDENTITY", True);
43    }
44   
45    /**
46    * A simple test that memory is released when all windows are closed.
47    * <ul>
48    * <li>generates a reasonably large alignment and loads it</li>
49    * <li>performs various operations on the alignment</li>
50    * <li>closes all windows</li>
51    * <li>requests garbage collection</li>
52    * <li>asserts that the remaining memory footprint (heap usage) is 'not large'
53    * </li>
54    * </ul>
55    * If the test fails, this suggests that a reference to some large object
56    * (perhaps the alignment data, or some annotation / Tree / PCA data) has
57    * failed to be garbage collected. If this is the case, the heap will need to
58    * be inspected manually (suggest using jvisualvm) in order to track down
59    * where large objects are still referenced. The code (for example
60    * AlignmentViewport.dispose()) should then be updated to ensure references to
61    * large objects are set to null when they are no longer required.
62    *
63    * @throws IOException
64    */
 
65  0 toggle @Test(groups = "Memory")
66    public void testFreeMemoryOnClose() throws IOException
67    {
68  0 File f = generateAlignment();
69  0 f.deleteOnExit();
70   
71  0 long expectedMin = 35L;
72  0 long usedMemoryAtStart=getUsedMemory();
73  0 if (usedMemoryAtStart>expectedMin)
74    {
75  0 System.err.println("used memory before test is "+usedMemoryAtStart+" > "+expectedMin+"MB .. adjusting minimum.");
76  0 expectedMin = usedMemoryAtStart;
77    }
78  0 doStuffInJalview(f);
79   
80  0 Desktop.instance.closeAll_actionPerformed(null);
81   
82  0 checkUsedMemory(expectedMin);
83    }
84   
 
85  0 toggle private static long getUsedMemory()
86    {
87  0 long availableMemory = Runtime.getRuntime().totalMemory() / ONE_MB;
88  0 long freeMemory = Runtime.getRuntime().freeMemory() / ONE_MB;
89  0 long usedMemory = availableMemory - freeMemory;
90  0 return usedMemory;
91    }
92    /**
93    * Requests garbage collection and then checks whether remaining memory in use
94    * is less than the expected value (in Megabytes)
95    *
96    * @param expectedMax
97    */
 
98  0 toggle protected void checkUsedMemory(long expectedMax)
99    {
100    /*
101    * request garbage collection and wait for it to run;
102    * NB there is no guarantee when, or whether, it will do so
103    * wait time depends on JRE/processor, generous allowance here
104    */
105  0 System.gc();
106  0 waitFor(1500);
107   
108    /*
109    * a second gc() call should not be necessary - but it is!
110    * the test passes with it, and fails without it
111    */
112  0 System.gc();
113  0 waitFor(1500);
114   
115    /*
116    * check used memory is 'reasonably low'
117    */
118  0 long usedMemory = getUsedMemory();
119    /*
120    * sanity check - fails if any frame was added after
121    * closeAll_actionPerformed
122    */
123  0 assertEquals(Desktop.instance.getAllFrames().length, 0);
124   
125    /*
126    * if this assertion fails
127    * - set a breakpoint here
128    * - run jvisualvm to inspect a heap dump of Jalview
129    * - identify large objects in the heap and their referers
130    * - fix code as necessary to null the references on close
131    */
132  0 System.out.println("Used memory after gc = " + usedMemory + "MB");
133  0 assertTrue(usedMemory < expectedMax, String.format(
134    "Used memory %d should be less than %d (Recommend running test manually to verify)",
135    usedMemory,
136    expectedMax));
137    }
138   
139    /**
140    * Loads an alignment from file and exercises various operations in Jalview
141    *
142    * @param f
143    */
 
144  0 toggle protected void doStuffInJalview(File f)
145    {
146    /*
147    * load alignment, wait for consensus and other threads to complete
148    */
149  0 AlignFrame af = new FileLoader().LoadFileWaitTillLoaded(f.getPath(),
150    DataSourceType.FILE);
151  0 while (af.getViewport().isCalcInProgress())
152    {
153  0 waitFor(200);
154    }
155   
156    /*
157    * open an Overview window
158    */
159  0 af.overviewMenuItem_actionPerformed(null);
160  0 assertNotNull(af.alignPanel.overviewPanel);
161   
162    /*
163    * exercise the pop-up menu in the Overview Panel (JAL-2864)
164    */
165  0 Object[] args = new Object[] {
166    new MouseEvent(af, 0, 0, 0, 0, 0, 1, true) };
167  0 PA.invokeMethod(af.alignPanel.overviewPanel,
168    "showPopupMenu(java.awt.event.MouseEvent)", args);
169   
170    /*
171    * set a selection group - potential memory leak if it retains
172    * a reference to the alignment
173    */
174  0 SequenceGroup sg = new SequenceGroup();
175  0 sg.setStartRes(0);
176  0 sg.setEndRes(100);
177  0 AlignmentI al = af.viewport.getAlignment();
178  0 for (int i = 0; i < al.getHeight(); i++)
179    {
180  0 sg.addSequence(al.getSequenceAt(i), false);
181    }
182  0 af.viewport.setSelectionGroup(sg);
183   
184    /*
185    * compute Tree and PCA (on all sequences, 100 columns)
186    */
187  0 af.openTreePcaDialog();
188  0 CalculationChooser dialog = af.alignPanel.getCalculationDialog();
189  0 dialog.openPcaPanel("BLOSUM62", dialog.getSimilarityParameters(true));
190  0 dialog.openTreePanel("BLOSUM62", dialog.getSimilarityParameters(false));
191   
192    /*
193    * wait until Tree and PCA have been computed
194    */
195  0 while (af.viewport.getCurrentTree() == null
196    && dialog.getPcaPanel().isWorking())
197    {
198  0 waitFor(10);
199    }
200   
201    /*
202    * give Swing time to add the PCA panel (?!?)
203    */
204  0 waitFor(100);
205    }
206   
207    /**
208    * Wait for waitMs miliseconds
209    *
210    * @param waitMs
211    */
 
212  0 toggle protected void waitFor(int waitMs)
213    {
214  0 try
215    {
216  0 Thread.sleep(waitMs);
217    } catch (InterruptedException e)
218    {
219    }
220    }
221   
222    /**
223    * Generates an alignment and saves it in a temporary file, to be loaded by
224    * Jalview. We use a peptide alignment (so Conservation and Quality are
225    * calculated), which is wide enough to ensure Consensus, Conservation and
226    * Occupancy have a significant memory footprint (if not removed from the
227    * heap).
228    *
229    * @return
230    * @throws IOException
231    */
 
232  0 toggle private File generateAlignment() throws IOException
233    {
234  0 File f = File.createTempFile("MemoryTest", "fa");
235  0 PrintStream ps = new PrintStream(f);
236  0 AlignmentGenerator ag = new AlignmentGenerator(false, ps);
237  0 int width = 100000;
238  0 int height = 100;
239  0 ag.generate(width, height, 0, 10, 15);
240  0 return f;
241    }
242    }