gecko/toolkit/components/places/tests/migration/test_current_from_v10.js

369 lines
9.4 KiB
JavaScript

/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
/**
* This file tests migration invariants from schema version 10 to the current
* schema version.
*/
////////////////////////////////////////////////////////////////////////////////
//// Constants
const kGuidAnnotationName = "sync/guid";
const kExpectedAnnotations = 5;
const kExpectedValidGuids = 2;
////////////////////////////////////////////////////////////////////////////////
//// Globals
// Set in test_initial_state to the value in the database.
var gItemGuid = [];
var gItemId = [];
var gPlaceGuid = [];
var gPlaceId = [];
////////////////////////////////////////////////////////////////////////////////
//// Helpers
/**
* Determines if a guid is valid or not.
*
* @return true if it is a valid guid, false otherwise.
*/
function isValidGuid(aGuid)
{
return /^[a-zA-Z0-9\-_]{12}$/.test(aGuid);
}
////////////////////////////////////////////////////////////////////////////////
//// Test Functions
function test_initial_state()
{
// Mostly sanity checks our starting DB to make sure it's setup as we expect
// it to be.
let dbFile = gProfD.clone();
dbFile.append(kDBName);
let db = Services.storage.openUnsharedDatabase(dbFile);
let stmt = db.createStatement("PRAGMA journal_mode");
do_check_true(stmt.executeStep());
// WAL journal mode should not be set on this database.
do_check_neq(stmt.getString(0).toLowerCase(), "wal");
stmt.finalize();
do_check_false(db.indexExists("moz_bookmarks_guid_uniqueindex"));
do_check_false(db.indexExists("moz_places_guid_uniqueindex"));
// There should be five item annotations for a bookmark guid.
stmt = db.createStatement(
"SELECT content AS guid, item_id "
+ "FROM moz_items_annos "
+ "WHERE anno_attribute_id = ( "
+ "SELECT id "
+ "FROM moz_anno_attributes "
+ "WHERE name = :attr_name "
+ ") "
);
stmt.params.attr_name = kGuidAnnotationName;
while (stmt.executeStep()) {
gItemGuid.push(stmt.row.guid);
gItemId.push(stmt.row.item_id)
}
do_check_eq(gItemGuid.length, gItemId.length);
do_check_eq(gItemGuid.length, kExpectedAnnotations);
stmt.finalize();
// There should be five item annotations for a place guid.
stmt = db.createStatement(
"SELECT content AS guid, place_id "
+ "FROM moz_annos "
+ "WHERE anno_attribute_id = ( "
+ "SELECT id "
+ "FROM moz_anno_attributes "
+ "WHERE name = :attr_name "
+ ") "
);
stmt.params.attr_name = kGuidAnnotationName;
while (stmt.executeStep()) {
gPlaceGuid.push(stmt.row.guid);
gPlaceId.push(stmt.row.place_id)
}
do_check_eq(gPlaceGuid.length, gPlaceId.length);
do_check_eq(gPlaceGuid.length, kExpectedAnnotations);
stmt.finalize();
// Check our schema version to make sure it is actually at 10.
do_check_eq(db.schemaVersion, 10);
db.close();
run_next_test();
}
function test_moz_bookmarks_guid_exists()
{
// This will throw if the column does not exist
let stmt = DBConn().createStatement(
"SELECT guid "
+ "FROM moz_bookmarks "
);
stmt.finalize();
run_next_test();
}
function test_bookmark_guids_non_null()
{
// First, sanity check that we have a non-zero amount of bookmarks.
let stmt = DBConn().createStatement(
"SELECT COUNT(1) "
+ "FROM moz_bookmarks "
);
do_check_true(stmt.executeStep());
do_check_neq(stmt.getInt32(0), 0);
stmt.finalize();
// Now, make sure we have no NULL guid entry.
stmt = DBConn().createStatement(
"SELECT guid "
+ "FROM moz_bookmarks "
+ "WHERE guid IS NULL "
);
do_check_false(stmt.executeStep());
stmt.finalize();
run_next_test();
}
function test_bookmark_guid_annotation_imported()
{
// Make sure we have the imported guid; not a newly generated one.
let stmt = DBConn().createStatement(
"SELECT id "
+ "FROM moz_bookmarks "
+ "WHERE guid = :guid "
+ "AND id = :item_id "
);
let validGuids = 0;
let seenGuids = [];
for (let i = 0; i < gItemGuid.length; i++) {
let guid = gItemGuid[i];
stmt.params.guid = guid;
stmt.params.item_id = gItemId[i];
// Check that it is a valid guid that we expect, and that it is not a
// duplicate (which would violate the unique constraint).
let valid = isValidGuid(guid) && seenGuids.indexOf(guid) == -1;
seenGuids.push(guid);
if (valid) {
validGuids++;
do_check_true(stmt.executeStep());
}
else {
do_check_false(stmt.executeStep());
}
stmt.reset();
}
do_check_eq(validGuids, kExpectedValidGuids);
stmt.finalize();
run_next_test();
}
function test_bookmark_guid_annotation_removed()
{
let stmt = DBConn().createStatement(
"SELECT COUNT(1) "
+ "FROM moz_items_annos "
+ "WHERE anno_attribute_id = ( "
+ "SELECT id "
+ "FROM moz_anno_attributes "
+ "WHERE name = :attr_name "
+ ") "
);
stmt.params.attr_name = kGuidAnnotationName;
do_check_true(stmt.executeStep());
do_check_eq(stmt.getInt32(0), 0);
stmt.finalize();
run_next_test();
}
function test_moz_places_guid_exists()
{
// This will throw if the column does not exist
let stmt = DBConn().createStatement(
"SELECT guid "
+ "FROM moz_places "
);
stmt.finalize();
run_next_test();
}
function test_place_guids_non_null()
{
// First, sanity check that we have a non-zero amount of places.
let stmt = DBConn().createStatement(
"SELECT COUNT(1) "
+ "FROM moz_places "
);
do_check_true(stmt.executeStep());
do_check_neq(stmt.getInt32(0), 0);
stmt.finalize();
// Now, make sure we have no NULL guid entry.
stmt = DBConn().createStatement(
"SELECT guid "
+ "FROM moz_places "
+ "WHERE guid IS NULL "
);
do_check_false(stmt.executeStep());
stmt.finalize();
run_next_test();
}
function test_place_guid_annotation_imported()
{
// Make sure we have the imported guid; not a newly generated one.
let stmt = DBConn().createStatement(
"SELECT id "
+ "FROM moz_places "
+ "WHERE guid = :guid "
+ "AND id = :item_id "
);
let validGuids = 0;
let seenGuids = [];
for (let i = 0; i < gPlaceGuid.length; i++) {
let guid = gPlaceGuid[i];
stmt.params.guid = guid;
stmt.params.item_id = gPlaceId[i];
// Check that it is a valid guid that we expect, and that it is not a
// duplicate (which would violate the unique constraint).
let valid = isValidGuid(guid) && seenGuids.indexOf(guid) == -1;
seenGuids.push(guid);
if (valid) {
validGuids++;
do_check_true(stmt.executeStep());
}
else {
do_check_false(stmt.executeStep());
}
stmt.reset();
}
do_check_eq(validGuids, kExpectedValidGuids);
stmt.finalize();
run_next_test();
}
function test_place_guid_annotation_removed()
{
let stmt = DBConn().createStatement(
"SELECT COUNT(1) "
+ "FROM moz_annos "
+ "WHERE anno_attribute_id = ( "
+ "SELECT id "
+ "FROM moz_anno_attributes "
+ "WHERE name = :attr_name "
+ ") "
);
stmt.params.attr_name = kGuidAnnotationName;
do_check_true(stmt.executeStep());
do_check_eq(stmt.getInt32(0), 0);
stmt.finalize();
run_next_test();
}
function test_moz_hosts()
{
// This will throw if the column does not exist
let stmt = DBConn().createStatement(
"SELECT host, frecency, typed "
+ "FROM moz_hosts "
);
stmt.finalize();
// moz_hosts is populated asynchronously, so query asynchronously to serialize
// to that.
// check the number of entries in moz_hosts equals the number of
// unique rev_host in moz_places
stmt = DBConn().createAsyncStatement(
"SELECT ("
+ "SELECT COUNT(host) "
+ "FROM moz_hosts), ("
+ "SELECT COUNT(DISTINCT rev_host) "
+ "FROM moz_places "
+ "WHERE LENGTH(rev_host) > 1)"
);
try {
stmt.executeAsync({
handleResult: function (aResultSet) {
let row = aResult.getNextRow();
let mozPlacesCount = row.getResultByIndex(0);
let mozHostsCount = row.getResultByIndex(1);
do_check_eq(mozPlacesCount, mozHostsCount);
},
handleError: function () {},
handleCompletion: function (aReason) {
do_check_eq(aReason, Ci.mozIStorageStatementCallback.REASON_FINISHED);
run_next_test();
}
});
}
finally {
stmt.finalize();
}
}
function test_final_state()
{
// We open a new database mostly so that we can check that the settings were
// actually saved.
let dbFile = gProfD.clone();
dbFile.append(kDBName);
let db = Services.storage.openUnsharedDatabase(dbFile);
let (stmt = db.createStatement("PRAGMA journal_mode")) {
do_check_true(stmt.executeStep());
// WAL journal mode should be set on this database.
do_check_eq(stmt.getString(0).toLowerCase(), "wal");
stmt.finalize();
}
do_check_true(db.indexExists("moz_bookmarks_guid_uniqueindex"));
do_check_true(db.indexExists("moz_places_guid_uniqueindex"));
do_check_true(db.indexExists("moz_favicons_guid_uniqueindex"));
do_check_eq(db.schemaVersion, CURRENT_SCHEMA_VERSION);
db.close();
run_next_test();
}
////////////////////////////////////////////////////////////////////////////////
//// Test Runner
[
test_initial_state,
test_moz_bookmarks_guid_exists,
test_bookmark_guids_non_null,
test_bookmark_guid_annotation_imported,
test_bookmark_guid_annotation_removed,
test_moz_places_guid_exists,
test_place_guids_non_null,
test_place_guid_annotation_imported,
test_place_guid_annotation_removed,
test_moz_hosts,
test_final_state,
].forEach(add_test);
function run_test()
{
setPlacesDatabase("places_v10.sqlite");
run_next_test();
}