summaryrefslogtreecommitdiffstats
path: root/toolkit/components/places/tests/migration/test_current_from_v34.js
diff options
context:
space:
mode:
Diffstat (limited to 'toolkit/components/places/tests/migration/test_current_from_v34.js')
-rw-r--r--toolkit/components/places/tests/migration/test_current_from_v34.js141
1 files changed, 141 insertions, 0 deletions
diff --git a/toolkit/components/places/tests/migration/test_current_from_v34.js b/toolkit/components/places/tests/migration/test_current_from_v34.js
new file mode 100644
index 000000000..115bcec67
--- /dev/null
+++ b/toolkit/components/places/tests/migration/test_current_from_v34.js
@@ -0,0 +1,141 @@
+Cu.importGlobalProperties(["URL", "crypto"]);
+
+const { TYPE_BOOKMARK, TYPE_FOLDER } = Ci.nsINavBookmarksService;
+const { EXPIRE_NEVER, TYPE_INT32 } = Ci.nsIAnnotationService;
+
+function makeGuid() {
+ return ChromeUtils.base64URLEncode(crypto.getRandomValues(new Uint8Array(9)), {
+ pad: false,
+ });
+}
+
+// These queries are more or less copied directly from Bookmarks.jsm, but
+// operate on the old, pre-migration DB. We can't use any of the Places SQL
+// functions yet, because those are only registered for the main connection.
+function* insertItem(db, info) {
+ let [parentInfo] = yield db.execute(`
+ SELECT b.id, (SELECT count(*) FROM moz_bookmarks
+ WHERE parent = b.id) AS childCount
+ FROM moz_bookmarks b
+ WHERE b.guid = :parentGuid`,
+ { parentGuid: info.parentGuid });
+
+ let guid = makeGuid();
+ yield db.execute(`
+ INSERT INTO moz_bookmarks (fk, type, parent, position, guid)
+ VALUES ((SELECT id FROM moz_places WHERE url = :url),
+ :type, :parent, :position, :guid)`,
+ { url: info.url || "nonexistent", type: info.type, guid,
+ // Just append items.
+ position: parentInfo.getResultByName("childCount"),
+ parent: parentInfo.getResultByName("id") });
+
+ let id = (yield db.execute(`
+ SELECT id FROM moz_bookmarks WHERE guid = :guid LIMIT 1`,
+ { guid }))[0].getResultByName("id");
+
+ return { id, guid };
+}
+
+function insertBookmark(db, info) {
+ return db.executeTransaction(function* () {
+ if (info.type == TYPE_BOOKMARK) {
+ // We don't have access to the hash function here, so we omit the
+ // `url_hash` column. These will be fixed up automatically during
+ // migration.
+ let url = new URL(info.url);
+ let placeGuid = makeGuid();
+ yield db.execute(`
+ INSERT INTO moz_places (url, rev_host, hidden, frecency, guid)
+ VALUES (:url, :rev_host, 0, -1, :guid)`,
+ { url: url.href, guid: placeGuid,
+ rev_host: PlacesUtils.getReversedHost(url) });
+ }
+ return yield* insertItem(db, info);
+ });
+}
+
+function* insertAnno(db, itemId, name, value) {
+ yield db.execute(`INSERT OR IGNORE INTO moz_anno_attributes (name)
+ VALUES (:name)`, { name });
+ yield db.execute(`
+ INSERT INTO moz_items_annos
+ (item_id, anno_attribute_id, content, flags,
+ expiration, type, dateAdded, lastModified)
+ VALUES (:itemId,
+ (SELECT id FROM moz_anno_attributes
+ WHERE name = :name),
+ 1, 0, :expiration, :type, 0, 0)
+ `, { itemId, name, expiration: EXPIRE_NEVER, type: TYPE_INT32 });
+}
+
+function insertMobileFolder(db) {
+ return db.executeTransaction(function* () {
+ let item = yield* insertItem(db, {
+ type: TYPE_FOLDER,
+ parentGuid: "root________",
+ });
+ yield* insertAnno(db, item.id, "mobile/bookmarksRoot", 1);
+ return item;
+ });
+}
+
+var mobileId, mobileGuid, fxGuid;
+var dupeMobileId, dupeMobileGuid, tbGuid;
+
+add_task(function* setup() {
+ yield setupPlacesDatabase("places_v34.sqlite");
+ // Setup database contents to be migrated.
+ let path = OS.Path.join(OS.Constants.Path.profileDir, DB_FILENAME);
+ let db = yield Sqlite.openConnection({ path });
+
+ do_print("Create mobile folder with bookmarks");
+ ({ id: mobileId, guid: mobileGuid } = yield insertMobileFolder(db));
+ ({ guid: fxGuid } = yield insertBookmark(db, {
+ type: TYPE_BOOKMARK,
+ url: "http://getfirefox.com",
+ parentGuid: mobileGuid,
+ }));
+
+ // We should only have one mobile folder, but, in case an old version of Sync
+ // did the wrong thing and created multiple mobile folders, we should merge
+ // their contents into the new mobile root.
+ do_print("Create second mobile folder with different bookmarks");
+ ({ id: dupeMobileId, guid: dupeMobileGuid } = yield insertMobileFolder(db));
+ ({ guid: tbGuid } = yield insertBookmark(db, {
+ type: TYPE_BOOKMARK,
+ url: "http://getthunderbird.com",
+ parentGuid: dupeMobileGuid,
+ }));
+
+ yield db.close();
+});
+
+add_task(function* database_is_valid() {
+ // Accessing the database for the first time triggers migration.
+ Assert.equal(PlacesUtils.history.databaseStatus,
+ PlacesUtils.history.DATABASE_STATUS_UPGRADED);
+
+ let db = yield PlacesUtils.promiseDBConnection();
+ Assert.equal((yield db.getSchemaVersion()), CURRENT_SCHEMA_VERSION);
+});
+
+add_task(function* test_mobile_root() {
+ let fxBmk = yield PlacesUtils.bookmarks.fetch(fxGuid);
+ equal(fxBmk.parentGuid, PlacesUtils.bookmarks.mobileGuid,
+ "Firefox bookmark should be moved to new mobile root");
+ equal(fxBmk.index, 0, "Firefox bookmark should be first child of new root");
+
+ let tbBmk = yield PlacesUtils.bookmarks.fetch(tbGuid);
+ equal(tbBmk.parentGuid, PlacesUtils.bookmarks.mobileGuid,
+ "Thunderbird bookmark should be moved to new mobile root");
+ equal(tbBmk.index, 1,
+ "Thunderbird bookmark should be second child of new root");
+
+ let mobileRootId = PlacesUtils.promiseItemId(
+ PlacesUtils.bookmarks.mobileGuid);
+ let annoItemIds = PlacesUtils.annotations.getItemsWithAnnotation(
+ PlacesUtils.MOBILE_ROOT_ANNO, {});
+ deepEqual(annoItemIds, [mobileRootId],
+ "Only mobile root should have mobile anno");
+});