services/common/tests/unit/test_restrequest.js

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/services/common/tests/unit/test_restrequest.js	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,840 @@
     1.4 +/* Any copyright is dedicated to the Public Domain.
     1.5 +   http://creativecommons.org/publicdomain/zero/1.0/ */
     1.6 +
     1.7 +"use strict";
     1.8 +
     1.9 +Cu.import("resource://gre/modules/NetUtil.jsm");
    1.10 +Cu.import("resource://gre/modules/Log.jsm");
    1.11 +Cu.import("resource://services-common/rest.js");
    1.12 +Cu.import("resource://services-common/utils.js");
    1.13 +
    1.14 +function run_test() {
    1.15 +  Log.repository.getLogger("Services.Common.RESTRequest").level =
    1.16 +    Log.Level.Trace;
    1.17 +  initTestLogging("Trace");
    1.18 +
    1.19 +  run_next_test();
    1.20 +}
    1.21 +
    1.22 +/**
    1.23 + * Initializing a RESTRequest with an invalid URI throws
    1.24 + * NS_ERROR_MALFORMED_URI.
    1.25 + */
    1.26 +add_test(function test_invalid_uri() {
    1.27 +  do_check_throws(function() {
    1.28 +    new RESTRequest("an invalid URI");
    1.29 +  }, Cr.NS_ERROR_MALFORMED_URI);
    1.30 +  run_next_test();
    1.31 +});
    1.32 +
    1.33 +/**
    1.34 + * Verify initial values for attributes.
    1.35 + */
    1.36 +add_test(function test_attributes() {
    1.37 +  let uri = "http://foo.com/bar/baz";
    1.38 +  let request = new RESTRequest(uri);
    1.39 +
    1.40 +  do_check_true(request.uri instanceof Ci.nsIURI);
    1.41 +  do_check_eq(request.uri.spec, uri);
    1.42 +  do_check_eq(request.response, null);
    1.43 +  do_check_eq(request.status, request.NOT_SENT);
    1.44 +  let expectedLoadFlags = Ci.nsIRequest.LOAD_BYPASS_CACHE |
    1.45 +                          Ci.nsIRequest.INHIBIT_CACHING |
    1.46 +                          Ci.nsIRequest.LOAD_ANONYMOUS;
    1.47 +  do_check_eq(request.loadFlags, expectedLoadFlags);
    1.48 +
    1.49 +  run_next_test();
    1.50 +});
    1.51 +
    1.52 +/**
    1.53 + * Verify that a proxy auth redirect doesn't break us. This has to be the first
    1.54 + * request made in the file!
    1.55 + */
    1.56 +add_test(function test_proxy_auth_redirect() {
    1.57 +  let pacFetched = false;
    1.58 +  function pacHandler(metadata, response) {
    1.59 +    pacFetched = true;
    1.60 +    let body = 'function FindProxyForURL(url, host) { return "DIRECT"; }';
    1.61 +    response.setStatusLine(metadata.httpVersion, 200, "OK");
    1.62 +    response.setHeader("Content-Type", "application/x-ns-proxy-autoconfig", false);
    1.63 +    response.bodyOutputStream.write(body, body.length);
    1.64 +  }
    1.65 +
    1.66 +  let fetched = false;
    1.67 +  function original(metadata, response) {
    1.68 +    fetched = true;
    1.69 +    let body = "TADA!";
    1.70 +    response.setStatusLine(metadata.httpVersion, 200, "OK");
    1.71 +    response.bodyOutputStream.write(body, body.length);
    1.72 +  }
    1.73 +
    1.74 +  let server = httpd_setup({
    1.75 +    "/original": original,
    1.76 +    "/pac3":     pacHandler
    1.77 +  });
    1.78 +  PACSystemSettings.PACURI = server.baseURI + "/pac3";
    1.79 +  installFakePAC();
    1.80 +
    1.81 +  let res = new RESTRequest(server.baseURI + "/original");
    1.82 +  res.get(function (error) {
    1.83 +    do_check_true(pacFetched);
    1.84 +    do_check_true(fetched);
    1.85 +    do_check_true(!error);
    1.86 +    do_check_true(this.response.success);
    1.87 +    do_check_eq("TADA!", this.response.body);
    1.88 +    uninstallFakePAC();
    1.89 +    server.stop(run_next_test);
    1.90 +  });
    1.91 +});
    1.92 +
    1.93 +/**
    1.94 + * Ensure that failures that cause asyncOpen to throw
    1.95 + * result in callbacks being invoked.
    1.96 + * Bug 826086.
    1.97 + */
    1.98 +add_test(function test_forbidden_port() {
    1.99 +  let request = new RESTRequest("http://localhost:6000/");
   1.100 +  request.get(function(error) {
   1.101 +    if (!error) {
   1.102 +      do_throw("Should have got an error.");
   1.103 +    }
   1.104 +    do_check_eq(error.result, Components.results.NS_ERROR_PORT_ACCESS_NOT_ALLOWED);
   1.105 +    run_next_test();
   1.106 +  });
   1.107 +});
   1.108 +
   1.109 +/**
   1.110 + * Demonstrate API short-hand: create a request and dispatch it immediately.
   1.111 + */
   1.112 +add_test(function test_simple_get() {
   1.113 +  let handler = httpd_handler(200, "OK", "Huzzah!");
   1.114 +  let server = httpd_setup({"/resource": handler});
   1.115 +
   1.116 +  let request = new RESTRequest(server.baseURI + "/resource").get(function (error) {
   1.117 +    do_check_eq(error, null);
   1.118 +
   1.119 +    do_check_eq(this.status, this.COMPLETED);
   1.120 +    do_check_true(this.response.success);
   1.121 +    do_check_eq(this.response.status, 200);
   1.122 +    do_check_eq(this.response.body, "Huzzah!");
   1.123 +
   1.124 +    server.stop(run_next_test);
   1.125 +  });
   1.126 +  do_check_eq(request.status, request.SENT);
   1.127 +  do_check_eq(request.method, "GET");
   1.128 +});
   1.129 +
   1.130 +/**
   1.131 + * Test HTTP GET with all bells and whistles.
   1.132 + */
   1.133 +add_test(function test_get() {
   1.134 +  let handler = httpd_handler(200, "OK", "Huzzah!");
   1.135 +  let server = httpd_setup({"/resource": handler});
   1.136 +
   1.137 +  let request = new RESTRequest(server.baseURI + "/resource");
   1.138 +  do_check_eq(request.status, request.NOT_SENT);
   1.139 +
   1.140 +  request.onProgress = request.onComplete = function () {
   1.141 +    do_throw("This function should have been overwritten!");
   1.142 +  };
   1.143 +
   1.144 +  let onProgress_called = false;
   1.145 +  function onProgress() {
   1.146 +    onProgress_called = true;
   1.147 +    do_check_eq(this.status, request.IN_PROGRESS);
   1.148 +    do_check_true(this.response.body.length > 0);
   1.149 +
   1.150 +    do_check_true(!!(this.channel.loadFlags & Ci.nsIRequest.LOAD_BYPASS_CACHE));
   1.151 +    do_check_true(!!(this.channel.loadFlags & Ci.nsIRequest.INHIBIT_CACHING));
   1.152 +  };
   1.153 +
   1.154 +  function onComplete(error) {
   1.155 +    do_check_eq(error, null);
   1.156 +
   1.157 +    do_check_eq(this.status, this.COMPLETED);
   1.158 +    do_check_true(this.response.success);
   1.159 +    do_check_eq(this.response.status, 200);
   1.160 +    do_check_eq(this.response.body, "Huzzah!");
   1.161 +    do_check_eq(handler.request.method, "GET");
   1.162 +
   1.163 +    do_check_true(onProgress_called);
   1.164 +    CommonUtils.nextTick(function () {
   1.165 +      do_check_eq(request.onComplete, null);
   1.166 +      do_check_eq(request.onProgress, null);
   1.167 +      server.stop(run_next_test);
   1.168 +    });
   1.169 +  };
   1.170 +
   1.171 +  do_check_eq(request.get(onComplete, onProgress), request);
   1.172 +  do_check_eq(request.status, request.SENT);
   1.173 +  do_check_eq(request.method, "GET");
   1.174 +  do_check_throws(function () {
   1.175 +    request.get();
   1.176 +  });
   1.177 +});
   1.178 +
   1.179 +/**
   1.180 + * Test HTTP GET with UTF-8 content, and custom Content-Type.
   1.181 + */
   1.182 +add_test(function test_get_utf8() {
   1.183 +  let response = "Hello World or Καλημέρα κόσμε or こんにちは 世界";
   1.184 +
   1.185 +  let contentType = "text/plain";
   1.186 +  let charset = true;
   1.187 +  let charsetSuffix = "; charset=UTF-8";
   1.188 +
   1.189 +  let server = httpd_setup({"/resource": function(req, res) {
   1.190 +    res.setStatusLine(req.httpVersion, 200, "OK");
   1.191 +    res.setHeader("Content-Type", contentType + (charset ? charsetSuffix : ""));
   1.192 +
   1.193 +    let converter = Cc["@mozilla.org/intl/converter-output-stream;1"]
   1.194 +                    .createInstance(Ci.nsIConverterOutputStream);
   1.195 +    converter.init(res.bodyOutputStream, "UTF-8", 0, 0x0000);
   1.196 +    converter.writeString(response);
   1.197 +    converter.close();
   1.198 +  }});
   1.199 +
   1.200 +  // Check if charset in Content-Type is propertly interpreted.
   1.201 +  let request1 = new RESTRequest(server.baseURI + "/resource");
   1.202 +  request1.get(function(error) {
   1.203 +    do_check_null(error);
   1.204 +
   1.205 +    do_check_eq(request1.response.status, 200);
   1.206 +    do_check_eq(request1.response.body, response);
   1.207 +    do_check_eq(request1.response.headers["content-type"],
   1.208 +                contentType + charsetSuffix);
   1.209 +
   1.210 +    // Check that we default to UTF-8 if Content-Type doesn't have a charset.
   1.211 +    charset = false;
   1.212 +    let request2 = new RESTRequest(server.baseURI + "/resource");
   1.213 +    request2.get(function(error) {
   1.214 +      do_check_null(error);
   1.215 +
   1.216 +      do_check_eq(request2.response.status, 200);
   1.217 +      do_check_eq(request2.response.body, response);
   1.218 +      do_check_eq(request2.response.headers["content-type"], contentType);
   1.219 +      do_check_eq(request2.response.charset, "utf-8");
   1.220 +
   1.221 +      server.stop(run_next_test);
   1.222 +    });
   1.223 +  });
   1.224 +});
   1.225 +
   1.226 +/**
   1.227 + * Test more variations of charset handling.
   1.228 + */
   1.229 +add_test(function test_charsets() {
   1.230 +  let response = "Hello World, I can't speak Russian";
   1.231 +
   1.232 +  let contentType = "text/plain";
   1.233 +  let charset = true;
   1.234 +  let charsetSuffix = "; charset=us-ascii";
   1.235 +
   1.236 +  let server = httpd_setup({"/resource": function(req, res) {
   1.237 +    res.setStatusLine(req.httpVersion, 200, "OK");
   1.238 +    res.setHeader("Content-Type", contentType + (charset ? charsetSuffix : ""));
   1.239 +
   1.240 +    let converter = Cc["@mozilla.org/intl/converter-output-stream;1"]
   1.241 +                    .createInstance(Ci.nsIConverterOutputStream);
   1.242 +    converter.init(res.bodyOutputStream, "us-ascii", 0, 0x0000);
   1.243 +    converter.writeString(response);
   1.244 +    converter.close();
   1.245 +  }});
   1.246 +
   1.247 +  // Check that provided charset overrides hint.
   1.248 +  let request1 = new RESTRequest(server.baseURI + "/resource");
   1.249 +  request1.charset = "not-a-charset";
   1.250 +  request1.get(function(error) {
   1.251 +    do_check_null(error);
   1.252 +
   1.253 +    do_check_eq(request1.response.status, 200);
   1.254 +    do_check_eq(request1.response.body, response);
   1.255 +    do_check_eq(request1.response.headers["content-type"],
   1.256 +                contentType + charsetSuffix);
   1.257 +    do_check_eq(request1.response.charset, "us-ascii");
   1.258 +
   1.259 +    // Check that hint is used if Content-Type doesn't have a charset.
   1.260 +    charset = false;
   1.261 +    let request2 = new RESTRequest(server.baseURI + "/resource");
   1.262 +    request2.charset = "us-ascii";
   1.263 +    request2.get(function(error) {
   1.264 +      do_check_null(error);
   1.265 +
   1.266 +      do_check_eq(request2.response.status, 200);
   1.267 +      do_check_eq(request2.response.body, response);
   1.268 +      do_check_eq(request2.response.headers["content-type"], contentType);
   1.269 +      do_check_eq(request2.response.charset, "us-ascii");
   1.270 +
   1.271 +      server.stop(run_next_test);
   1.272 +    });
   1.273 +  });
   1.274 +});
   1.275 +
   1.276 +/**
   1.277 + * Test HTTP PUT with a simple string argument and default Content-Type.
   1.278 + */
   1.279 +add_test(function test_put() {
   1.280 +  let handler = httpd_handler(200, "OK", "Got it!");
   1.281 +  let server = httpd_setup({"/resource": handler});
   1.282 +
   1.283 +  let request = new RESTRequest(server.baseURI + "/resource");
   1.284 +  do_check_eq(request.status, request.NOT_SENT);
   1.285 +
   1.286 +  request.onProgress = request.onComplete = function () {
   1.287 +    do_throw("This function should have been overwritten!");
   1.288 +  };
   1.289 +
   1.290 +  let onProgress_called = false;
   1.291 +  function onProgress() {
   1.292 +    onProgress_called = true;
   1.293 +    do_check_eq(this.status, request.IN_PROGRESS);
   1.294 +    do_check_true(this.response.body.length > 0);
   1.295 +  };
   1.296 +
   1.297 +  function onComplete(error) {
   1.298 +    do_check_eq(error, null);
   1.299 +
   1.300 +    do_check_eq(this.status, this.COMPLETED);
   1.301 +    do_check_true(this.response.success);
   1.302 +    do_check_eq(this.response.status, 200);
   1.303 +    do_check_eq(this.response.body, "Got it!");
   1.304 +
   1.305 +    do_check_eq(handler.request.method, "PUT");
   1.306 +    do_check_eq(handler.request.body, "Hullo?");
   1.307 +    do_check_eq(handler.request.getHeader("Content-Type"), "text/plain");
   1.308 +
   1.309 +    do_check_true(onProgress_called);
   1.310 +    CommonUtils.nextTick(function () {
   1.311 +      do_check_eq(request.onComplete, null);
   1.312 +      do_check_eq(request.onProgress, null);
   1.313 +      server.stop(run_next_test);
   1.314 +    });
   1.315 +  };
   1.316 +
   1.317 +  do_check_eq(request.put("Hullo?", onComplete, onProgress), request);
   1.318 +  do_check_eq(request.status, request.SENT);
   1.319 +  do_check_eq(request.method, "PUT");
   1.320 +  do_check_throws(function () {
   1.321 +    request.put("Hai!");
   1.322 +  });
   1.323 +});
   1.324 +
   1.325 +/**
   1.326 + * Test HTTP POST with a simple string argument and default Content-Type.
   1.327 + */
   1.328 +add_test(function test_post() {
   1.329 +  let handler = httpd_handler(200, "OK", "Got it!");
   1.330 +  let server = httpd_setup({"/resource": handler});
   1.331 +
   1.332 +  let request = new RESTRequest(server.baseURI + "/resource");
   1.333 +  do_check_eq(request.status, request.NOT_SENT);
   1.334 +
   1.335 +  request.onProgress = request.onComplete = function () {
   1.336 +    do_throw("This function should have been overwritten!");
   1.337 +  };
   1.338 +
   1.339 +  let onProgress_called = false;
   1.340 +  function onProgress() {
   1.341 +    onProgress_called = true;
   1.342 +    do_check_eq(this.status, request.IN_PROGRESS);
   1.343 +    do_check_true(this.response.body.length > 0);
   1.344 +  };
   1.345 +
   1.346 +  function onComplete(error) {
   1.347 +    do_check_eq(error, null);
   1.348 +
   1.349 +    do_check_eq(this.status, this.COMPLETED);
   1.350 +    do_check_true(this.response.success);
   1.351 +    do_check_eq(this.response.status, 200);
   1.352 +    do_check_eq(this.response.body, "Got it!");
   1.353 +
   1.354 +    do_check_eq(handler.request.method, "POST");
   1.355 +    do_check_eq(handler.request.body, "Hullo?");
   1.356 +    do_check_eq(handler.request.getHeader("Content-Type"), "text/plain");
   1.357 +
   1.358 +    do_check_true(onProgress_called);
   1.359 +    CommonUtils.nextTick(function () {
   1.360 +      do_check_eq(request.onComplete, null);
   1.361 +      do_check_eq(request.onProgress, null);
   1.362 +      server.stop(run_next_test);
   1.363 +    });
   1.364 +  };
   1.365 +
   1.366 +  do_check_eq(request.post("Hullo?", onComplete, onProgress), request);
   1.367 +  do_check_eq(request.status, request.SENT);
   1.368 +  do_check_eq(request.method, "POST");
   1.369 +  do_check_throws(function () {
   1.370 +    request.post("Hai!");
   1.371 +  });
   1.372 +});
   1.373 +
   1.374 +/**
   1.375 + * Test HTTP DELETE.
   1.376 + */
   1.377 +add_test(function test_delete() {
   1.378 +  let handler = httpd_handler(200, "OK", "Got it!");
   1.379 +  let server = httpd_setup({"/resource": handler});
   1.380 +
   1.381 +  let request = new RESTRequest(server.baseURI + "/resource");
   1.382 +  do_check_eq(request.status, request.NOT_SENT);
   1.383 +
   1.384 +  request.onProgress = request.onComplete = function () {
   1.385 +    do_throw("This function should have been overwritten!");
   1.386 +  };
   1.387 +
   1.388 +  let onProgress_called = false;
   1.389 +  function onProgress() {
   1.390 +    onProgress_called = true;
   1.391 +    do_check_eq(this.status, request.IN_PROGRESS);
   1.392 +    do_check_true(this.response.body.length > 0);
   1.393 +  };
   1.394 +
   1.395 +  function onComplete(error) {
   1.396 +    do_check_eq(error, null);
   1.397 +
   1.398 +    do_check_eq(this.status, this.COMPLETED);
   1.399 +    do_check_true(this.response.success);
   1.400 +    do_check_eq(this.response.status, 200);
   1.401 +    do_check_eq(this.response.body, "Got it!");
   1.402 +    do_check_eq(handler.request.method, "DELETE");
   1.403 +
   1.404 +    do_check_true(onProgress_called);
   1.405 +    CommonUtils.nextTick(function () {
   1.406 +      do_check_eq(request.onComplete, null);
   1.407 +      do_check_eq(request.onProgress, null);
   1.408 +      server.stop(run_next_test);
   1.409 +    });
   1.410 +  };
   1.411 +
   1.412 +  do_check_eq(request.delete(onComplete, onProgress), request);
   1.413 +  do_check_eq(request.status, request.SENT);
   1.414 +  do_check_eq(request.method, "DELETE");
   1.415 +  do_check_throws(function () {
   1.416 +    request.delete();
   1.417 +  });
   1.418 +});
   1.419 +
   1.420 +/**
   1.421 + * Test an HTTP response with a non-200 status code.
   1.422 + */
   1.423 +add_test(function test_get_404() {
   1.424 +  let handler = httpd_handler(404, "Not Found", "Cannae find it!");
   1.425 +  let server = httpd_setup({"/resource": handler});
   1.426 +
   1.427 +  let request = new RESTRequest(server.baseURI + "/resource");
   1.428 +  request.get(function (error) {
   1.429 +    do_check_eq(error, null);
   1.430 +
   1.431 +    do_check_eq(this.status, this.COMPLETED);
   1.432 +    do_check_false(this.response.success);
   1.433 +    do_check_eq(this.response.status, 404);
   1.434 +    do_check_eq(this.response.body, "Cannae find it!");
   1.435 +
   1.436 +    server.stop(run_next_test);
   1.437 +  });
   1.438 +});
   1.439 +
   1.440 +/**
   1.441 + * The 'data' argument to PUT, if not a string already, is automatically
   1.442 + * stringified as JSON.
   1.443 + */
   1.444 +add_test(function test_put_json() {
   1.445 +  let handler = httpd_handler(200, "OK");
   1.446 +  let server = httpd_setup({"/resource": handler});
   1.447 +
   1.448 +  let sample_data = {
   1.449 +    some: "sample_data",
   1.450 +    injson: "format",
   1.451 +    number: 42
   1.452 +  };
   1.453 +  let request = new RESTRequest(server.baseURI + "/resource");
   1.454 +  request.put(sample_data, function (error) {
   1.455 +    do_check_eq(error, null);
   1.456 +
   1.457 +    do_check_eq(this.status, this.COMPLETED);
   1.458 +    do_check_true(this.response.success);
   1.459 +    do_check_eq(this.response.status, 200);
   1.460 +    do_check_eq(this.response.body, "");
   1.461 +
   1.462 +    do_check_eq(handler.request.method, "PUT");
   1.463 +    do_check_eq(handler.request.body, JSON.stringify(sample_data));
   1.464 +    do_check_eq(handler.request.getHeader("Content-Type"), "text/plain");
   1.465 +
   1.466 +    server.stop(run_next_test);
   1.467 +  });
   1.468 +});
   1.469 +
   1.470 +/**
   1.471 + * The 'data' argument to POST, if not a string already, is automatically
   1.472 + * stringified as JSON.
   1.473 + */
   1.474 +add_test(function test_post_json() {
   1.475 +  let handler = httpd_handler(200, "OK");
   1.476 +  let server = httpd_setup({"/resource": handler});
   1.477 +
   1.478 +  let sample_data = {
   1.479 +    some: "sample_data",
   1.480 +    injson: "format",
   1.481 +    number: 42
   1.482 +  };
   1.483 +  let request = new RESTRequest(server.baseURI + "/resource");
   1.484 +  request.post(sample_data, function (error) {
   1.485 +    do_check_eq(error, null);
   1.486 +
   1.487 +    do_check_eq(this.status, this.COMPLETED);
   1.488 +    do_check_true(this.response.success);
   1.489 +    do_check_eq(this.response.status, 200);
   1.490 +    do_check_eq(this.response.body, "");
   1.491 +
   1.492 +    do_check_eq(handler.request.method, "POST");
   1.493 +    do_check_eq(handler.request.body, JSON.stringify(sample_data));
   1.494 +    do_check_eq(handler.request.getHeader("Content-Type"), "text/plain");
   1.495 +
   1.496 +    server.stop(run_next_test);
   1.497 +  });
   1.498 +});
   1.499 +
   1.500 +/**
   1.501 + * HTTP PUT with a custom Content-Type header.
   1.502 + */
   1.503 +add_test(function test_put_override_content_type() {
   1.504 +  let handler = httpd_handler(200, "OK");
   1.505 +  let server = httpd_setup({"/resource": handler});
   1.506 +
   1.507 +  let request = new RESTRequest(server.baseURI + "/resource");
   1.508 +  request.setHeader("Content-Type", "application/lolcat");
   1.509 +  request.put("O HAI!!1!", function (error) {
   1.510 +    do_check_eq(error, null);
   1.511 +
   1.512 +    do_check_eq(this.status, this.COMPLETED);
   1.513 +    do_check_true(this.response.success);
   1.514 +    do_check_eq(this.response.status, 200);
   1.515 +    do_check_eq(this.response.body, "");
   1.516 +
   1.517 +    do_check_eq(handler.request.method, "PUT");
   1.518 +    do_check_eq(handler.request.body, "O HAI!!1!");
   1.519 +    do_check_eq(handler.request.getHeader("Content-Type"), "application/lolcat");
   1.520 +
   1.521 +    server.stop(run_next_test);
   1.522 +  });
   1.523 +});
   1.524 +
   1.525 +/**
   1.526 + * HTTP POST with a custom Content-Type header.
   1.527 + */
   1.528 +add_test(function test_post_override_content_type() {
   1.529 +  let handler = httpd_handler(200, "OK");
   1.530 +  let server = httpd_setup({"/resource": handler});
   1.531 +
   1.532 +  let request = new RESTRequest(server.baseURI + "/resource");
   1.533 +  request.setHeader("Content-Type", "application/lolcat");
   1.534 +  request.post("O HAI!!1!", function (error) {
   1.535 +    do_check_eq(error, null);
   1.536 +
   1.537 +    do_check_eq(this.status, this.COMPLETED);
   1.538 +    do_check_true(this.response.success);
   1.539 +    do_check_eq(this.response.status, 200);
   1.540 +    do_check_eq(this.response.body, "");
   1.541 +
   1.542 +    do_check_eq(handler.request.method, "POST");
   1.543 +    do_check_eq(handler.request.body, "O HAI!!1!");
   1.544 +    do_check_eq(handler.request.getHeader("Content-Type"), "application/lolcat");
   1.545 +
   1.546 +    server.stop(run_next_test);
   1.547 +  });
   1.548 +});
   1.549 +
   1.550 +/**
   1.551 + * No special headers are sent by default on a GET request.
   1.552 + */
   1.553 +add_test(function test_get_no_headers() {
   1.554 +  let handler = httpd_handler(200, "OK");
   1.555 +  let server = httpd_setup({"/resource": handler});
   1.556 +
   1.557 +  let ignore_headers = ["host", "user-agent", "accept", "accept-language",
   1.558 +                        "accept-encoding", "accept-charset", "keep-alive",
   1.559 +                        "connection", "pragma", "cache-control",
   1.560 +                        "content-length"];
   1.561 +
   1.562 +  new RESTRequest(server.baseURI + "/resource").get(function (error) {
   1.563 +    do_check_eq(error, null);
   1.564 +
   1.565 +    do_check_eq(this.response.status, 200);
   1.566 +    do_check_eq(this.response.body, "");
   1.567 +
   1.568 +    let server_headers = handler.request.headers;
   1.569 +    while (server_headers.hasMoreElements()) {
   1.570 +      let header = server_headers.getNext().toString();
   1.571 +      if (ignore_headers.indexOf(header) == -1) {
   1.572 +        do_throw("Got unexpected header!");
   1.573 +      }
   1.574 +    }
   1.575 +
   1.576 +    server.stop(run_next_test);
   1.577 +  });
   1.578 +});
   1.579 +
   1.580 +/**
   1.581 + * Test changing the URI after having created the request.
   1.582 + */
   1.583 +add_test(function test_changing_uri() {
   1.584 +  let handler = httpd_handler(200, "OK");
   1.585 +  let server = httpd_setup({"/resource": handler});
   1.586 +
   1.587 +  let request = new RESTRequest("http://localhost:1234/the-wrong-resource");
   1.588 +  request.uri = CommonUtils.makeURI(server.baseURI + "/resource");
   1.589 +  request.get(function (error) {
   1.590 +    do_check_eq(error, null);
   1.591 +    do_check_eq(this.response.status, 200);
   1.592 +    server.stop(run_next_test);
   1.593 +  });
   1.594 +});
   1.595 +
   1.596 +/**
   1.597 + * Test setting HTTP request headers.
   1.598 + */
   1.599 +add_test(function test_request_setHeader() {
   1.600 +  let handler = httpd_handler(200, "OK");
   1.601 +  let server = httpd_setup({"/resource": handler});
   1.602 +
   1.603 +  let request = new RESTRequest(server.baseURI + "/resource");
   1.604 +
   1.605 +  request.setHeader("X-What-Is-Weave", "awesome");
   1.606 +  request.setHeader("X-WHAT-is-Weave", "more awesomer");
   1.607 +  request.setHeader("Another-Header", "Hello World");
   1.608 +
   1.609 +  request.get(function (error) {
   1.610 +    do_check_eq(error, null);
   1.611 +
   1.612 +    do_check_eq(this.response.status, 200);
   1.613 +    do_check_eq(this.response.body, "");
   1.614 +
   1.615 +    do_check_eq(handler.request.getHeader("X-What-Is-Weave"), "more awesomer");
   1.616 +    do_check_eq(handler.request.getHeader("another-header"), "Hello World");
   1.617 +
   1.618 +    server.stop(run_next_test);
   1.619 +  });
   1.620 +});
   1.621 +
   1.622 +/**
   1.623 + * Test receiving HTTP response headers.
   1.624 + */
   1.625 +add_test(function test_response_headers() {
   1.626 +  function handler(request, response) {
   1.627 +    response.setHeader("X-What-Is-Weave", "awesome");
   1.628 +    response.setHeader("Another-Header", "Hello World");
   1.629 +    response.setStatusLine(request.httpVersion, 200, "OK");
   1.630 +  }
   1.631 +  let server = httpd_setup({"/resource": handler});
   1.632 +  let request = new RESTRequest(server.baseURI + "/resource");
   1.633 +
   1.634 +  request.get(function (error) {
   1.635 +    do_check_eq(error, null);
   1.636 +
   1.637 +    do_check_eq(this.response.status, 200);
   1.638 +    do_check_eq(this.response.body, "");
   1.639 +
   1.640 +    do_check_eq(this.response.headers["x-what-is-weave"], "awesome");
   1.641 +    do_check_eq(this.response.headers["another-header"], "Hello World");
   1.642 +
   1.643 +    server.stop(run_next_test);
   1.644 +  });
   1.645 +});
   1.646 +
   1.647 +/**
   1.648 + * The onComplete() handler gets called in case of any network errors
   1.649 + * (e.g. NS_ERROR_CONNECTION_REFUSED).
   1.650 + */
   1.651 +add_test(function test_connection_refused() {
   1.652 +  let request = new RESTRequest("http://localhost:1234/resource");
   1.653 +  request.onProgress = function onProgress() {
   1.654 +    do_throw("Shouldn't have called request.onProgress()!");
   1.655 +  };
   1.656 +  request.get(function (error) {
   1.657 +    do_check_eq(error.result, Cr.NS_ERROR_CONNECTION_REFUSED);
   1.658 +    do_check_eq(error.message, "NS_ERROR_CONNECTION_REFUSED");
   1.659 +    do_check_eq(this.status, this.COMPLETED);
   1.660 +    run_next_test();
   1.661 +  });
   1.662 +  do_check_eq(request.status, request.SENT);
   1.663 +});
   1.664 +
   1.665 +/**
   1.666 + * Abort a request that just sent off.
   1.667 + */
   1.668 +add_test(function test_abort() {
   1.669 +  function handler() {
   1.670 +    do_throw("Shouldn't have gotten here!");
   1.671 +  }
   1.672 +  let server = httpd_setup({"/resource": handler});
   1.673 +
   1.674 +  let request = new RESTRequest(server.baseURI + "/resource");
   1.675 +
   1.676 +  // Aborting a request that hasn't been sent yet is pointless and will throw.
   1.677 +  do_check_throws(function () {
   1.678 +    request.abort();
   1.679 +  });
   1.680 +
   1.681 +  request.onProgress = request.onComplete = function () {
   1.682 +    do_throw("Shouldn't have gotten here!");
   1.683 +  };
   1.684 +  request.get();
   1.685 +  request.abort();
   1.686 +
   1.687 +  // Aborting an already aborted request is pointless and will throw.
   1.688 +  do_check_throws(function () {
   1.689 +    request.abort();
   1.690 +  });
   1.691 +
   1.692 +  do_check_eq(request.status, request.ABORTED);
   1.693 +  CommonUtils.nextTick(function () {
   1.694 +    server.stop(run_next_test);
   1.695 +  });
   1.696 +});
   1.697 +
   1.698 +/**
   1.699 + * A non-zero 'timeout' property specifies the amount of seconds to wait after
   1.700 + * channel activity until the request is automatically canceled.
   1.701 + */
   1.702 +add_test(function test_timeout() {
   1.703 +  let server = new HttpServer();
   1.704 +  let server_connection;
   1.705 +  server._handler.handleResponse = function(connection) {
   1.706 +    // This is a handler that doesn't do anything, just keeps the connection
   1.707 +    // open, thereby mimicking a timing out connection. We keep a reference to
   1.708 +    // the open connection for later so it can be properly disposed of. That's
   1.709 +    // why you really only want to make one HTTP request to this server ever.
   1.710 +    server_connection = connection;
   1.711 +  };
   1.712 +  server.start();
   1.713 +  let identity = server.identity;
   1.714 +  let uri = identity.primaryScheme + "://" + identity.primaryHost + ":" +
   1.715 +            identity.primaryPort;
   1.716 +
   1.717 +  let request = new RESTRequest(uri + "/resource");
   1.718 +  request.timeout = 0.1; // 100 milliseconds
   1.719 +  request.get(function (error) {
   1.720 +    do_check_eq(error.result, Cr.NS_ERROR_NET_TIMEOUT);
   1.721 +    do_check_eq(this.status, this.ABORTED);
   1.722 +
   1.723 +    // server_connection is undefined on the Android emulator for reasons
   1.724 +    // unknown. Yet, we still get here. If this test is refactored, we should
   1.725 +    // investigate the reason why the above callback is behaving differently.
   1.726 +    if (server_connection) {
   1.727 +      _("Closing connection.");
   1.728 +      server_connection.close();
   1.729 +    }
   1.730 +
   1.731 +    _("Shutting down server.");
   1.732 +    server.stop(run_next_test);
   1.733 +  });
   1.734 +});
   1.735 +
   1.736 +/**
   1.737 + * An exception thrown in 'onProgress' propagates to the 'onComplete' handler.
   1.738 + */
   1.739 +add_test(function test_exception_in_onProgress() {
   1.740 +  let handler = httpd_handler(200, "OK", "Foobar");
   1.741 +  let server = httpd_setup({"/resource": handler});
   1.742 +
   1.743 +  let request = new RESTRequest(server.baseURI + "/resource");
   1.744 +  request.onProgress = function onProgress() {
   1.745 +    it.does.not.exist();
   1.746 +  };
   1.747 +  request.get(function onComplete(error) {
   1.748 +    do_check_eq(error, "ReferenceError: it is not defined");
   1.749 +    do_check_eq(this.status, this.ABORTED);
   1.750 +
   1.751 +    server.stop(run_next_test);
   1.752 +  });
   1.753 +});
   1.754 +
   1.755 +add_test(function test_new_channel() {
   1.756 +  _("Ensure a redirect to a new channel is handled properly.");
   1.757 +
   1.758 +  function checkUA(metadata) {
   1.759 +    let ua = metadata.getHeader("User-Agent");
   1.760 +    _("User-Agent is " + ua);
   1.761 +    do_check_eq("foo bar", ua);
   1.762 +  }
   1.763 +
   1.764 +  let redirectRequested = false;
   1.765 +  let redirectURL;
   1.766 +  function redirectHandler(metadata, response) {
   1.767 +    checkUA(metadata);
   1.768 +    redirectRequested = true;
   1.769 +
   1.770 +    let body = "Redirecting";
   1.771 +    response.setStatusLine(metadata.httpVersion, 307, "TEMPORARY REDIRECT");
   1.772 +    response.setHeader("Location", redirectURL);
   1.773 +    response.bodyOutputStream.write(body, body.length);
   1.774 +  }
   1.775 +
   1.776 +  let resourceRequested = false;
   1.777 +  function resourceHandler(metadata, response) {
   1.778 +    checkUA(metadata);
   1.779 +    resourceRequested = true;
   1.780 +
   1.781 +    let body = "Test";
   1.782 +    response.setHeader("Content-Type", "text/plain");
   1.783 +    response.bodyOutputStream.write(body, body.length);
   1.784 +  }
   1.785 +
   1.786 +  let server1 = httpd_setup({"/redirect": redirectHandler});
   1.787 +  let server2 = httpd_setup({"/resource": resourceHandler});
   1.788 +  redirectURL = server2.baseURI + "/resource";
   1.789 +
   1.790 +  function advance() {
   1.791 +    server1.stop(function () {
   1.792 +      server2.stop(run_next_test);
   1.793 +    });
   1.794 +  }
   1.795 +
   1.796 +  let request = new RESTRequest(server1.baseURI + "/redirect");
   1.797 +  request.setHeader("User-Agent", "foo bar");
   1.798 +
   1.799 +  // Swizzle in our own fakery, because this redirect is neither
   1.800 +  // internal nor URI-preserving. RESTRequest's policy is to only
   1.801 +  // copy headers under certain circumstances.
   1.802 +  let protoMethod = request.shouldCopyOnRedirect;
   1.803 +  request.shouldCopyOnRedirect = function wrapped(o, n, f) {
   1.804 +    // Check the default policy.
   1.805 +    do_check_false(protoMethod.call(this, o, n, f));
   1.806 +    return true;
   1.807 +  };
   1.808 +
   1.809 +  request.get(function onComplete(error) {
   1.810 +    let response = this.response;
   1.811 +
   1.812 +    do_check_eq(200, response.status);
   1.813 +    do_check_eq("Test", response.body);
   1.814 +    do_check_true(redirectRequested);
   1.815 +    do_check_true(resourceRequested);
   1.816 +
   1.817 +    advance();
   1.818 +  });
   1.819 +});
   1.820 +
   1.821 +add_test(function test_not_sending_cookie() {
   1.822 +  function handler(metadata, response) {
   1.823 +    let body = "COOKIE!";
   1.824 +    response.setStatusLine(metadata.httpVersion, 200, "OK");
   1.825 +    response.bodyOutputStream.write(body, body.length);
   1.826 +    do_check_false(metadata.hasHeader("Cookie"));
   1.827 +  }
   1.828 +  let server = httpd_setup({"/test": handler});
   1.829 +
   1.830 +  let cookieSer = Cc["@mozilla.org/cookieService;1"]
   1.831 +                    .getService(Ci.nsICookieService);
   1.832 +  let uri = CommonUtils.makeURI(server.baseURI);
   1.833 +  cookieSer.setCookieString(uri, null, "test=test; path=/;", null);
   1.834 +
   1.835 +  let res = new RESTRequest(server.baseURI + "/test");
   1.836 +  res.get(function (error) {
   1.837 +    do_check_null(error);
   1.838 +    do_check_true(this.response.success);
   1.839 +    do_check_eq("COOKIE!", this.response.body);
   1.840 +    server.stop(run_next_test);
   1.841 +  });
   1.842 +});
   1.843 +

mercurial