services/sync/tests/unit/test_httpd_sync_server.js

branch
TOR_BUG_9701
changeset 15
b8a032363ba2
equal deleted inserted replaced
-1:000000000000 0:140052be7f44
1 /* Any copyright is dedicated to the Public Domain.
2 http://creativecommons.org/publicdomain/zero/1.0/ */
3
4 Cu.import("resource://services-sync/util.js");
5
6 function run_test() {
7 Log.repository.getLogger("Sync.Test.Server").level = Log.Level.Trace;
8 initTestLogging();
9 run_next_test();
10 }
11
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 });
23
24 add_test(function test_url_parsing() {
25 let server = new SyncServer();
26
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"));
36
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");
45
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);
49
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);
58
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);
63
64 run_next_test();
65 });
66
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 }
74
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 });
93
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 }
103
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);
112
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));
121
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 });
144
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";
149
150 let server = new SyncServer();
151 let creation = server.timestamp();
152 server.registerUser("john", "password");
153
154 server.createContents("john", {
155 crypto: {foos: {foo: "bar"}}
156 });
157 let coll = server.user("john").collection("crypto");
158 do_check_true(!!coll);
159
160 _("We're tracking timestamps.");
161 do_check_true(coll.timestamp >= creation);
162
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 };
191
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 };
210
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 }
248
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 });
262
263 add_test(function test_x_weave_records() {
264 let server = new SyncServer();
265 server.registerUser("john", "password");
266
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