Bug 1807268 - Re-enable verifyShowClipboardSuggestionsToggleTest UI test r=jajohnson
[gecko.git] / netwerk / test / unit / test_alt-data_closeWithStatus.js
blobb0427f2e9a1291b1bd59ddc781b09e9187cbfd84
1 /**
2  * Test for the "alternative data stream" - closing the stream with an error.
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 something in alt data (using the asyncWait method)
7  * - then we abort the operation calling closeWithStatus()
8  * - we flush the HTTP cache
9  * - we reload the same URL using a new channel, again prefering the alt data be loaded
10  * - again we receive the data from the server.
11  */
13 "use strict";
15 const { HttpServer } = ChromeUtils.importESModule(
16   "resource://testing-common/httpd.sys.mjs"
19 ChromeUtils.defineLazyGetter(this, "URL", function () {
20   return "http://localhost:" + httpServer.identity.primaryPort + "/content";
21 });
23 var httpServer = null;
25 // needs to be rooted
26 var cacheFlushObserver = (cacheFlushObserver = {
27   observe() {
28     cacheFlushObserver = null;
29     readServerContentAgain();
30   },
31 });
33 var currentThread = null;
35 function make_channel(url) {
36   return NetUtil.newChannel({ uri: url, loadUsingSystemPrincipal: true });
39 function inChildProcess() {
40   return Services.appinfo.processType != Ci.nsIXULRuntime.PROCESS_TYPE_DEFAULT;
43 const responseContent = "response body";
44 const responseContent2 = "response body 2";
45 const altContent = "!@#$%^&*()";
46 const altContentType = "text/binary";
48 var shouldPassRevalidation = true;
50 var cache_storage = null;
52 function contentHandler(metadata, response) {
53   response.setHeader("Content-Type", "text/plain");
54   response.setHeader("Cache-Control", "no-cache");
55   response.setHeader("ETag", "test-etag1");
57   let etag;
58   try {
59     etag = metadata.getHeader("If-None-Match");
60   } catch (ex) {
61     etag = "";
62   }
64   if (etag == "test-etag1" && shouldPassRevalidation) {
65     response.setStatusLine(metadata.httpVersion, 304, "Not Modified");
66   } else {
67     var content = shouldPassRevalidation ? responseContent : responseContent2;
68     response.bodyOutputStream.write(content, content.length);
69   }
72 function check_has_alt_data_in_index(aHasAltData, callback) {
73   if (inChildProcess()) {
74     callback();
75     return;
76   }
78   syncWithCacheIOThread(() => {
79     var hasAltData = {};
80     cache_storage.getCacheIndexEntryAttrs(createURI(URL), "", hasAltData, {});
81     Assert.equal(hasAltData.value, aHasAltData);
82     callback();
83   }, true);
86 function run_test() {
87   do_get_profile();
88   httpServer = new HttpServer();
89   httpServer.registerPathHandler("/content", contentHandler);
90   httpServer.start(-1);
91   do_test_pending();
93   if (!inChildProcess()) {
94     cache_storage = getCacheStorage("disk");
95     wait_for_cache_index(asyncOpen);
96   } else {
97     asyncOpen();
98   }
101 function asyncOpen() {
102   var chan = make_channel(URL);
104   var cc = chan.QueryInterface(Ci.nsICacheInfoChannel);
105   cc.preferAlternativeDataType(
106     altContentType,
107     "",
108     Ci.nsICacheInfoChannel.ASYNC
109   );
111   chan.asyncOpen(new ChannelListener(readServerContent, null));
114 function readServerContent(request, buffer) {
115   var cc = request.QueryInterface(Ci.nsICacheInfoChannel);
117   Assert.equal(buffer, responseContent);
118   Assert.equal(cc.alternativeDataType, "");
119   check_has_alt_data_in_index(false, () => {
120     if (!inChildProcess()) {
121       currentThread = Services.tm.currentThread;
122     }
124     executeSoon(() => {
125       var os = cc.openAlternativeOutputStream(
126         altContentType,
127         altContent.length
128       );
130       var aos = os.QueryInterface(Ci.nsIAsyncOutputStream);
131       aos.asyncWait(
132         _ => {
133           os.write(altContent, altContent.length);
134           aos.closeWithStatus(Cr.NS_ERROR_FAILURE);
135           executeSoon(flushAndReadServerContentAgain);
136         },
137         0,
138         0,
139         currentThread
140       );
141     });
142   });
145 function flushAndReadServerContentAgain() {
146   // We need to do a GC pass to ensure the cache entry has been freed.
147   gc();
148   if (!inChildProcess()) {
149     Services.cache2
150       .QueryInterface(Ci.nsICacheTesting)
151       .flush(cacheFlushObserver);
152   } else {
153     do_send_remote_message("flush");
154     do_await_remote_message("flushed").then(() => {
155       readServerContentAgain();
156     });
157   }
160 function readServerContentAgain() {
161   var chan = make_channel(URL);
162   var cc = chan.QueryInterface(Ci.nsICacheInfoChannel);
163   cc.preferAlternativeDataType(
164     "dummy1",
165     "text/javascript",
166     Ci.nsICacheInfoChannel.ASYNC
167   );
168   cc.preferAlternativeDataType(
169     altContentType,
170     "text/plain",
171     Ci.nsICacheInfoChannel.ASYNC
172   );
173   cc.preferAlternativeDataType("dummy2", "", Ci.nsICacheInfoChannel.ASYNC);
175   chan.asyncOpen(new ChannelListener(readServerContentAgainCB, null));
178 function readServerContentAgainCB(request, buffer) {
179   var cc = request.QueryInterface(Ci.nsICacheInfoChannel);
181   Assert.equal(buffer, responseContent);
182   Assert.equal(cc.alternativeDataType, "");
183   check_has_alt_data_in_index(false, () => httpServer.stop(do_test_finished));