diff options
Diffstat (limited to '')
-rw-r--r-- | netwerk/test/unit/test_cache-entry-id.js | 220 |
1 files changed, 220 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..f0011de47f --- /dev/null +++ b/netwerk/test/unit/test_cache-entry-id.js @@ -0,0 +1,220 @@ +/** + * Test for the "CacheEntryId" under several cases. + */ + +"use strict"; + +const { HttpServer } = ChromeUtils.importESModule( + "resource://testing-common/httpd.sys.mjs" +); + +ChromeUtils.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 || + Services.appinfo.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, + "", + Ci.nsICacheInfoChannel.ASYNC + ); + } + + 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)) + ); +} |