< 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 >