|
1 /* Any copyright is dedicated to the Public Domain. |
|
2 * http://creativecommons.org/publicdomain/zero/1.0/ */ |
|
3 |
|
4 Cu.import("resource://gre/modules/Log.jsm"); |
|
5 Cu.import("resource://services-common/observers.js"); |
|
6 Cu.import("resource://services-sync/identity.js"); |
|
7 Cu.import("resource://services-sync/resource.js"); |
|
8 Cu.import("resource://services-sync/util.js"); |
|
9 |
|
10 let logger; |
|
11 |
|
12 let fetched = false; |
|
13 function server_open(metadata, response) { |
|
14 let body; |
|
15 if (metadata.method == "GET") { |
|
16 fetched = true; |
|
17 body = "This path exists"; |
|
18 response.setStatusLine(metadata.httpVersion, 200, "OK"); |
|
19 } else { |
|
20 body = "Wrong request method"; |
|
21 response.setStatusLine(metadata.httpVersion, 405, "Method Not Allowed"); |
|
22 } |
|
23 response.bodyOutputStream.write(body, body.length); |
|
24 } |
|
25 |
|
26 function server_protected(metadata, response) { |
|
27 let body; |
|
28 |
|
29 if (basic_auth_matches(metadata, "guest", "guest")) { |
|
30 body = "This path exists and is protected"; |
|
31 response.setStatusLine(metadata.httpVersion, 200, "OK, authorized"); |
|
32 response.setHeader("WWW-Authenticate", 'Basic realm="secret"', false); |
|
33 } else { |
|
34 body = "This path exists and is protected - failed"; |
|
35 response.setStatusLine(metadata.httpVersion, 401, "Unauthorized"); |
|
36 response.setHeader("WWW-Authenticate", 'Basic realm="secret"', false); |
|
37 } |
|
38 |
|
39 response.bodyOutputStream.write(body, body.length); |
|
40 } |
|
41 |
|
42 function server_404(metadata, response) { |
|
43 let body = "File not found"; |
|
44 response.setStatusLine(metadata.httpVersion, 404, "Not Found"); |
|
45 response.bodyOutputStream.write(body, body.length); |
|
46 } |
|
47 |
|
48 let pacFetched = false; |
|
49 function server_pac(metadata, response) { |
|
50 _("Invoked PAC handler."); |
|
51 pacFetched = true; |
|
52 let body = 'function FindProxyForURL(url, host) { return "DIRECT"; }'; |
|
53 response.setStatusLine(metadata.httpVersion, 200, "OK"); |
|
54 response.setHeader("Content-Type", "application/x-ns-proxy-autoconfig", false); |
|
55 response.bodyOutputStream.write(body, body.length); |
|
56 } |
|
57 |
|
58 let sample_data = { |
|
59 some: "sample_data", |
|
60 injson: "format", |
|
61 number: 42 |
|
62 }; |
|
63 |
|
64 function server_upload(metadata, response) { |
|
65 let body; |
|
66 |
|
67 let input = readBytesFromInputStream(metadata.bodyInputStream); |
|
68 if (input == JSON.stringify(sample_data)) { |
|
69 body = "Valid data upload via " + metadata.method; |
|
70 response.setStatusLine(metadata.httpVersion, 200, "OK"); |
|
71 } else { |
|
72 body = "Invalid data upload via " + metadata.method + ': ' + input; |
|
73 response.setStatusLine(metadata.httpVersion, 500, "Internal Server Error"); |
|
74 } |
|
75 |
|
76 response.bodyOutputStream.write(body, body.length); |
|
77 } |
|
78 |
|
79 function server_delete(metadata, response) { |
|
80 let body; |
|
81 if (metadata.method == "DELETE") { |
|
82 body = "This resource has been deleted"; |
|
83 response.setStatusLine(metadata.httpVersion, 200, "OK"); |
|
84 } else { |
|
85 body = "Wrong request method"; |
|
86 response.setStatusLine(metadata.httpVersion, 405, "Method Not Allowed"); |
|
87 } |
|
88 response.bodyOutputStream.write(body, body.length); |
|
89 } |
|
90 |
|
91 function server_json(metadata, response) { |
|
92 let body = JSON.stringify(sample_data); |
|
93 response.setStatusLine(metadata.httpVersion, 200, "OK"); |
|
94 response.bodyOutputStream.write(body, body.length); |
|
95 } |
|
96 |
|
97 const TIMESTAMP = 1274380461; |
|
98 |
|
99 function server_timestamp(metadata, response) { |
|
100 let body = "Thank you for your request"; |
|
101 response.setHeader("X-Weave-Timestamp", ''+TIMESTAMP, false); |
|
102 response.setStatusLine(metadata.httpVersion, 200, "OK"); |
|
103 response.bodyOutputStream.write(body, body.length); |
|
104 } |
|
105 |
|
106 function server_backoff(metadata, response) { |
|
107 let body = "Hey, back off!"; |
|
108 response.setHeader("X-Weave-Backoff", '600', false); |
|
109 response.setStatusLine(metadata.httpVersion, 200, "OK"); |
|
110 response.bodyOutputStream.write(body, body.length); |
|
111 } |
|
112 |
|
113 function server_quota_notice(request, response) { |
|
114 let body = "You're approaching quota."; |
|
115 response.setHeader("X-Weave-Quota-Remaining", '1048576', false); |
|
116 response.setStatusLine(request.httpVersion, 200, "OK"); |
|
117 response.bodyOutputStream.write(body, body.length); |
|
118 } |
|
119 |
|
120 function server_quota_error(request, response) { |
|
121 let body = "14"; |
|
122 response.setHeader("X-Weave-Quota-Remaining", '-1024', false); |
|
123 response.setStatusLine(request.httpVersion, 400, "OK"); |
|
124 response.bodyOutputStream.write(body, body.length); |
|
125 } |
|
126 |
|
127 function server_headers(metadata, response) { |
|
128 let ignore_headers = ["host", "user-agent", "accept", "accept-language", |
|
129 "accept-encoding", "accept-charset", "keep-alive", |
|
130 "connection", "pragma", "cache-control", |
|
131 "content-length"]; |
|
132 let headers = metadata.headers; |
|
133 let header_names = []; |
|
134 while (headers.hasMoreElements()) { |
|
135 let header = headers.getNext().toString(); |
|
136 if (ignore_headers.indexOf(header) == -1) { |
|
137 header_names.push(header); |
|
138 } |
|
139 } |
|
140 header_names = header_names.sort(); |
|
141 |
|
142 headers = {}; |
|
143 for each (let header in header_names) { |
|
144 headers[header] = metadata.getHeader(header); |
|
145 } |
|
146 let body = JSON.stringify(headers); |
|
147 response.setStatusLine(metadata.httpVersion, 200, "OK"); |
|
148 response.bodyOutputStream.write(body, body.length); |
|
149 } |
|
150 |
|
151 let quotaValue; |
|
152 Observers.add("weave:service:quota:remaining", |
|
153 function (subject) { quotaValue = subject; }); |
|
154 |
|
155 function run_test() { |
|
156 logger = Log.repository.getLogger('Test'); |
|
157 Log.repository.rootLogger.addAppender(new Log.DumpAppender()); |
|
158 |
|
159 Svc.Prefs.set("network.numRetries", 1); // speed up test |
|
160 run_next_test(); |
|
161 } |
|
162 |
|
163 // This apparently has to come first in order for our PAC URL to be hit. |
|
164 // Don't put any other HTTP requests earlier in the file! |
|
165 add_test(function test_proxy_auth_redirect() { |
|
166 _("Ensure that a proxy auth redirect (which switches out our channel) " + |
|
167 "doesn't break AsyncResource."); |
|
168 let server = httpd_setup({ |
|
169 "/open": server_open, |
|
170 "/pac2": server_pac |
|
171 }); |
|
172 |
|
173 PACSystemSettings.PACURI = server.baseURI + "/pac2"; |
|
174 installFakePAC(); |
|
175 let res = new AsyncResource(server.baseURI + "/open"); |
|
176 res.get(function (error, result) { |
|
177 do_check_true(!error); |
|
178 do_check_true(pacFetched); |
|
179 do_check_true(fetched); |
|
180 do_check_eq("This path exists", result); |
|
181 pacFetched = fetched = false; |
|
182 uninstallFakePAC(); |
|
183 server.stop(run_next_test); |
|
184 }); |
|
185 }); |
|
186 |
|
187 add_test(function test_new_channel() { |
|
188 _("Ensure a redirect to a new channel is handled properly."); |
|
189 |
|
190 let resourceRequested = false; |
|
191 function resourceHandler(metadata, response) { |
|
192 resourceRequested = true; |
|
193 |
|
194 let body = "Test"; |
|
195 response.setHeader("Content-Type", "text/plain"); |
|
196 response.bodyOutputStream.write(body, body.length); |
|
197 } |
|
198 |
|
199 let locationURL; |
|
200 function redirectHandler(metadata, response) { |
|
201 let body = "Redirecting"; |
|
202 response.setStatusLine(metadata.httpVersion, 307, "TEMPORARY REDIRECT"); |
|
203 response.setHeader("Location", locationURL); |
|
204 response.bodyOutputStream.write(body, body.length); |
|
205 } |
|
206 |
|
207 let server = httpd_setup({"/resource": resourceHandler, |
|
208 "/redirect": redirectHandler}); |
|
209 locationURL = server.baseURI + "/resource"; |
|
210 |
|
211 let request = new AsyncResource(server.baseURI + "/redirect"); |
|
212 request.get(function onRequest(error, content) { |
|
213 do_check_null(error); |
|
214 do_check_true(resourceRequested); |
|
215 do_check_eq(200, content.status); |
|
216 do_check_true("content-type" in content.headers); |
|
217 do_check_eq("text/plain", content.headers["content-type"]); |
|
218 |
|
219 server.stop(run_next_test); |
|
220 }); |
|
221 }); |
|
222 |
|
223 |
|
224 let server; |
|
225 |
|
226 add_test(function setup() { |
|
227 server = httpd_setup({ |
|
228 "/open": server_open, |
|
229 "/protected": server_protected, |
|
230 "/404": server_404, |
|
231 "/upload": server_upload, |
|
232 "/delete": server_delete, |
|
233 "/json": server_json, |
|
234 "/timestamp": server_timestamp, |
|
235 "/headers": server_headers, |
|
236 "/backoff": server_backoff, |
|
237 "/pac2": server_pac, |
|
238 "/quota-notice": server_quota_notice, |
|
239 "/quota-error": server_quota_error |
|
240 }); |
|
241 |
|
242 run_next_test(); |
|
243 }); |
|
244 |
|
245 add_test(function test_members() { |
|
246 _("Resource object members"); |
|
247 let uri = server.baseURI + "/open"; |
|
248 let res = new AsyncResource(uri); |
|
249 do_check_true(res.uri instanceof Ci.nsIURI); |
|
250 do_check_eq(res.uri.spec, uri); |
|
251 do_check_eq(res.spec, uri); |
|
252 do_check_eq(typeof res.headers, "object"); |
|
253 do_check_eq(typeof res.authenticator, "object"); |
|
254 // Initially res.data is null since we haven't performed a GET or |
|
255 // PUT/POST request yet. |
|
256 do_check_eq(res.data, null); |
|
257 |
|
258 run_next_test(); |
|
259 }); |
|
260 |
|
261 add_test(function test_get() { |
|
262 _("GET a non-password-protected resource"); |
|
263 let res = new AsyncResource(server.baseURI + "/open"); |
|
264 res.get(function (error, content) { |
|
265 do_check_eq(error, null); |
|
266 do_check_eq(content, "This path exists"); |
|
267 do_check_eq(content.status, 200); |
|
268 do_check_true(content.success); |
|
269 // res.data has been updated with the result from the request |
|
270 do_check_eq(res.data, content); |
|
271 |
|
272 // Observe logging messages. |
|
273 let logger = res._log; |
|
274 let dbg = logger.debug; |
|
275 let debugMessages = []; |
|
276 logger.debug = function (msg) { |
|
277 debugMessages.push(msg); |
|
278 dbg.call(this, msg); |
|
279 } |
|
280 |
|
281 // Since we didn't receive proper JSON data, accessing content.obj |
|
282 // will result in a SyntaxError from JSON.parse |
|
283 let didThrow = false; |
|
284 try { |
|
285 content.obj; |
|
286 } catch (ex) { |
|
287 didThrow = true; |
|
288 } |
|
289 do_check_true(didThrow); |
|
290 do_check_eq(debugMessages.length, 1); |
|
291 do_check_eq(debugMessages[0], |
|
292 "Parse fail: Response body starts: \"\"This path exists\"\"."); |
|
293 logger.debug = dbg; |
|
294 |
|
295 run_next_test(); |
|
296 }); |
|
297 }); |
|
298 |
|
299 add_test(function test_basicauth() { |
|
300 _("Test that the BasicAuthenticator doesn't screw up header case."); |
|
301 let res1 = new AsyncResource(server.baseURI + "/foo"); |
|
302 res1.setHeader("Authorization", "Basic foobar"); |
|
303 do_check_eq(res1._headers["authorization"], "Basic foobar"); |
|
304 do_check_eq(res1.headers["authorization"], "Basic foobar"); |
|
305 |
|
306 run_next_test(); |
|
307 }); |
|
308 |
|
309 add_test(function test_get_protected_fail() { |
|
310 _("GET a password protected resource (test that it'll fail w/o pass, no throw)"); |
|
311 let res2 = new AsyncResource(server.baseURI + "/protected"); |
|
312 res2.get(function (error, content) { |
|
313 do_check_eq(error, null); |
|
314 do_check_eq(content, "This path exists and is protected - failed"); |
|
315 do_check_eq(content.status, 401); |
|
316 do_check_false(content.success); |
|
317 run_next_test(); |
|
318 }); |
|
319 }); |
|
320 |
|
321 add_test(function test_get_protected_success() { |
|
322 _("GET a password protected resource"); |
|
323 let identity = new IdentityManager(); |
|
324 let auth = identity.getBasicResourceAuthenticator("guest", "guest"); |
|
325 let res3 = new AsyncResource(server.baseURI + "/protected"); |
|
326 res3.authenticator = auth; |
|
327 do_check_eq(res3.authenticator, auth); |
|
328 res3.get(function (error, content) { |
|
329 do_check_eq(error, null); |
|
330 do_check_eq(content, "This path exists and is protected"); |
|
331 do_check_eq(content.status, 200); |
|
332 do_check_true(content.success); |
|
333 run_next_test(); |
|
334 }); |
|
335 }); |
|
336 |
|
337 add_test(function test_get_404() { |
|
338 _("GET a non-existent resource (test that it'll fail, but not throw)"); |
|
339 let res4 = new AsyncResource(server.baseURI + "/404"); |
|
340 res4.get(function (error, content) { |
|
341 do_check_eq(error, null); |
|
342 do_check_eq(content, "File not found"); |
|
343 do_check_eq(content.status, 404); |
|
344 do_check_false(content.success); |
|
345 |
|
346 // Check some headers of the 404 response |
|
347 do_check_eq(content.headers.connection, "close"); |
|
348 do_check_eq(content.headers.server, "httpd.js"); |
|
349 do_check_eq(content.headers["content-length"], 14); |
|
350 |
|
351 run_next_test(); |
|
352 }); |
|
353 }); |
|
354 |
|
355 add_test(function test_put_string() { |
|
356 _("PUT to a resource (string)"); |
|
357 let res_upload = new AsyncResource(server.baseURI + "/upload"); |
|
358 res_upload.put(JSON.stringify(sample_data), function(error, content) { |
|
359 do_check_eq(error, null); |
|
360 do_check_eq(content, "Valid data upload via PUT"); |
|
361 do_check_eq(content.status, 200); |
|
362 do_check_eq(res_upload.data, content); |
|
363 run_next_test(); |
|
364 }); |
|
365 }); |
|
366 |
|
367 add_test(function test_put_object() { |
|
368 _("PUT to a resource (object)"); |
|
369 let res_upload = new AsyncResource(server.baseURI + "/upload"); |
|
370 res_upload.put(sample_data, function (error, content) { |
|
371 do_check_eq(error, null); |
|
372 do_check_eq(content, "Valid data upload via PUT"); |
|
373 do_check_eq(content.status, 200); |
|
374 do_check_eq(res_upload.data, content); |
|
375 run_next_test(); |
|
376 }); |
|
377 }); |
|
378 |
|
379 add_test(function test_put_data_string() { |
|
380 _("PUT without data arg (uses resource.data) (string)"); |
|
381 let res_upload = new AsyncResource(server.baseURI + "/upload"); |
|
382 res_upload.data = JSON.stringify(sample_data); |
|
383 res_upload.put(function (error, content) { |
|
384 do_check_eq(error, null); |
|
385 do_check_eq(content, "Valid data upload via PUT"); |
|
386 do_check_eq(content.status, 200); |
|
387 do_check_eq(res_upload.data, content); |
|
388 run_next_test(); |
|
389 }); |
|
390 }); |
|
391 |
|
392 add_test(function test_put_data_object() { |
|
393 _("PUT without data arg (uses resource.data) (object)"); |
|
394 let res_upload = new AsyncResource(server.baseURI + "/upload"); |
|
395 res_upload.data = sample_data; |
|
396 res_upload.put(function (error, content) { |
|
397 do_check_eq(error, null); |
|
398 do_check_eq(content, "Valid data upload via PUT"); |
|
399 do_check_eq(content.status, 200); |
|
400 do_check_eq(res_upload.data, content); |
|
401 run_next_test(); |
|
402 }); |
|
403 }); |
|
404 |
|
405 add_test(function test_post_string() { |
|
406 _("POST to a resource (string)"); |
|
407 let res_upload = new AsyncResource(server.baseURI + "/upload"); |
|
408 res_upload.post(JSON.stringify(sample_data), function (error, content) { |
|
409 do_check_eq(error, null); |
|
410 do_check_eq(content, "Valid data upload via POST"); |
|
411 do_check_eq(content.status, 200); |
|
412 do_check_eq(res_upload.data, content); |
|
413 run_next_test(); |
|
414 }); |
|
415 }); |
|
416 |
|
417 add_test(function test_post_object() { |
|
418 _("POST to a resource (object)"); |
|
419 let res_upload = new AsyncResource(server.baseURI + "/upload"); |
|
420 res_upload.post(sample_data, function (error, content) { |
|
421 do_check_eq(error, null); |
|
422 do_check_eq(content, "Valid data upload via POST"); |
|
423 do_check_eq(content.status, 200); |
|
424 do_check_eq(res_upload.data, content); |
|
425 run_next_test(); |
|
426 }); |
|
427 }); |
|
428 |
|
429 add_test(function test_post_data_string() { |
|
430 _("POST without data arg (uses resource.data) (string)"); |
|
431 let res_upload = new AsyncResource(server.baseURI + "/upload"); |
|
432 res_upload.data = JSON.stringify(sample_data); |
|
433 res_upload.post(function (error, content) { |
|
434 do_check_eq(error, null); |
|
435 do_check_eq(content, "Valid data upload via POST"); |
|
436 do_check_eq(content.status, 200); |
|
437 do_check_eq(res_upload.data, content); |
|
438 run_next_test(); |
|
439 }); |
|
440 }); |
|
441 |
|
442 add_test(function test_post_data_object() { |
|
443 _("POST without data arg (uses resource.data) (object)"); |
|
444 let res_upload = new AsyncResource(server.baseURI + "/upload"); |
|
445 res_upload.data = sample_data; |
|
446 res_upload.post(function (error, content) { |
|
447 do_check_eq(error, null); |
|
448 do_check_eq(content, "Valid data upload via POST"); |
|
449 do_check_eq(content.status, 200); |
|
450 do_check_eq(res_upload.data, content); |
|
451 run_next_test(); |
|
452 }); |
|
453 }); |
|
454 |
|
455 add_test(function test_delete() { |
|
456 _("DELETE a resource"); |
|
457 let res6 = new AsyncResource(server.baseURI + "/delete"); |
|
458 res6.delete(function (error, content) { |
|
459 do_check_eq(error, null); |
|
460 do_check_eq(content, "This resource has been deleted"); |
|
461 do_check_eq(content.status, 200); |
|
462 run_next_test(); |
|
463 }); |
|
464 }); |
|
465 |
|
466 add_test(function test_json_body() { |
|
467 _("JSON conversion of response body"); |
|
468 let res7 = new AsyncResource(server.baseURI + "/json"); |
|
469 res7.get(function (error, content) { |
|
470 do_check_eq(error, null); |
|
471 do_check_eq(content, JSON.stringify(sample_data)); |
|
472 do_check_eq(content.status, 200); |
|
473 do_check_eq(JSON.stringify(content.obj), JSON.stringify(sample_data)); |
|
474 run_next_test(); |
|
475 }); |
|
476 }); |
|
477 |
|
478 add_test(function test_weave_timestamp() { |
|
479 _("X-Weave-Timestamp header updates AsyncResource.serverTime"); |
|
480 // Before having received any response containing the |
|
481 // X-Weave-Timestamp header, AsyncResource.serverTime is null. |
|
482 do_check_eq(AsyncResource.serverTime, null); |
|
483 let res8 = new AsyncResource(server.baseURI + "/timestamp"); |
|
484 res8.get(function (error, content) { |
|
485 do_check_eq(error, null); |
|
486 do_check_eq(AsyncResource.serverTime, TIMESTAMP); |
|
487 run_next_test(); |
|
488 }); |
|
489 }); |
|
490 |
|
491 add_test(function test_get_no_headers() { |
|
492 _("GET: no special request headers"); |
|
493 let res_headers = new AsyncResource(server.baseURI + "/headers"); |
|
494 res_headers.get(function (error, content) { |
|
495 do_check_eq(error, null); |
|
496 do_check_eq(content, '{}'); |
|
497 run_next_test(); |
|
498 }); |
|
499 }); |
|
500 |
|
501 add_test(function test_put_default_content_type() { |
|
502 _("PUT: Content-Type defaults to text/plain"); |
|
503 let res_headers = new AsyncResource(server.baseURI + "/headers"); |
|
504 res_headers.put('data', function (error, content) { |
|
505 do_check_eq(error, null); |
|
506 do_check_eq(content, JSON.stringify({"content-type": "text/plain"})); |
|
507 run_next_test(); |
|
508 }); |
|
509 }); |
|
510 |
|
511 add_test(function test_post_default_content_type() { |
|
512 _("POST: Content-Type defaults to text/plain"); |
|
513 let res_headers = new AsyncResource(server.baseURI + "/headers"); |
|
514 res_headers.post('data', function (error, content) { |
|
515 do_check_eq(error, null); |
|
516 do_check_eq(content, JSON.stringify({"content-type": "text/plain"})); |
|
517 run_next_test(); |
|
518 }); |
|
519 }); |
|
520 |
|
521 add_test(function test_setHeader() { |
|
522 _("setHeader(): setting simple header"); |
|
523 let res_headers = new AsyncResource(server.baseURI + "/headers"); |
|
524 res_headers.setHeader('X-What-Is-Weave', 'awesome'); |
|
525 do_check_eq(res_headers.headers['x-what-is-weave'], 'awesome'); |
|
526 res_headers.get(function (error, content) { |
|
527 do_check_eq(error, null); |
|
528 do_check_eq(content, JSON.stringify({"x-what-is-weave": "awesome"})); |
|
529 run_next_test(); |
|
530 }); |
|
531 }); |
|
532 |
|
533 add_test(function test_setHeader_overwrite() { |
|
534 _("setHeader(): setting multiple headers, overwriting existing header"); |
|
535 let res_headers = new AsyncResource(server.baseURI + "/headers"); |
|
536 res_headers.setHeader('X-WHAT-is-Weave', 'more awesomer'); |
|
537 res_headers.setHeader('X-Another-Header', 'hello world'); |
|
538 do_check_eq(res_headers.headers['x-what-is-weave'], 'more awesomer'); |
|
539 do_check_eq(res_headers.headers['x-another-header'], 'hello world'); |
|
540 res_headers.get(function (error, content) { |
|
541 do_check_eq(error, null); |
|
542 do_check_eq(content, JSON.stringify({"x-another-header": "hello world", |
|
543 "x-what-is-weave": "more awesomer"})); |
|
544 |
|
545 run_next_test(); |
|
546 }); |
|
547 }); |
|
548 |
|
549 add_test(function test_headers_object() { |
|
550 _("Setting headers object"); |
|
551 let res_headers = new AsyncResource(server.baseURI + "/headers"); |
|
552 res_headers.headers = {}; |
|
553 res_headers.get(function (error, content) { |
|
554 do_check_eq(error, null); |
|
555 do_check_eq(content, "{}"); |
|
556 run_next_test(); |
|
557 }); |
|
558 }); |
|
559 |
|
560 add_test(function test_put_override_content_type() { |
|
561 _("PUT: override default Content-Type"); |
|
562 let res_headers = new AsyncResource(server.baseURI + "/headers"); |
|
563 res_headers.setHeader('Content-Type', 'application/foobar'); |
|
564 do_check_eq(res_headers.headers['content-type'], 'application/foobar'); |
|
565 res_headers.put('data', function (error, content) { |
|
566 do_check_eq(error, null); |
|
567 do_check_eq(content, JSON.stringify({"content-type": "application/foobar"})); |
|
568 run_next_test(); |
|
569 }); |
|
570 }); |
|
571 |
|
572 add_test(function test_post_override_content_type() { |
|
573 _("POST: override default Content-Type"); |
|
574 let res_headers = new AsyncResource(server.baseURI + "/headers"); |
|
575 res_headers.setHeader('Content-Type', 'application/foobar'); |
|
576 res_headers.post('data', function (error, content) { |
|
577 do_check_eq(error, null); |
|
578 do_check_eq(content, JSON.stringify({"content-type": "application/foobar"})); |
|
579 run_next_test(); |
|
580 }); |
|
581 }); |
|
582 |
|
583 add_test(function test_weave_backoff() { |
|
584 _("X-Weave-Backoff header notifies observer"); |
|
585 let backoffInterval; |
|
586 function onBackoff(subject, data) { |
|
587 backoffInterval = subject; |
|
588 } |
|
589 Observers.add("weave:service:backoff:interval", onBackoff); |
|
590 |
|
591 let res10 = new AsyncResource(server.baseURI + "/backoff"); |
|
592 res10.get(function (error, content) { |
|
593 do_check_eq(error, null); |
|
594 do_check_eq(backoffInterval, 600); |
|
595 run_next_test(); |
|
596 }); |
|
597 }); |
|
598 |
|
599 add_test(function test_quota_error() { |
|
600 _("X-Weave-Quota-Remaining header notifies observer on successful requests."); |
|
601 let res10 = new AsyncResource(server.baseURI + "/quota-error"); |
|
602 res10.get(function (error, content) { |
|
603 do_check_eq(error, null); |
|
604 do_check_eq(content.status, 400); |
|
605 do_check_eq(quotaValue, undefined); // HTTP 400, so no observer notification. |
|
606 run_next_test(); |
|
607 }); |
|
608 }); |
|
609 |
|
610 add_test(function test_quota_notice() { |
|
611 let res10 = new AsyncResource(server.baseURI + "/quota-notice"); |
|
612 res10.get(function (error, content) { |
|
613 do_check_eq(error, null); |
|
614 do_check_eq(content.status, 200); |
|
615 do_check_eq(quotaValue, 1048576); |
|
616 run_next_test(); |
|
617 }); |
|
618 }); |
|
619 |
|
620 add_test(function test_preserve_exceptions() { |
|
621 _("Error handling in ChannelListener etc. preserves exception information"); |
|
622 let res11 = new AsyncResource("http://localhost:12345/does/not/exist"); |
|
623 res11.get(function (error, content) { |
|
624 do_check_neq(error, null); |
|
625 do_check_eq(error.result, Cr.NS_ERROR_CONNECTION_REFUSED); |
|
626 do_check_eq(error.message, "NS_ERROR_CONNECTION_REFUSED"); |
|
627 run_next_test(); |
|
628 }); |
|
629 }); |
|
630 |
|
631 add_test(function test_xpc_exception_handling() { |
|
632 _("Exception handling inside fetches."); |
|
633 let res14 = new AsyncResource(server.baseURI + "/json"); |
|
634 res14._onProgress = function(rec) { |
|
635 // Provoke an XPC exception without a Javascript wrapper. |
|
636 Services.io.newURI("::::::::", null, null); |
|
637 }; |
|
638 let warnings = []; |
|
639 res14._log.warn = function(msg) { warnings.push(msg); }; |
|
640 |
|
641 res14.get(function (error, content) { |
|
642 do_check_eq(error.result, Cr.NS_ERROR_MALFORMED_URI); |
|
643 do_check_eq(error.message, "NS_ERROR_MALFORMED_URI"); |
|
644 do_check_eq(content, null); |
|
645 do_check_eq(warnings.pop(), |
|
646 "Got exception calling onProgress handler during fetch of " + |
|
647 server.baseURI + "/json"); |
|
648 |
|
649 run_next_test(); |
|
650 }); |
|
651 }); |
|
652 |
|
653 add_test(function test_js_exception_handling() { |
|
654 _("JS exception handling inside fetches."); |
|
655 let res15 = new AsyncResource(server.baseURI + "/json"); |
|
656 res15._onProgress = function(rec) { |
|
657 throw "BOO!"; |
|
658 }; |
|
659 let warnings = []; |
|
660 res15._log.warn = function(msg) { warnings.push(msg); }; |
|
661 |
|
662 res15.get(function (error, content) { |
|
663 do_check_eq(error.result, Cr.NS_ERROR_XPC_JS_THREW_STRING); |
|
664 do_check_eq(error.message, "NS_ERROR_XPC_JS_THREW_STRING"); |
|
665 do_check_eq(content, null); |
|
666 do_check_eq(warnings.pop(), |
|
667 "Got exception calling onProgress handler during fetch of " + |
|
668 server.baseURI + "/json"); |
|
669 |
|
670 run_next_test(); |
|
671 }); |
|
672 }); |
|
673 |
|
674 add_test(function test_timeout() { |
|
675 _("Ensure channel timeouts are thrown appropriately."); |
|
676 let res19 = new AsyncResource(server.baseURI + "/json"); |
|
677 res19.ABORT_TIMEOUT = 0; |
|
678 res19.get(function (error, content) { |
|
679 do_check_eq(error.result, Cr.NS_ERROR_NET_TIMEOUT); |
|
680 run_next_test(); |
|
681 }); |
|
682 }); |
|
683 |
|
684 add_test(function test_uri_construction() { |
|
685 _("Testing URI construction."); |
|
686 let args = []; |
|
687 args.push("newer=" + 1234); |
|
688 args.push("limit=" + 1234); |
|
689 args.push("sort=" + 1234); |
|
690 |
|
691 let query = "?" + args.join("&"); |
|
692 |
|
693 let uri1 = Utils.makeURI("http://foo/" + query) |
|
694 .QueryInterface(Ci.nsIURL); |
|
695 let uri2 = Utils.makeURI("http://foo/") |
|
696 .QueryInterface(Ci.nsIURL); |
|
697 uri2.query = query; |
|
698 do_check_eq(uri1.query, uri2.query); |
|
699 |
|
700 run_next_test(); |
|
701 }); |
|
702 |
|
703 add_test(function test_not_sending_cookie() { |
|
704 function handler(metadata, response) { |
|
705 let body = "COOKIE!"; |
|
706 response.setStatusLine(metadata.httpVersion, 200, "OK"); |
|
707 response.bodyOutputStream.write(body, body.length); |
|
708 do_check_false(metadata.hasHeader("Cookie")); |
|
709 } |
|
710 let cookieSer = Cc["@mozilla.org/cookieService;1"] |
|
711 .getService(Ci.nsICookieService); |
|
712 let uri = CommonUtils.makeURI(server.baseURI); |
|
713 cookieSer.setCookieString(uri, null, "test=test; path=/;", null); |
|
714 |
|
715 let res = new AsyncResource(server.baseURI + "/test"); |
|
716 res.get(function (error) { |
|
717 do_check_null(error); |
|
718 do_check_true(this.response.success); |
|
719 do_check_eq("COOKIE!", this.response.body); |
|
720 server.stop(run_next_test); |
|
721 }); |
|
722 }); |
|
723 |
|
724 /** |
|
725 * End of tests that rely on a single HTTP server. |
|
726 * All tests after this point must begin and end their own. |
|
727 */ |
|
728 add_test(function eliminate_server() { |
|
729 server.stop(run_next_test); |
|
730 }); |