< prev index next >

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

Print this page

        

*** 85,94 **** --- 85,96 ---- 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,231 **** --- 220,260 ---- 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,301 **** stage.setHeight(180); stage.setScene(scene); webview.getEngine().getLoadWorker().stateProperty().addListener((ov, o, n) -> { if (n == Worker.State.SUCCEEDED) { final JSObject window = (JSObject) webview.getEngine().executeScript("window"); assertNotNull(window); window.setMember("callback1", stage); } }); webview.getEngine().loadContent(html); stage.show(); refs.add( new WeakReference<Object>(stage)); } }); ! Util.sleep(SLEEP_TIME); Util.runAndWait(() -> { for (int i = 0; i < NUM_STAGES; i++) { stages[i].hide(); } stages = null; }); ! for (int j = 0; j < 2; j++) { System.gc(); ! Util.sleep(SLEEP_TIME); ! Set<WeakReference<Object>> collected = new HashSet<>(); ! for (WeakReference<Object> ref : refs) { ! if (ref.get() == null) { ! collected.add(ref); } - } - 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()); } - 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 { Util.runAndWait(() -> { int stagePosition = 40; for (int i = 0; i < NUM_STAGES; i++) { --- 271,333 ---- 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)); } }); ! 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 < 5; j++) { System.gc(); ! System.runFinalization(); ! if (isAllStagesNull()) { ! break; } ! Util.sleep(SLEEP_TIME); } 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,342 **** stage.setHeight(180); stage.setScene(scene); webview.getEngine().getLoadWorker().stateProperty().addListener((ov, o, n) -> { if (n == Worker.State.SUCCEEDED) { final JSObject window = (JSObject) webview.getEngine().executeScript("window"); assertNotNull(window); window.setMember("callback1", stage); webview.getEngine().executeScript("document.getElementById(\"mybtn1\").click()"); } }); webview.getEngine().loadContent(html); stage.show(); } }); ! Util.sleep(SLEEP_TIME); System.gc(); ! for (int i = 0; i < NUM_STAGES; i++) { ! assertTrue(callbackStatus[i]); } } @Test public void testJsCallbackReleaseFunction() throws Exception { Util.runAndWait(() -> { int stagePosition = 40; for (int i = 0; i < NUM_STAGES; i++) { --- 344,398 ---- 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(); } }); ! 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 (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,362 **** --- 409,419 ---- 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,390 **** // 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()"); } }); webview.getEngine().loadContent(html); stage.show(); } }); ! Util.sleep(SLEEP_TIME); System.gc(); assertFalse(unexpectedCallback); } @Test public void testJsCallbackConsoleFunction() throws Exception { Util.runAndWait(() -> { int stagePosition = 40; for (int i = 0; i < NUM_STAGES; i++) { --- 422,471 ---- // 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(); } }); ! 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,430 **** stage.setHeight(180); stage.setScene(scene); webview.getEngine().getLoadWorker().stateProperty().addListener((ov, o, n) -> { if (n == Worker.State.SUCCEEDED) { final JSObject window = (JSObject) webview.getEngine().executeScript("window"); assertNotNull(window); window.setMember("console", new Object()); System.gc(); System.gc(); webview.getEngine().executeScript("window.console.debug = function() {}"); } }); webview.getEngine().loadContent(html); stage.show(); } }); ! Util.sleep(SLEEP_TIME); System.gc(); } @Test public void testJsCallbackStrongRefPrimitiveArrayFunction() throws Exception { Util.runAndWait(() -> { int stagePosition = 40; for (int i = 0; i < NUM_STAGES; i++) { --- 482,529 ---- 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(); } }); ! 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,473 **** stage.setHeight(180); stage.setScene(scene); webview.getEngine().getLoadWorker().stateProperty().addListener((ov, o, n) -> { if (n == Worker.State.SUCCEEDED) { 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()"); } }); webview.getEngine().loadContent(html); stage.show(); } }); ! Util.sleep(SLEEP_TIME); System.gc(); ! for (int i = 0; i < NUM_STAGES; i++) { ! assertTrue(callbackStatus[i]); } } @Test public void testJsCallbackLocalPrimitiveArrayFunctionWithGC() throws Exception { Util.runAndWait(() -> { int[] localPrimitiveArray = {1, 2, 3, 4, 5}; int stagePosition = 40; --- 540,597 ---- 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(); } }); ! 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 (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,525 **** stage.setHeight(180); stage.setScene(scene); webview.getEngine().getLoadWorker().stateProperty().addListener((ov, o, n) -> { if (n == Worker.State.SUCCEEDED) { 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(); } }); webview.getEngine().loadContent(html); stage.show(); } }); Util.sleep(SLEEP_TIME); - System.gc(); Util.runAndWait(() -> { for (int i = 0; i < NUM_STAGES; i++) { System.gc(); webviewArray[i].getEngine().executeScript("document.getElementById(\"mybtn2\").onclick = function() {callback2.jscallback3(localPrimitiveArray);}"); webviewArray[i].getEngine().executeScript("document.getElementById(\"mybtn2\").click()"); } }); assertFalse(unexpectedCallback); } @Test public void testJsCallbackStrongRefObjectArrayFunction() throws Exception { Util.runAndWait(() -> { int stagePosition = 40; for (int i = 0; i < NUM_STAGES; i++) { --- 610,674 ---- 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); 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,568 **** stage.setHeight(180); stage.setScene(scene); webview.getEngine().getLoadWorker().stateProperty().addListener((ov, o, n) -> { if (n == Worker.State.SUCCEEDED) { 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()"); } }); webview.getEngine().loadContent(html); stage.show(); } }); ! Util.sleep(SLEEP_TIME); System.gc(); ! for (int i = 0; i < NUM_STAGES; i++) { ! assertTrue(callbackStatus[i]); } } @Test public void testJsCallbackLocalObjectArrayFunctionWithGC() throws Exception { Util.runAndWait(() -> { int stagePosition = 40; for (int i = 0; i < NUM_STAGES; i++) { --- 685,743 ---- 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(); } }); ! 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 (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,612 **** stage.setHeight(180); stage.setScene(scene); webview.getEngine().getLoadWorker().stateProperty().addListener((ov, o, n) -> { if (n == Worker.State.SUCCEEDED) { 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(); } }); webview.getEngine().loadContent(html); stage.show(); } }); Util.sleep(SLEEP_TIME); - System.gc(); Util.runAndWait(() -> { for (int i = 0; i < NUM_STAGES; i++) { System.gc(); webviewArray[i].getEngine().executeScript("document.getElementById(\"mybtn2\").onclick = function() {callback2.jscallback5(localObjectArray);}"); webviewArray[i].getEngine().executeScript("document.getElementById(\"mybtn2\").click()"); } }); assertFalse(unexpectedCallback); } } --- 755,811 ---- 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); 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 >