Merge commit 'alpha/update_2_12_for_2_11_2_series_merge^2' into HEAD
[jalview.git] / test / jalview / gui / FreeUpMemoryTest.java
index 09ee560..09ef88b 100644 (file)
@@ -3,6 +3,7 @@ package jalview.gui;
 import static org.testng.Assert.assertNotNull;
 import static org.testng.Assert.assertTrue;
 
+
 import java.awt.event.MouseEvent;
 import java.io.File;
 import java.io.IOException;
@@ -90,8 +91,7 @@ public class FreeUpMemoryTest
   /*
    * maximum retained heap usage (in MB) for a passing test
    */
-  private static int MAX_RESIDUAL_HEAP = 38;
-
+  private static int MAX_RESIDUAL_HEAP = 45;
   /**
    * Configure (read-only) Jalview property settings for test
    */
@@ -102,24 +102,51 @@ public class FreeUpMemoryTest
             new String[]
             { "-nonews", "-props", "test/jalview/testProps.jvprops" });
     String True = Boolean.TRUE.toString();
-    Cache.applicationProperties.setProperty("SHOW_ANNOTATIONS", True);
-    Cache.applicationProperties.setProperty("SHOW_QUALITY", True);
-    Cache.applicationProperties.setProperty("SHOW_CONSERVATION", True);
-    Cache.applicationProperties.setProperty("SHOW_OCCUPANCY", True);
-    Cache.applicationProperties.setProperty("SHOW_IDENTITY", True);
+    Cache.setPropertyNoSave("SHOW_ANNOTATIONS", True);
+    Cache.setPropertyNoSave("SHOW_QUALITY", True);
+    Cache.setPropertyNoSave("SHOW_CONSERVATION", True);
+    Cache.setPropertyNoSave("SHOW_OCCUPANCY", True);
+    Cache.setPropertyNoSave("SHOW_IDENTITY", True);
   }
 
+  /**
+   * A simple test that memory is released when all windows are closed.
+   * <ul>
+   * <li>generates a reasonably large alignment and loads it</li>
+   * <li>performs various operations on the alignment</li>
+   * <li>closes all windows</li>
+   * <li>requests garbage collection</li>
+   * <li>asserts that the remaining memory footprint (heap usage) is 'not large'
+   * </li>
+   * </ul>
+   * If the test fails, this suggests that a reference to some large object
+   * (perhaps the alignment data, or some annotation / Tree / PCA data) has
+   * failed to be garbage collected. If this is the case, the heap will need to
+   * be inspected manually (suggest using jvisualvm) in order to track down
+   * where large objects are still referenced. The code (for example
+   * AlignmentViewport.dispose()) should then be updated to ensure references to
+   * large objects are set to null when they are no longer required.
+   * 
+   * @throws IOException
+   */
   @Test(groups = "Memory")
   public void testFreeMemoryOnClose() throws IOException
   {
     File f = generateAlignment();
     f.deleteOnExit();
 
+    long expectedMin = MAX_RESIDUAL_HEAP;
+    long usedMemoryAtStart=getUsedMemory();
+    if (usedMemoryAtStart>expectedMin)
+    {
+      System.err.println("used memory before test is "+usedMemoryAtStart+" > "+expectedMin+"MB .. adjusting minimum.");
+      expectedMin = usedMemoryAtStart;
+    }
     doStuffInJalview(f);
 
-    Desktop.instance.closeAll_actionPerformed(null);
+    Desktop.getInstance().closeAll_actionPerformed(null);
 
-    checkUsedMemory(MAX_RESIDUAL_HEAP);
+    checkUsedMemory(expectedMin);
   }
 
   /**
@@ -133,10 +160,8 @@ public class FreeUpMemoryTest
     long availableMemory = Runtime.getRuntime().totalMemory();
     long freeMemory = Runtime.getRuntime().freeMemory();
     long usedMemory = availableMemory - freeMemory;
-
-    return (int) (usedMemory/ ONE_MB);
+    return (int) (usedMemory / ONE_MB);
   }
-
   /**
    * Requests garbage collection and then checks whether remaining memory in use
    * is less than the expected value (in Megabytes)
@@ -150,6 +175,7 @@ public class FreeUpMemoryTest
      * NB there is no guarantee when, or whether, it will do so
      */
     long usedMemory = 0L;
+    Long minUsedMemory = null;
     int gcCount = 0;
     while (gcCount < 3)
     {
@@ -157,6 +183,10 @@ public class FreeUpMemoryTest
       System.gc();
       waitFor(1500);
       usedMemory = getUsedMemory();
+      if (minUsedMemory == null || usedMemory < minUsedMemory)
+      {
+        minUsedMemory = usedMemory;
+      }
       if (usedMemory < expectedMax)
       {
         break;
@@ -171,9 +201,9 @@ public class FreeUpMemoryTest
      * - take a heap dump and identify large objects in the heap and their referers
      * - fix code as necessary to null the references on close
      */
-    System.out
-            .println("Used memory after " + gcCount + " call(s) to gc() = "
-                    + usedMemory + "MB (should be <=" + expectedMax + ")");
+    System.out.println("(Minimum) Used memory after " + gcCount
+            + " call(s) to gc() = " + minUsedMemory + "MB (should be <="
+            + expectedMax + ")");
     assertTrue(usedMemory <= expectedMax, String.format(
             "Used memory %d should be less than %d (Recommend running test manually to verify)",
             usedMemory, expectedMax));