summaryrefslogtreecommitdiffstats
path: root/netwerk/test/unit/test_cache-entry-id.js
diff options
context:
space:
mode:
Diffstat (limited to 'netwerk/test/unit/test_cache-entry-id.js')
-rw-r--r--netwerk/test/unit/test_cache-entry-id.js215
1 files changed, 215 insertions, 0 deletions
diff --git a/netwerk/test/unit/test_cache-entry-id.js b/netwerk/test/unit/test_cache-entry-id.js
new file mode 100644
index 0000000000..121c30ced4
--- /dev/null
+++ b/netwerk/test/unit/test_cache-entry-id.js
@@ -0,0 +1,215 @@
+/**
+ * Test for the "CacheEntryId" under several cases.
+ */
+
+"use strict";
+
+const { HttpServer } = ChromeUtils.import("resource://testing-common/httpd.js");
+
+XPCOMUtils.defineLazyGetter(this, "URL", function() {
+ return "http://localhost:" + httpServer.identity.primaryPort + "/content";
+});
+
+var httpServer = null;
+
+const responseContent = "response body";
+const responseContent2 = "response body 2";
+const altContent = "!@#$%^&*()";
+const altContentType = "text/binary";
+
+function isParentProcess() {
+ let appInfo = Cc["@mozilla.org/xre/app-info;1"];
+ return (
+ !appInfo ||
+ appInfo.getService(Ci.nsIXULRuntime).processType ==
+ Ci.nsIXULRuntime.PROCESS_TYPE_DEFAULT
+ );
+}
+
+var handlers = [
+ (m, r) => {
+ r.bodyOutputStream.write(responseContent, responseContent.length);
+ },
+ (m, r) => {
+ r.setStatusLine(m.httpVersion, 304, "Not Modified");
+ },
+ (m, r) => {
+ r.setStatusLine(m.httpVersion, 304, "Not Modified");
+ },
+ (m, r) => {
+ r.setStatusLine(m.httpVersion, 304, "Not Modified");
+ },
+ (m, r) => {
+ r.setStatusLine(m.httpVersion, 304, "Not Modified");
+ },
+ (m, r) => {
+ r.bodyOutputStream.write(responseContent2, responseContent2.length);
+ },
+ (m, r) => {
+ r.setStatusLine(m.httpVersion, 304, "Not Modified");
+ },
+];
+
+function contentHandler(metadata, response) {
+ response.setHeader("Content-Type", "text/plain");
+ response.setHeader("Cache-Control", "no-cache");
+
+ var handler = handlers.shift();
+ if (handler) {
+ handler(metadata, response);
+ return;
+ }
+
+ Assert.ok(false, "Should not reach here.");
+}
+
+function fetch(preferredDataType = null) {
+ return new Promise(resolve => {
+ var chan = NetUtil.newChannel({ uri: URL, loadUsingSystemPrincipal: true });
+
+ if (preferredDataType) {
+ var cc = chan.QueryInterface(Ci.nsICacheInfoChannel);
+ cc.preferAlternativeDataType(altContentType, "", true);
+ }
+
+ chan.asyncOpen(
+ new ChannelListener((request, buffer, ctx, isFromCache, cacheEntryId) => {
+ resolve({ request, buffer, isFromCache, cacheEntryId });
+ }, null)
+ );
+ });
+}
+
+function check(
+ response,
+ content,
+ preferredDataType,
+ isFromCache,
+ cacheEntryIdChecker
+) {
+ var cc = response.request.QueryInterface(Ci.nsICacheInfoChannel);
+
+ Assert.equal(response.buffer, content);
+ Assert.equal(cc.alternativeDataType, preferredDataType);
+ Assert.equal(response.isFromCache, isFromCache);
+ Assert.ok(!cacheEntryIdChecker || cacheEntryIdChecker(response.cacheEntryId));
+
+ return response;
+}
+
+function writeAltData(request) {
+ var cc = request.QueryInterface(Ci.nsICacheInfoChannel);
+ var os = cc.openAlternativeOutputStream(altContentType, altContent.length);
+ os.write(altContent, altContent.length);
+ os.close();
+ gc(); // We need to do a GC pass to ensure the cache entry has been freed.
+
+ return new Promise(resolve => {
+ if (isParentProcess()) {
+ Services.cache2.QueryInterface(Ci.nsICacheTesting).flush(resolve);
+ } else {
+ do_send_remote_message("flush");
+ do_await_remote_message("flushed").then(resolve);
+ }
+ });
+}
+
+function run_test() {
+ do_get_profile();
+ httpServer = new HttpServer();
+ httpServer.registerPathHandler("/content", contentHandler);
+ httpServer.start(-1);
+ do_test_pending();
+
+ var targetCacheEntryId = null;
+
+ return (
+ Promise.resolve()
+ // Setup testing environment: Placing alternative data into HTTP cache.
+ .then(_ => fetch(altContentType))
+ .then(r =>
+ check(
+ r,
+ responseContent,
+ "",
+ false,
+ cacheEntryId => cacheEntryId === undefined
+ )
+ )
+ .then(r => writeAltData(r.request))
+
+ // Start testing.
+ .then(_ => fetch(altContentType))
+ .then(r =>
+ check(
+ r,
+ altContent,
+ altContentType,
+ true,
+ cacheEntryId => cacheEntryId !== undefined
+ )
+ )
+ .then(r => (targetCacheEntryId = r.cacheEntryId))
+
+ .then(_ => fetch())
+ .then(r =>
+ check(
+ r,
+ responseContent,
+ "",
+ true,
+ cacheEntryId => cacheEntryId === targetCacheEntryId
+ )
+ )
+
+ .then(_ => fetch(altContentType))
+ .then(r =>
+ check(
+ r,
+ altContent,
+ altContentType,
+ true,
+ cacheEntryId => cacheEntryId === targetCacheEntryId
+ )
+ )
+
+ .then(_ => fetch())
+ .then(r =>
+ check(
+ r,
+ responseContent,
+ "",
+ true,
+ cacheEntryId => cacheEntryId === targetCacheEntryId
+ )
+ )
+
+ .then(_ => fetch()) // The response is changed here.
+ .then(r =>
+ check(
+ r,
+ responseContent2,
+ "",
+ false,
+ cacheEntryId => cacheEntryId === undefined
+ )
+ )
+
+ .then(_ => fetch())
+ .then(r =>
+ check(
+ r,
+ responseContent2,
+ "",
+ true,
+ cacheEntryId =>
+ cacheEntryId !== undefined && cacheEntryId !== targetCacheEntryId
+ )
+ )
+
+ // Tear down.
+ .catch(e => Assert.ok(false, "Unexpected exception: " + e))
+ .then(_ => Assert.equal(handlers.length, 0))
+ .then(_ => httpServer.stop(do_test_finished))
+ );
+}