diff options
Diffstat (limited to 'toolkit/components/contentprefs/tests/unit/test_contentPrefs.js')
-rw-r--r-- | toolkit/components/contentprefs/tests/unit/test_contentPrefs.js | 463 |
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(); + } +} |