michael@0: /* Any copyright is dedicated to the Public Domain. michael@0: http://creativecommons.org/publicdomain/zero/1.0/ */ michael@0: michael@0: Cu.import("resource://gre/modules/PlacesUtils.jsm"); michael@0: Cu.import("resource://services-common/async.js"); michael@0: Cu.import("resource://services-sync/util.js"); michael@0: Cu.import("resource://services-sync/engines.js"); michael@0: Cu.import("resource://services-sync/engines/history.js"); michael@0: Cu.import("resource://services-sync/engines/bookmarks.js"); michael@0: Cu.import("resource://services-sync/service.js"); michael@0: michael@0: const kDBName = "places.sqlite"; michael@0: const storageSvc = Cc["@mozilla.org/storage/service;1"] michael@0: .getService(Ci.mozIStorageService); michael@0: michael@0: const fxuri = Utils.makeURI("http://getfirefox.com/"); michael@0: const tburi = Utils.makeURI("http://getthunderbird.com/"); michael@0: michael@0: function setPlacesDatabase(aFileName) { michael@0: removePlacesDatabase(); michael@0: _("Copying over places.sqlite."); michael@0: let file = do_get_file(aFileName); michael@0: file.copyTo(gSyncProfile, kDBName); michael@0: } michael@0: michael@0: function removePlacesDatabase() { michael@0: _("Removing places.sqlite."); michael@0: let file = gSyncProfile.clone(); michael@0: file.append(kDBName); michael@0: try { michael@0: file.remove(false); michael@0: } catch (ex) { michael@0: // Windows is awesome. NOT. michael@0: } michael@0: } michael@0: michael@0: Svc.Obs.add("places-shutdown", function () { michael@0: do_timeout(0, removePlacesDatabase); michael@0: }); michael@0: michael@0: michael@0: // Verify initial database state. Function borrowed from places tests. michael@0: add_test(function test_initial_state() { michael@0: _("Verify initial setup: v11 database is available"); michael@0: michael@0: // Mostly sanity checks our starting DB to make sure it's setup as we expect michael@0: // it to be. michael@0: let dbFile = gSyncProfile.clone(); michael@0: dbFile.append(kDBName); michael@0: let db = storageSvc.openUnsharedDatabase(dbFile); michael@0: michael@0: let stmt = db.createStatement("PRAGMA journal_mode"); michael@0: do_check_true(stmt.executeStep()); michael@0: // WAL journal mode should have been unset this database when it was migrated michael@0: // down to v10. michael@0: do_check_neq(stmt.getString(0).toLowerCase(), "wal"); michael@0: stmt.finalize(); michael@0: michael@0: do_check_true(db.indexExists("moz_bookmarks_guid_uniqueindex")); michael@0: do_check_true(db.indexExists("moz_places_guid_uniqueindex")); michael@0: michael@0: // There should be a non-zero amount of bookmarks without a guid. michael@0: stmt = db.createStatement( michael@0: "SELECT COUNT(1) " michael@0: + "FROM moz_bookmarks " michael@0: + "WHERE guid IS NULL " michael@0: ); michael@0: do_check_true(stmt.executeStep()); michael@0: do_check_neq(stmt.getInt32(0), 0); michael@0: stmt.finalize(); michael@0: michael@0: // There should be a non-zero amount of places without a guid. michael@0: stmt = db.createStatement( michael@0: "SELECT COUNT(1) " michael@0: + "FROM moz_places " michael@0: + "WHERE guid IS NULL " michael@0: ); michael@0: do_check_true(stmt.executeStep()); michael@0: do_check_neq(stmt.getInt32(0), 0); michael@0: stmt.finalize(); michael@0: michael@0: // Check our schema version to make sure it is actually at 10. michael@0: do_check_eq(db.schemaVersion, 10); michael@0: michael@0: db.close(); michael@0: michael@0: run_next_test(); michael@0: }); michael@0: michael@0: add_test(function test_history_guids() { michael@0: let engine = new HistoryEngine(Service); michael@0: let store = engine._store; michael@0: michael@0: let places = [ michael@0: { michael@0: uri: fxuri, michael@0: title: "Get Firefox!", michael@0: visits: [{ michael@0: visitDate: Date.now() * 1000, michael@0: transitionType: Ci.nsINavHistoryService.TRANSITION_LINK michael@0: }] michael@0: }, michael@0: { michael@0: uri: tburi, michael@0: title: "Get Thunderbird!", michael@0: visits: [{ michael@0: visitDate: Date.now() * 1000, michael@0: transitionType: Ci.nsINavHistoryService.TRANSITION_LINK michael@0: }] michael@0: } michael@0: ]; michael@0: PlacesUtils.asyncHistory.updatePlaces(places, { michael@0: handleError: function handleError() { michael@0: do_throw("Unexpected error in adding visit."); michael@0: }, michael@0: handleResult: function handleResult() {}, michael@0: handleCompletion: onVisitAdded michael@0: }); michael@0: michael@0: function onVisitAdded() { michael@0: let fxguid = store.GUIDForUri(fxuri, true); michael@0: let tbguid = store.GUIDForUri(tburi, true); michael@0: dump("fxguid: " + fxguid + "\n"); michael@0: dump("tbguid: " + tbguid + "\n"); michael@0: michael@0: _("History: Verify GUIDs are added to the guid column."); michael@0: let connection = PlacesUtils.history michael@0: .QueryInterface(Ci.nsPIPlacesDatabase) michael@0: .DBConnection; michael@0: let stmt = connection.createAsyncStatement( michael@0: "SELECT id FROM moz_places WHERE guid = :guid"); michael@0: michael@0: stmt.params.guid = fxguid; michael@0: let result = Async.querySpinningly(stmt, ["id"]); michael@0: do_check_eq(result.length, 1); michael@0: michael@0: stmt.params.guid = tbguid; michael@0: result = Async.querySpinningly(stmt, ["id"]); michael@0: do_check_eq(result.length, 1); michael@0: stmt.finalize(); michael@0: michael@0: _("History: Verify GUIDs weren't added to annotations."); michael@0: stmt = connection.createAsyncStatement( michael@0: "SELECT a.content AS guid FROM moz_annos a WHERE guid = :guid"); michael@0: michael@0: stmt.params.guid = fxguid; michael@0: result = Async.querySpinningly(stmt, ["guid"]); michael@0: do_check_eq(result.length, 0); michael@0: michael@0: stmt.params.guid = tbguid; michael@0: result = Async.querySpinningly(stmt, ["guid"]); michael@0: do_check_eq(result.length, 0); michael@0: stmt.finalize(); michael@0: michael@0: run_next_test(); michael@0: } michael@0: }); michael@0: michael@0: add_test(function test_bookmark_guids() { michael@0: let engine = new BookmarksEngine(Service); michael@0: let store = engine._store; michael@0: michael@0: let fxid = PlacesUtils.bookmarks.insertBookmark( michael@0: PlacesUtils.bookmarks.toolbarFolder, michael@0: fxuri, michael@0: PlacesUtils.bookmarks.DEFAULT_INDEX, michael@0: "Get Firefox!"); michael@0: let tbid = PlacesUtils.bookmarks.insertBookmark( michael@0: PlacesUtils.bookmarks.toolbarFolder, michael@0: tburi, michael@0: PlacesUtils.bookmarks.DEFAULT_INDEX, michael@0: "Get Thunderbird!"); michael@0: michael@0: let fxguid = store.GUIDForId(fxid); michael@0: let tbguid = store.GUIDForId(tbid); michael@0: michael@0: _("Bookmarks: Verify GUIDs are added to the guid column."); michael@0: let connection = PlacesUtils.history michael@0: .QueryInterface(Ci.nsPIPlacesDatabase) michael@0: .DBConnection; michael@0: let stmt = connection.createAsyncStatement( michael@0: "SELECT id FROM moz_bookmarks WHERE guid = :guid"); michael@0: michael@0: stmt.params.guid = fxguid; michael@0: let result = Async.querySpinningly(stmt, ["id"]); michael@0: do_check_eq(result.length, 1); michael@0: do_check_eq(result[0].id, fxid); michael@0: michael@0: stmt.params.guid = tbguid; michael@0: result = Async.querySpinningly(stmt, ["id"]); michael@0: do_check_eq(result.length, 1); michael@0: do_check_eq(result[0].id, tbid); michael@0: stmt.finalize(); michael@0: michael@0: _("Bookmarks: Verify GUIDs weren't added to annotations."); michael@0: stmt = connection.createAsyncStatement( michael@0: "SELECT a.content AS guid FROM moz_items_annos a WHERE guid = :guid"); michael@0: michael@0: stmt.params.guid = fxguid; michael@0: result = Async.querySpinningly(stmt, ["guid"]); michael@0: do_check_eq(result.length, 0); michael@0: michael@0: stmt.params.guid = tbguid; michael@0: result = Async.querySpinningly(stmt, ["guid"]); michael@0: do_check_eq(result.length, 0); michael@0: stmt.finalize(); michael@0: michael@0: run_next_test(); michael@0: }); michael@0: michael@0: function run_test() { michael@0: setPlacesDatabase("places_v10_from_v11.sqlite"); michael@0: michael@0: run_next_test(); michael@0: }