summaryrefslogtreecommitdiffstats
path: root/toolkit/components/places/tests/migration/test_current_from_v43.js
diff options
context:
space:
mode:
Diffstat (limited to 'toolkit/components/places/tests/migration/test_current_from_v43.js')
-rw-r--r--toolkit/components/places/tests/migration/test_current_from_v43.js253
1 files changed, 253 insertions, 0 deletions
diff --git a/toolkit/components/places/tests/migration/test_current_from_v43.js b/toolkit/components/places/tests/migration/test_current_from_v43.js
new file mode 100644
index 0000000000..70a383bb2e
--- /dev/null
+++ b/toolkit/components/places/tests/migration/test_current_from_v43.js
@@ -0,0 +1,253 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+const EXPECTED_REMAINING_ROOTS = [
+ ...PlacesUtils.bookmarks.userContentRoots,
+ PlacesUtils.bookmarks.tagsGuid,
+];
+
+const EXPECTED_REMOVED_BOOKMARK_GUIDS = [
+ // These first ones are the old left-pane folder queries
+ "SNLmwJH6GtW9", // Root Query
+ "r0dY_2_y4mlx", // History
+ "xGGhZK3b6GnW", // Downloads
+ "EJG6I1nKkQFQ", // Tags
+ "gSyHo5oNSUJV", // All Bookmarks
+ // These are simulated add-on injections that we expect to be removed.
+ "exaddon_____",
+ "exaddon1____",
+ "exaddon2____",
+ "exaddon3____",
+ "test________",
+];
+
+const EXPECTED_REMOVED_ANNOTATIONS = [
+ "PlacesOrganizer/OrganizerFolder",
+ "PlacesOrganizer/OrganizerQuery",
+];
+
+const EXPECTED_REMOVED_PLACES_ENTRIES = ["exaddonh____", "exaddonh3___"];
+const EXPECTED_KEPT_PLACES_ENTRY = "exaddonh2___";
+const EXPECTED_REMOVED_KEYWORDS = ["exaddon", "exaddon2"];
+
+async function assertItemIn(db, table, field, expectedItems) {
+ let rows = await db.execute(`SELECT ${field} from ${table}`);
+
+ Assert.ok(
+ rows.length >= expectedItems.length,
+ "Should be at least the number of annotations we expect to be removed."
+ );
+
+ let fieldValues = rows.map(row => row.getResultByName(field));
+
+ for (let item of expectedItems) {
+ Assert.ok(
+ fieldValues.includes(item),
+ `${table} should have ${expectedItems}`
+ );
+ }
+}
+
+add_task(async function setup() {
+ await setupPlacesDatabase("places_v43.sqlite");
+
+ // Setup database contents to be migrated.
+ let path = PathUtils.join(PathUtils.profileDir, DB_FILENAME);
+ let db = await Sqlite.openConnection({ path });
+
+ let rows = await db.execute(`SELECT * FROM moz_bookmarks_deleted`);
+ Assert.equal(rows.length, 0, "Should be nothing in moz_bookmarks_deleted");
+
+ // Break roots parenting, to test for Bug 1472127.
+ await db.execute(`INSERT INTO moz_bookmarks (title, parent, position, guid)
+ VALUES ("test", 1, 0, "test________")`);
+ await db.execute(`UPDATE moz_bookmarks
+ SET parent = (SELECT id FROM moz_bookmarks WHERE guid = "test________")
+ WHERE guid = "menu________"`);
+
+ await assertItemIn(
+ db,
+ "moz_anno_attributes",
+ "name",
+ EXPECTED_REMOVED_ANNOTATIONS
+ );
+ await assertItemIn(
+ db,
+ "moz_bookmarks",
+ "guid",
+ EXPECTED_REMOVED_BOOKMARK_GUIDS
+ );
+ await assertItemIn(db, "moz_keywords", "keyword", EXPECTED_REMOVED_KEYWORDS);
+ await assertItemIn(db, "moz_places", "guid", EXPECTED_REMOVED_PLACES_ENTRIES);
+
+ await db.close();
+});
+
+add_task(async 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 = await PlacesUtils.promiseDBConnection();
+ Assert.equal(await db.getSchemaVersion(), CURRENT_SCHEMA_VERSION);
+});
+
+add_task(async function test_roots_removed() {
+ let db = await PlacesUtils.promiseDBConnection();
+ let rows = await db.execute(
+ `
+ SELECT id FROM moz_bookmarks
+ WHERE guid = :guid
+ `,
+ { guid: PlacesUtils.bookmarks.rootGuid }
+ );
+ Assert.equal(rows.length, 1, "Should have exactly one root row.");
+ let rootId = rows[0].getResultByName("id");
+
+ rows = await db.execute(
+ `
+ SELECT guid FROM moz_bookmarks
+ WHERE parent = :rootId`,
+ { rootId }
+ );
+
+ Assert.equal(
+ rows.length,
+ EXPECTED_REMAINING_ROOTS.length,
+ "Should only have the built-in folder roots."
+ );
+
+ for (let row of rows) {
+ let guid = row.getResultByName("guid");
+ Assert.ok(
+ EXPECTED_REMAINING_ROOTS.includes(guid),
+ `Should have only the expected guids remaining, unexpected guid: ${guid}`
+ );
+ }
+
+ // Check the reparented menu now.
+ rows = await db.execute(
+ `
+ SELECT id, parent FROM moz_bookmarks
+ WHERE guid = :guid
+ `,
+ { guid: PlacesUtils.bookmarks.menuGuid }
+ );
+ Assert.equal(rows.length, 1, "Should have found the menu root.");
+ Assert.equal(
+ rows[0].getResultByName("parent"),
+ await PlacesUtils.promiseItemId(PlacesUtils.bookmarks.rootGuid),
+ "Should have moved the menu back to the Places root."
+ );
+});
+
+add_task(async function test_tombstones_added() {
+ let db = await PlacesUtils.promiseDBConnection();
+
+ let rows = await db.execute(`
+ SELECT guid FROM moz_bookmarks_deleted
+ `);
+
+ for (let row of rows) {
+ let guid = row.getResultByName("guid");
+ Assert.ok(
+ EXPECTED_REMOVED_BOOKMARK_GUIDS.includes(guid),
+ `Should have tombstoned the expected guids, unexpected guid: ${guid}`
+ );
+ }
+
+ Assert.equal(
+ rows.length,
+ EXPECTED_REMOVED_BOOKMARK_GUIDS.length,
+ "Should have removed all the expected bookmarks."
+ );
+});
+
+add_task(async function test_annotations_removed() {
+ let db = await PlacesUtils.promiseDBConnection();
+
+ await assertAnnotationsRemoved(db, EXPECTED_REMOVED_ANNOTATIONS);
+});
+
+add_task(async function test_check_history_entries() {
+ let db = await PlacesUtils.promiseDBConnection();
+
+ for (let entry of EXPECTED_REMOVED_PLACES_ENTRIES) {
+ let rows = await db.execute(`
+ SELECT id FROM moz_places
+ WHERE guid = '${entry}'`);
+
+ Assert.equal(
+ rows.length,
+ 0,
+ `Should have removed an orphaned history entry ${EXPECTED_REMOVED_PLACES_ENTRIES}.`
+ );
+ }
+
+ let rows = await db.execute(
+ `
+ SELECT foreign_count FROM moz_places
+ WHERE guid = :guid
+ `,
+ { guid: EXPECTED_KEPT_PLACES_ENTRY }
+ );
+
+ Assert.equal(
+ rows.length,
+ 1,
+ `Should have kept visited history entry ${EXPECTED_KEPT_PLACES_ENTRY}`
+ );
+
+ let foreignCount = rows[0].getResultByName("foreign_count");
+ Assert.equal(
+ foreignCount,
+ 0,
+ `Should have updated the foreign_count for ${EXPECTED_KEPT_PLACES_ENTRY}`
+ );
+});
+
+add_task(async function test_check_keyword_removed() {
+ let db = await PlacesUtils.promiseDBConnection();
+
+ for (let keyword of EXPECTED_REMOVED_KEYWORDS) {
+ let rows = await db.execute(
+ `
+ SELECT keyword FROM moz_keywords
+ WHERE keyword = :keyword
+ `,
+ { keyword }
+ );
+
+ Assert.equal(
+ rows.length,
+ 0,
+ `Should have removed the expected keyword: ${keyword}.`
+ );
+ }
+});
+
+add_task(async function test_no_orphan_annotations() {
+ let db = await PlacesUtils.promiseDBConnection();
+
+ await assertNoOrphanAnnotations(db);
+});
+
+add_task(async function test_no_orphan_keywords() {
+ let db = await PlacesUtils.promiseDBConnection();
+
+ let rows = await db.execute(`
+ SELECT place_id FROM moz_keywords
+ WHERE place_id NOT IN (SELECT id from moz_places)
+ `);
+
+ Assert.equal(rows.length, 0, `Should have no orphan keywords.`);
+});
+
+add_task(async function test_meta_exists() {
+ let db = await PlacesUtils.promiseDBConnection();
+ await db.execute(`SELECT 1 FROM moz_meta`);
+});