test_httpd_sync_server.js (8053B)
1 /* Any copyright is dedicated to the Public Domain. 2 http://creativecommons.org/publicdomain/zero/1.0/ */ 3 4 add_test(function test_creation() { 5 // Explicit callback for this one. 6 let server = new SyncServer(Object.create(SyncServerCallback)); 7 Assert.ok(!!server); // Just so we have a check. 8 server.start(null, function () { 9 _("Started on " + server.port); 10 server.stop(run_next_test); 11 }); 12 }); 13 14 add_test(function test_url_parsing() { 15 let server = new SyncServer(); 16 17 // Check that we can parse a WBO URI. 18 let parts = server.pathRE.exec("/1.1/johnsmith/storage/crypto/keys"); 19 let [all, version, username, first, rest] = parts; 20 Assert.equal(all, "/1.1/johnsmith/storage/crypto/keys"); 21 Assert.equal(version, "1.1"); 22 Assert.equal(username, "johnsmith"); 23 Assert.equal(first, "storage"); 24 Assert.equal(rest, "crypto/keys"); 25 Assert.equal(null, server.pathRE.exec("/nothing/else")); 26 27 // Check that we can parse a collection URI. 28 parts = server.pathRE.exec("/1.1/johnsmith/storage/crypto"); 29 [all, version, username, first, rest] = parts; 30 Assert.equal(all, "/1.1/johnsmith/storage/crypto"); 31 Assert.equal(version, "1.1"); 32 Assert.equal(username, "johnsmith"); 33 Assert.equal(first, "storage"); 34 Assert.equal(rest, "crypto"); 35 36 // We don't allow trailing slash on storage URI. 37 parts = server.pathRE.exec("/1.1/johnsmith/storage/"); 38 Assert.equal(parts, undefined); 39 40 // storage alone is a valid request. 41 parts = server.pathRE.exec("/1.1/johnsmith/storage"); 42 [all, version, username, first, rest] = parts; 43 Assert.equal(all, "/1.1/johnsmith/storage"); 44 Assert.equal(version, "1.1"); 45 Assert.equal(username, "johnsmith"); 46 Assert.equal(first, "storage"); 47 Assert.equal(rest, undefined); 48 49 parts = server.storageRE.exec("storage"); 50 let collection; 51 [all, , collection] = parts; 52 Assert.equal(all, "storage"); 53 Assert.equal(collection, undefined); 54 55 run_next_test(); 56 }); 57 58 const { RESTRequest } = ChromeUtils.importESModule( 59 "resource://services-common/rest.sys.mjs" 60 ); 61 function localRequest(server, path) { 62 _("localRequest: " + path); 63 let url = server.baseURI.substr(0, server.baseURI.length - 1) + path; 64 _("url: " + url); 65 return new RESTRequest(url); 66 } 67 68 add_task(async function test_basic_http() { 69 let server = new SyncServer(); 70 server.registerUser("john", "password"); 71 Assert.ok(server.userExists("john")); 72 server.start(); 73 _("Started on " + server.port); 74 75 let req = localRequest(server, "/1.1/john/storage/crypto/keys"); 76 _("req is " + req); 77 // Shouldn't reject, beyond that we don't care. 78 await req.get(); 79 80 await promiseStopServer(server); 81 }); 82 83 add_task(async function test_info_collections() { 84 let server = new SyncServer(Object.create(SyncServerCallback)); 85 function responseHasCorrectHeaders(r) { 86 Assert.equal(r.status, 200); 87 Assert.equal(r.headers["content-type"], "application/json"); 88 Assert.ok("x-weave-timestamp" in r.headers); 89 } 90 91 server.registerUser("john", "password"); 92 server.start(); 93 94 let req = localRequest(server, "/1.1/john/info/collections"); 95 await req.get(); 96 responseHasCorrectHeaders(req.response); 97 Assert.equal(req.response.body, "{}"); 98 99 let putReq = localRequest(server, "/1.1/john/storage/crypto/keys"); 100 let payload = JSON.stringify({ foo: "bar" }); 101 let putResp = await putReq.put(payload); 102 103 responseHasCorrectHeaders(putResp); 104 105 let putResponseBody = putResp.body; 106 _("PUT response body: " + JSON.stringify(putResponseBody)); 107 108 // When we PUT something to crypto/keys, "crypto" appears in the response. 109 req = localRequest(server, "/1.1/john/info/collections"); 110 111 await req.get(); 112 responseHasCorrectHeaders(req.response); 113 let expectedColl = server.getCollection("john", "crypto"); 114 Assert.ok(!!expectedColl); 115 let modified = expectedColl.timestamp; 116 Assert.greater(modified, 0); 117 Assert.equal(putResponseBody, modified); 118 Assert.equal(JSON.parse(req.response.body).crypto, modified); 119 120 await promiseStopServer(server); 121 }); 122 123 add_task(async function test_storage_request() { 124 let keysURL = "/1.1/john/storage/crypto/keys?foo=bar"; 125 let foosURL = "/1.1/john/storage/crypto/foos"; 126 let storageURL = "/1.1/john/storage"; 127 128 let server = new SyncServer(); 129 let creation = server.timestamp(); 130 server.registerUser("john", "password"); 131 132 server.createContents("john", { 133 crypto: { foos: { foo: "bar" } }, 134 }); 135 let coll = server.user("john").collection("crypto"); 136 Assert.ok(!!coll); 137 138 _("We're tracking timestamps."); 139 Assert.greaterOrEqual(coll.timestamp, creation); 140 141 async function retrieveWBONotExists() { 142 let req = localRequest(server, keysURL); 143 let response = await req.get(); 144 _("Body is " + response.body); 145 _("Modified is " + response.newModified); 146 Assert.equal(response.status, 404); 147 Assert.equal(response.body, "Not found"); 148 } 149 150 async function retrieveWBOExists() { 151 let req = localRequest(server, foosURL); 152 let response = await req.get(); 153 _("Body is " + response.body); 154 _("Modified is " + response.newModified); 155 let parsedBody = JSON.parse(response.body); 156 Assert.equal(parsedBody.id, "foos"); 157 Assert.equal(parsedBody.modified, coll.wbo("foos").modified); 158 Assert.equal(JSON.parse(parsedBody.payload).foo, "bar"); 159 } 160 161 async function deleteWBONotExists() { 162 let req = localRequest(server, keysURL); 163 server.callback.onItemDeleted = function () { 164 do_throw("onItemDeleted should not have been called."); 165 }; 166 167 let response = await req.delete(); 168 169 _("Body is " + response.body); 170 _("Modified is " + response.newModified); 171 Assert.equal(response.status, 200); 172 delete server.callback.onItemDeleted; 173 } 174 175 async function deleteWBOExists() { 176 let req = localRequest(server, foosURL); 177 server.callback.onItemDeleted = function (username, collection, wboID) { 178 _("onItemDeleted called for " + collection + "/" + wboID); 179 delete server.callback.onItemDeleted; 180 Assert.equal(username, "john"); 181 Assert.equal(collection, "crypto"); 182 Assert.equal(wboID, "foos"); 183 }; 184 await req.delete(); 185 _("Body is " + req.response.body); 186 _("Modified is " + req.response.newModified); 187 Assert.equal(req.response.status, 200); 188 } 189 190 async function deleteStorage() { 191 _("Testing DELETE on /storage."); 192 let now = server.timestamp(); 193 _("Timestamp: " + now); 194 let req = localRequest(server, storageURL); 195 await req.delete(); 196 197 _("Body is " + req.response.body); 198 _("Modified is " + req.response.newModified); 199 let parsedBody = JSON.parse(req.response.body); 200 Assert.greaterOrEqual(parsedBody, now); 201 do_check_empty(server.users.john.collections); 202 } 203 204 async function getStorageFails() { 205 _("Testing that GET on /storage fails."); 206 let req = localRequest(server, storageURL); 207 await req.get(); 208 Assert.equal(req.response.status, 405); 209 Assert.equal(req.response.headers.allow, "DELETE"); 210 } 211 212 async function getMissingCollectionWBO() { 213 _("Testing that fetching a WBO from an on-existent collection 404s."); 214 let req = localRequest(server, storageURL + "/foobar/baz"); 215 await req.get(); 216 Assert.equal(req.response.status, 404); 217 } 218 219 server.start(null); 220 221 await retrieveWBONotExists(); 222 await retrieveWBOExists(); 223 await deleteWBOExists(); 224 await deleteWBONotExists(); 225 await getStorageFails(); 226 await getMissingCollectionWBO(); 227 await deleteStorage(); 228 229 await promiseStopServer(server); 230 }); 231 232 add_task(async function test_x_weave_records() { 233 let server = new SyncServer(); 234 server.registerUser("john", "password"); 235 236 server.createContents("john", { 237 crypto: { foos: { foo: "bar" }, bars: { foo: "baz" } }, 238 }); 239 server.start(); 240 241 let wbo = localRequest(server, "/1.1/john/storage/crypto/foos"); 242 await wbo.get(); 243 Assert.equal(false, "x-weave-records" in wbo.response.headers); 244 let col = localRequest(server, "/1.1/john/storage/crypto"); 245 await col.get(); 246 // Collection fetches do. 247 Assert.equal(col.response.headers["x-weave-records"], "2"); 248 249 await promiseStopServer(server); 250 });