|
1 /* Any copyright is dedicated to the Public Domain. |
|
2 http://creativecommons.org/publicdomain/zero/1.0/ */ |
|
3 |
|
4 Cu.import("resource://gre/modules/PlacesUtils.jsm"); |
|
5 Cu.import("resource://gre/modules/BookmarkJSONUtils.jsm"); |
|
6 Cu.import("resource://services-common/async.js"); |
|
7 Cu.import("resource://gre/modules/Log.jsm"); |
|
8 Cu.import("resource://services-sync/engines.js"); |
|
9 Cu.import("resource://services-sync/engines/bookmarks.js"); |
|
10 Cu.import("resource://services-sync/service.js"); |
|
11 Cu.import("resource://services-sync/util.js"); |
|
12 Cu.import("resource://testing-common/services/sync/utils.js"); |
|
13 Cu.import("resource://gre/modules/Promise.jsm"); |
|
14 |
|
15 Service.engineManager.register(BookmarksEngine); |
|
16 |
|
17 add_test(function bad_record_allIDs() { |
|
18 let server = new SyncServer(); |
|
19 server.start(); |
|
20 let syncTesting = new SyncTestingInfrastructure(server.server); |
|
21 |
|
22 _("Ensure that bad Places queries don't cause an error in getAllIDs."); |
|
23 let engine = new BookmarksEngine(Service); |
|
24 let store = engine._store; |
|
25 let badRecordID = PlacesUtils.bookmarks.insertBookmark( |
|
26 PlacesUtils.bookmarks.toolbarFolder, |
|
27 Utils.makeURI("place:folder=1138"), |
|
28 PlacesUtils.bookmarks.DEFAULT_INDEX, |
|
29 null); |
|
30 |
|
31 do_check_true(badRecordID > 0); |
|
32 _("Record is " + badRecordID); |
|
33 _("Type: " + PlacesUtils.bookmarks.getItemType(badRecordID)); |
|
34 |
|
35 _("Fetching children."); |
|
36 store._getChildren("toolbar", {}); |
|
37 |
|
38 _("Fetching all IDs."); |
|
39 let all = store.getAllIDs(); |
|
40 |
|
41 _("All IDs: " + JSON.stringify(all)); |
|
42 do_check_true("menu" in all); |
|
43 do_check_true("toolbar" in all); |
|
44 |
|
45 _("Clean up."); |
|
46 PlacesUtils.bookmarks.removeItem(badRecordID); |
|
47 server.stop(run_next_test); |
|
48 }); |
|
49 |
|
50 add_test(function test_ID_caching() { |
|
51 let server = new SyncServer(); |
|
52 server.start(); |
|
53 let syncTesting = new SyncTestingInfrastructure(server.server); |
|
54 |
|
55 _("Ensure that Places IDs are not cached."); |
|
56 let engine = new BookmarksEngine(Service); |
|
57 let store = engine._store; |
|
58 _("All IDs: " + JSON.stringify(store.getAllIDs())); |
|
59 |
|
60 let mobileID = store.idForGUID("mobile"); |
|
61 _("Change the GUID for that item, and drop the mobile anno."); |
|
62 store._setGUID(mobileID, "abcdefghijkl"); |
|
63 PlacesUtils.annotations.removeItemAnnotation(mobileID, "mobile/bookmarksRoot"); |
|
64 |
|
65 let err; |
|
66 let newMobileID; |
|
67 |
|
68 // With noCreate, we don't find an entry. |
|
69 try { |
|
70 newMobileID = store.idForGUID("mobile", true); |
|
71 _("New mobile ID: " + newMobileID); |
|
72 } catch (ex) { |
|
73 err = ex; |
|
74 _("Error: " + Utils.exceptionStr(err)); |
|
75 } |
|
76 |
|
77 do_check_true(!err); |
|
78 |
|
79 // With !noCreate, lookup works, and it's different. |
|
80 newMobileID = store.idForGUID("mobile", false); |
|
81 _("New mobile ID: " + newMobileID); |
|
82 do_check_true(!!newMobileID); |
|
83 do_check_neq(newMobileID, mobileID); |
|
84 |
|
85 // And it's repeatable, even with creation enabled. |
|
86 do_check_eq(newMobileID, store.idForGUID("mobile", false)); |
|
87 |
|
88 do_check_eq(store.GUIDForId(mobileID), "abcdefghijkl"); |
|
89 server.stop(run_next_test); |
|
90 }); |
|
91 |
|
92 function serverForFoo(engine) { |
|
93 return serverForUsers({"foo": "password"}, { |
|
94 meta: {global: {engines: {bookmarks: {version: engine.version, |
|
95 syncID: engine.syncID}}}}, |
|
96 bookmarks: {} |
|
97 }); |
|
98 } |
|
99 |
|
100 add_test(function test_processIncoming_error_orderChildren() { |
|
101 _("Ensure that _orderChildren() is called even when _processIncoming() throws an error."); |
|
102 |
|
103 let engine = new BookmarksEngine(Service); |
|
104 let store = engine._store; |
|
105 let server = serverForFoo(engine); |
|
106 new SyncTestingInfrastructure(server.server); |
|
107 |
|
108 let collection = server.user("foo").collection("bookmarks"); |
|
109 |
|
110 try { |
|
111 |
|
112 let folder1_id = PlacesUtils.bookmarks.createFolder( |
|
113 PlacesUtils.bookmarks.toolbarFolder, "Folder 1", 0); |
|
114 let folder1_guid = store.GUIDForId(folder1_id); |
|
115 |
|
116 let fxuri = Utils.makeURI("http://getfirefox.com/"); |
|
117 let tburi = Utils.makeURI("http://getthunderbird.com/"); |
|
118 |
|
119 let bmk1_id = PlacesUtils.bookmarks.insertBookmark( |
|
120 folder1_id, fxuri, PlacesUtils.bookmarks.DEFAULT_INDEX, "Get Firefox!"); |
|
121 let bmk1_guid = store.GUIDForId(bmk1_id); |
|
122 let bmk2_id = PlacesUtils.bookmarks.insertBookmark( |
|
123 folder1_id, tburi, PlacesUtils.bookmarks.DEFAULT_INDEX, "Get Thunderbird!"); |
|
124 let bmk2_guid = store.GUIDForId(bmk2_id); |
|
125 |
|
126 // Create a server record for folder1 where we flip the order of |
|
127 // the children. |
|
128 let folder1_payload = store.createRecord(folder1_guid).cleartext; |
|
129 folder1_payload.children.reverse(); |
|
130 collection.insert(folder1_guid, encryptPayload(folder1_payload)); |
|
131 |
|
132 // Create a bogus record that when synced down will provoke a |
|
133 // network error which in turn provokes an exception in _processIncoming. |
|
134 const BOGUS_GUID = "zzzzzzzzzzzz"; |
|
135 let bogus_record = collection.insert(BOGUS_GUID, "I'm a bogus record!"); |
|
136 bogus_record.get = function get() { |
|
137 throw "Sync this!"; |
|
138 }; |
|
139 |
|
140 // Make the 10 minutes old so it will only be synced in the toFetch phase. |
|
141 bogus_record.modified = Date.now() / 1000 - 60 * 10; |
|
142 engine.lastSync = Date.now() / 1000 - 60; |
|
143 engine.toFetch = [BOGUS_GUID]; |
|
144 |
|
145 let error; |
|
146 try { |
|
147 engine.sync(); |
|
148 } catch(ex) { |
|
149 error = ex; |
|
150 } |
|
151 do_check_true(!!error); |
|
152 |
|
153 // Verify that the bookmark order has been applied. |
|
154 let new_children = store.createRecord(folder1_guid).children; |
|
155 do_check_eq(new_children.length, 2); |
|
156 do_check_eq(new_children[0], folder1_payload.children[0]); |
|
157 do_check_eq(new_children[1], folder1_payload.children[1]); |
|
158 |
|
159 do_check_eq(PlacesUtils.bookmarks.getItemIndex(bmk1_id), 1); |
|
160 do_check_eq(PlacesUtils.bookmarks.getItemIndex(bmk2_id), 0); |
|
161 |
|
162 } finally { |
|
163 store.wipe(); |
|
164 Svc.Prefs.resetBranch(""); |
|
165 Service.recordManager.clearCache(); |
|
166 server.stop(run_next_test); |
|
167 } |
|
168 }); |
|
169 |
|
170 add_task(function test_restorePromptsReupload() { |
|
171 _("Ensure that restoring from a backup will reupload all records."); |
|
172 let engine = new BookmarksEngine(Service); |
|
173 let store = engine._store; |
|
174 let server = serverForFoo(engine); |
|
175 new SyncTestingInfrastructure(server.server); |
|
176 |
|
177 let collection = server.user("foo").collection("bookmarks"); |
|
178 |
|
179 Svc.Obs.notify("weave:engine:start-tracking"); // We skip usual startup... |
|
180 |
|
181 try { |
|
182 |
|
183 let folder1_id = PlacesUtils.bookmarks.createFolder( |
|
184 PlacesUtils.bookmarks.toolbarFolder, "Folder 1", 0); |
|
185 let folder1_guid = store.GUIDForId(folder1_id); |
|
186 _("Folder 1: " + folder1_id + ", " + folder1_guid); |
|
187 |
|
188 let fxuri = Utils.makeURI("http://getfirefox.com/"); |
|
189 let tburi = Utils.makeURI("http://getthunderbird.com/"); |
|
190 |
|
191 _("Create a single record."); |
|
192 let bmk1_id = PlacesUtils.bookmarks.insertBookmark( |
|
193 folder1_id, fxuri, PlacesUtils.bookmarks.DEFAULT_INDEX, "Get Firefox!"); |
|
194 let bmk1_guid = store.GUIDForId(bmk1_id); |
|
195 _("Get Firefox!: " + bmk1_id + ", " + bmk1_guid); |
|
196 |
|
197 |
|
198 let dirSvc = Cc["@mozilla.org/file/directory_service;1"] |
|
199 .getService(Ci.nsIProperties); |
|
200 |
|
201 let backupFile = dirSvc.get("TmpD", Ci.nsILocalFile); |
|
202 |
|
203 _("Make a backup."); |
|
204 backupFile.append("t_b_e_" + Date.now() + ".json"); |
|
205 |
|
206 _("Backing up to file " + backupFile.path); |
|
207 backupFile.create(Ci.nsILocalFile.NORMAL_FILE_TYPE, 0600); |
|
208 yield BookmarkJSONUtils.exportToFile(backupFile); |
|
209 |
|
210 _("Create a different record and sync."); |
|
211 let bmk2_id = PlacesUtils.bookmarks.insertBookmark( |
|
212 folder1_id, tburi, PlacesUtils.bookmarks.DEFAULT_INDEX, "Get Thunderbird!"); |
|
213 let bmk2_guid = store.GUIDForId(bmk2_id); |
|
214 _("Get Thunderbird!: " + bmk2_id + ", " + bmk2_guid); |
|
215 |
|
216 PlacesUtils.bookmarks.removeItem(bmk1_id); |
|
217 |
|
218 let error; |
|
219 try { |
|
220 engine.sync(); |
|
221 } catch(ex) { |
|
222 error = ex; |
|
223 _("Got error: " + Utils.exceptionStr(ex)); |
|
224 } |
|
225 do_check_true(!error); |
|
226 |
|
227 _("Verify that there's only one bookmark on the server, and it's Thunderbird."); |
|
228 // Of course, there's also the Bookmarks Toolbar and Bookmarks Menu... |
|
229 let wbos = collection.keys(function (id) { |
|
230 return ["menu", "toolbar", "mobile", folder1_guid].indexOf(id) == -1; |
|
231 }); |
|
232 do_check_eq(wbos.length, 1); |
|
233 do_check_eq(wbos[0], bmk2_guid); |
|
234 |
|
235 _("Now restore from a backup."); |
|
236 yield BookmarkJSONUtils.importFromFile(backupFile, true); |
|
237 |
|
238 _("Ensure we have the bookmarks we expect locally."); |
|
239 let guids = store.getAllIDs(); |
|
240 _("GUIDs: " + JSON.stringify(guids)); |
|
241 let found = false; |
|
242 let count = 0; |
|
243 let newFX; |
|
244 for (let guid in guids) { |
|
245 count++; |
|
246 let id = store.idForGUID(guid, true); |
|
247 // Only one bookmark, so _all_ should be Firefox! |
|
248 if (PlacesUtils.bookmarks.getItemType(id) == PlacesUtils.bookmarks.TYPE_BOOKMARK) { |
|
249 let uri = PlacesUtils.bookmarks.getBookmarkURI(id); |
|
250 _("Found URI " + uri.spec + " for GUID " + guid); |
|
251 do_check_eq(uri.spec, fxuri.spec); |
|
252 newFX = guid; // Save the new GUID after restore. |
|
253 found = true; // Only runs if the above check passes. |
|
254 } |
|
255 } |
|
256 _("We found it: " + found); |
|
257 do_check_true(found); |
|
258 |
|
259 _("Have the correct number of IDs locally, too."); |
|
260 do_check_eq(count, ["menu", "toolbar", folder1_id, bmk1_id].length); |
|
261 |
|
262 _("Sync again. This'll wipe bookmarks from the server."); |
|
263 try { |
|
264 engine.sync(); |
|
265 } catch(ex) { |
|
266 error = ex; |
|
267 _("Got error: " + Utils.exceptionStr(ex)); |
|
268 } |
|
269 do_check_true(!error); |
|
270 |
|
271 _("Verify that there's only one bookmark on the server, and it's Firefox."); |
|
272 // Of course, there's also the Bookmarks Toolbar and Bookmarks Menu... |
|
273 let payloads = server.user("foo").collection("bookmarks").payloads(); |
|
274 let bookmarkWBOs = payloads.filter(function (wbo) { |
|
275 return wbo.type == "bookmark"; |
|
276 }); |
|
277 let folderWBOs = payloads.filter(function (wbo) { |
|
278 return ((wbo.type == "folder") && |
|
279 (wbo.id != "menu") && |
|
280 (wbo.id != "toolbar")); |
|
281 }); |
|
282 |
|
283 do_check_eq(bookmarkWBOs.length, 1); |
|
284 do_check_eq(bookmarkWBOs[0].id, newFX); |
|
285 do_check_eq(bookmarkWBOs[0].bmkUri, fxuri.spec); |
|
286 do_check_eq(bookmarkWBOs[0].title, "Get Firefox!"); |
|
287 |
|
288 _("Our old friend Folder 1 is still in play."); |
|
289 do_check_eq(folderWBOs.length, 1); |
|
290 do_check_eq(folderWBOs[0].title, "Folder 1"); |
|
291 |
|
292 } finally { |
|
293 store.wipe(); |
|
294 Svc.Prefs.resetBranch(""); |
|
295 Service.recordManager.clearCache(); |
|
296 let deferred = Promise.defer(); |
|
297 server.stop(deferred.resolve); |
|
298 yield deferred.promise; |
|
299 } |
|
300 }); |
|
301 |
|
302 function FakeRecord(constructor, r) { |
|
303 constructor.call(this, "bookmarks", r.id); |
|
304 for (let x in r) { |
|
305 this[x] = r[x]; |
|
306 } |
|
307 } |
|
308 |
|
309 // Bug 632287. |
|
310 add_test(function test_mismatched_types() { |
|
311 _("Ensure that handling a record that changes type causes deletion " + |
|
312 "then re-adding."); |
|
313 |
|
314 let oldRecord = { |
|
315 "id": "l1nZZXfB8nC7", |
|
316 "type":"folder", |
|
317 "parentName":"Bookmarks Toolbar", |
|
318 "title":"Innerst i Sneglehode", |
|
319 "description":null, |
|
320 "parentid": "toolbar" |
|
321 }; |
|
322 |
|
323 let newRecord = { |
|
324 "id": "l1nZZXfB8nC7", |
|
325 "type":"livemark", |
|
326 "siteUri":"http://sneglehode.wordpress.com/", |
|
327 "feedUri":"http://sneglehode.wordpress.com/feed/", |
|
328 "parentName":"Bookmarks Toolbar", |
|
329 "title":"Innerst i Sneglehode", |
|
330 "description":null, |
|
331 "children": |
|
332 ["HCRq40Rnxhrd", "YeyWCV1RVsYw", "GCceVZMhvMbP", "sYi2hevdArlF", |
|
333 "vjbZlPlSyGY8", "UtjUhVyrpeG6", "rVq8WMG2wfZI", "Lx0tcy43ZKhZ", |
|
334 "oT74WwV8_j4P", "IztsItWVSo3-"], |
|
335 "parentid": "toolbar" |
|
336 }; |
|
337 |
|
338 let engine = new BookmarksEngine(Service); |
|
339 let store = engine._store; |
|
340 let server = serverForFoo(engine); |
|
341 new SyncTestingInfrastructure(server.server); |
|
342 |
|
343 _("GUID: " + store.GUIDForId(6, true)); |
|
344 |
|
345 try { |
|
346 let bms = PlacesUtils.bookmarks; |
|
347 let oldR = new FakeRecord(BookmarkFolder, oldRecord); |
|
348 let newR = new FakeRecord(Livemark, newRecord); |
|
349 oldR._parent = PlacesUtils.bookmarks.toolbarFolder; |
|
350 newR._parent = PlacesUtils.bookmarks.toolbarFolder; |
|
351 |
|
352 store.applyIncoming(oldR); |
|
353 _("Applied old. It's a folder."); |
|
354 let oldID = store.idForGUID(oldR.id); |
|
355 _("Old ID: " + oldID); |
|
356 do_check_eq(bms.getItemType(oldID), bms.TYPE_FOLDER); |
|
357 do_check_false(PlacesUtils.annotations |
|
358 .itemHasAnnotation(oldID, PlacesUtils.LMANNO_FEEDURI)); |
|
359 |
|
360 store.applyIncoming(newR); |
|
361 let newID = store.idForGUID(newR.id); |
|
362 _("New ID: " + newID); |
|
363 |
|
364 _("Applied new. It's a livemark."); |
|
365 do_check_eq(bms.getItemType(newID), bms.TYPE_FOLDER); |
|
366 do_check_true(PlacesUtils.annotations |
|
367 .itemHasAnnotation(newID, PlacesUtils.LMANNO_FEEDURI)); |
|
368 |
|
369 } finally { |
|
370 store.wipe(); |
|
371 Svc.Prefs.resetBranch(""); |
|
372 Service.recordManager.clearCache(); |
|
373 server.stop(run_next_test); |
|
374 } |
|
375 }); |
|
376 |
|
377 add_test(function test_bookmark_guidMap_fail() { |
|
378 _("Ensure that failures building the GUID map cause early death."); |
|
379 |
|
380 let engine = new BookmarksEngine(Service); |
|
381 let store = engine._store; |
|
382 |
|
383 let store = engine._store; |
|
384 let server = serverForFoo(engine); |
|
385 let coll = server.user("foo").collection("bookmarks"); |
|
386 new SyncTestingInfrastructure(server.server); |
|
387 |
|
388 // Add one item to the server. |
|
389 let itemID = PlacesUtils.bookmarks.createFolder( |
|
390 PlacesUtils.bookmarks.toolbarFolder, "Folder 1", 0); |
|
391 let itemGUID = store.GUIDForId(itemID); |
|
392 let itemPayload = store.createRecord(itemGUID).cleartext; |
|
393 coll.insert(itemGUID, encryptPayload(itemPayload)); |
|
394 |
|
395 engine.lastSync = 1; // So we don't back up. |
|
396 |
|
397 // Make building the GUID map fail. |
|
398 store.getAllIDs = function () { throw "Nooo"; }; |
|
399 |
|
400 // Ensure that we throw when accessing _guidMap. |
|
401 engine._syncStartup(); |
|
402 _("No error."); |
|
403 do_check_false(engine._guidMapFailed); |
|
404 |
|
405 _("We get an error if building _guidMap fails in use."); |
|
406 let err; |
|
407 try { |
|
408 _(engine._guidMap); |
|
409 } catch (ex) { |
|
410 err = ex; |
|
411 } |
|
412 do_check_eq(err.code, Engine.prototype.eEngineAbortApplyIncoming); |
|
413 do_check_eq(err.cause, "Nooo"); |
|
414 |
|
415 _("We get an error and abort during processIncoming."); |
|
416 err = undefined; |
|
417 try { |
|
418 engine._processIncoming(); |
|
419 } catch (ex) { |
|
420 err = ex; |
|
421 } |
|
422 do_check_eq(err, "Nooo"); |
|
423 |
|
424 server.stop(run_next_test); |
|
425 }); |
|
426 |
|
427 add_test(function test_bookmark_is_taggable() { |
|
428 let engine = new BookmarksEngine(Service); |
|
429 let store = engine._store; |
|
430 |
|
431 do_check_true(store.isTaggable("bookmark")); |
|
432 do_check_true(store.isTaggable("microsummary")); |
|
433 do_check_true(store.isTaggable("query")); |
|
434 do_check_false(store.isTaggable("folder")); |
|
435 do_check_false(store.isTaggable("livemark")); |
|
436 do_check_false(store.isTaggable(null)); |
|
437 do_check_false(store.isTaggable(undefined)); |
|
438 do_check_false(store.isTaggable("")); |
|
439 |
|
440 run_next_test(); |
|
441 }); |
|
442 |
|
443 add_test(function test_bookmark_tag_but_no_uri() { |
|
444 _("Ensure that a bookmark record with tags, but no URI, doesn't throw an exception."); |
|
445 |
|
446 let engine = new BookmarksEngine(Service); |
|
447 let store = engine._store; |
|
448 |
|
449 // We're simply checking that no exception is thrown, so |
|
450 // no actual checks in this test. |
|
451 |
|
452 store._tagURI(null, ["foo"]); |
|
453 store._tagURI(null, null); |
|
454 store._tagURI(Utils.makeURI("about:fake"), null); |
|
455 |
|
456 let record = { |
|
457 _parent: PlacesUtils.bookmarks.toolbarFolder, |
|
458 id: Utils.makeGUID(), |
|
459 description: "", |
|
460 tags: ["foo"], |
|
461 title: "Taggy tag", |
|
462 type: "folder" |
|
463 }; |
|
464 |
|
465 // Because update() walks the cleartext. |
|
466 record.cleartext = record; |
|
467 |
|
468 store.create(record); |
|
469 record.tags = ["bar"]; |
|
470 store.update(record); |
|
471 |
|
472 run_next_test(); |
|
473 }); |
|
474 |
|
475 add_test(function test_misreconciled_root() { |
|
476 _("Ensure that we don't reconcile an arbitrary record with a root."); |
|
477 |
|
478 let engine = new BookmarksEngine(Service); |
|
479 let store = engine._store; |
|
480 let server = serverForFoo(engine); |
|
481 |
|
482 // Log real hard for this test. |
|
483 store._log.trace = store._log.debug; |
|
484 engine._log.trace = engine._log.debug; |
|
485 |
|
486 engine._syncStartup(); |
|
487 |
|
488 // Let's find out where the toolbar is right now. |
|
489 let toolbarBefore = store.createRecord("toolbar", "bookmarks"); |
|
490 let toolbarIDBefore = store.idForGUID("toolbar"); |
|
491 do_check_neq(-1, toolbarIDBefore); |
|
492 |
|
493 let parentGUIDBefore = toolbarBefore.parentid; |
|
494 let parentIDBefore = store.idForGUID(parentGUIDBefore); |
|
495 do_check_neq(-1, parentIDBefore); |
|
496 do_check_eq("string", typeof(parentGUIDBefore)); |
|
497 |
|
498 _("Current parent: " + parentGUIDBefore + " (" + parentIDBefore + ")."); |
|
499 |
|
500 let to_apply = { |
|
501 id: "zzzzzzzzzzzz", |
|
502 type: "folder", |
|
503 title: "Bookmarks Toolbar", |
|
504 description: "Now you're for it.", |
|
505 parentName: "", |
|
506 parentid: "mobile", // Why not? |
|
507 children: [], |
|
508 }; |
|
509 |
|
510 let rec = new FakeRecord(BookmarkFolder, to_apply); |
|
511 let encrypted = encryptPayload(rec.cleartext); |
|
512 encrypted.decrypt = function () { |
|
513 for (let x in rec) { |
|
514 encrypted[x] = rec[x]; |
|
515 } |
|
516 }; |
|
517 |
|
518 _("Applying record."); |
|
519 engine._processIncoming({ |
|
520 get: function () { |
|
521 this.recordHandler(encrypted); |
|
522 return {success: true} |
|
523 }, |
|
524 }); |
|
525 |
|
526 // Ensure that afterwards, toolbar is still there. |
|
527 // As of 2012-12-05, this only passes because Places doesn't use "toolbar" as |
|
528 // the real GUID, instead using a generated one. Sync does the translation. |
|
529 let toolbarAfter = store.createRecord("toolbar", "bookmarks"); |
|
530 let parentGUIDAfter = toolbarAfter.parentid; |
|
531 let parentIDAfter = store.idForGUID(parentGUIDAfter); |
|
532 do_check_eq(store.GUIDForId(toolbarIDBefore), "toolbar"); |
|
533 do_check_eq(parentGUIDBefore, parentGUIDAfter); |
|
534 do_check_eq(parentIDBefore, parentIDAfter); |
|
535 |
|
536 server.stop(run_next_test); |
|
537 }); |
|
538 |
|
539 function run_test() { |
|
540 initTestLogging("Trace"); |
|
541 generateNewKeys(Service.collectionKeys); |
|
542 run_next_test(); |
|
543 } |