Bug 1110446 P3 Add a test that forces a Cache object to be orphaned and reclaimed. r=ehsan
authorBen Kelly <ben@wanderview.com>
Thu, 25 Jun 2015 22:22:47 -0700
changeset 268406 a9f10e13ec411dc65660b04ac6772d2baefb915d
parent 268405 b89856b358ea1e5673da81e7e5c11e6b4a2dfaf3
child 268407 331d60f2c42e1e3995931791284da9804bcbe3bf
push id4932
push userjlund@mozilla.com
push dateMon, 10 Aug 2015 18:23:06 +0000
treeherdermozilla-esr52@6dd5a4f5f745 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersehsan
bugs1110446
milestone41.0a1
Bug 1110446 P3 Add a test that forces a Cache object to be orphaned and reclaimed. r=ehsan
dom/cache/test/mochitest/mochitest.ini
dom/cache/test/mochitest/test_cache_orphaned_cache.html
--- a/dom/cache/test/mochitest/mochitest.ini
+++ b/dom/cache/test/mochitest/mochitest.ini
@@ -35,8 +35,9 @@ support-files =
 [test_cache_put.html]
 [test_cache_requestCache.html]
 [test_cache_delete.html]
 [test_cache_put_reorder.html]
 [test_cache_https.html]
   skip-if = buildapp == 'b2g' # bug 1162353
 [test_cache_restart.html]
 [test_cache_shrink.html]
+[test_cache_orphaned_cache.html]
new file mode 100644
--- /dev/null
+++ b/dom/cache/test/mochitest/test_cache_orphaned_cache.html
@@ -0,0 +1,171 @@
+<!-- Any copyright is dedicated to the Public Domain.
+   - http://creativecommons.org/publicdomain/zero/1.0/ -->
+<!DOCTYPE HTML>
+<html>
+<head>
+  <title>Test Cache with QuotaManager Restart</title>
+  <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <script type="text/javascript" src="large_url_list.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<script class="testbody" type="text/javascript">
+function setupTestIframe() {
+  return new Promise(function(resolve) {
+    var iframe = document.createElement("iframe");
+    iframe.src = "empty.html";
+    iframe.onload = function() {
+      window.caches = iframe.contentWindow.caches;
+      resolve();
+    };
+    document.body.appendChild(iframe);
+  });
+}
+
+function clearStorage() {
+  return new Promise(function(resolve, reject) {
+    var principal = SpecialPowers.wrap(document).nodePrincipal;
+    var appId, inBrowser;
+    var nsIPrincipal = SpecialPowers.Components.interfaces.nsIPrincipal;
+    if (principal.appId != nsIPrincipal.UNKNOWN_APP_ID &&
+        principal.appId != nsIPrincipal.NO_APP_ID) {
+      appId = principal.appId;
+      inBrowser = principal.isInBrowserElement;
+    }
+    SpecialPowers.clearStorageForURI(document.documentURI, resolve, appId,
+                                     inBrowser);
+  });
+}
+
+function storageUsage() {
+  return new Promise(function(resolve, reject) {
+    var principal = SpecialPowers.wrap(document).nodePrincipal;
+    var appId, inBrowser;
+    var nsIPrincipal = SpecialPowers.Components.interfaces.nsIPrincipal;
+    if (principal.appId != nsIPrincipal.UNKNOWN_APP_ID &&
+        principal.appId != nsIPrincipal.NO_APP_ID) {
+      appId = principal.appId;
+      inBrowser = principal.isInBrowserElement;
+    }
+    SpecialPowers.getStorageUsageForURI(document.documentURI, resolve, appId,
+                                        inBrowser);
+  });
+}
+
+function resetStorage() {
+  return new Promise(function(resolve, reject) {
+    var principal = SpecialPowers.wrap(document).nodePrincipal;
+    var appId, inBrowser;
+    var nsIPrincipal = SpecialPowers.Components.interfaces.nsIPrincipal;
+    if (principal.appId != nsIPrincipal.UNKNOWN_APP_ID &&
+        principal.appId != nsIPrincipal.NO_APP_ID) {
+      appId = principal.appId;
+      inBrowser = principal.isInBrowserElement;
+    }
+    SpecialPowers.resetStorageForURI(document.documentURI, resolve, appId,
+                                     inBrowser);
+  });
+}
+
+function gc() {
+  return new Promise(function(resolve, reject) {
+    SpecialPowers.exactGC(window, resolve);
+  });
+}
+
+SimpleTest.waitForExplicitFinish();
+SpecialPowers.pushPrefEnv({
+  "set": [["dom.caches.enabled", true],
+          ["dom.quotaManager.testing", true]],
+}, function() {
+  var name = 'toBeOrphaned';
+  var cache = null;
+  var initialUsage = 0;
+  var fullUsage = 0;
+  var resetUsage = 0;
+  var endUsage = 0;
+  var url = 'cache_add.js';
+
+  // start from a fresh origin directory so other tests do not influence our
+  // results
+  setupTestIframe().then(function() {
+    return clearStorage();
+  }).then(function() {
+    return storageUsage();
+  }).then(function(usage) {
+    is(0, usage, 'disk usage should be zero to start');
+  })
+
+  // Initialize and populate an initial cache to get the base sqlite pages
+  // and directory structure allocated.
+  .then(function() {
+    return caches.open(name);
+  }).then(function(c) {
+    return c.add(url);
+  }).then(function() {
+    return gc();
+  }).then(function() {
+    return caches.delete(name);
+  }).then(function(deleted) {
+    ok(deleted, 'cache should be deleted');
+  })
+
+  // Now measure initial disk usage
+  .then(function() {
+    return resetStorage();
+  }).then(function() {
+    return storageUsage();
+  }).then(function(usage) {
+    initialUsage = usage;
+  })
+
+  // Now re-populate the Cache object
+  .then(function() {
+    return caches.open(name);
+  }).then(function(c) {
+    cache = c;
+    return cache.add(url);
+  }).then(function() {
+    return caches.delete(name);
+  }).then(function(deleted) {
+    ok(deleted, 'cache should be deleted');
+  })
+
+  // Reset the quota dir while the cache is deleted, but still referenced
+  // from the DOM.  This forces it to be orphaned.
+  .then(function() {
+    return resetStorage();
+  }).then(function() {
+    return storageUsage();
+  }).then(function(usage) {
+    fullUsage = usage;
+    ok(fullUsage > initialUsage, 'disk usage should have grown');
+  })
+
+  // Now perform a new Cache operation that will reopen the origin.  This
+  // should clean up the orphaned Cache data.
+  .then(function() {
+    return caches.has(name);
+  }).then(function(result) {
+    ok(!result, 'cache should not exist in storage');
+  })
+
+  // Finally, verify orphaned data was cleaned up by re-checking the disk
+  // usage.  Reset the storage first to ensure any WAL transaction files
+  // are flushed before measuring the usage.
+  .then(function() {
+    return resetStorage();
+  }).then(function() {
+    return storageUsage();
+  }).then(function(usage) {
+    endUsage = usage;
+    dump("### ### initial:" + initialUsage + ", full:" + fullUsage +
+         ", end:" + endUsage + "\n");
+    ok(endUsage < fullUsage, 'disk usage should have shrank');
+    is(endUsage, initialUsage, 'disk usage should return to original');
+    SimpleTest.finish();
+  });
+});
+</script>
+</body>
+</html>