no bug - Bumping Firefox l10n changesets r=release a=l10n-bump DONTBUILD CLOSED TREE
[gecko.git] / netwerk / test / unit / test_alt-data_simple.js
blob7fa175db28fb57d68805b0d552d4324988834498
1 /**
2  * Test for the "alternative data stream" stored withing a cache entry.
3  *
4  * - we load a URL with preference for an alt data (check what we get is the raw data,
5  *   since there was nothing previously cached)
6  * - we store the alt data along the channel (to the cache entry)
7  * - we flush the HTTP cache
8  * - we reload the same URL using a new channel, again prefering the alt data be loaded
9  * - this time the alt data must arive
10  */
12 "use strict";
14 const { HttpServer } = ChromeUtils.importESModule(
15   "resource://testing-common/httpd.sys.mjs"
18 ChromeUtils.defineLazyGetter(this, "URL", function () {
19   return "http://localhost:" + httpServer.identity.primaryPort + "/content";
20 });
22 var httpServer = null;
24 function make_channel(url) {
25   return NetUtil.newChannel({ uri: url, loadUsingSystemPrincipal: true });
28 function inChildProcess() {
29   return Services.appinfo.processType != Ci.nsIXULRuntime.PROCESS_TYPE_DEFAULT;
32 const responseContent = "response body";
33 const responseContent2 = "response body 2";
34 const altContent = "!@#$%^&*()";
35 const altContentType = "text/binary";
37 var servedNotModified = false;
38 var shouldPassRevalidation = true;
40 var cache_storage = null;
42 function contentHandler(metadata, response) {
43   response.setHeader("Content-Type", "text/plain");
44   response.setHeader("Cache-Control", "no-cache");
45   response.setHeader("ETag", "test-etag1");
47   let etag;
48   try {
49     etag = metadata.getHeader("If-None-Match");
50   } catch (ex) {
51     etag = "";
52   }
54   if (etag == "test-etag1" && shouldPassRevalidation) {
55     response.setStatusLine(metadata.httpVersion, 304, "Not Modified");
56     servedNotModified = true;
57   } else {
58     var content = shouldPassRevalidation ? responseContent : responseContent2;
59     response.bodyOutputStream.write(content, content.length);
60   }
63 function check_has_alt_data_in_index(aHasAltData, callback) {
64   if (inChildProcess()) {
65     callback();
66     return;
67   }
69   syncWithCacheIOThread(() => {
70     var hasAltData = {};
71     cache_storage.getCacheIndexEntryAttrs(createURI(URL), "", hasAltData, {});
72     Assert.equal(hasAltData.value, aHasAltData);
73     callback();
74   }, true);
77 function run_test() {
78   do_get_profile();
79   httpServer = new HttpServer();
80   httpServer.registerPathHandler("/content", contentHandler);
81   httpServer.start(-1);
82   do_test_pending();
84   if (!inChildProcess()) {
85     cache_storage = getCacheStorage("disk");
86     wait_for_cache_index(asyncOpen);
87   } else {
88     asyncOpen();
89   }
92 function asyncOpen() {
93   var chan = make_channel(URL);
95   var cc = chan.QueryInterface(Ci.nsICacheInfoChannel);
96   cc.preferAlternativeDataType(
97     altContentType,
98     "",
99     Ci.nsICacheInfoChannel.ASYNC
100   );
102   chan.asyncOpen(new ChannelListener(readServerContent, null));
105 function readServerContent(request, buffer) {
106   var cc = request.QueryInterface(Ci.nsICacheInfoChannel);
108   Assert.equal(buffer, responseContent);
109   Assert.equal(cc.alternativeDataType, "");
110   check_has_alt_data_in_index(false, () => {
111     executeSoon(() => {
112       var os = cc.openAlternativeOutputStream(
113         altContentType,
114         altContent.length
115       );
116       os.write(altContent, altContent.length);
117       os.close();
119       executeSoon(flushAndOpenAltChannel);
120     });
121   });
124 // needs to be rooted
125 var cacheFlushObserver = (cacheFlushObserver = {
126   observe() {
127     cacheFlushObserver = null;
128     openAltChannel();
129   },
132 function flushAndOpenAltChannel() {
133   // We need to do a GC pass to ensure the cache entry has been freed.
134   gc();
135   if (!inChildProcess()) {
136     Services.cache2
137       .QueryInterface(Ci.nsICacheTesting)
138       .flush(cacheFlushObserver);
139   } else {
140     do_send_remote_message("flush");
141     do_await_remote_message("flushed").then(() => {
142       openAltChannel();
143     });
144   }
147 function openAltChannel() {
148   var chan = make_channel(URL);
149   var cc = chan.QueryInterface(Ci.nsICacheInfoChannel);
150   cc.preferAlternativeDataType(
151     "dummy1",
152     "text/javascript",
153     Ci.nsICacheInfoChannel.ASYNC
154   );
155   cc.preferAlternativeDataType(
156     altContentType,
157     "text/plain",
158     Ci.nsICacheInfoChannel.ASYNC
159   );
160   cc.preferAlternativeDataType("dummy2", "", Ci.nsICacheInfoChannel.ASYNC);
162   chan.asyncOpen(new ChannelListener(readAltContent, null));
165 function readAltContent(request, buffer) {
166   var cc = request.QueryInterface(Ci.nsICacheInfoChannel);
168   Assert.equal(servedNotModified, true);
169   Assert.equal(cc.alternativeDataType, altContentType);
170   Assert.equal(buffer, altContent);
171   check_has_alt_data_in_index(true, () => {
172     cc.getOriginalInputStream({
173       onInputStreamReady(aInputStream) {
174         executeSoon(() => readOriginalInputStream(aInputStream));
175       },
176     });
177   });
180 function readOriginalInputStream(aInputStream) {
181   // We expect the async stream length to match the expected content.
182   // If the test times out, it's probably because of this.
183   try {
184     let originalData = read_stream(aInputStream, responseContent.length);
185     Assert.equal(originalData, responseContent);
186     requestAgain();
187   } catch (e) {
188     equal(e.result, Cr.NS_BASE_STREAM_WOULD_BLOCK);
189     executeSoon(() => readOriginalInputStream(aInputStream));
190   }
193 function requestAgain() {
194   shouldPassRevalidation = false;
195   var chan = make_channel(URL);
196   var cc = chan.QueryInterface(Ci.nsICacheInfoChannel);
197   cc.preferAlternativeDataType(
198     altContentType,
199     "",
200     Ci.nsICacheInfoChannel.ASYNC
201   );
202   chan.asyncOpen(new ChannelListener(readEmptyAltContent, null));
205 function readEmptyAltContent(request, buffer) {
206   var cc = request.QueryInterface(Ci.nsICacheInfoChannel);
208   // the cache is overwrite and the alt-data is reset
209   Assert.equal(cc.alternativeDataType, "");
210   Assert.equal(buffer, responseContent2);
211   check_has_alt_data_in_index(false, () => httpServer.stop(do_test_finished));