services/sync/tests/unit/test_httpd_sync_server.js

Thu, 22 Jan 2015 13:21:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 22 Jan 2015 13:21:57 +0100
branch
TOR_BUG_9701
changeset 15
b8a032363ba2
permissions
-rw-r--r--

Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6

     1 /* Any copyright is dedicated to the Public Domain.
     2    http://creativecommons.org/publicdomain/zero/1.0/ */
     4 Cu.import("resource://services-sync/util.js");
     6 function run_test() {
     7   Log.repository.getLogger("Sync.Test.Server").level = Log.Level.Trace;
     8   initTestLogging();
     9   run_next_test();
    10 }
    12 add_test(function test_creation() {
    13   // Explicit callback for this one.
    14   let server = new SyncServer({
    15     __proto__: SyncServerCallback,
    16   });
    17   do_check_true(!!server);       // Just so we have a check.
    18   server.start(null, function () {
    19     _("Started on " + server.port);
    20     server.stop(run_next_test);
    21   });
    22 });
    24 add_test(function test_url_parsing() {
    25   let server = new SyncServer();
    27   // Check that we can parse a WBO URI.
    28   let parts = server.pathRE.exec("/1.1/johnsmith/storage/crypto/keys");
    29   let [all, version, username, first, rest] = parts;
    30   do_check_eq(all, "/1.1/johnsmith/storage/crypto/keys");
    31   do_check_eq(version, "1.1");
    32   do_check_eq(username, "johnsmith");
    33   do_check_eq(first, "storage");
    34   do_check_eq(rest, "crypto/keys");
    35   do_check_eq(null, server.pathRE.exec("/nothing/else"));
    37   // Check that we can parse a collection URI.
    38   parts = server.pathRE.exec("/1.1/johnsmith/storage/crypto");
    39   let [all, version, username, first, rest] = parts;
    40   do_check_eq(all, "/1.1/johnsmith/storage/crypto");
    41   do_check_eq(version, "1.1");
    42   do_check_eq(username, "johnsmith");
    43   do_check_eq(first, "storage");
    44   do_check_eq(rest, "crypto");
    46   // We don't allow trailing slash on storage URI.
    47   parts = server.pathRE.exec("/1.1/johnsmith/storage/");
    48   do_check_eq(parts, undefined);
    50   // storage alone is a valid request.
    51   parts = server.pathRE.exec("/1.1/johnsmith/storage");
    52   let [all, version, username, first, rest] = parts;
    53   do_check_eq(all, "/1.1/johnsmith/storage");
    54   do_check_eq(version, "1.1");
    55   do_check_eq(username, "johnsmith");
    56   do_check_eq(first, "storage");
    57   do_check_eq(rest, undefined);
    59   parts = server.storageRE.exec("storage");
    60   let [all, storage, collection, id] = parts;
    61   do_check_eq(all, "storage");
    62   do_check_eq(collection, undefined);
    64   run_next_test();
    65 });
    67 Cu.import("resource://services-common/rest.js");
    68 function localRequest(server, path) {
    69   _("localRequest: " + path);
    70   let url = server.baseURI.substr(0, server.baseURI.length - 1) + path;
    71   _("url: " + url);
    72   return new RESTRequest(url);
    73 }
    75 add_test(function test_basic_http() {
    76   let server = new SyncServer();
    77   server.registerUser("john", "password");
    78   do_check_true(server.userExists("john"));
    79   server.start(null, function () {
    80     _("Started on " + server.port);
    81     Utils.nextTick(function () {
    82       let req = localRequest(server, "/1.1/john/storage/crypto/keys");
    83       _("req is " + req);
    84       req.get(function (err) {
    85         do_check_eq(null, err);
    86         Utils.nextTick(function () {
    87           server.stop(run_next_test);
    88         });
    89       });
    90     });
    91   });
    92 });
    94 add_test(function test_info_collections() {
    95   let server = new SyncServer({
    96     __proto__: SyncServerCallback
    97   });
    98   function responseHasCorrectHeaders(r) {
    99     do_check_eq(r.status, 200);
   100     do_check_eq(r.headers["content-type"], "application/json");
   101     do_check_true("x-weave-timestamp" in r.headers);
   102   }
   104   server.registerUser("john", "password");
   105   server.start(null, function () {
   106     Utils.nextTick(function () {
   107       let req = localRequest(server, "/1.1/john/info/collections");
   108       req.get(function (err) {
   109         // Initial info/collections fetch is empty.
   110         do_check_eq(null, err);
   111         responseHasCorrectHeaders(this.response);
   113         do_check_eq(this.response.body, "{}");
   114         Utils.nextTick(function () {
   115           // When we PUT something to crypto/keys, "crypto" appears in the response.
   116           function cb(err) {
   117             do_check_eq(null, err);
   118             responseHasCorrectHeaders(this.response);
   119             let putResponseBody = this.response.body;
   120             _("PUT response body: " + JSON.stringify(putResponseBody));
   122             req = localRequest(server, "/1.1/john/info/collections");
   123             req.get(function (err) {
   124               do_check_eq(null, err);
   125               responseHasCorrectHeaders(this.response);
   126               let expectedColl = server.getCollection("john", "crypto");
   127               do_check_true(!!expectedColl);
   128               let modified = expectedColl.timestamp;
   129               do_check_true(modified > 0);
   130               do_check_eq(putResponseBody, modified);
   131               do_check_eq(JSON.parse(this.response.body).crypto, modified);
   132               Utils.nextTick(function () {
   133                 server.stop(run_next_test);
   134               });
   135             });
   136           }
   137           let payload = JSON.stringify({foo: "bar"});
   138           localRequest(server, "/1.1/john/storage/crypto/keys").put(payload, cb);
   139         });
   140       });
   141     });
   142   });
   143 });
   145 add_test(function test_storage_request() {
   146   let keysURL = "/1.1/john/storage/crypto/keys?foo=bar";
   147   let foosURL = "/1.1/john/storage/crypto/foos";
   148   let storageURL = "/1.1/john/storage";
   150   let server = new SyncServer();
   151   let creation = server.timestamp();
   152   server.registerUser("john", "password");
   154   server.createContents("john", {
   155     crypto: {foos: {foo: "bar"}}
   156   });
   157   let coll = server.user("john").collection("crypto");
   158   do_check_true(!!coll);
   160   _("We're tracking timestamps.");
   161   do_check_true(coll.timestamp >= creation);
   163   function retrieveWBONotExists(next) {
   164     let req = localRequest(server, keysURL);
   165     req.get(function (err) {
   166       _("Body is " + this.response.body);
   167       _("Modified is " + this.response.newModified);
   168       do_check_eq(null, err);
   169       do_check_eq(this.response.status, 404);
   170       do_check_eq(this.response.body, "Not found");
   171       Utils.nextTick(next);
   172     });
   173   }
   174   function retrieveWBOExists(next) {
   175     let req = localRequest(server, foosURL);
   176     req.get(function (err) {
   177       _("Body is " + this.response.body);
   178       _("Modified is " + this.response.newModified);
   179       let parsedBody = JSON.parse(this.response.body);
   180       do_check_eq(parsedBody.id, "foos");
   181       do_check_eq(parsedBody.modified, coll.wbo("foos").modified);
   182       do_check_eq(JSON.parse(parsedBody.payload).foo, "bar");
   183       Utils.nextTick(next);
   184     });
   185   }
   186   function deleteWBONotExists(next) {
   187     let req = localRequest(server, keysURL);
   188     server.callback.onItemDeleted = function (username, collection, wboID) {
   189       do_throw("onItemDeleted should not have been called.");
   190     };
   192     req.delete(function (err) {
   193       _("Body is " + this.response.body);
   194       _("Modified is " + this.response.newModified);
   195       do_check_eq(this.response.status, 200);
   196       delete server.callback.onItemDeleted;
   197       Utils.nextTick(next);
   198     });
   199   }
   200   function deleteWBOExists(next) {
   201     let req = localRequest(server, foosURL);
   202     server.callback.onItemDeleted = function (username, collection, wboID) {
   203       _("onItemDeleted called for " + collection + "/" + wboID);
   204       delete server.callback.onItemDeleted;
   205       do_check_eq(username, "john");
   206       do_check_eq(collection, "crypto");
   207       do_check_eq(wboID, "foos");
   208       Utils.nextTick(next);
   209     };
   211     req.delete(function (err) {
   212       _("Body is " + this.response.body);
   213       _("Modified is " + this.response.newModified);
   214       do_check_eq(this.response.status, 200);
   215     });
   216   }
   217   function deleteStorage(next) {
   218     _("Testing DELETE on /storage.");
   219     let now = server.timestamp();
   220     _("Timestamp: " + now);
   221     let req = localRequest(server, storageURL);
   222     req.delete(function (err) {
   223       _("Body is " + this.response.body);
   224       _("Modified is " + this.response.newModified);
   225       let parsedBody = JSON.parse(this.response.body);
   226       do_check_true(parsedBody >= now);
   227       do_check_empty(server.users["john"].collections);
   228       Utils.nextTick(next);
   229     });
   230   }
   231   function getStorageFails(next) {
   232     _("Testing that GET on /storage fails.");
   233     let req = localRequest(server, storageURL);
   234     req.get(function (err) {
   235       do_check_eq(this.response.status, 405);
   236       do_check_eq(this.response.headers["allow"], "DELETE");
   237       Utils.nextTick(next);
   238     });
   239   }
   240   function getMissingCollectionWBO(next) {
   241     _("Testing that fetching a WBO from an on-existent collection 404s.");
   242     let req = localRequest(server, storageURL + "/foobar/baz");
   243     req.get(function (err) {
   244       do_check_eq(this.response.status, 404);
   245       Utils.nextTick(next);
   246     });
   247   }
   249   server.start(null,
   250     Async.chain(
   251       retrieveWBONotExists,
   252       retrieveWBOExists,
   253       deleteWBOExists,
   254       deleteWBONotExists,
   255       getStorageFails,
   256       getMissingCollectionWBO,
   257       deleteStorage,
   258       server.stop.bind(server),
   259       run_next_test
   260     ));
   261 });
   263 add_test(function test_x_weave_records() {
   264   let server = new SyncServer();
   265   server.registerUser("john", "password");
   267   server.createContents("john", {
   268     crypto: {foos: {foo: "bar"},
   269              bars: {foo: "baz"}}
   270   });
   271   server.start(null, function () {
   272     let wbo = localRequest(server, "/1.1/john/storage/crypto/foos");
   273     wbo.get(function (err) {
   274       // WBO fetches don't have one.
   275       do_check_false("x-weave-records" in this.response.headers);
   276       let col = localRequest(server, "/1.1/john/storage/crypto");
   277       col.get(function (err) {
   278         // Collection fetches do.
   279         do_check_eq(this.response.headers["x-weave-records"], "2");
   280         server.stop(run_next_test);
   281       });
   282     });
   283   });
   284 });

mercurial