addon-sdk/source/test/test-simple-storage.js

branch
TOR_BUG_3246
changeset 7
129ffea94266
equal deleted inserted replaced
-1:000000000000 0:ac3c99d63026
1 /* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
4
5 const file = require("sdk/io/file");
6 const prefs = require("sdk/preferences/service");
7
8 const QUOTA_PREF = "extensions.addon-sdk.simple-storage.quota";
9 const WRITE_PERIOD_PREF = "extensions.addon-sdk.simple-storage.writePeriod";
10
11 let {Cc,Ci} = require("chrome");
12
13 const { Loader } = require("sdk/test/loader");
14 const { id } = require("sdk/self");
15
16 let storeFile = Cc["@mozilla.org/file/directory_service;1"].
17 getService(Ci.nsIProperties).
18 get("ProfD", Ci.nsIFile);
19 storeFile.append("jetpack");
20 storeFile.append(id);
21 storeFile.append("simple-storage");
22 file.mkpath(storeFile.path);
23 storeFile.append("store.json");
24 let storeFilename = storeFile.path;
25
26 function manager(loader) loader.sandbox("sdk/simple-storage").manager;
27
28 exports.testSetGet = function (assert, done) {
29 // Load the module once, set a value.
30 let loader = Loader(module);
31 let ss = loader.require("sdk/simple-storage");
32 manager(loader).jsonStore.onWrite = function (storage) {
33 assert.ok(file.exists(storeFilename), "Store file should exist");
34
35 // Load the module again and make sure the value stuck.
36 loader = Loader(module);
37 ss = loader.require("sdk/simple-storage");
38 assert.equal(ss.storage.foo, val, "Value should persist");
39 manager(loader).jsonStore.onWrite = function (storage) {
40 assert.fail("Nothing should be written since `storage` was not changed.");
41 };
42 loader.unload();
43 file.remove(storeFilename);
44 done();
45 };
46 let val = "foo";
47 ss.storage.foo = val;
48 assert.equal(ss.storage.foo, val, "Value read should be value set");
49 loader.unload();
50 };
51
52 exports.testSetGetRootArray = function (assert, done) {
53 setGetRoot(assert, done, [1, 2, 3], function (arr1, arr2) {
54 if (arr1.length !== arr2.length)
55 return false;
56 for (let i = 0; i < arr1.length; i++) {
57 if (arr1[i] !== arr2[i])
58 return false;
59 }
60 return true;
61 });
62 };
63
64 exports.testSetGetRootBool = function (assert, done) {
65 setGetRoot(assert, done, true);
66 };
67
68 exports.testSetGetRootFunction = function (assert, done) {
69 setGetRootError(assert, done, function () {},
70 "Setting storage to a function should fail");
71 };
72
73 exports.testSetGetRootNull = function (assert, done) {
74 setGetRoot(assert, done, null);
75 };
76
77 exports.testSetGetRootNumber = function (assert, done) {
78 setGetRoot(assert, done, 3.14);
79 };
80
81 exports.testSetGetRootObject = function (assert, done) {
82 setGetRoot(assert, done, { foo: 1, bar: 2 }, function (obj1, obj2) {
83 for (let prop in obj1) {
84 if (!(prop in obj2) || obj2[prop] !== obj1[prop])
85 return false;
86 }
87 for (let prop in obj2) {
88 if (!(prop in obj1) || obj1[prop] !== obj2[prop])
89 return false;
90 }
91 return true;
92 });
93 };
94
95 exports.testSetGetRootString = function (assert, done) {
96 setGetRoot(assert, done, "sho' 'nuff");
97 };
98
99 exports.testSetGetRootUndefined = function (assert, done) {
100 setGetRootError(assert, done, undefined, "Setting storage to undefined should fail");
101 };
102
103 exports.testEmpty = function (assert) {
104 let loader = Loader(module);
105 let ss = loader.require("sdk/simple-storage");
106 loader.unload();
107 assert.ok(!file.exists(storeFilename), "Store file should not exist");
108 };
109
110 exports.testStorageDataRecovery = function(assert) {
111 const data = {
112 a: true,
113 b: [3, 13],
114 c: "guilty!",
115 d: { e: 1, f: 2 }
116 };
117 let stream = file.open(storeFilename, "w");
118 stream.write(JSON.stringify(data));
119 stream.close();
120 let loader = Loader(module);
121 let ss = loader.require("sdk/simple-storage");
122 assert.deepEqual(ss.storage, data, "Recovered data should be the same as written");
123 file.remove(storeFilename);
124 loader.unload();
125 }
126
127 exports.testMalformed = function (assert) {
128 let stream = file.open(storeFilename, "w");
129 stream.write("i'm not json");
130 stream.close();
131 let loader = Loader(module);
132 let ss = loader.require("sdk/simple-storage");
133 let empty = true;
134 for (let key in ss.storage) {
135 empty = false;
136 break;
137 }
138 assert.ok(empty, "Malformed storage should cause root to be empty");
139 file.remove(storeFilename);
140 loader.unload();
141 };
142
143 // Go over quota and handle it by listener.
144 exports.testQuotaExceededHandle = function (assert, done) {
145 prefs.set(QUOTA_PREF, 18);
146
147 let loader = Loader(module);
148 let ss = loader.require("sdk/simple-storage");
149 ss.on("OverQuota", function () {
150 assert.pass("OverQuota was emitted as expected");
151 assert.equal(this, ss, "`this` should be simple storage");
152 ss.storage = { x: 4, y: 5 };
153
154 manager(loader).jsonStore.onWrite = function () {
155 loader = Loader(module);
156 ss = loader.require("sdk/simple-storage");
157 let numProps = 0;
158 for (let prop in ss.storage)
159 numProps++;
160 assert.ok(numProps, 2,
161 "Store should contain 2 values: " + ss.storage.toSource());
162 assert.equal(ss.storage.x, 4, "x value should be correct");
163 assert.equal(ss.storage.y, 5, "y value should be correct");
164 manager(loader).jsonStore.onWrite = function (storage) {
165 assert.fail("Nothing should be written since `storage` was not changed.");
166 };
167 loader.unload();
168 prefs.reset(QUOTA_PREF);
169 done();
170 };
171 loader.unload();
172 });
173 // This will be JSON.stringify()ed to: {"a":1,"b":2,"c":3} (19 bytes)
174 ss.storage = { a: 1, b: 2, c: 3 };
175 manager(loader).jsonStore.write();
176 };
177
178 // Go over quota but don't handle it. The last good state should still persist.
179 exports.testQuotaExceededNoHandle = function (assert, done) {
180 prefs.set(QUOTA_PREF, 5);
181
182 let loader = Loader(module);
183 let ss = loader.require("sdk/simple-storage");
184
185 manager(loader).jsonStore.onWrite = function (storage) {
186 loader = Loader(module);
187 ss = loader.require("sdk/simple-storage");
188 assert.equal(ss.storage, val,
189 "Value should have persisted: " + ss.storage);
190 ss.storage = "some very long string that is very long";
191 ss.on("OverQuota", function () {
192 assert.pass("OverQuota emitted as expected");
193 manager(loader).jsonStore.onWrite = function () {
194 assert.fail("Over-quota value should not have been written");
195 };
196 loader.unload();
197
198 loader = Loader(module);
199 ss = loader.require("sdk/simple-storage");
200 assert.equal(ss.storage, val,
201 "Over-quota value should not have been written, " +
202 "old value should have persisted: " + ss.storage);
203 manager(loader).jsonStore.onWrite = function (storage) {
204 assert.fail("Nothing should be written since `storage` was not changed.");
205 };
206 loader.unload();
207 prefs.reset(QUOTA_PREF);
208 done();
209 });
210 manager(loader).jsonStore.write();
211 };
212
213 let val = "foo";
214 ss.storage = val;
215 loader.unload();
216 };
217
218 exports.testQuotaUsage = function (assert, done) {
219 let quota = 21;
220 prefs.set(QUOTA_PREF, quota);
221
222 let loader = Loader(module);
223 let ss = loader.require("sdk/simple-storage");
224
225 // {"a":1} (7 bytes)
226 ss.storage = { a: 1 };
227 assert.equal(ss.quotaUsage, 7 / quota, "quotaUsage should be correct");
228
229 // {"a":1,"bb":2} (14 bytes)
230 ss.storage = { a: 1, bb: 2 };
231 assert.equal(ss.quotaUsage, 14 / quota, "quotaUsage should be correct");
232
233 // {"a":1,"bb":2,"cc":3} (21 bytes)
234 ss.storage = { a: 1, bb: 2, cc: 3 };
235 assert.equal(ss.quotaUsage, 21 / quota, "quotaUsage should be correct");
236
237 manager(loader).jsonStore.onWrite = function () {
238 prefs.reset(QUOTA_PREF);
239 done();
240 };
241 loader.unload();
242 };
243
244 exports.testUninstall = function (assert, done) {
245 let loader = Loader(module);
246 let ss = loader.require("sdk/simple-storage");
247 manager(loader).jsonStore.onWrite = function () {
248 assert.ok(file.exists(storeFilename), "Store file should exist");
249
250 loader = Loader(module);
251 ss = loader.require("sdk/simple-storage");
252 loader.unload("uninstall");
253 assert.ok(!file.exists(storeFilename), "Store file should be removed");
254 done();
255 };
256 ss.storage.foo = "foo";
257 loader.unload();
258 };
259
260 exports.testChangeInnerArray = function(assert, done) {
261 prefs.set(WRITE_PERIOD_PREF, 10);
262
263 let expected = {
264 x: [5, 7],
265 y: [7, 28],
266 z: [6, 2]
267 };
268
269 // Load the module, set a value.
270 let loader = Loader(module);
271 let ss = loader.require("sdk/simple-storage");
272 manager(loader).jsonStore.onWrite = function (storage) {
273 assert.ok(file.exists(storeFilename), "Store file should exist");
274
275 // Load the module again and check the result
276 loader = Loader(module);
277 ss = loader.require("sdk/simple-storage");
278 assert.equal(JSON.stringify(ss.storage),
279 JSON.stringify(expected), "Should see the expected object");
280
281 // Add a property
282 ss.storage.x.push(["bar"]);
283 expected.x.push(["bar"]);
284 manager(loader).jsonStore.onWrite = function (storage) {
285 assert.equal(JSON.stringify(ss.storage),
286 JSON.stringify(expected), "Should see the expected object");
287
288 // Modify a property
289 ss.storage.y[0] = 42;
290 expected.y[0] = 42;
291 manager(loader).jsonStore.onWrite = function (storage) {
292 assert.equal(JSON.stringify(ss.storage),
293 JSON.stringify(expected), "Should see the expected object");
294
295 // Delete a property
296 delete ss.storage.z[1];
297 delete expected.z[1];
298 manager(loader).jsonStore.onWrite = function (storage) {
299 assert.equal(JSON.stringify(ss.storage),
300 JSON.stringify(expected), "Should see the expected object");
301
302 // Modify the new inner-object
303 ss.storage.x[2][0] = "baz";
304 expected.x[2][0] = "baz";
305 manager(loader).jsonStore.onWrite = function (storage) {
306 assert.equal(JSON.stringify(ss.storage),
307 JSON.stringify(expected), "Should see the expected object");
308
309 manager(loader).jsonStore.onWrite = function (storage) {
310 assert.fail("Nothing should be written since `storage` was not changed.");
311 };
312 loader.unload();
313
314 // Load the module again and check the result
315 loader = Loader(module);
316 ss = loader.require("sdk/simple-storage");
317 assert.equal(JSON.stringify(ss.storage),
318 JSON.stringify(expected), "Should see the expected object");
319 loader.unload();
320 file.remove(storeFilename);
321 prefs.reset(WRITE_PERIOD_PREF);
322 done();
323 };
324 };
325 };
326 };
327 };
328
329 ss.storage = {
330 x: [5, 7],
331 y: [7, 28],
332 z: [6, 2]
333 };
334 assert.equal(JSON.stringify(ss.storage),
335 JSON.stringify(expected), "Should see the expected object");
336
337 loader.unload();
338 };
339
340 exports.testChangeInnerObject = function(assert, done) {
341 prefs.set(WRITE_PERIOD_PREF, 10);
342
343 let expected = {
344 x: {
345 a: 5,
346 b: 7
347 },
348 y: {
349 c: 7,
350 d: 28
351 },
352 z: {
353 e: 6,
354 f: 2
355 }
356 };
357
358 // Load the module, set a value.
359 let loader = Loader(module);
360 let ss = loader.require("sdk/simple-storage");
361 manager(loader).jsonStore.onWrite = function (storage) {
362 assert.ok(file.exists(storeFilename), "Store file should exist");
363
364 // Load the module again and check the result
365 loader = Loader(module);
366 ss = loader.require("sdk/simple-storage");
367 assert.equal(JSON.stringify(ss.storage),
368 JSON.stringify(expected), "Should see the expected object");
369
370 // Add a property
371 ss.storage.x.g = {foo: "bar"};
372 expected.x.g = {foo: "bar"};
373 manager(loader).jsonStore.onWrite = function (storage) {
374 assert.equal(JSON.stringify(ss.storage),
375 JSON.stringify(expected), "Should see the expected object");
376
377 // Modify a property
378 ss.storage.y.c = 42;
379 expected.y.c = 42;
380 manager(loader).jsonStore.onWrite = function (storage) {
381 assert.equal(JSON.stringify(ss.storage),
382 JSON.stringify(expected), "Should see the expected object");
383
384 // Delete a property
385 delete ss.storage.z.f;
386 delete expected.z.f;
387 manager(loader).jsonStore.onWrite = function (storage) {
388 assert.equal(JSON.stringify(ss.storage),
389 JSON.stringify(expected), "Should see the expected object");
390
391 // Modify the new inner-object
392 ss.storage.x.g.foo = "baz";
393 expected.x.g.foo = "baz";
394 manager(loader).jsonStore.onWrite = function (storage) {
395 assert.equal(JSON.stringify(ss.storage),
396 JSON.stringify(expected), "Should see the expected object");
397
398 manager(loader).jsonStore.onWrite = function (storage) {
399 assert.fail("Nothing should be written since `storage` was not changed.");
400 };
401 loader.unload();
402
403 // Load the module again and check the result
404 loader = Loader(module);
405 ss = loader.require("sdk/simple-storage");
406 assert.equal(JSON.stringify(ss.storage),
407 JSON.stringify(expected), "Should see the expected object");
408 loader.unload();
409 file.remove(storeFilename);
410 prefs.reset(WRITE_PERIOD_PREF);
411 done();
412 };
413 };
414 };
415 };
416 };
417
418 ss.storage = {
419 x: {
420 a: 5,
421 b: 7
422 },
423 y: {
424 c: 7,
425 d: 28
426 },
427 z: {
428 e: 6,
429 f: 2
430 }
431 };
432 assert.equal(JSON.stringify(ss.storage),
433 JSON.stringify(expected), "Should see the expected object");
434
435 loader.unload();
436 };
437
438 exports.testSetNoSetRead = function (assert, done) {
439 // Load the module, set a value.
440 let loader = Loader(module);
441 let ss = loader.require("sdk/simple-storage");
442 manager(loader).jsonStore.onWrite = function (storage) {
443 assert.ok(file.exists(storeFilename), "Store file should exist");
444
445 // Load the module again but don't access ss.storage.
446 loader = Loader(module);
447 ss = loader.require("sdk/simple-storage");
448 manager(loader).jsonStore.onWrite = function (storage) {
449 assert.fail("Nothing should be written since `storage` was not accessed.");
450 };
451 loader.unload();
452
453 // Load the module a third time and make sure the value stuck.
454 loader = Loader(module);
455 ss = loader.require("sdk/simple-storage");
456 assert.equal(ss.storage.foo, val, "Value should persist");
457 manager(loader).jsonStore.onWrite = function (storage) {
458 assert.fail("Nothing should be written since `storage` was not changed.");
459 };
460 loader.unload();
461 file.remove(storeFilename);
462 done();
463 };
464 let val = "foo";
465 ss.storage.foo = val;
466 assert.equal(ss.storage.foo, val, "Value read should be value set");
467 loader.unload();
468 };
469
470
471 function setGetRoot(assert, done, val, compare) {
472 compare = compare || function (a, b) a === b;
473
474 // Load the module once, set a value.
475 let loader = Loader(module);
476 let ss = loader.require("sdk/simple-storage");
477 manager(loader).jsonStore.onWrite = function () {
478 assert.ok(file.exists(storeFilename), "Store file should exist");
479
480 // Load the module again and make sure the value stuck.
481 loader = Loader(module);
482 ss = loader.require("sdk/simple-storage");
483 assert.ok(compare(ss.storage, val), "Value should persist");
484 manager(loader).jsonStore.onWrite = function (storage) {
485 assert.fail("Nothing should be written since `storage` was not changed.");
486 };
487 loader.unload();
488 file.remove(storeFilename);
489 done();
490 };
491 ss.storage = val;
492 assert.ok(compare(ss.storage, val), "Value read should be value set");
493 loader.unload();
494 }
495
496 function setGetRootError(assert, done, val, msg) {
497 let pred = new RegExp("storage must be one of the following types: " +
498 "array, boolean, null, number, object, string");
499 let loader = Loader(module);
500 let ss = loader.require("sdk/simple-storage");
501 assert.throws(function () ss.storage = val, pred, msg);
502 done();
503 loader.unload();
504 }
505
506 require('sdk/test').run(exports);

mercurial