diff options
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.js | 253 |
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`); +}); |