summaryrefslogtreecommitdiffstats
path: root/toolkit/components/contentprefs/tests/unit/test_contentPrefs.js
diff options
context:
space:
mode:
Diffstat (limited to 'toolkit/components/contentprefs/tests/unit/test_contentPrefs.js')
-rw-r--r--toolkit/components/contentprefs/tests/unit/test_contentPrefs.js463
1 files changed, 463 insertions, 0 deletions
diff --git a/toolkit/components/contentprefs/tests/unit/test_contentPrefs.js b/toolkit/components/contentprefs/tests/unit/test_contentPrefs.js
new file mode 100644
index 000000000..f7e99ea9d
--- /dev/null
+++ b/toolkit/components/contentprefs/tests/unit/test_contentPrefs.js
@@ -0,0 +1,463 @@
+/* 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.
+ 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.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();
+ }
+}