Add two regression tests for reference cycle in IndexedDB
authorsihui_liu@apple.com <sihui_liu@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 13 Feb 2019 17:12:57 +0000 (17:12 +0000)
committersihui_liu@apple.com <sihui_liu@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 13 Feb 2019 17:12:57 +0000 (17:12 +0000)
https://bugs.webkit.org/show_bug.cgi?id=194527

Reviewed by Geoffrey Garen.

* fast/dom/reference-cycle-leaks.html:
* platform/win/TestExpectations:
The added tests are failing on win bots for unknown reasons, propably related to webkit.org/b/193540. Skip them
on win.

* storage/indexeddb/resources/result-request-cycle.js: Added.
(prepareDatabase):
* storage/indexeddb/resources/value-cursor-cycle.js: Added.
(prepareDatabase):
(onOpen.cursorRequest.onsuccess):
* storage/indexeddb/result-request-cycle-expected.txt: Added.
* storage/indexeddb/result-request-cycle.html: Added.
* storage/indexeddb/value-cursor-cycle-expected.txt: Added.
* storage/indexeddb/value-cursor-cycle.html: Added.

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@241436 268f45cc-cd09-0410-ab3c-d52691b4dbfc

LayoutTests/ChangeLog
LayoutTests/fast/dom/reference-cycle-leaks.html
LayoutTests/platform/win/TestExpectations
LayoutTests/storage/indexeddb/resources/result-request-cycle.js [new file with mode: 0644]
LayoutTests/storage/indexeddb/resources/value-cursor-cycle.js [new file with mode: 0644]
LayoutTests/storage/indexeddb/result-request-cycle-expected.txt [new file with mode: 0644]
LayoutTests/storage/indexeddb/result-request-cycle.html [new file with mode: 0644]
LayoutTests/storage/indexeddb/value-cursor-cycle-expected.txt [new file with mode: 0644]
LayoutTests/storage/indexeddb/value-cursor-cycle.html [new file with mode: 0644]

index ade8e20..52e92b4 100644 (file)
@@ -1,3 +1,25 @@
+2019-02-13  Sihui Liu  <sihui_liu@apple.com>
+
+        Add two regression tests for reference cycle in IndexedDB
+        https://bugs.webkit.org/show_bug.cgi?id=194527
+
+        Reviewed by Geoffrey Garen.
+
+        * fast/dom/reference-cycle-leaks.html:
+        * platform/win/TestExpectations:
+        The added tests are failing on win bots for unknown reasons, propably related to webkit.org/b/193540. Skip them 
+        on win.
+
+        * storage/indexeddb/resources/result-request-cycle.js: Added.
+        (prepareDatabase):
+        * storage/indexeddb/resources/value-cursor-cycle.js: Added.
+        (prepareDatabase):
+        (onOpen.cursorRequest.onsuccess):
+        * storage/indexeddb/result-request-cycle-expected.txt: Added.
+        * storage/indexeddb/result-request-cycle.html: Added.
+        * storage/indexeddb/value-cursor-cycle-expected.txt: Added.
+        * storage/indexeddb/value-cursor-cycle.html: Added.
+
 2019-02-13  Antoine Quint  <graouts@apple.com>
 
         Support simulated mouse events on iOS based on a PlatformTouchEvent
index f71e0d5..b96a4da 100644 (file)
@@ -117,13 +117,8 @@ function createPopStateEventStateCycle()
     leakDetectionNode.event = new PopStateEvent("x", { state: leakDetectionNode });
 }
 
-function createIDBRequestResultCycle()
-{
-    // FIXME: Need to write this test and reorganize so it can be asynchronous.
-    // Get an IDBRequest with a result that is a structured clone (see IDBTransaction::didGetRecordOnServer).
-    // Add a property to the result object that references the request.
-    // Add another property to the result object that references a leak detection node.
-}
+// Reference cycle of IDBRequest and IDBCursor is tested in
+// storage/indexeddb/value-cursor-cycle.html and LayoutTests/storage/indexeddb/result-request-cycle.html.
 
 // PaymentResponse details reference cycle is tested in
 // http/tests/paymentrequest/payment-response-reference-cycle-leak.https.html.
index 56bdb22..d02f39e 100644 (file)
@@ -4270,3 +4270,6 @@ webkit.org/b/193540 js/slow-stress/simple-custom-getter.html [ Skip ]
 webkit.org/b/193540 performance-api/performance-observer-no-document-leak.html [ Skip ]
 
 webkit.org/b/194451 accessibility/set-value-not-work-for-disabled-sliders.html [ Failure ]
+
+storage/indexeddb/result-request-cycle.html [ Skip ]
+storage/indexeddb/value-cursor-cycle.html [ Skip ]
diff --git a/LayoutTests/storage/indexeddb/resources/result-request-cycle.js b/LayoutTests/storage/indexeddb/resources/result-request-cycle.js
new file mode 100644 (file)
index 0000000..477548c
--- /dev/null
@@ -0,0 +1,56 @@
+if (this.importScripts) {
+    importScripts('../../../resources/js-test.js');
+    importScripts('shared.js');
+}
+
+description("Verify that IDBRequest is not leaked when there is a reference cycle for result attribute");
+
+indexedDBTest(prepareDatabase, onOpen);
+
+function prepareDatabase(evt)
+{
+    preamble(evt);
+    evalAndLog("db = event.target.result");
+    evalAndLog("store = db.createObjectStore('store')");
+    store.put({ value: 'value1' }, 'key1');
+    store.put({ value: 'value2' }, 'key2');
+}
+
+function onOpen(evt)
+{
+    preamble(evt);
+    evalAndLog("db = event.target.result");
+    evalAndLog("tx = db.transaction('store')");
+    evalAndLog("store = tx.objectStore('store')");
+
+    evalAndLog("getRequest = store.get('key1')");
+    getRequest.onsuccess = (evt) => {
+        preamble(evt);
+
+        debug("Verify that the request's result can be accessed lazily:");
+        evalAndLog("gc()");
+
+        evalAndLog("result = getRequest.result");
+        shouldBeEqualToString("result.value", "value1");
+        evalAndLog("result.source = getRequest");
+    }
+
+    evalAndLog("getRequest2 = store.get('key2')");
+    getRequest2.onsuccess = (evt) => {
+        shouldBeEqualToString("getRequest2.result.value", "value2");
+
+        getRequestObervation = internals.observeGC(getRequest);
+        resultObservation = internals.observeGC(result);
+        evalAndLog("getRequest = null");
+        evalAndLog("gc()");
+        shouldBeFalse("getRequestObervation.wasCollected");
+        shouldBeFalse("resultObservation.wasCollected");
+
+        evalAndLog("result = null");
+        evalAndLog("gc()");
+        shouldBeTrue("getRequestObervation.wasCollected");
+        shouldBeTrue("resultObservation.wasCollected");
+    }
+
+    tx.oncomplete = finishJSTest;
+}
\ No newline at end of file
diff --git a/LayoutTests/storage/indexeddb/resources/value-cursor-cycle.js b/LayoutTests/storage/indexeddb/resources/value-cursor-cycle.js
new file mode 100644 (file)
index 0000000..c33fc29
--- /dev/null
@@ -0,0 +1,54 @@
+if (this.importScripts) {
+    importScripts('../../../resources/js-test.js');
+    importScripts('shared.js');
+}
+
+description("Verify that IDBCursor is not leaked when there is a reference cycle for value attribute");
+
+indexedDBTest(prepareDatabase, onOpen);
+
+function prepareDatabase(evt)
+{
+    preamble(evt);
+    evalAndLog("db = event.target.result");
+    evalAndLog("store = db.createObjectStore('store')");
+    store.put({ name: 'value' }, 'key');
+}
+
+function onOpen(evt)
+{
+    preamble(evt);
+    evalAndLog("db = event.target.result");
+    evalAndLog("tx = db.transaction('store')");
+    evalAndLog("store = tx.objectStore('store')");
+
+    evalAndLog("cursorRequest = store.openCursor()");
+    cursorRequest.onsuccess = function openCursorRequestSuccess(evt) {
+        preamble(evt);
+    };
+
+    evalAndLog("getRequest = store.get('key')");
+    getRequest.onsuccess = () => {
+        shouldBeEqualToString("getRequest.result.name", "value");
+
+        evalAndLog("cursor = cursorRequest.result");
+        shouldBeNonNull("cursor");
+        evalAndLog("value = cursor.value");
+        shouldBeEqualToString("value.name", "value");
+        evalAndLog("value.cycle = cursor");
+
+        cursorObservation = internals.observeGC(cursor);
+        valueObservation = internals.observeGC(value);
+        evalAndLog("cursor = null");
+        evalAndLog("cursorRequest = null");
+        evalAndLog("gc()");
+        shouldBeFalse("cursorObservation.wasCollected");
+
+        evalAndLog("value = null");
+        evalAndLog("gc()");
+        shouldBeTrue("cursorObservation.wasCollected");
+        shouldBeTrue("valueObservation.wasCollected");
+    }
+
+    tx.oncomplete = finishJSTest;
+}
\ No newline at end of file
diff --git a/LayoutTests/storage/indexeddb/result-request-cycle-expected.txt b/LayoutTests/storage/indexeddb/result-request-cycle-expected.txt
new file mode 100644 (file)
index 0000000..7c91fe2
--- /dev/null
@@ -0,0 +1,40 @@
+Verify that IDBRequest is not leaked when there is a reference cycle for result attribute
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+indexedDB = self.indexedDB || self.webkitIndexedDB || self.mozIndexedDB || self.msIndexedDB || self.OIndexedDB;
+
+indexedDB.deleteDatabase(dbname)
+indexedDB.open(dbname)
+
+prepareDatabase():
+db = event.target.result
+store = db.createObjectStore('store')
+
+onOpen():
+db = event.target.result
+tx = db.transaction('store')
+store = tx.objectStore('store')
+getRequest = store.get('key1')
+getRequest2 = store.get('key2')
+
+():
+Verify that the request's result can be accessed lazily:
+gc()
+result = getRequest.result
+PASS result.value is "value1"
+result.source = getRequest
+PASS getRequest2.result.value is "value2"
+getRequest = null
+gc()
+PASS getRequestObervation.wasCollected is false
+PASS resultObservation.wasCollected is false
+result = null
+gc()
+PASS getRequestObervation.wasCollected is true
+PASS resultObservation.wasCollected is true
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
diff --git a/LayoutTests/storage/indexeddb/result-request-cycle.html b/LayoutTests/storage/indexeddb/result-request-cycle.html
new file mode 100644 (file)
index 0000000..b2a5e26
--- /dev/null
@@ -0,0 +1,9 @@
+<html>
+<head>
+<script src="../../resources/js-test.js"></script>
+<script src="resources/shared.js"></script>
+</head>
+<body>
+<script src="resources/result-request-cycle.js"></script>
+</body>
+</html>
diff --git a/LayoutTests/storage/indexeddb/value-cursor-cycle-expected.txt b/LayoutTests/storage/indexeddb/value-cursor-cycle-expected.txt
new file mode 100644 (file)
index 0000000..57145c2
--- /dev/null
@@ -0,0 +1,40 @@
+Verify that IDBCursor is not leaked when there is a reference cycle for value attribute
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+indexedDB = self.indexedDB || self.webkitIndexedDB || self.mozIndexedDB || self.msIndexedDB || self.OIndexedDB;
+
+indexedDB.deleteDatabase(dbname)
+indexedDB.open(dbname)
+
+prepareDatabase():
+db = event.target.result
+store = db.createObjectStore('store')
+
+onOpen():
+db = event.target.result
+tx = db.transaction('store')
+store = tx.objectStore('store')
+cursorRequest = store.openCursor()
+getRequest = store.get('key')
+
+openCursorRequestSuccess():
+PASS getRequest.result.name is "value"
+cursor = cursorRequest.result
+PASS cursor is non-null.
+value = cursor.value
+PASS value.name is "value"
+value.cycle = cursor
+cursor = null
+cursorRequest = null
+gc()
+PASS cursorObservation.wasCollected is false
+value = null
+gc()
+PASS cursorObservation.wasCollected is true
+PASS valueObservation.wasCollected is true
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
diff --git a/LayoutTests/storage/indexeddb/value-cursor-cycle.html b/LayoutTests/storage/indexeddb/value-cursor-cycle.html
new file mode 100644 (file)
index 0000000..9c62007
--- /dev/null
@@ -0,0 +1,9 @@
+<html>
+<head>
+<script src="../../resources/js-test.js"></script>
+<script src="resources/shared.js"></script>
+</head>
+<body>
+<script src="resources/value-cursor-cycle.js"></script>
+</body>
+</html>