gecko-dev/toolkit/components/contentprefs/tests/unit/test_contentPrefs.js

471 lines
18 KiB
JavaScript

/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
function run_test() {
//**************************************************************************//
// Database Creation, Schema Migration, and Backup
// Note: in these tests we use createInstance instead of getService
// so we can instantiate the service multiple times and make it run
// its database initialization code each time.
// Create a new database.
{
ContentPrefTest.deleteDatabase();
// Get the service and make sure it has a ready database connection.
let cps = Cc["@mozilla.org/content-pref/service;1"].
createInstance(Ci.nsIContentPrefService);
do_check_true(cps.DBConnection.connectionReady);
cps.DBConnection.close();
}
// Open an existing database.
{
let dbFile = ContentPrefTest.deleteDatabase();
let cps = Cc["@mozilla.org/content-pref/service;1"].
createInstance(Ci.nsIContentPrefService);
cps.DBConnection.close();
do_check_true(dbFile.exists());
// Get the service and make sure it has a ready database connection.
cps = Cc["@mozilla.org/content-pref/service;1"].
createInstance(Ci.nsIContentPrefService);
do_check_true(cps.DBConnection.connectionReady);
cps.DBConnection.close();
}
// Open an empty database.
{
let dbFile = ContentPrefTest.deleteDatabase();
// Create an empty database.
let dbService = Cc["@mozilla.org/storage/service;1"].
getService(Ci.mozIStorageService);
let dbConnection = dbService.openDatabase(dbFile);
do_check_eq(dbConnection.schemaVersion, 0);
dbConnection.close();
do_check_true(dbFile.exists());
// Get the service and make sure it has created the schema.
let cps = Cc["@mozilla.org/content-pref/service;1"].
createInstance(Ci.nsIContentPrefService);
do_check_neq(cps.DBConnection.schemaVersion, 0);
cps.DBConnection.close();
}
// Open a corrupted database.
{
let dbFile = ContentPrefTest.deleteDatabase();
let backupDBFile = ContentPrefTest.deleteBackupDatabase();
// Create a corrupted database.
let foStream = Cc["@mozilla.org/network/file-output-stream;1"].
createInstance(Ci.nsIFileOutputStream);
foStream.init(dbFile, 0x02 | 0x08 | 0x20, 0o666, 0);
let garbageData = "garbage that makes SQLite think the file is corrupted";
foStream.write(garbageData, garbageData.length);
foStream.close();
// Get the service and make sure it backs up and recreates the database.
let cps = Cc["@mozilla.org/content-pref/service;1"].
createInstance(Ci.nsIContentPrefService);
do_check_true(backupDBFile.exists());
do_check_true(cps.DBConnection.connectionReady);
cps.DBConnection.close();
}
// Open a database with a corrupted schema.
{
let dbFile = ContentPrefTest.deleteDatabase();
let backupDBFile = ContentPrefTest.deleteBackupDatabase();
// Create an empty database and set the schema version to a number
// that will trigger a schema migration that will fail.
let dbService = Cc["@mozilla.org/storage/service;1"].
getService(Ci.mozIStorageService);
let dbConnection = dbService.openDatabase(dbFile);
dbConnection.schemaVersion = -1;
dbConnection.close();
do_check_true(dbFile.exists());
// Get the service and make sure it backs up and recreates the database.
let cps = Cc["@mozilla.org/content-pref/service;1"].
createInstance(Ci.nsIContentPrefService);
do_check_true(backupDBFile.exists());
do_check_true(cps.DBConnection.connectionReady);
cps.DBConnection.close();
}
// Now get the content pref service for real for use by the rest of the tests.
let cps = new ContentPrefInstance(null);
var uri = ContentPrefTest.getURI("http://www.example.com/");
// Make sure disk synchronization checking is turned off by default.
var statement = cps.DBConnection.createStatement("PRAGMA synchronous");
statement.executeStep();
do_check_eq(0, statement.getInt32(0));
//**************************************************************************//
// Nonexistent Pref
do_check_eq(cps.getPref(uri, "test.nonexistent.getPref"), undefined);
do_check_eq(cps.setPref(uri, "test.nonexistent.setPref", 5), undefined);
do_check_false(cps.hasPref(uri, "test.nonexistent.hasPref"));
do_check_eq(cps.removePref(uri, "test.nonexistent.removePref"), undefined);
//**************************************************************************//
// Existing Pref
cps.setPref(uri, "test.existing", 5);
// getPref should return the pref value
do_check_eq(cps.getPref(uri, "test.existing"), 5);
// setPref should return undefined and change the value of the pref
do_check_eq(cps.setPref(uri, "test.existing", 6), undefined);
do_check_eq(cps.getPref(uri, "test.existing"), 6);
// hasPref should return true
do_check_true(cps.hasPref(uri, "test.existing"));
// removePref should return undefined and remove the pref
do_check_eq(cps.removePref(uri, "test.existing"), undefined);
do_check_false(cps.hasPref(uri, "test.existing"));
//**************************************************************************//
// Round-Trip Data Integrity
// Make sure pref values remain the same from setPref to getPref.
cps.setPref(uri, "test.data-integrity.integer", 5);
do_check_eq(cps.getPref(uri, "test.data-integrity.integer"), 5);
cps.setPref(uri, "test.data-integrity.float", 5.5);
do_check_eq(cps.getPref(uri, "test.data-integrity.float"), 5.5);
cps.setPref(uri, "test.data-integrity.boolean", true);
do_check_eq(cps.getPref(uri, "test.data-integrity.boolean"), true);
cps.setPref(uri, "test.data-integrity.string", "test");
do_check_eq(cps.getPref(uri, "test.data-integrity.string"), "test");
cps.setPref(uri, "test.data-integrity.null", null);
do_check_eq(cps.getPref(uri, "test.data-integrity.null"), null);
// XXX Test arbitrary binary data.
// Make sure hasPref and removePref work on all data types.
do_check_true(cps.hasPref(uri, "test.data-integrity.integer"));
do_check_true(cps.hasPref(uri, "test.data-integrity.float"));
do_check_true(cps.hasPref(uri, "test.data-integrity.boolean"));
do_check_true(cps.hasPref(uri, "test.data-integrity.string"));
do_check_true(cps.hasPref(uri, "test.data-integrity.null"));
do_check_eq(cps.removePref(uri, "test.data-integrity.integer"), undefined);
do_check_eq(cps.removePref(uri, "test.data-integrity.float"), undefined);
do_check_eq(cps.removePref(uri, "test.data-integrity.boolean"), undefined);
do_check_eq(cps.removePref(uri, "test.data-integrity.string"), undefined);
do_check_eq(cps.removePref(uri, "test.data-integrity.null"), undefined);
do_check_false(cps.hasPref(uri, "test.data-integrity.integer"));
do_check_false(cps.hasPref(uri, "test.data-integrity.float"));
do_check_false(cps.hasPref(uri, "test.data-integrity.boolean"));
do_check_false(cps.hasPref(uri, "test.data-integrity.string"));
do_check_false(cps.hasPref(uri, "test.data-integrity.null"));
//**************************************************************************//
// getPrefs
cps.setPref(uri, "test.getPrefs.a", 1);
cps.setPref(uri, "test.getPrefs.b", 2);
cps.setPref(uri, "test.getPrefs.c", 3);
var prefs = cps.getPrefs(uri);
do_check_true(prefs.hasKey("test.getPrefs.a"));
do_check_eq(prefs.get("test.getPrefs.a"), 1);
do_check_true(prefs.hasKey("test.getPrefs.b"));
do_check_eq(prefs.get("test.getPrefs.b"), 2);
do_check_true(prefs.hasKey("test.getPrefs.c"));
do_check_eq(prefs.get("test.getPrefs.c"), 3);
//**************************************************************************//
// Site-Specificity
// These are all different sites, and setting a pref for one of them
// shouldn't set it for the others.
var uri1 = ContentPrefTest.getURI("http://www.domain1.com/");
var uri2 = ContentPrefTest.getURI("http://foo.domain1.com/");
var uri3 = ContentPrefTest.getURI("http://domain1.com/");
var uri4 = ContentPrefTest.getURI("http://www.domain2.com/");
cps.setPref(uri1, "test.site-specificity.uri1", 5);
do_check_false(cps.hasPref(uri2, "test.site-specificity.uri1"));
do_check_false(cps.hasPref(uri3, "test.site-specificity.uri1"));
do_check_false(cps.hasPref(uri4, "test.site-specificity.uri1"));
cps.setPref(uri2, "test.site-specificity.uri2", 5);
do_check_false(cps.hasPref(uri1, "test.site-specificity.uri2"));
do_check_false(cps.hasPref(uri3, "test.site-specificity.uri2"));
do_check_false(cps.hasPref(uri4, "test.site-specificity.uri2"));
cps.setPref(uri3, "test.site-specificity.uri3", 5);
do_check_false(cps.hasPref(uri1, "test.site-specificity.uri3"));
do_check_false(cps.hasPref(uri2, "test.site-specificity.uri3"));
do_check_false(cps.hasPref(uri4, "test.site-specificity.uri3"));
cps.setPref(uri4, "test.site-specificity.uri4", 5);
do_check_false(cps.hasPref(uri1, "test.site-specificity.uri4"));
do_check_false(cps.hasPref(uri2, "test.site-specificity.uri4"));
do_check_false(cps.hasPref(uri3, "test.site-specificity.uri4"));
//**************************************************************************//
// Observers
var specificObserver = {
interfaces: [Ci.nsIContentPrefObserver, Ci.nsISupports],
QueryInterface: function ContentPrefTest_QueryInterface(iid) {
if (!this.interfaces.some( function(v) { return iid.equals(v) } ))
throw Cr.NS_ERROR_NO_INTERFACE;
return this;
},
numTimesSetCalled: 0,
onContentPrefSet: function specificObserver_onContentPrefSet(group, name, value) {
++this.numTimesSetCalled;
do_check_eq(group, "www.example.com");
do_check_eq(name, "test.observer.1");
do_check_eq(value, "test value");
},
numTimesRemovedCalled: 0,
onContentPrefRemoved: function specificObserver_onContentPrefRemoved(group, name) {
++this.numTimesRemovedCalled;
do_check_eq(group, "www.example.com");
do_check_eq(name, "test.observer.1");
}
};
var genericObserver = {
interfaces: [Ci.nsIContentPrefObserver, Ci.nsISupports],
QueryInterface: function ContentPrefTest_QueryInterface(iid) {
if (!this.interfaces.some( function(v) { return iid.equals(v) } ))
throw Cr.NS_ERROR_NO_INTERFACE;
return this;
},
numTimesSetCalled: 0,
onContentPrefSet: function genericObserver_onContentPrefSet(group, name, value, isPrivate) {
++this.numTimesSetCalled;
do_check_eq(group, "www.example.com");
if (name == "test.observer.private")
do_check_true(isPrivate);
else if (name == "test.observer.normal")
do_check_false(isPrivate);
else if (name != "test.observer.1" && name != "test.observer.2")
do_throw("genericObserver.onContentPrefSet: " +
"name not in (test.observer.(1|2|normal|private))");
do_check_eq(value, "test value");
},
numTimesRemovedCalled: 0,
onContentPrefRemoved: function genericObserver_onContentPrefRemoved(group, name, isPrivate) {
++this.numTimesRemovedCalled;
do_check_eq(group, "www.example.com");
if (name == "test.observer.private")
do_check_true(isPrivate);
else if (name == "test.observer.normal")
do_check_false(isPrivate);
if (name != "test.observer.1" && name != "test.observer.2" &&
name != "test.observer.normal" && name != "test.observer.private") {
do_throw("genericObserver.onContentPrefSet: " +
"name not in (test.observer.(1|2|normal|private))");
}
}
};
// Make sure we can add observers, observers get notified about changes,
// specific observers only get notified about changes to the specific setting,
// and generic observers get notified about changes to all settings.
cps.addObserver("test.observer.1", specificObserver);
cps.addObserver(null, genericObserver);
cps.setPref(uri, "test.observer.1", "test value");
cps.setPref(uri, "test.observer.2", "test value");
cps.removePref(uri, "test.observer.1");
cps.removePref(uri, "test.observer.2");
do_check_eq(specificObserver.numTimesSetCalled, 1);
do_check_eq(genericObserver.numTimesSetCalled, 2);
do_check_eq(specificObserver.numTimesRemovedCalled, 1);
do_check_eq(genericObserver.numTimesRemovedCalled, 2);
// // Make sure information about private context is properly
// // retrieved by the observer.
cps.setPref(uri, "test.observer.private", "test value", {usePrivateBrowsing: true});
cps.setPref(uri, "test.observer.normal", "test value", {usePrivateBrowsing: false});
cps.removePref(uri, "test.observer.private");
cps.removePref(uri, "test.observer.normal");
// Make sure we can remove observers and they don't get notified
// about changes anymore.
cps.removeObserver("test.observer.1", specificObserver);
cps.removeObserver(null, genericObserver);
cps.setPref(uri, "test.observer.1", "test value");
cps.removePref(uri, "test.observer.1", "test value");
do_check_eq(specificObserver.numTimesSetCalled, 1);
do_check_eq(genericObserver.numTimesSetCalled, 4);
do_check_eq(specificObserver.numTimesRemovedCalled, 1);
do_check_eq(genericObserver.numTimesRemovedCalled, 3);
//**************************************************************************//
// Get/Remove Prefs By Name
{
var anObserver = {
interfaces: [Ci.nsIContentPrefObserver, Ci.nsISupports],
QueryInterface: function ContentPrefTest_QueryInterface(iid) {
if (!this.interfaces.some( function(v) { return iid.equals(v) } ))
throw Cr.NS_ERROR_NO_INTERFACE;
return this;
},
onContentPrefSet: function anObserver_onContentPrefSet(group, name, value) {
},
expectedDomains: [],
numTimesRemovedCalled: 0,
onContentPrefRemoved: function anObserver_onContentPrefRemoved(group, name) {
++this.numTimesRemovedCalled;
// remove the domain from the list of expected domains
var index = this.expectedDomains.indexOf(group);
do_check_true(index >= 0);
this.expectedDomains.splice(index, 1);
}
};
let uri1 = ContentPrefTest.getURI("http://www.domain1.com/");
let uri2 = ContentPrefTest.getURI("http://foo.domain1.com/");
let uri3 = ContentPrefTest.getURI("http://domain1.com/");
let uri4 = ContentPrefTest.getURI("http://www.domain2.com/");
cps.setPref(uri1, "test.byname.1", 1);
cps.setPref(uri1, "test.byname.2", 2);
cps.setPref(uri2, "test.byname.1", 4);
cps.setPref(uri3, "test.byname.3", 8);
cps.setPref(uri4, "test.byname.1", 16);
cps.setPref(null, "test.byname.1", 32);
cps.setPref(null, "test.byname.2", false);
function enumerateAndCheck(testName, expectedSum, expectedDomains) {
var prefsByName = cps.getPrefsByName(testName);
var enumerator = prefsByName.enumerator;
var sum = 0;
while (enumerator.hasMoreElements()) {
var property = enumerator.getNext().QueryInterface(Components.interfaces.nsIProperty);
sum += parseInt(property.value);
// remove the domain from the list of expected domains
var index = expectedDomains.indexOf(property.name);
do_check_true(index >= 0);
expectedDomains.splice(index, 1);
}
do_check_eq(sum, expectedSum);
// check all domains have been removed from the array
do_check_eq(expectedDomains.length, 0);
}
enumerateAndCheck("test.byname.1", 53,
["foo.domain1.com", null, "www.domain1.com", "www.domain2.com"]);
enumerateAndCheck("test.byname.2", 2, ["www.domain1.com", null]);
enumerateAndCheck("test.byname.3", 8, ["domain1.com"]);
cps.addObserver("test.byname.1", anObserver);
anObserver.expectedDomains = ["foo.domain1.com", null, "www.domain1.com", "www.domain2.com"];
cps.removePrefsByName("test.byname.1");
do_check_false(cps.hasPref(uri1, "test.byname.1"));
do_check_false(cps.hasPref(uri2, "test.byname.1"));
do_check_false(cps.hasPref(uri3, "test.byname.1"));
do_check_false(cps.hasPref(uri4, "test.byname.1"));
do_check_false(cps.hasPref(null, "test.byname.1"));
do_check_true(cps.hasPref(uri1, "test.byname.2"));
do_check_true(cps.hasPref(uri3, "test.byname.3"));
do_check_eq(anObserver.numTimesRemovedCalled, 4);
do_check_eq(anObserver.expectedDomains.length, 0);
cps.removeObserver("test.byname.1", anObserver);
// Clean up after ourselves
cps.removePref(uri1, "test.byname.2");
cps.removePref(uri3, "test.byname.3");
cps.removePref(null, "test.byname.2");
}
//**************************************************************************//
// Clear Private Data Pref Removal
{
let uri1 = ContentPrefTest.getURI("http://www.domain1.com/");
let uri2 = ContentPrefTest.getURI("http://www.domain2.com/");
let uri3 = ContentPrefTest.getURI("http://www.domain3.com/");
let dbConnection = cps.DBConnection;
let prefCount = dbConnection.createStatement("SELECT COUNT(*) AS count FROM prefs");
let groupCount = dbConnection.createStatement("SELECT COUNT(*) AS count FROM groups");
// Add some prefs for multiple domains.
cps.setPref(uri1, "test.removeAllGroups", 1);
cps.setPref(uri2, "test.removeAllGroups", 2);
cps.setPref(uri3, "test.removeAllGroups", 3);
// Add a global pref.
cps.setPref(null, "test.removeAllGroups", 1);
// Make sure there are some prefs and groups in the database.
prefCount.executeStep();
do_check_true(prefCount.row.count > 0);
prefCount.reset();
groupCount.executeStep();
do_check_true(groupCount.row.count > 0);
groupCount.reset();
// Remove all prefs and groups from the database using the same routine
// the Clear Private Data dialog uses.
cps.removeGroupedPrefs();
// Make sure there are no longer any groups in the database and the only pref
// is the global one.
prefCount.executeStep();
do_check_true(prefCount.row.count == 1);
prefCount.reset();
groupCount.executeStep();
do_check_true(groupCount.row.count == 0);
groupCount.reset();
let globalPref = dbConnection.createStatement("SELECT groupID FROM prefs");
globalPref.executeStep();
do_check_true(globalPref.row.groupID == null);
globalPref.reset();
}
}