< prev index next >

tests/system/src/test/java/test/memoryleak/JSCallbackMemoryTest.java

Print this page

        

@@ -85,10 +85,12 @@
 
     private final int[] primitiveArray = { 1, 2, 3, 4, 5 };
 
     private final Object[] objectArray = { new Object(), new Object(), new Object(), new Object() };
 
+    private AssertionError encounteredException = null;
+
     public final class MyObject {
 
         // called from JavaScript
         public void jsobjcallback() {
             if (VERBOSE) {

@@ -218,14 +220,41 @@
                 stages = null;
             }
         });
     }
 
+    private boolean isAllStagesNull() {
+        Set<WeakReference<Object>> collected = new HashSet<>();
+
+        for (WeakReference<Object> ref : refs) {
+            if (ref.get() != null) {
+                return false;
+            }
+            collected.add(ref);
+        }
+
+        refs.removeAll(collected);
+
+        return true;
+    }
+
+    private boolean isAllCallbackStatusTrue() {
+
+        for (int i = 0; i < NUM_STAGES; i++) {
+            if (callbackStatus[i] == false) {
+                return false;
+            }
+        }
+
+        return true;
+    }
+
     // ========================== TEST CASES ==========================
 
     @Test
     public void testJsCallbackLeak() throws Exception {
+        final CountDownLatch latch = new CountDownLatch(1);
 
         Util.runAndWait(() -> {
 
             int stagePosition = 40;
             for (int i = 0; i < NUM_STAGES; i++) {

@@ -242,60 +271,63 @@
                 stage.setHeight(180);
                 stage.setScene(scene);
 
                 webview.getEngine().getLoadWorker().stateProperty().addListener((ov, o, n) -> {
                     if (n == Worker.State.SUCCEEDED) {
+                        try {
                         final JSObject window = (JSObject) webview.getEngine().executeScript("window");
                         assertNotNull(window);
                         window.setMember("callback1", stage);
+                        } catch(AssertionError ex) {
+                            encounteredException = ex;
+                        } finally {
+                            latch.countDown();
+                        }
                     }
                 });
 
                 webview.getEngine().loadContent(html);
                 stage.show();
                 refs.add( new WeakReference<Object>(stage));
             }
         });
 
-        Util.sleep(SLEEP_TIME);
+        if (encounteredException != null) {
+            throw encounteredException;
+        }
+
+        try {
+            latch.await();
+        } catch (InterruptedException ex) {
+            throw new AssertionError(ex);
+        }
 
         Util.runAndWait(() -> {
 
             for (int i = 0; i < NUM_STAGES; i++) {
                 stages[i].hide();
             }
             stages = null;
         });
 
 
-        for (int j = 0; j < 2; j++) {
+        for (int j = 0; j < 5; j++) {
             System.gc();
-            Util.sleep(SLEEP_TIME);
-            Set<WeakReference<Object>> collected = new HashSet<>();
+            System.runFinalization();
 
-            for (WeakReference<Object> ref : refs) {
-                if (ref.get() == null) {
-                    collected.add(ref);
+            if (isAllStagesNull()) {
+                break;
                 }
-            }
-            refs.removeAll(collected);
 
-            if (j == 0) {
-                // First time GC -> Collected will be equal to NUM_STAGES and refs size (remaining) will be 0
-                assertEquals(NUM_STAGES, collected.size());
-                assertEquals(0, refs.size());
+            Util.sleep(SLEEP_TIME);
             }
-            else {
-                // Second time GC -> Collected will be 0 and refs size (remaining) will be 0
-                assertEquals(0, collected.size());
                 assertEquals(0, refs.size());
             }
-        }
-    }
 
     @Test
     public void testJsCallbackFunction() throws Exception {
+        final CountDownLatch latch = new CountDownLatch(1);
 
         Util.runAndWait(() -> {
 
             int stagePosition = 40;
             for (int i = 0; i < NUM_STAGES; i++) {

@@ -312,31 +344,55 @@
                 stage.setHeight(180);
                 stage.setScene(scene);
 
                 webview.getEngine().getLoadWorker().stateProperty().addListener((ov, o, n) -> {
                     if (n == Worker.State.SUCCEEDED) {
+                        try {
                         final JSObject window = (JSObject) webview.getEngine().executeScript("window");
                         assertNotNull(window);
                         window.setMember("callback1", stage);
                         webview.getEngine().executeScript("document.getElementById(\"mybtn1\").click()");
+                        } catch(AssertionError ex) {
+                            encounteredException = ex;
+                        } finally {
+                            latch.countDown();
+                        }
                     }
                 });
 
                 webview.getEngine().loadContent(html);
                 stage.show();
             }
         });
 
-        Util.sleep(SLEEP_TIME);
+        if (encounteredException != null) {
+            throw encounteredException;
+        }
+
+        try {
+            latch.await();
+        } catch (InterruptedException ex) {
+            throw new AssertionError(ex);
+        }
+
+        for (int j = 0; j < 5; j++) {
         System.gc();
-        for (int i = 0; i < NUM_STAGES; i++) {
-            assertTrue(callbackStatus[i]);
+            System.runFinalization();
+
+            if (isAllCallbackStatusTrue()) {
+                break;
         }
+
+            Util.sleep(SLEEP_TIME);
+        }
+
+        assertTrue("All Button Callback return true", isAllCallbackStatusTrue());
     }
 
     @Test
     public void testJsCallbackReleaseFunction() throws Exception {
+        final CountDownLatch latch = new CountDownLatch(1);
 
         Util.runAndWait(() -> {
 
             int stagePosition = 40;
             for (int i = 0; i < NUM_STAGES; i++) {

@@ -353,10 +409,11 @@
                 stage.setHeight(180);
                 stage.setScene(scene);
 
                 webview.getEngine().getLoadWorker().stateProperty().addListener((ov, o, n) -> {
                     if (n == Worker.State.SUCCEEDED) {
+                        try {
                         final JSObject window = (JSObject) webview.getEngine().executeScript("window");
                         assertNotNull(window);
                         window.setMember("callback1", stage);
                         window.setMember("callback4", myObj);
 

@@ -365,26 +422,50 @@
                         // Below executeScript call will make myObj=null and GC'ed
                         webview.getEngine().executeScript("document.getElementById(\"mybtn3\").click()");
 
                         // Below executeScript call should not execute the JS callback (jsobjcallback) and should not cause crash as above executeScript just made myObj=null;
                         webview.getEngine().executeScript("document.getElementById(\"mybtn4\").click()");
+                        } catch(AssertionError ex) {
+                            encounteredException = ex;
+                        } finally {
+                            latch.countDown();
+                        }
                     }
                 });
 
                 webview.getEngine().loadContent(html);
                 stage.show();
             }
         });
 
-        Util.sleep(SLEEP_TIME);
+        if (encounteredException != null) {
+            throw encounteredException;
+        }
+
+        try {
+            latch.await();
+        } catch (InterruptedException ex) {
+            throw new AssertionError(ex);
+        }
+
+        for (int j = 0; j < 5; j++) {
         System.gc();
+            System.runFinalization();
+
+            if (unexpectedCallback) {
+                break;
+            }
+
+            Util.sleep(SLEEP_TIME);
+        }
 
         assertFalse(unexpectedCallback);
     }
 
     @Test
     public void testJsCallbackConsoleFunction() throws Exception {
+        final CountDownLatch latch = new CountDownLatch(1);
 
         Util.runAndWait(() -> {
 
             int stagePosition = 40;
             for (int i = 0; i < NUM_STAGES; i++) {

@@ -401,30 +482,48 @@
                 stage.setHeight(180);
                 stage.setScene(scene);
 
                 webview.getEngine().getLoadWorker().stateProperty().addListener((ov, o, n) -> {
                     if (n == Worker.State.SUCCEEDED) {
+                        try {
                         final JSObject window = (JSObject) webview.getEngine().executeScript("window");
                         assertNotNull(window);
 
                         window.setMember("console", new Object());
                         System.gc(); System.gc();
+                            System.runFinalization();
                         webview.getEngine().executeScript("window.console.debug = function() {}");
+                        } catch(AssertionError ex) {
+                            encounteredException = ex;
+                        } finally {
+                            latch.countDown();
+                        }
                     }
                 });
 
                 webview.getEngine().loadContent(html);
                 stage.show();
             }
         });
 
-        Util.sleep(SLEEP_TIME);
+        if (encounteredException != null) {
+            throw encounteredException;
+        }
+
+        try {
+            latch.await();
+        } catch (InterruptedException ex) {
+            throw new AssertionError(ex);
+        }
+
         System.gc();
+        System.runFinalization();
     }
 
     @Test
     public void testJsCallbackStrongRefPrimitiveArrayFunction() throws Exception {
+        final CountDownLatch latch = new CountDownLatch(1);
 
         Util.runAndWait(() -> {
 
             int stagePosition = 40;
             for (int i = 0; i < NUM_STAGES; i++) {

@@ -441,33 +540,58 @@
                 stage.setHeight(180);
                 stage.setScene(scene);
 
                 webview.getEngine().getLoadWorker().stateProperty().addListener((ov, o, n) -> {
                     if (n == Worker.State.SUCCEEDED) {
+                        try {
                         final JSObject window = (JSObject) webview.getEngine().executeScript("window");
                         assertNotNull(window);
                         window.setMember("callback2", stage);
                         window.setMember("primitiveArray", primitiveArray);
                         webview.getEngine().executeScript("document.getElementById(\"mybtn2\").onclick = function() {callback2.jscallback2(primitiveArray);}");
                         webview.getEngine().executeScript("document.getElementById(\"mybtn2\").click()");
+                        } catch(AssertionError ex) {
+                            encounteredException = ex;
+                        } finally {
+                            latch.countDown();
+                        }
                     }
                 });
 
                 webview.getEngine().loadContent(html);
                 stage.show();
             }
         });
 
-        Util.sleep(SLEEP_TIME);
+        if (encounteredException != null) {
+            throw encounteredException;
+        }
+
+        try {
+            latch.await();
+        } catch (InterruptedException ex) {
+            throw new AssertionError(ex);
+        }
+
+        for (int j = 0; j < 5; j++) {
         System.gc();
-        for (int i = 0; i < NUM_STAGES; i++) {
-            assertTrue(callbackStatus[i]);
+            System.runFinalization();
+
+            if (isAllCallbackStatusTrue()) {
+                break;
         }
+
+            Util.sleep(SLEEP_TIME);
+        }
+
+        assertTrue("All Button Callback return true", isAllCallbackStatusTrue());
     }
 
     @Test
     public void testJsCallbackLocalPrimitiveArrayFunctionWithGC() throws Exception {
+        final CountDownLatch latch1 = new CountDownLatch(1);
+        final CountDownLatch latch2 = new CountDownLatch(1);
 
         Util.runAndWait(() -> {
 
             int[] localPrimitiveArray = {1, 2, 3, 4, 5};
             int stagePosition = 40;

@@ -486,40 +610,65 @@
                 stage.setHeight(180);
                 stage.setScene(scene);
 
                 webview.getEngine().getLoadWorker().stateProperty().addListener((ov, o, n) -> {
                     if (n == Worker.State.SUCCEEDED) {
+                        try {
                         final JSObject window = (JSObject) webview.getEngine().executeScript("window");
                         assertNotNull(window);
                         window.setMember("callback2", stage);
                         window.setMember("localPrimitiveArray", new int[] { 1, 2, 3, 4, 5 });
                         System.gc(); System.gc();
+                            System.runFinalization();
+                        } catch(AssertionError ex) {
+                            encounteredException = ex;
+                        } finally {
+                            latch1.countDown();
+                        }
                     }
                 });
 
                 webview.getEngine().loadContent(html);
                 stage.show();
             }
         });
 
+        if (encounteredException != null) {
+            throw encounteredException;
+        }
+
+        try {
+            latch1.await();
+        } catch (InterruptedException ex) {
+            throw new AssertionError(ex);
+        }
+
         Util.sleep(SLEEP_TIME);
-        System.gc();
 
         Util.runAndWait(() -> {
 
             for (int i = 0; i < NUM_STAGES; i++) {
                 System.gc();
+                System.runFinalization();
                 webviewArray[i].getEngine().executeScript("document.getElementById(\"mybtn2\").onclick = function() {callback2.jscallback3(localPrimitiveArray);}");
                 webviewArray[i].getEngine().executeScript("document.getElementById(\"mybtn2\").click()");
             }
+            latch2.countDown();
         });
 
+        try {
+            latch2.await();
+        } catch (InterruptedException ex) {
+            throw new AssertionError(ex);
+        }
+
         assertFalse(unexpectedCallback);
     }
 
     @Test
     public void testJsCallbackStrongRefObjectArrayFunction() throws Exception {
+        final CountDownLatch latch = new CountDownLatch(1);
 
         Util.runAndWait(() -> {
 
             int stagePosition = 40;
             for (int i = 0; i < NUM_STAGES; i++) {

@@ -536,33 +685,59 @@
                 stage.setHeight(180);
                 stage.setScene(scene);
 
                 webview.getEngine().getLoadWorker().stateProperty().addListener((ov, o, n) -> {
                     if (n == Worker.State.SUCCEEDED) {
+                        try {
                         final JSObject window = (JSObject) webview.getEngine().executeScript("window");
                         assertNotNull(window);
                         window.setMember("callback2", stage);
                         window.setMember("objectArray", objectArray);
                         webview.getEngine().executeScript("document.getElementById(\"mybtn2\").onclick = function() {callback2.jscallback4(objectArray);}");
                         webview.getEngine().executeScript("document.getElementById(\"mybtn2\").click()");
+                        } catch(AssertionError ex) {
+                            encounteredException = ex;
+                        } finally {
+                            latch.countDown();
+                        }
                     }
                 });
 
                 webview.getEngine().loadContent(html);
                 stage.show();
             }
         });
 
-        Util.sleep(SLEEP_TIME);
+        if (encounteredException != null) {
+            throw encounteredException;
+        }
+
+        try {
+            latch.await();
+        } catch (InterruptedException ex) {
+            throw new AssertionError(ex);
+        }
+
+        for (int j = 0; j < 5; j++) {
         System.gc();
-        for (int i = 0; i < NUM_STAGES; i++) {
-            assertTrue(callbackStatus[i]);
+            System.runFinalization();
+
+            if (isAllCallbackStatusTrue()) {
+                break;
         }
+
+            Util.sleep(SLEEP_TIME);
+        }
+
+        assertTrue("All Button Callback return true", isAllCallbackStatusTrue());
+
     }
 
     @Test
     public void testJsCallbackLocalObjectArrayFunctionWithGC() throws Exception {
+        final CountDownLatch latch1 = new CountDownLatch(1);
+        final CountDownLatch latch2 = new CountDownLatch(1);
 
         Util.runAndWait(() -> {
 
             int stagePosition = 40;
             for (int i = 0; i < NUM_STAGES; i++) {

@@ -580,33 +755,57 @@
                 stage.setHeight(180);
                 stage.setScene(scene);
 
                 webview.getEngine().getLoadWorker().stateProperty().addListener((ov, o, n) -> {
                     if (n == Worker.State.SUCCEEDED) {
+                        try {
                         final JSObject window = (JSObject) webview.getEngine().executeScript("window");
                         assertNotNull(window);
                         window.setMember("callback2", stage);
                         window.setMember("localObjectArray", new Object[] { new Object(), new Object(), new Object(), new Object() });
                         System.gc(); System.gc();
+                            System.runFinalization();
+                        } catch(AssertionError ex) {
+                            encounteredException = ex;
+                        } finally {
+                            latch1.countDown();
+                        }
                     }
                 });
 
                 webview.getEngine().loadContent(html);
                 stage.show();
             }
         });
 
+        if (encounteredException != null) {
+            throw encounteredException;
+        }
+
+        try {
+            latch1.await();
+        } catch (InterruptedException ex) {
+            throw new AssertionError(ex);
+        }
+
         Util.sleep(SLEEP_TIME);
-        System.gc();
 
         Util.runAndWait(() -> {
 
             for (int i = 0; i < NUM_STAGES; i++) {
                 System.gc();
+                System.runFinalization();
                 webviewArray[i].getEngine().executeScript("document.getElementById(\"mybtn2\").onclick = function() {callback2.jscallback5(localObjectArray);}");
                 webviewArray[i].getEngine().executeScript("document.getElementById(\"mybtn2\").click()");
             }
+            latch2.countDown();
         });
 
+        try {
+            latch2.await();
+        } catch (InterruptedException ex) {
+            throw new AssertionError(ex);
+        }
+
         assertFalse(unexpectedCallback);
     }
 }
< prev index next >