1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/services/sync/tests/unit/test_resource_async.js Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,730 @@ 1.4 +/* Any copyright is dedicated to the Public Domain. 1.5 + * http://creativecommons.org/publicdomain/zero/1.0/ */ 1.6 + 1.7 +Cu.import("resource://gre/modules/Log.jsm"); 1.8 +Cu.import("resource://services-common/observers.js"); 1.9 +Cu.import("resource://services-sync/identity.js"); 1.10 +Cu.import("resource://services-sync/resource.js"); 1.11 +Cu.import("resource://services-sync/util.js"); 1.12 + 1.13 +let logger; 1.14 + 1.15 +let fetched = false; 1.16 +function server_open(metadata, response) { 1.17 + let body; 1.18 + if (metadata.method == "GET") { 1.19 + fetched = true; 1.20 + body = "This path exists"; 1.21 + response.setStatusLine(metadata.httpVersion, 200, "OK"); 1.22 + } else { 1.23 + body = "Wrong request method"; 1.24 + response.setStatusLine(metadata.httpVersion, 405, "Method Not Allowed"); 1.25 + } 1.26 + response.bodyOutputStream.write(body, body.length); 1.27 +} 1.28 + 1.29 +function server_protected(metadata, response) { 1.30 + let body; 1.31 + 1.32 + if (basic_auth_matches(metadata, "guest", "guest")) { 1.33 + body = "This path exists and is protected"; 1.34 + response.setStatusLine(metadata.httpVersion, 200, "OK, authorized"); 1.35 + response.setHeader("WWW-Authenticate", 'Basic realm="secret"', false); 1.36 + } else { 1.37 + body = "This path exists and is protected - failed"; 1.38 + response.setStatusLine(metadata.httpVersion, 401, "Unauthorized"); 1.39 + response.setHeader("WWW-Authenticate", 'Basic realm="secret"', false); 1.40 + } 1.41 + 1.42 + response.bodyOutputStream.write(body, body.length); 1.43 +} 1.44 + 1.45 +function server_404(metadata, response) { 1.46 + let body = "File not found"; 1.47 + response.setStatusLine(metadata.httpVersion, 404, "Not Found"); 1.48 + response.bodyOutputStream.write(body, body.length); 1.49 +} 1.50 + 1.51 +let pacFetched = false; 1.52 +function server_pac(metadata, response) { 1.53 + _("Invoked PAC handler."); 1.54 + pacFetched = true; 1.55 + let body = 'function FindProxyForURL(url, host) { return "DIRECT"; }'; 1.56 + response.setStatusLine(metadata.httpVersion, 200, "OK"); 1.57 + response.setHeader("Content-Type", "application/x-ns-proxy-autoconfig", false); 1.58 + response.bodyOutputStream.write(body, body.length); 1.59 +} 1.60 + 1.61 +let sample_data = { 1.62 + some: "sample_data", 1.63 + injson: "format", 1.64 + number: 42 1.65 +}; 1.66 + 1.67 +function server_upload(metadata, response) { 1.68 + let body; 1.69 + 1.70 + let input = readBytesFromInputStream(metadata.bodyInputStream); 1.71 + if (input == JSON.stringify(sample_data)) { 1.72 + body = "Valid data upload via " + metadata.method; 1.73 + response.setStatusLine(metadata.httpVersion, 200, "OK"); 1.74 + } else { 1.75 + body = "Invalid data upload via " + metadata.method + ': ' + input; 1.76 + response.setStatusLine(metadata.httpVersion, 500, "Internal Server Error"); 1.77 + } 1.78 + 1.79 + response.bodyOutputStream.write(body, body.length); 1.80 +} 1.81 + 1.82 +function server_delete(metadata, response) { 1.83 + let body; 1.84 + if (metadata.method == "DELETE") { 1.85 + body = "This resource has been deleted"; 1.86 + response.setStatusLine(metadata.httpVersion, 200, "OK"); 1.87 + } else { 1.88 + body = "Wrong request method"; 1.89 + response.setStatusLine(metadata.httpVersion, 405, "Method Not Allowed"); 1.90 + } 1.91 + response.bodyOutputStream.write(body, body.length); 1.92 +} 1.93 + 1.94 +function server_json(metadata, response) { 1.95 + let body = JSON.stringify(sample_data); 1.96 + response.setStatusLine(metadata.httpVersion, 200, "OK"); 1.97 + response.bodyOutputStream.write(body, body.length); 1.98 +} 1.99 + 1.100 +const TIMESTAMP = 1274380461; 1.101 + 1.102 +function server_timestamp(metadata, response) { 1.103 + let body = "Thank you for your request"; 1.104 + response.setHeader("X-Weave-Timestamp", ''+TIMESTAMP, false); 1.105 + response.setStatusLine(metadata.httpVersion, 200, "OK"); 1.106 + response.bodyOutputStream.write(body, body.length); 1.107 +} 1.108 + 1.109 +function server_backoff(metadata, response) { 1.110 + let body = "Hey, back off!"; 1.111 + response.setHeader("X-Weave-Backoff", '600', false); 1.112 + response.setStatusLine(metadata.httpVersion, 200, "OK"); 1.113 + response.bodyOutputStream.write(body, body.length); 1.114 +} 1.115 + 1.116 +function server_quota_notice(request, response) { 1.117 + let body = "You're approaching quota."; 1.118 + response.setHeader("X-Weave-Quota-Remaining", '1048576', false); 1.119 + response.setStatusLine(request.httpVersion, 200, "OK"); 1.120 + response.bodyOutputStream.write(body, body.length); 1.121 +} 1.122 + 1.123 +function server_quota_error(request, response) { 1.124 + let body = "14"; 1.125 + response.setHeader("X-Weave-Quota-Remaining", '-1024', false); 1.126 + response.setStatusLine(request.httpVersion, 400, "OK"); 1.127 + response.bodyOutputStream.write(body, body.length); 1.128 +} 1.129 + 1.130 +function server_headers(metadata, response) { 1.131 + let ignore_headers = ["host", "user-agent", "accept", "accept-language", 1.132 + "accept-encoding", "accept-charset", "keep-alive", 1.133 + "connection", "pragma", "cache-control", 1.134 + "content-length"]; 1.135 + let headers = metadata.headers; 1.136 + let header_names = []; 1.137 + while (headers.hasMoreElements()) { 1.138 + let header = headers.getNext().toString(); 1.139 + if (ignore_headers.indexOf(header) == -1) { 1.140 + header_names.push(header); 1.141 + } 1.142 + } 1.143 + header_names = header_names.sort(); 1.144 + 1.145 + headers = {}; 1.146 + for each (let header in header_names) { 1.147 + headers[header] = metadata.getHeader(header); 1.148 + } 1.149 + let body = JSON.stringify(headers); 1.150 + response.setStatusLine(metadata.httpVersion, 200, "OK"); 1.151 + response.bodyOutputStream.write(body, body.length); 1.152 +} 1.153 + 1.154 +let quotaValue; 1.155 +Observers.add("weave:service:quota:remaining", 1.156 + function (subject) { quotaValue = subject; }); 1.157 + 1.158 +function run_test() { 1.159 + logger = Log.repository.getLogger('Test'); 1.160 + Log.repository.rootLogger.addAppender(new Log.DumpAppender()); 1.161 + 1.162 + Svc.Prefs.set("network.numRetries", 1); // speed up test 1.163 + run_next_test(); 1.164 +} 1.165 + 1.166 +// This apparently has to come first in order for our PAC URL to be hit. 1.167 +// Don't put any other HTTP requests earlier in the file! 1.168 +add_test(function test_proxy_auth_redirect() { 1.169 + _("Ensure that a proxy auth redirect (which switches out our channel) " + 1.170 + "doesn't break AsyncResource."); 1.171 + let server = httpd_setup({ 1.172 + "/open": server_open, 1.173 + "/pac2": server_pac 1.174 + }); 1.175 + 1.176 + PACSystemSettings.PACURI = server.baseURI + "/pac2"; 1.177 + installFakePAC(); 1.178 + let res = new AsyncResource(server.baseURI + "/open"); 1.179 + res.get(function (error, result) { 1.180 + do_check_true(!error); 1.181 + do_check_true(pacFetched); 1.182 + do_check_true(fetched); 1.183 + do_check_eq("This path exists", result); 1.184 + pacFetched = fetched = false; 1.185 + uninstallFakePAC(); 1.186 + server.stop(run_next_test); 1.187 + }); 1.188 +}); 1.189 + 1.190 +add_test(function test_new_channel() { 1.191 + _("Ensure a redirect to a new channel is handled properly."); 1.192 + 1.193 + let resourceRequested = false; 1.194 + function resourceHandler(metadata, response) { 1.195 + resourceRequested = true; 1.196 + 1.197 + let body = "Test"; 1.198 + response.setHeader("Content-Type", "text/plain"); 1.199 + response.bodyOutputStream.write(body, body.length); 1.200 + } 1.201 + 1.202 + let locationURL; 1.203 + function redirectHandler(metadata, response) { 1.204 + let body = "Redirecting"; 1.205 + response.setStatusLine(metadata.httpVersion, 307, "TEMPORARY REDIRECT"); 1.206 + response.setHeader("Location", locationURL); 1.207 + response.bodyOutputStream.write(body, body.length); 1.208 + } 1.209 + 1.210 + let server = httpd_setup({"/resource": resourceHandler, 1.211 + "/redirect": redirectHandler}); 1.212 + locationURL = server.baseURI + "/resource"; 1.213 + 1.214 + let request = new AsyncResource(server.baseURI + "/redirect"); 1.215 + request.get(function onRequest(error, content) { 1.216 + do_check_null(error); 1.217 + do_check_true(resourceRequested); 1.218 + do_check_eq(200, content.status); 1.219 + do_check_true("content-type" in content.headers); 1.220 + do_check_eq("text/plain", content.headers["content-type"]); 1.221 + 1.222 + server.stop(run_next_test); 1.223 + }); 1.224 +}); 1.225 + 1.226 + 1.227 +let server; 1.228 + 1.229 +add_test(function setup() { 1.230 + server = httpd_setup({ 1.231 + "/open": server_open, 1.232 + "/protected": server_protected, 1.233 + "/404": server_404, 1.234 + "/upload": server_upload, 1.235 + "/delete": server_delete, 1.236 + "/json": server_json, 1.237 + "/timestamp": server_timestamp, 1.238 + "/headers": server_headers, 1.239 + "/backoff": server_backoff, 1.240 + "/pac2": server_pac, 1.241 + "/quota-notice": server_quota_notice, 1.242 + "/quota-error": server_quota_error 1.243 + }); 1.244 + 1.245 + run_next_test(); 1.246 +}); 1.247 + 1.248 +add_test(function test_members() { 1.249 + _("Resource object members"); 1.250 + let uri = server.baseURI + "/open"; 1.251 + let res = new AsyncResource(uri); 1.252 + do_check_true(res.uri instanceof Ci.nsIURI); 1.253 + do_check_eq(res.uri.spec, uri); 1.254 + do_check_eq(res.spec, uri); 1.255 + do_check_eq(typeof res.headers, "object"); 1.256 + do_check_eq(typeof res.authenticator, "object"); 1.257 + // Initially res.data is null since we haven't performed a GET or 1.258 + // PUT/POST request yet. 1.259 + do_check_eq(res.data, null); 1.260 + 1.261 + run_next_test(); 1.262 +}); 1.263 + 1.264 +add_test(function test_get() { 1.265 + _("GET a non-password-protected resource"); 1.266 + let res = new AsyncResource(server.baseURI + "/open"); 1.267 + res.get(function (error, content) { 1.268 + do_check_eq(error, null); 1.269 + do_check_eq(content, "This path exists"); 1.270 + do_check_eq(content.status, 200); 1.271 + do_check_true(content.success); 1.272 + // res.data has been updated with the result from the request 1.273 + do_check_eq(res.data, content); 1.274 + 1.275 + // Observe logging messages. 1.276 + let logger = res._log; 1.277 + let dbg = logger.debug; 1.278 + let debugMessages = []; 1.279 + logger.debug = function (msg) { 1.280 + debugMessages.push(msg); 1.281 + dbg.call(this, msg); 1.282 + } 1.283 + 1.284 + // Since we didn't receive proper JSON data, accessing content.obj 1.285 + // will result in a SyntaxError from JSON.parse 1.286 + let didThrow = false; 1.287 + try { 1.288 + content.obj; 1.289 + } catch (ex) { 1.290 + didThrow = true; 1.291 + } 1.292 + do_check_true(didThrow); 1.293 + do_check_eq(debugMessages.length, 1); 1.294 + do_check_eq(debugMessages[0], 1.295 + "Parse fail: Response body starts: \"\"This path exists\"\"."); 1.296 + logger.debug = dbg; 1.297 + 1.298 + run_next_test(); 1.299 + }); 1.300 +}); 1.301 + 1.302 +add_test(function test_basicauth() { 1.303 + _("Test that the BasicAuthenticator doesn't screw up header case."); 1.304 + let res1 = new AsyncResource(server.baseURI + "/foo"); 1.305 + res1.setHeader("Authorization", "Basic foobar"); 1.306 + do_check_eq(res1._headers["authorization"], "Basic foobar"); 1.307 + do_check_eq(res1.headers["authorization"], "Basic foobar"); 1.308 + 1.309 + run_next_test(); 1.310 +}); 1.311 + 1.312 +add_test(function test_get_protected_fail() { 1.313 + _("GET a password protected resource (test that it'll fail w/o pass, no throw)"); 1.314 + let res2 = new AsyncResource(server.baseURI + "/protected"); 1.315 + res2.get(function (error, content) { 1.316 + do_check_eq(error, null); 1.317 + do_check_eq(content, "This path exists and is protected - failed"); 1.318 + do_check_eq(content.status, 401); 1.319 + do_check_false(content.success); 1.320 + run_next_test(); 1.321 + }); 1.322 +}); 1.323 + 1.324 +add_test(function test_get_protected_success() { 1.325 + _("GET a password protected resource"); 1.326 + let identity = new IdentityManager(); 1.327 + let auth = identity.getBasicResourceAuthenticator("guest", "guest"); 1.328 + let res3 = new AsyncResource(server.baseURI + "/protected"); 1.329 + res3.authenticator = auth; 1.330 + do_check_eq(res3.authenticator, auth); 1.331 + res3.get(function (error, content) { 1.332 + do_check_eq(error, null); 1.333 + do_check_eq(content, "This path exists and is protected"); 1.334 + do_check_eq(content.status, 200); 1.335 + do_check_true(content.success); 1.336 + run_next_test(); 1.337 + }); 1.338 +}); 1.339 + 1.340 +add_test(function test_get_404() { 1.341 + _("GET a non-existent resource (test that it'll fail, but not throw)"); 1.342 + let res4 = new AsyncResource(server.baseURI + "/404"); 1.343 + res4.get(function (error, content) { 1.344 + do_check_eq(error, null); 1.345 + do_check_eq(content, "File not found"); 1.346 + do_check_eq(content.status, 404); 1.347 + do_check_false(content.success); 1.348 + 1.349 + // Check some headers of the 404 response 1.350 + do_check_eq(content.headers.connection, "close"); 1.351 + do_check_eq(content.headers.server, "httpd.js"); 1.352 + do_check_eq(content.headers["content-length"], 14); 1.353 + 1.354 + run_next_test(); 1.355 + }); 1.356 +}); 1.357 + 1.358 +add_test(function test_put_string() { 1.359 + _("PUT to a resource (string)"); 1.360 + let res_upload = new AsyncResource(server.baseURI + "/upload"); 1.361 + res_upload.put(JSON.stringify(sample_data), function(error, content) { 1.362 + do_check_eq(error, null); 1.363 + do_check_eq(content, "Valid data upload via PUT"); 1.364 + do_check_eq(content.status, 200); 1.365 + do_check_eq(res_upload.data, content); 1.366 + run_next_test(); 1.367 + }); 1.368 +}); 1.369 + 1.370 +add_test(function test_put_object() { 1.371 + _("PUT to a resource (object)"); 1.372 + let res_upload = new AsyncResource(server.baseURI + "/upload"); 1.373 + res_upload.put(sample_data, function (error, content) { 1.374 + do_check_eq(error, null); 1.375 + do_check_eq(content, "Valid data upload via PUT"); 1.376 + do_check_eq(content.status, 200); 1.377 + do_check_eq(res_upload.data, content); 1.378 + run_next_test(); 1.379 + }); 1.380 +}); 1.381 + 1.382 +add_test(function test_put_data_string() { 1.383 + _("PUT without data arg (uses resource.data) (string)"); 1.384 + let res_upload = new AsyncResource(server.baseURI + "/upload"); 1.385 + res_upload.data = JSON.stringify(sample_data); 1.386 + res_upload.put(function (error, content) { 1.387 + do_check_eq(error, null); 1.388 + do_check_eq(content, "Valid data upload via PUT"); 1.389 + do_check_eq(content.status, 200); 1.390 + do_check_eq(res_upload.data, content); 1.391 + run_next_test(); 1.392 + }); 1.393 +}); 1.394 + 1.395 +add_test(function test_put_data_object() { 1.396 + _("PUT without data arg (uses resource.data) (object)"); 1.397 + let res_upload = new AsyncResource(server.baseURI + "/upload"); 1.398 + res_upload.data = sample_data; 1.399 + res_upload.put(function (error, content) { 1.400 + do_check_eq(error, null); 1.401 + do_check_eq(content, "Valid data upload via PUT"); 1.402 + do_check_eq(content.status, 200); 1.403 + do_check_eq(res_upload.data, content); 1.404 + run_next_test(); 1.405 + }); 1.406 +}); 1.407 + 1.408 +add_test(function test_post_string() { 1.409 + _("POST to a resource (string)"); 1.410 + let res_upload = new AsyncResource(server.baseURI + "/upload"); 1.411 + res_upload.post(JSON.stringify(sample_data), function (error, content) { 1.412 + do_check_eq(error, null); 1.413 + do_check_eq(content, "Valid data upload via POST"); 1.414 + do_check_eq(content.status, 200); 1.415 + do_check_eq(res_upload.data, content); 1.416 + run_next_test(); 1.417 + }); 1.418 +}); 1.419 + 1.420 +add_test(function test_post_object() { 1.421 + _("POST to a resource (object)"); 1.422 + let res_upload = new AsyncResource(server.baseURI + "/upload"); 1.423 + res_upload.post(sample_data, function (error, content) { 1.424 + do_check_eq(error, null); 1.425 + do_check_eq(content, "Valid data upload via POST"); 1.426 + do_check_eq(content.status, 200); 1.427 + do_check_eq(res_upload.data, content); 1.428 + run_next_test(); 1.429 + }); 1.430 +}); 1.431 + 1.432 +add_test(function test_post_data_string() { 1.433 + _("POST without data arg (uses resource.data) (string)"); 1.434 + let res_upload = new AsyncResource(server.baseURI + "/upload"); 1.435 + res_upload.data = JSON.stringify(sample_data); 1.436 + res_upload.post(function (error, content) { 1.437 + do_check_eq(error, null); 1.438 + do_check_eq(content, "Valid data upload via POST"); 1.439 + do_check_eq(content.status, 200); 1.440 + do_check_eq(res_upload.data, content); 1.441 + run_next_test(); 1.442 + }); 1.443 +}); 1.444 + 1.445 +add_test(function test_post_data_object() { 1.446 + _("POST without data arg (uses resource.data) (object)"); 1.447 + let res_upload = new AsyncResource(server.baseURI + "/upload"); 1.448 + res_upload.data = sample_data; 1.449 + res_upload.post(function (error, content) { 1.450 + do_check_eq(error, null); 1.451 + do_check_eq(content, "Valid data upload via POST"); 1.452 + do_check_eq(content.status, 200); 1.453 + do_check_eq(res_upload.data, content); 1.454 + run_next_test(); 1.455 + }); 1.456 +}); 1.457 + 1.458 +add_test(function test_delete() { 1.459 + _("DELETE a resource"); 1.460 + let res6 = new AsyncResource(server.baseURI + "/delete"); 1.461 + res6.delete(function (error, content) { 1.462 + do_check_eq(error, null); 1.463 + do_check_eq(content, "This resource has been deleted"); 1.464 + do_check_eq(content.status, 200); 1.465 + run_next_test(); 1.466 + }); 1.467 +}); 1.468 + 1.469 +add_test(function test_json_body() { 1.470 + _("JSON conversion of response body"); 1.471 + let res7 = new AsyncResource(server.baseURI + "/json"); 1.472 + res7.get(function (error, content) { 1.473 + do_check_eq(error, null); 1.474 + do_check_eq(content, JSON.stringify(sample_data)); 1.475 + do_check_eq(content.status, 200); 1.476 + do_check_eq(JSON.stringify(content.obj), JSON.stringify(sample_data)); 1.477 + run_next_test(); 1.478 + }); 1.479 +}); 1.480 + 1.481 +add_test(function test_weave_timestamp() { 1.482 + _("X-Weave-Timestamp header updates AsyncResource.serverTime"); 1.483 + // Before having received any response containing the 1.484 + // X-Weave-Timestamp header, AsyncResource.serverTime is null. 1.485 + do_check_eq(AsyncResource.serverTime, null); 1.486 + let res8 = new AsyncResource(server.baseURI + "/timestamp"); 1.487 + res8.get(function (error, content) { 1.488 + do_check_eq(error, null); 1.489 + do_check_eq(AsyncResource.serverTime, TIMESTAMP); 1.490 + run_next_test(); 1.491 + }); 1.492 +}); 1.493 + 1.494 +add_test(function test_get_no_headers() { 1.495 + _("GET: no special request headers"); 1.496 + let res_headers = new AsyncResource(server.baseURI + "/headers"); 1.497 + res_headers.get(function (error, content) { 1.498 + do_check_eq(error, null); 1.499 + do_check_eq(content, '{}'); 1.500 + run_next_test(); 1.501 + }); 1.502 +}); 1.503 + 1.504 +add_test(function test_put_default_content_type() { 1.505 + _("PUT: Content-Type defaults to text/plain"); 1.506 + let res_headers = new AsyncResource(server.baseURI + "/headers"); 1.507 + res_headers.put('data', function (error, content) { 1.508 + do_check_eq(error, null); 1.509 + do_check_eq(content, JSON.stringify({"content-type": "text/plain"})); 1.510 + run_next_test(); 1.511 + }); 1.512 +}); 1.513 + 1.514 +add_test(function test_post_default_content_type() { 1.515 + _("POST: Content-Type defaults to text/plain"); 1.516 + let res_headers = new AsyncResource(server.baseURI + "/headers"); 1.517 + res_headers.post('data', function (error, content) { 1.518 + do_check_eq(error, null); 1.519 + do_check_eq(content, JSON.stringify({"content-type": "text/plain"})); 1.520 + run_next_test(); 1.521 + }); 1.522 +}); 1.523 + 1.524 +add_test(function test_setHeader() { 1.525 + _("setHeader(): setting simple header"); 1.526 + let res_headers = new AsyncResource(server.baseURI + "/headers"); 1.527 + res_headers.setHeader('X-What-Is-Weave', 'awesome'); 1.528 + do_check_eq(res_headers.headers['x-what-is-weave'], 'awesome'); 1.529 + res_headers.get(function (error, content) { 1.530 + do_check_eq(error, null); 1.531 + do_check_eq(content, JSON.stringify({"x-what-is-weave": "awesome"})); 1.532 + run_next_test(); 1.533 + }); 1.534 +}); 1.535 + 1.536 +add_test(function test_setHeader_overwrite() { 1.537 + _("setHeader(): setting multiple headers, overwriting existing header"); 1.538 + let res_headers = new AsyncResource(server.baseURI + "/headers"); 1.539 + res_headers.setHeader('X-WHAT-is-Weave', 'more awesomer'); 1.540 + res_headers.setHeader('X-Another-Header', 'hello world'); 1.541 + do_check_eq(res_headers.headers['x-what-is-weave'], 'more awesomer'); 1.542 + do_check_eq(res_headers.headers['x-another-header'], 'hello world'); 1.543 + res_headers.get(function (error, content) { 1.544 + do_check_eq(error, null); 1.545 + do_check_eq(content, JSON.stringify({"x-another-header": "hello world", 1.546 + "x-what-is-weave": "more awesomer"})); 1.547 + 1.548 + run_next_test(); 1.549 + }); 1.550 +}); 1.551 + 1.552 +add_test(function test_headers_object() { 1.553 + _("Setting headers object"); 1.554 + let res_headers = new AsyncResource(server.baseURI + "/headers"); 1.555 + res_headers.headers = {}; 1.556 + res_headers.get(function (error, content) { 1.557 + do_check_eq(error, null); 1.558 + do_check_eq(content, "{}"); 1.559 + run_next_test(); 1.560 + }); 1.561 +}); 1.562 + 1.563 +add_test(function test_put_override_content_type() { 1.564 + _("PUT: override default Content-Type"); 1.565 + let res_headers = new AsyncResource(server.baseURI + "/headers"); 1.566 + res_headers.setHeader('Content-Type', 'application/foobar'); 1.567 + do_check_eq(res_headers.headers['content-type'], 'application/foobar'); 1.568 + res_headers.put('data', function (error, content) { 1.569 + do_check_eq(error, null); 1.570 + do_check_eq(content, JSON.stringify({"content-type": "application/foobar"})); 1.571 + run_next_test(); 1.572 + }); 1.573 +}); 1.574 + 1.575 +add_test(function test_post_override_content_type() { 1.576 + _("POST: override default Content-Type"); 1.577 + let res_headers = new AsyncResource(server.baseURI + "/headers"); 1.578 + res_headers.setHeader('Content-Type', 'application/foobar'); 1.579 + res_headers.post('data', function (error, content) { 1.580 + do_check_eq(error, null); 1.581 + do_check_eq(content, JSON.stringify({"content-type": "application/foobar"})); 1.582 + run_next_test(); 1.583 + }); 1.584 +}); 1.585 + 1.586 +add_test(function test_weave_backoff() { 1.587 + _("X-Weave-Backoff header notifies observer"); 1.588 + let backoffInterval; 1.589 + function onBackoff(subject, data) { 1.590 + backoffInterval = subject; 1.591 + } 1.592 + Observers.add("weave:service:backoff:interval", onBackoff); 1.593 + 1.594 + let res10 = new AsyncResource(server.baseURI + "/backoff"); 1.595 + res10.get(function (error, content) { 1.596 + do_check_eq(error, null); 1.597 + do_check_eq(backoffInterval, 600); 1.598 + run_next_test(); 1.599 + }); 1.600 +}); 1.601 + 1.602 +add_test(function test_quota_error() { 1.603 + _("X-Weave-Quota-Remaining header notifies observer on successful requests."); 1.604 + let res10 = new AsyncResource(server.baseURI + "/quota-error"); 1.605 + res10.get(function (error, content) { 1.606 + do_check_eq(error, null); 1.607 + do_check_eq(content.status, 400); 1.608 + do_check_eq(quotaValue, undefined); // HTTP 400, so no observer notification. 1.609 + run_next_test(); 1.610 + }); 1.611 +}); 1.612 + 1.613 +add_test(function test_quota_notice() { 1.614 + let res10 = new AsyncResource(server.baseURI + "/quota-notice"); 1.615 + res10.get(function (error, content) { 1.616 + do_check_eq(error, null); 1.617 + do_check_eq(content.status, 200); 1.618 + do_check_eq(quotaValue, 1048576); 1.619 + run_next_test(); 1.620 + }); 1.621 +}); 1.622 + 1.623 +add_test(function test_preserve_exceptions() { 1.624 + _("Error handling in ChannelListener etc. preserves exception information"); 1.625 + let res11 = new AsyncResource("http://localhost:12345/does/not/exist"); 1.626 + res11.get(function (error, content) { 1.627 + do_check_neq(error, null); 1.628 + do_check_eq(error.result, Cr.NS_ERROR_CONNECTION_REFUSED); 1.629 + do_check_eq(error.message, "NS_ERROR_CONNECTION_REFUSED"); 1.630 + run_next_test(); 1.631 + }); 1.632 +}); 1.633 + 1.634 +add_test(function test_xpc_exception_handling() { 1.635 + _("Exception handling inside fetches."); 1.636 + let res14 = new AsyncResource(server.baseURI + "/json"); 1.637 + res14._onProgress = function(rec) { 1.638 + // Provoke an XPC exception without a Javascript wrapper. 1.639 + Services.io.newURI("::::::::", null, null); 1.640 + }; 1.641 + let warnings = []; 1.642 + res14._log.warn = function(msg) { warnings.push(msg); }; 1.643 + 1.644 + res14.get(function (error, content) { 1.645 + do_check_eq(error.result, Cr.NS_ERROR_MALFORMED_URI); 1.646 + do_check_eq(error.message, "NS_ERROR_MALFORMED_URI"); 1.647 + do_check_eq(content, null); 1.648 + do_check_eq(warnings.pop(), 1.649 + "Got exception calling onProgress handler during fetch of " + 1.650 + server.baseURI + "/json"); 1.651 + 1.652 + run_next_test(); 1.653 + }); 1.654 +}); 1.655 + 1.656 +add_test(function test_js_exception_handling() { 1.657 + _("JS exception handling inside fetches."); 1.658 + let res15 = new AsyncResource(server.baseURI + "/json"); 1.659 + res15._onProgress = function(rec) { 1.660 + throw "BOO!"; 1.661 + }; 1.662 + let warnings = []; 1.663 + res15._log.warn = function(msg) { warnings.push(msg); }; 1.664 + 1.665 + res15.get(function (error, content) { 1.666 + do_check_eq(error.result, Cr.NS_ERROR_XPC_JS_THREW_STRING); 1.667 + do_check_eq(error.message, "NS_ERROR_XPC_JS_THREW_STRING"); 1.668 + do_check_eq(content, null); 1.669 + do_check_eq(warnings.pop(), 1.670 + "Got exception calling onProgress handler during fetch of " + 1.671 + server.baseURI + "/json"); 1.672 + 1.673 + run_next_test(); 1.674 + }); 1.675 +}); 1.676 + 1.677 +add_test(function test_timeout() { 1.678 + _("Ensure channel timeouts are thrown appropriately."); 1.679 + let res19 = new AsyncResource(server.baseURI + "/json"); 1.680 + res19.ABORT_TIMEOUT = 0; 1.681 + res19.get(function (error, content) { 1.682 + do_check_eq(error.result, Cr.NS_ERROR_NET_TIMEOUT); 1.683 + run_next_test(); 1.684 + }); 1.685 +}); 1.686 + 1.687 +add_test(function test_uri_construction() { 1.688 + _("Testing URI construction."); 1.689 + let args = []; 1.690 + args.push("newer=" + 1234); 1.691 + args.push("limit=" + 1234); 1.692 + args.push("sort=" + 1234); 1.693 + 1.694 + let query = "?" + args.join("&"); 1.695 + 1.696 + let uri1 = Utils.makeURI("http://foo/" + query) 1.697 + .QueryInterface(Ci.nsIURL); 1.698 + let uri2 = Utils.makeURI("http://foo/") 1.699 + .QueryInterface(Ci.nsIURL); 1.700 + uri2.query = query; 1.701 + do_check_eq(uri1.query, uri2.query); 1.702 + 1.703 + run_next_test(); 1.704 +}); 1.705 + 1.706 +add_test(function test_not_sending_cookie() { 1.707 + function handler(metadata, response) { 1.708 + let body = "COOKIE!"; 1.709 + response.setStatusLine(metadata.httpVersion, 200, "OK"); 1.710 + response.bodyOutputStream.write(body, body.length); 1.711 + do_check_false(metadata.hasHeader("Cookie")); 1.712 + } 1.713 + let cookieSer = Cc["@mozilla.org/cookieService;1"] 1.714 + .getService(Ci.nsICookieService); 1.715 + let uri = CommonUtils.makeURI(server.baseURI); 1.716 + cookieSer.setCookieString(uri, null, "test=test; path=/;", null); 1.717 + 1.718 + let res = new AsyncResource(server.baseURI + "/test"); 1.719 + res.get(function (error) { 1.720 + do_check_null(error); 1.721 + do_check_true(this.response.success); 1.722 + do_check_eq("COOKIE!", this.response.body); 1.723 + server.stop(run_next_test); 1.724 + }); 1.725 +}); 1.726 + 1.727 +/** 1.728 + * End of tests that rely on a single HTTP server. 1.729 + * All tests after this point must begin and end their own. 1.730 + */ 1.731 +add_test(function eliminate_server() { 1.732 + server.stop(run_next_test); 1.733 +});