Backed out changeset b71c8c052463 (bug 1943846) for causing mass failures. CLOSED...
[gecko.git] / netwerk / test / unit / test_synthesized_response.js
blob303cd34039f7b4502cd2ea2f071c697af8150454
1 "use strict";
3 const { HttpServer } = ChromeUtils.importESModule(
4 "resource://testing-common/httpd.sys.mjs"
5 );
7 ChromeUtils.defineLazyGetter(this, "URL", function () {
8 return "http://localhost:" + httpServer.identity.primaryPort;
9 });
11 var httpServer = null;
13 function isParentProcess() {
14 let appInfo = Cc["@mozilla.org/xre/app-info;1"];
15 return (
16 !appInfo ||
17 Services.appinfo.processType == Ci.nsIXULRuntime.PROCESS_TYPE_DEFAULT
21 if (isParentProcess()) {
22 // ensure the cache service is prepped when running the test
23 // We only do this in the main process, as the cache storage service leaks
24 // when instantiated in the content process.
25 Services.cache2;
28 var gotOnProgress;
29 var gotOnStatus;
31 function make_channel(url, body, cb) {
32 gotOnProgress = false;
33 gotOnStatus = false;
34 var chan = NetUtil.newChannel({
35 uri: url,
36 loadUsingSystemPrincipal: true,
37 }).QueryInterface(Ci.nsIHttpChannel);
38 chan.notificationCallbacks = {
39 numChecks: 0,
40 QueryInterface: ChromeUtils.generateQI([
41 "nsINetworkInterceptController",
42 "nsIInterfaceRequestor",
43 "nsIProgressEventSink",
44 ]),
45 getInterface(iid) {
46 return this.QueryInterface(iid);
48 onProgress() {
49 gotOnProgress = true;
51 onStatus() {
52 gotOnStatus = true;
54 shouldPrepareForIntercept() {
55 Assert.equal(this.numChecks, 0);
56 this.numChecks++;
57 return true;
59 channelIntercepted(channel) {
60 channel.QueryInterface(Ci.nsIInterceptedChannel);
61 if (body) {
62 var synthesized = Cc[
63 "@mozilla.org/io/string-input-stream;1"
64 ].createInstance(Ci.nsIStringInputStream);
65 synthesized.setByteStringData(body);
67 channel.startSynthesizedResponse(synthesized, null, null, "", false);
68 channel.finishSynthesizedResponse();
70 if (cb) {
71 cb(channel);
73 return {
74 dispatch() {},
78 return chan;
81 const REMOTE_BODY = "http handler body";
82 const NON_REMOTE_BODY = "synthesized body";
83 const NON_REMOTE_BODY_2 = "synthesized body #2";
85 function bodyHandler(metadata, response) {
86 response.setHeader("Content-Type", "text/plain");
87 response.write(REMOTE_BODY);
90 function run_test() {
91 httpServer = new HttpServer();
92 httpServer.registerPathHandler("/body", bodyHandler);
93 httpServer.start(-1);
95 run_next_test();
98 function handle_synthesized_response(request, buffer) {
99 Assert.equal(buffer, NON_REMOTE_BODY);
100 Assert.ok(gotOnStatus);
101 Assert.ok(gotOnProgress);
102 run_next_test();
105 function handle_synthesized_response_2(request, buffer) {
106 Assert.equal(buffer, NON_REMOTE_BODY_2);
107 Assert.ok(gotOnStatus);
108 Assert.ok(gotOnProgress);
109 run_next_test();
112 function handle_remote_response(request, buffer) {
113 Assert.equal(buffer, REMOTE_BODY);
114 Assert.ok(gotOnStatus);
115 Assert.ok(gotOnProgress);
116 run_next_test();
119 // hit the network instead of synthesizing
120 add_test(function () {
121 var chan = make_channel(URL + "/body", null, function (channel) {
122 channel.resetInterception(false);
124 chan.asyncOpen(new ChannelListener(handle_remote_response, null));
127 // synthesize a response
128 add_test(function () {
129 var chan = make_channel(URL + "/body", NON_REMOTE_BODY);
130 chan.asyncOpen(
131 new ChannelListener(handle_synthesized_response, null, CL_ALLOW_UNKNOWN_CL)
135 // hit the network instead of synthesizing, to test that no previous synthesized
136 // cache entry is used.
137 add_test(function () {
138 var chan = make_channel(URL + "/body", null, function (channel) {
139 channel.resetInterception(false);
141 chan.asyncOpen(new ChannelListener(handle_remote_response, null));
144 // synthesize a different response to ensure no previous response is cached
145 add_test(function () {
146 var chan = make_channel(URL + "/body", NON_REMOTE_BODY_2);
147 chan.asyncOpen(
148 new ChannelListener(
149 handle_synthesized_response_2,
150 null,
151 CL_ALLOW_UNKNOWN_CL
156 // ensure that the channel waits for a decision and synthesizes headers correctly
157 add_test(function () {
158 var chan = make_channel(URL + "/body", null, function (channel) {
159 do_timeout(100, function () {
160 var synthesized = Cc[
161 "@mozilla.org/io/string-input-stream;1"
162 ].createInstance(Ci.nsIStringInputStream);
163 synthesized.setByteStringData(NON_REMOTE_BODY);
164 channel.synthesizeHeader("Content-Length", NON_REMOTE_BODY.length);
165 channel.startSynthesizedResponse(synthesized, null, null, "", false);
166 channel.finishSynthesizedResponse();
169 chan.asyncOpen(new ChannelListener(handle_synthesized_response, null));
172 // ensure that the channel waits for a decision
173 add_test(function () {
174 var chan = make_channel(URL + "/body", null, function (channel) {
175 do_timeout(100, function () {
176 channel.resetInterception(false);
179 chan.asyncOpen(new ChannelListener(handle_remote_response, null));
182 // ensure that the intercepted channel supports suspend/resume
183 add_test(function () {
184 var chan = make_channel(URL + "/body", null, function (intercepted) {
185 var synthesized = Cc[
186 "@mozilla.org/io/string-input-stream;1"
187 ].createInstance(Ci.nsIStringInputStream);
188 synthesized.setByteStringData(NON_REMOTE_BODY);
190 // set the content-type to ensure that the stream converter doesn't hold up notifications
191 // and cause the test to fail
192 intercepted.synthesizeHeader("Content-Type", "text/plain");
193 intercepted.startSynthesizedResponse(synthesized, null, null, "", false);
194 intercepted.finishSynthesizedResponse();
196 chan.asyncOpen(
197 new ChannelListener(
198 handle_synthesized_response,
199 null,
200 CL_ALLOW_UNKNOWN_CL | CL_SUSPEND | CL_EXPECT_3S_DELAY
205 // ensure that the intercepted channel can be cancelled
206 add_test(function () {
207 var chan = make_channel(URL + "/body", null, function (intercepted) {
208 intercepted.cancelInterception(Cr.NS_BINDING_ABORTED);
210 chan.asyncOpen(new ChannelListener(run_next_test, null, CL_EXPECT_FAILURE));
213 // ensure that the channel can't be cancelled via nsIInterceptedChannel after making a decision
214 add_test(function () {
215 var chan = make_channel(URL + "/body", null, function (channel) {
216 channel.resetInterception(false);
217 do_timeout(0, function () {
218 var gotexception = false;
219 try {
220 channel.cancelInterception();
221 } catch (x) {
222 gotexception = true;
224 Assert.ok(gotexception);
227 chan.asyncOpen(new ChannelListener(handle_remote_response, null));
230 // ensure that the intercepted channel can be canceled during the response
231 add_test(function () {
232 var chan = make_channel(URL + "/body", null, function (intercepted) {
233 var synthesized = Cc[
234 "@mozilla.org/io/string-input-stream;1"
235 ].createInstance(Ci.nsIStringInputStream);
236 synthesized.setByteStringData(NON_REMOTE_BODY);
238 let channel = intercepted.channel;
239 intercepted.startSynthesizedResponse(synthesized, null, null, "", false);
240 intercepted.finishSynthesizedResponse();
241 channel.cancel(Cr.NS_BINDING_ABORTED);
243 chan.asyncOpen(
244 new ChannelListener(
245 run_next_test,
246 null,
247 CL_EXPECT_FAILURE | CL_ALLOW_UNKNOWN_CL
252 // ensure that the intercepted channel can be canceled before the response
253 add_test(function () {
254 var chan = make_channel(URL + "/body", null, function (intercepted) {
255 var synthesized = Cc[
256 "@mozilla.org/io/string-input-stream;1"
257 ].createInstance(Ci.nsIStringInputStream);
258 synthesized.setByteStringData(NON_REMOTE_BODY);
260 intercepted.channel.cancel(Cr.NS_BINDING_ABORTED);
262 // This should not throw, but result in the channel firing callbacks
263 // with an error status.
264 intercepted.startSynthesizedResponse(synthesized, null, null, "", false);
265 intercepted.finishSynthesizedResponse();
267 chan.asyncOpen(
268 new ChannelListener(
269 run_next_test,
270 null,
271 CL_EXPECT_FAILURE | CL_ALLOW_UNKNOWN_CL
276 // Ensure that nsIInterceptedChannel.channelIntercepted() can return an error.
277 // In this case we should automatically ResetInterception() and complete the
278 // network request.
279 add_test(function () {
280 var chan = make_channel(URL + "/body", null, function () {
281 throw new Error("boom");
283 chan.asyncOpen(new ChannelListener(handle_remote_response, null));
286 add_test(function () {
287 httpServer.stop(run_next_test);