diff options
Diffstat (limited to 'modules/libpref/test/unit')
-rw-r--r-- | modules/libpref/test/unit/data/testPref.js | 6 | ||||
-rw-r--r-- | modules/libpref/test/unit/data/testPrefSticky.js | 2 | ||||
-rw-r--r-- | modules/libpref/test/unit/data/testPrefStickyUser.js | 5 | ||||
-rw-r--r-- | modules/libpref/test/unit/extdata/testExt.js | 2 | ||||
-rw-r--r-- | modules/libpref/test/unit/head_libPrefs.js | 45 | ||||
-rw-r--r-- | modules/libpref/test/unit/test_bug345529.js | 34 | ||||
-rw-r--r-- | modules/libpref/test/unit/test_bug506224.js | 29 | ||||
-rw-r--r-- | modules/libpref/test/unit/test_bug577950.js | 28 | ||||
-rw-r--r-- | modules/libpref/test/unit/test_bug790374.js | 55 | ||||
-rw-r--r-- | modules/libpref/test/unit/test_changeType.js | 63 | ||||
-rw-r--r-- | modules/libpref/test/unit/test_dirtyPrefs.js | 75 | ||||
-rw-r--r-- | modules/libpref/test/unit/test_extprefs.js | 70 | ||||
-rw-r--r-- | modules/libpref/test/unit/test_libPrefs.js | 392 | ||||
-rw-r--r-- | modules/libpref/test/unit/test_stickyprefs.js | 170 | ||||
-rw-r--r-- | modules/libpref/test/unit/test_warnings.js | 69 | ||||
-rw-r--r-- | modules/libpref/test/unit/xpcshell.ini | 18 |
16 files changed, 1063 insertions, 0 deletions
diff --git a/modules/libpref/test/unit/data/testPref.js b/modules/libpref/test/unit/data/testPref.js new file mode 100644 index 000000000..0864e7ce8 --- /dev/null +++ b/modules/libpref/test/unit/data/testPref.js @@ -0,0 +1,6 @@ +user_pref("testPref.bool1", true); +user_pref("testPref.bool2", false); +user_pref("testPref.int1", 23); +user_pref("testPref.int2", -1236); +user_pref("testPref.char1", "_testPref"); +user_pref("testPref.char2", "älskar");
\ No newline at end of file diff --git a/modules/libpref/test/unit/data/testPrefSticky.js b/modules/libpref/test/unit/data/testPrefSticky.js new file mode 100644 index 000000000..69b3165fb --- /dev/null +++ b/modules/libpref/test/unit/data/testPrefSticky.js @@ -0,0 +1,2 @@ +pref("testPref.unsticky.bool", true); +sticky_pref("testPref.sticky.bool", false); diff --git a/modules/libpref/test/unit/data/testPrefStickyUser.js b/modules/libpref/test/unit/data/testPrefStickyUser.js new file mode 100644 index 000000000..0ea090681 --- /dev/null +++ b/modules/libpref/test/unit/data/testPrefStickyUser.js @@ -0,0 +1,5 @@ +// testPrefSticky.js defined this pref as a sticky_pref(). Once a sticky +// pref has been changed, it's written as a user_pref(). +// So this test file reflects that scenario. +// Note the default in testPrefSticky.js is also false. +user_pref("testPref.sticky.bool", false); diff --git a/modules/libpref/test/unit/extdata/testExt.js b/modules/libpref/test/unit/extdata/testExt.js new file mode 100644 index 000000000..17c684969 --- /dev/null +++ b/modules/libpref/test/unit/extdata/testExt.js @@ -0,0 +1,2 @@ +pref("testPref.bool2", true); +pref("testExtPref.bool", true); diff --git a/modules/libpref/test/unit/head_libPrefs.js b/modules/libpref/test/unit/head_libPrefs.js new file mode 100644 index 000000000..b5e763419 --- /dev/null +++ b/modules/libpref/test/unit/head_libPrefs.js @@ -0,0 +1,45 @@ +/* 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/. */ + +const NS_APP_USER_PROFILE_50_DIR = "ProfD"; + +var Ci = Components.interfaces; +var Cc = Components.classes; +var Cr = Components.results; +var Cu = Components.utils; + +function do_check_throws(f, result, stack) +{ + if (!stack) + stack = Components.stack.caller; + + try { + f(); + } catch (exc) { + if (exc.result == result) + return; + do_throw("expected result " + result + ", caught " + exc, stack); + } + do_throw("expected result " + result + ", none thrown", stack); +} + +var dirSvc = Cc["@mozilla.org/file/directory_service;1"].getService(Ci.nsIProperties); + +// Register current test directory as provider for the profile directory. +var provider = { + getFile: function(prop, persistent) { + persistent.value = true; + if (prop == NS_APP_USER_PROFILE_50_DIR) + return dirSvc.get("CurProcD", Ci.nsIFile); + throw Components.Exception("Tried to get test directory '" + prop + "'", Cr.NS_ERROR_FAILURE); + }, + QueryInterface: function(iid) { + if (iid.equals(Ci.nsIDirectoryServiceProvider) || + iid.equals(Ci.nsISupports)) { + return this; + } + throw Cr.NS_ERROR_NO_INTERFACE; + } +}; +dirSvc.QueryInterface(Ci.nsIDirectoryService).registerProvider(provider); diff --git a/modules/libpref/test/unit/test_bug345529.js b/modules/libpref/test/unit/test_bug345529.js new file mode 100644 index 000000000..2e4616a6b --- /dev/null +++ b/modules/libpref/test/unit/test_bug345529.js @@ -0,0 +1,34 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/licenses/publicdomain/ */ + +// Regression test for bug 345529 - crash removing an observer during an +// nsPref:changed notification. +function run_test() { + const Cc = Components.classes; + const Ci = Components.interfaces; + const PREF_NAME = "testPref"; + + var prefs = Cc["@mozilla.org/preferences-service;1"] + .getService(Ci.nsIPrefBranch); + var observer = { + QueryInterface: function QueryInterface(aIID) { + if (aIID.equals(Ci.nsIObserver) || + aIID.equals(Ci.nsISupports)) + return this; + throw Components.results.NS_NOINTERFACE; + }, + + observe: function observe(aSubject, aTopic, aState) { + prefs.removeObserver(PREF_NAME, observer); + } + } + prefs.addObserver(PREF_NAME, observer, false); + + prefs.setCharPref(PREF_NAME, "test0") + // This second call isn't needed on a clean profile: it makes sure + // the observer gets called even if the pref already had the value + // "test0" before this test. + prefs.setCharPref(PREF_NAME, "test1") + + do_check_true(true); +} diff --git a/modules/libpref/test/unit/test_bug506224.js b/modules/libpref/test/unit/test_bug506224.js new file mode 100644 index 000000000..3fb723974 --- /dev/null +++ b/modules/libpref/test/unit/test_bug506224.js @@ -0,0 +1,29 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/licenses/publicdomain/ */ + +function run_test() { + const Cc = Components.classes; + const Ci = Components.interfaces; + const PREF_NAME = "testPref"; + + var ps = Cc["@mozilla.org/preferences-service;1"] + .getService(Ci.nsIPrefService); + var prefs = ps.getDefaultBranch(null); + var userprefs = ps.getBranch(null); + + prefs.setCharPref(PREF_NAME, "test0"); + prefs.lockPref(PREF_NAME); + do_check_eq("test0", userprefs.getCharPref(PREF_NAME)); + do_check_eq(false, userprefs.prefHasUserValue(PREF_NAME)); + + var file = do_get_profile(); + file.append("prefs.js"); + ps.savePrefFile(file); + + prefs.unlockPref(PREF_NAME); + prefs.setCharPref(PREF_NAME, "test1"); + ps.readUserPrefs(file); + + do_check_eq("test1", userprefs.getCharPref(PREF_NAME)); + do_check_eq(false, userprefs.prefHasUserValue(PREF_NAME)); +} diff --git a/modules/libpref/test/unit/test_bug577950.js b/modules/libpref/test/unit/test_bug577950.js new file mode 100644 index 000000000..b4f28e902 --- /dev/null +++ b/modules/libpref/test/unit/test_bug577950.js @@ -0,0 +1,28 @@ +/* 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() { + var ps = Cc["@mozilla.org/preferences-service;1"]. + getService(Ci.nsIPrefService); + + var pb = Cc["@mozilla.org/preferences-service;1"]. + getService(Ci.nsIPrefBranch); + + var observer = { + QueryInterface: function QueryInterface(aIID) { + if (aIID.equals(Ci.nsIObserver) || + aIID.equals(Ci.nsISupports)) + return this; + throw Components.results.NS_NOINTERFACE; + }, + + observe: function observe(aSubject, aTopic, aState) { + // Don't do anything. + } + } + + /* Set the same pref twice. This shouldn't leak. */ + pb.addObserver("UserPref.nonexistent.setIntPref", observer, false); + pb.addObserver("UserPref.nonexistent.setIntPref", observer, false); +} diff --git a/modules/libpref/test/unit/test_bug790374.js b/modules/libpref/test/unit/test_bug790374.js new file mode 100644 index 000000000..64ca620ed --- /dev/null +++ b/modules/libpref/test/unit/test_bug790374.js @@ -0,0 +1,55 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/licenses/publicdomain/ */ + +function run_test() { + const Cc = Components.classes; + const Ci = Components.interfaces; + const Cr = Components.results; + const PREF_NAME = "testPref"; + + var ps = Cc["@mozilla.org/preferences-service;1"] + .getService(Ci.nsIPrefService); + var prefs = ps.getDefaultBranch(null); + var userprefs = ps.getBranch(null); + + /* First, test to make sure we can parse a float from a string properly. */ + prefs.setCharPref(PREF_NAME, "9.674"); + prefs.lockPref(PREF_NAME); + var myFloat = 9.674; + var fudge = 0.001; + var floatPref = userprefs.getFloatPref(PREF_NAME); + do_check_true(myFloat+fudge >= floatPref); + do_check_true(myFloat-fudge <= floatPref); + + /* Now test some failure conditions. */ + prefs.unlockPref(PREF_NAME); + prefs.setCharPref(PREF_NAME, ""); + prefs.lockPref(PREF_NAME); + do_check_throws(function() { + userprefs.getFloatPref(PREF_NAME); + }, Cr.NS_ERROR_ILLEGAL_VALUE); + + prefs.unlockPref(PREF_NAME); + prefs.setCharPref(PREF_NAME, "18.0a1"); + prefs.lockPref(PREF_NAME); + + do_check_throws(function() { + userprefs.getFloatPref(PREF_NAME); + }, Cr.NS_ERROR_ILLEGAL_VALUE); + + prefs.unlockPref(PREF_NAME); + prefs.setCharPref(PREF_NAME, "09.25.2012"); + prefs.lockPref(PREF_NAME); + + do_check_throws(function() { + userprefs.getFloatPref(PREF_NAME); + }, Cr.NS_ERROR_ILLEGAL_VALUE); + + prefs.unlockPref(PREF_NAME); + prefs.setCharPref(PREF_NAME, "aString"); + prefs.lockPref(PREF_NAME); + + do_check_throws(function() { + userprefs.getFloatPref(PREF_NAME); + }, Cr.NS_ERROR_ILLEGAL_VALUE); +} diff --git a/modules/libpref/test/unit/test_changeType.js b/modules/libpref/test/unit/test_changeType.js new file mode 100644 index 000000000..573d561a4 --- /dev/null +++ b/modules/libpref/test/unit/test_changeType.js @@ -0,0 +1,63 @@ +/* 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/. */ + +/* Tests for changing the type of a preference (bug 985998) */ + +const PREF_INVALID = 0; +const PREF_BOOL = 128; +const PREF_INT = 64; +const PREF_STRING = 32; + +function run_test() { + + var ps = Cc["@mozilla.org/preferences-service;1"]. + getService(Ci.nsIPrefService); + + let defaultBranch = ps.getDefaultBranch(""); + let userBranch = ps.getBranch(""); + + //**************************************************************************// + // Can't change the type of prefs that have default values + + defaultBranch.setBoolPref("TypeTest.existing.bool", true); + defaultBranch.setIntPref("TypeTest.existing.int", 23); + defaultBranch.setCharPref("TypeTest.existing.char", "hey"); + + // The user branch reads back the expected default + do_check_eq(userBranch.getBoolPref("TypeTest.existing.bool"), true); + do_check_eq(userBranch.getIntPref("TypeTest.existing.int"), 23); + do_check_eq(userBranch.getCharPref("TypeTest.existing.char"), "hey"); + + // All the combinations of attempted type changes + do_check_throws(function() { + userBranch.setCharPref("TypeTest.existing.bool", "boo"); }, Cr.NS_ERROR_UNEXPECTED); + do_check_throws(function() { + userBranch.setIntPref("TypeTest.existing.bool", 5); }, Cr.NS_ERROR_UNEXPECTED); + do_check_throws(function() { + userBranch.setCharPref("TypeTest.existing.int", "boo"); }, Cr.NS_ERROR_UNEXPECTED); + do_check_throws(function() { + userBranch.setBoolPref("TypeTest.existing.int", true); }, Cr.NS_ERROR_UNEXPECTED); + do_check_throws(function() { + userBranch.setBoolPref("TypeTest.existing.char", true); }, Cr.NS_ERROR_UNEXPECTED); + do_check_throws(function() { + userBranch.setIntPref("TypeTest.existing.char", 6); }, Cr.NS_ERROR_UNEXPECTED); + + + //**************************************************************************// + // Prefs that don't have default values can mutate + let pref = "TypeTest.user"; + userBranch.setBoolPref(pref, true); + userBranch.setCharPref(pref, "yay"); + do_check_eq(userBranch.getCharPref(pref), "yay"); + userBranch.setIntPref(pref, 7); + do_check_eq(userBranch.getIntPref(pref), 7); + userBranch.setBoolPref(pref, false); + do_check_eq(userBranch.getBoolPref(pref), false); + userBranch.setIntPref(pref, 8); + do_check_eq(userBranch.getIntPref(pref), 8); + userBranch.setCharPref(pref, "whee"); + do_check_eq(userBranch.getCharPref(pref), "whee"); + userBranch.setBoolPref(pref, true); + do_check_eq(userBranch.getBoolPref(pref), true); +} diff --git a/modules/libpref/test/unit/test_dirtyPrefs.js b/modules/libpref/test/unit/test_dirtyPrefs.js new file mode 100644 index 000000000..361171616 --- /dev/null +++ b/modules/libpref/test/unit/test_dirtyPrefs.js @@ -0,0 +1,75 @@ +/* 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/. */ + +/* Tests for handling of the preferences 'dirty' flag (bug 985998) */ + +const PREF_INVALID = 0; +const PREF_BOOL = 128; +const PREF_INT = 64; +const PREF_STRING = 32; + +function run_test() { + + var ps = Cc["@mozilla.org/preferences-service;1"]. + getService(Ci.nsIPrefService); + + let defaultBranch = ps.getDefaultBranch(""); + let userBranch = ps.getBranch(""); + + let prefFile = do_get_profile(); + prefFile.append("prefs.js"); + + //**************************************************************************// + // prefs are not dirty after a write + ps.savePrefFile(prefFile); + do_check_false(ps.dirty); + + // set a new a user value, we should become dirty + userBranch.setBoolPref("DirtyTest.new.bool", true); + do_check_true(ps.dirty); + ps.savePrefFile(prefFile); + // Overwrite a pref with the same value => not dirty + userBranch.setBoolPref("DirtyTest.new.bool", true); + do_check_false(ps.dirty); + + // Repeat for the other two types + userBranch.setIntPref("DirtyTest.new.int", 1); + do_check_true(ps.dirty); + ps.savePrefFile(prefFile); + // Overwrite a pref with the same value => not dirty + userBranch.setIntPref("DirtyTest.new.int", 1); + do_check_false(ps.dirty); + + userBranch.setCharPref("DirtyTest.new.char", "oop"); + do_check_true(ps.dirty); + ps.savePrefFile(prefFile); + // Overwrite a pref with the same value => not dirty + userBranch.setCharPref("DirtyTest.new.char", "oop"); + do_check_false(ps.dirty); + + // change *type* of a user value -> dirty + userBranch.setBoolPref("DirtyTest.new.char", false); + do_check_true(ps.dirty); + ps.savePrefFile(prefFile); + + // Set a default pref => not dirty (defaults don't go into prefs.js) + defaultBranch.setBoolPref("DirtyTest.existing.bool", true); + do_check_false(ps.dirty); + // Fail to change type of a pref with default value -> not dirty + do_check_throws(function() { + userBranch.setCharPref("DirtyTest.existing.bool", "boo"); }, Cr.NS_ERROR_UNEXPECTED); + do_check_false(ps.dirty); + + // Set user value same as default, not dirty + userBranch.setBoolPref("DirtyTest.existing.bool", true); + do_check_false(ps.dirty); + // User value different from default, dirty + userBranch.setBoolPref("DirtyTest.existing.bool", false); + do_check_true(ps.dirty); + ps.savePrefFile(prefFile); + // Back to default value, dirty again + userBranch.setBoolPref("DirtyTest.existing.bool", true); + do_check_true(ps.dirty); + ps.savePrefFile(prefFile); +} diff --git a/modules/libpref/test/unit/test_extprefs.js b/modules/libpref/test/unit/test_extprefs.js new file mode 100644 index 000000000..37f8de167 --- /dev/null +++ b/modules/libpref/test/unit/test_extprefs.js @@ -0,0 +1,70 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/licenses/publicdomain/ */ + +Components.utils.import("resource://gre/modules/XPCOMUtils.jsm"); +Components.utils.import("resource://gre/modules/Services.jsm"); + +// The profile directory is already set up in the head_ files. + +function arrayenumerator(a) +{ + return { + i_: 0, + QueryInterface: XPCOMUtils.generateQI([Ci.nsISimpleEnumerator]), + hasMoreElements: function ae_hasMoreElements() { + return this.i_ < a.length; + }, + getNext: function ae_getNext() { + return a[this.i_++]; + } + }; +} + +function run_test() { + var ps = Cc["@mozilla.org/preferences-service;1"]. + getService(Ci.nsIPrefService).QueryInterface(Ci.nsIPrefBranch); + + var extprefs = [do_get_file("extdata")]; + + var extProvider = { + QueryInterface: XPCOMUtils.generateQI([Ci.nsIDirectoryServiceProvider, + Ci.nsIDirectoryServiceProvider2]), + getFile: function ep_getFile() { + throw Cr.NS_ERROR_FAILURE; + }, + + getFiles: function ep_getFiles(key) { + if (key != "ExtPrefDL") + throw Cr.NS_ERROR_FAILURE; + + return arrayenumerator(extprefs); + } + }; + + let prefFile = do_get_file("data/testPref.js"); + + do_check_throws(function() { + ps.getBoolPref("testExtPref.bool"); + }, Cr.NS_ERROR_UNEXPECTED); + do_check_throws(function() { + ps.getBoolPref("testPref.bool1"); + }, Cr.NS_ERROR_UNEXPECTED); + + ps.readUserPrefs(prefFile); + + do_check_true(ps.getBoolPref("testPref.bool1")); + ps.setBoolPref("testPref.bool1", false); + do_check_false(ps.getBoolPref("testPref.bool1")); + + dirSvc.registerProvider(extProvider); + Services.obs.notifyObservers(null, "load-extension-defaults", null); + + // The extension default should be available. + do_check_true(ps.getBoolPref("testExtPref.bool")); + + // The extension default should not override existing user prefs + do_check_false(ps.getBoolPref("testPref.bool2")); + + // The extension default should not modify existing set values + do_check_false(ps.getBoolPref("testPref.bool1")); +} diff --git a/modules/libpref/test/unit/test_libPrefs.js b/modules/libpref/test/unit/test_libPrefs.js new file mode 100644 index 000000000..be9c629e0 --- /dev/null +++ b/modules/libpref/test/unit/test_libPrefs.js @@ -0,0 +1,392 @@ +/* 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/. */ + +const PREF_INVALID = 0; +const PREF_BOOL = 128; +const PREF_INT = 64; +const PREF_STRING = 32; + +const MAX_PREF_LENGTH = 1 * 1024 * 1024; + +function makeList(a) +{ + var o = {}; + for(var i=0; i<a.length; i++) + { + o[a[i]] = ''; + } + return o; +} + +function run_test() { + + var ps = Cc["@mozilla.org/preferences-service;1"]. + getService(Ci.nsIPrefService); + + var pb2= Cc["@mozilla.org/preferences-service;1"]. + getService(Ci.nsIPrefBranch); + + var pb = Cc["@mozilla.org/preferences-service;1"]. + getService(Ci.nsIPrefBranch); + + //**************************************************************************// + // Nullsafety + + do_check_throws(function() { + pb.getPrefType(null); }, Cr.NS_ERROR_INVALID_ARG); + do_check_throws(function() { + pb.getBoolPref(null); }, Cr.NS_ERROR_INVALID_ARG); + do_check_throws(function() { + pb.setBoolPref(null, false); }, Cr.NS_ERROR_INVALID_ARG); + do_check_throws(function() { + pb.getIntPref(null); }, Cr.NS_ERROR_INVALID_ARG); + do_check_throws(function() { + pb.setIntPref(null, 0); }, Cr.NS_ERROR_INVALID_ARG); + do_check_throws(function() { + pb.getCharPref(null); }, Cr.NS_ERROR_INVALID_ARG); + do_check_throws(function() { + pb.setCharPref(null, null); }, Cr.NS_ERROR_INVALID_ARG); + do_check_throws(function() { + pb.getComplexValue(null, Components.interfaces.nsISupportsString); }, Cr.NS_ERROR_INVALID_ARG); + do_check_throws(function() { + pb.setComplexValue(null, Components.interfaces.nsISupportsString, pb); }, Cr.NS_ERROR_INVALID_ARG); + do_check_throws(function() { + pb.clearUserPref(null); }, Cr.NS_ERROR_INVALID_ARG); + do_check_throws(function() { + pb.prefHasUserValue(null); }, Cr.NS_ERROR_INVALID_ARG); + do_check_throws(function() { + pb.lockPref(null); }, Cr.NS_ERROR_INVALID_ARG); + do_check_throws(function() { + pb.prefIsLocked(null); }, Cr.NS_ERROR_INVALID_ARG); + do_check_throws(function() { + pb.unlockPref(null); }, Cr.NS_ERROR_INVALID_ARG); + do_check_throws(function() { + pb.deleteBranch(null); }, Cr.NS_ERROR_INVALID_ARG); + do_check_throws(function() { + pb.getChildList(null); }, Cr.NS_ERROR_INVALID_ARG); + + //**************************************************************************// + // Nonexisting user preferences + + do_check_eq(pb.prefHasUserValue("UserPref.nonexistent.hasUserValue"), false); + pb.clearUserPref("UserPref.nonexistent.clearUserPref"); // shouldn't throw + do_check_eq(pb.getPrefType("UserPref.nonexistent.getPrefType"), PREF_INVALID); + do_check_eq(pb.root, ""); + + // bool... + do_check_throws(function() { + pb.getBoolPref("UserPref.nonexistent.getBoolPref");}, Cr.NS_ERROR_UNEXPECTED); + pb.setBoolPref("UserPref.nonexistent.setBoolPref", false); + do_check_eq(pb.getBoolPref("UserPref.nonexistent.setBoolPref"), false); + + // int... + do_check_throws(function() { + pb.getIntPref("UserPref.nonexistent.getIntPref");}, Cr.NS_ERROR_UNEXPECTED); + pb.setIntPref("UserPref.nonexistent.setIntPref", 5); + do_check_eq(pb.getIntPref("UserPref.nonexistent.setIntPref"), 5); + + // char + do_check_throws(function() { + pb.getCharPref("UserPref.nonexistent.getCharPref");}, Cr.NS_ERROR_UNEXPECTED); + pb.setCharPref("UserPref.nonexistent.setCharPref", "_test"); + do_check_eq(pb.getCharPref("UserPref.nonexistent.setCharPref"), "_test"); + + //**************************************************************************// + // Existing user Prefs and data integrity test (round-trip match) + + pb.setBoolPref("UserPref.existing.bool", true); + pb.setIntPref("UserPref.existing.int", 23); + pb.setCharPref("UserPref.existing.char", "hey"); + + // getPref should return the pref value + do_check_eq(pb.getBoolPref("UserPref.existing.bool"), true); + do_check_eq(pb.getIntPref("UserPref.existing.int"), 23); + do_check_eq(pb.getCharPref("UserPref.existing.char"), "hey"); + + // setPref should not complain and should change the value of the pref + pb.setBoolPref("UserPref.existing.bool", false); + do_check_eq(pb.getBoolPref("UserPref.existing.bool"), false); + pb.setIntPref("UserPref.existing.int", 24); + do_check_eq(pb.getIntPref("UserPref.existing.int"), 24); + pb.setCharPref("UserPref.existing.char", "hej då!"); + do_check_eq(pb.getCharPref("UserPref.existing.char"), "hej då!"); + + // prefHasUserValue should return true now + do_check_true(pb.prefHasUserValue("UserPref.existing.bool")); + do_check_true(pb.prefHasUserValue("UserPref.existing.int")); + do_check_true(pb.prefHasUserValue("UserPref.existing.char")); + + // clearUserPref should remove the pref + pb.clearUserPref("UserPref.existing.bool"); + do_check_false(pb.prefHasUserValue("UserPref.existing.bool")); + pb.clearUserPref("UserPref.existing.int"); + do_check_false(pb.prefHasUserValue("UserPref.existing.int")); + pb.clearUserPref("UserPref.existing.char"); + do_check_false(pb.prefHasUserValue("UserPref.existing.char")); + + //**************************************************************************// + // Large value test + + let largeStr = new Array(MAX_PREF_LENGTH + 1).join('x'); + pb.setCharPref("UserPref.large.char", largeStr); + largeStr += 'x'; + do_check_throws(function() { + pb.setCharPref("UserPref.large.char", largeStr); }, Cr.NS_ERROR_ILLEGAL_VALUE); + + //**************************************************************************// + // getPrefType test + + // bool... + pb.setBoolPref("UserPref.getPrefType.bool", true); + do_check_eq(pb.getPrefType("UserPref.getPrefType.bool"), PREF_BOOL); + + // int... + pb.setIntPref("UserPref.getPrefType.int", -234); + do_check_eq(pb.getPrefType("UserPref.getPrefType.int"), PREF_INT); + + // char... + pb.setCharPref("UserPref.getPrefType.char", "testing1..2"); + do_check_eq(pb.getPrefType("UserPref.getPrefType.char"), PREF_STRING); + + //**************************************************************************// + // getBranch tests + + do_check_eq(ps.root, ""); + + // bool ... + pb.setBoolPref("UserPref.root.boolPref", true); + let pb_1 = ps.getBranch("UserPref.root."); + do_check_eq(pb_1.getBoolPref("boolPref"), true); + let pb_2 = ps.getBranch("UserPref.root.boolPref"); + do_check_eq(pb_2.getBoolPref(""), true); + pb_2.setBoolPref(".anotherPref", false); + let pb_3 = ps.getBranch("UserPref.root.boolPre"); + do_check_eq(pb_3.getBoolPref("f.anotherPref"), false); + + // int ... + pb.setIntPref("UserPref.root.intPref", 23); + pb_1 = ps.getBranch("UserPref.root."); + do_check_eq(pb_1.getIntPref("intPref"), 23); + pb_2 = ps.getBranch("UserPref.root.intPref"); + do_check_eq(pb_2.getIntPref(""), 23); + pb_2.setIntPref(".anotherPref", 69); + pb_3 = ps.getBranch("UserPref.root.intPre"); + do_check_eq(pb_3.getIntPref("f.anotherPref"), 69); + + // char... + pb.setCharPref("UserPref.root.charPref", "_char"); + pb_1 = ps.getBranch("UserPref.root."); + do_check_eq(pb_1.getCharPref("charPref"), "_char"); + pb_2 = ps.getBranch("UserPref.root.charPref"); + do_check_eq(pb_2.getCharPref(""), "_char"); + pb_2.setCharPref(".anotherPref", "_another"); + pb_3 = ps.getBranch("UserPref.root.charPre"); + do_check_eq(pb_3.getCharPref("f.anotherPref"), "_another"); + + //**************************************************************************// + // getChildlist tests + + // get an already set prefBranch + pb1 = ps.getBranch("UserPref.root."); + let prefList = pb1.getChildList(""); + do_check_eq(prefList.length, 6); + + // check for specific prefs in the array : the order is not important + do_check_true("boolPref" in makeList(prefList)); + do_check_true("intPref" in makeList(prefList)); + do_check_true("charPref" in makeList(prefList)); + do_check_true("boolPref.anotherPref" in makeList(prefList)); + do_check_true("intPref.anotherPref" in makeList(prefList)); + do_check_true("charPref.anotherPref" in makeList(prefList)); + + //**************************************************************************// + // Default branch tests + + // bool... + pb1 = ps.getDefaultBranch(""); + pb1.setBoolPref("DefaultPref.bool", true); + do_check_eq(pb1.getBoolPref("DefaultPref.bool"), true); + do_check_false(pb1.prefHasUserValue("DefaultPref.bool")); + ps.setBoolPref("DefaultPref.bool", false); + do_check_true(pb1.prefHasUserValue("DefaultPref.bool")); + do_check_eq(ps.getBoolPref("DefaultPref.bool"), false); + + // int... + pb1 = ps.getDefaultBranch(""); + pb1.setIntPref("DefaultPref.int", 100); + do_check_eq(pb1.getIntPref("DefaultPref.int"), 100); + do_check_false(pb1.prefHasUserValue("DefaultPref.int")); + ps.setIntPref("DefaultPref.int", 50); + do_check_true(pb1.prefHasUserValue("DefaultPref.int")); + do_check_eq(ps.getIntPref("DefaultPref.int"), 50); + + // char... + pb1 = ps.getDefaultBranch(""); + pb1.setCharPref("DefaultPref.char", "_default"); + do_check_eq(pb1.getCharPref("DefaultPref.char"), "_default"); + do_check_false(pb1.prefHasUserValue("DefaultPref.char")); + ps.setCharPref("DefaultPref.char", "_user"); + do_check_true(pb1.prefHasUserValue("DefaultPref.char")); + do_check_eq(ps.getCharPref("DefaultPref.char"), "_user"); + + //**************************************************************************// + // pref Locking/Unlocking tests + + // locking and unlocking a nonexistent pref should throw + do_check_throws(function() { + ps.lockPref("DefaultPref.nonexistent");}, Cr.NS_ERROR_UNEXPECTED); + do_check_throws(function() { + ps.unlockPref("DefaultPref.nonexistent");}, Cr.NS_ERROR_UNEXPECTED); + + // getting a locked pref branch should return the "default" value + do_check_false(ps.prefIsLocked("DefaultPref.char")); + ps.lockPref("DefaultPref.char"); + do_check_eq(ps.getCharPref("DefaultPref.char"), "_default"); + do_check_true(ps.prefIsLocked("DefaultPref.char")); + + // getting an unlocked pref branch should return the "user" value + ps.unlockPref("DefaultPref.char"); + do_check_eq(ps.getCharPref("DefaultPref.char"), "_user"); + do_check_false(ps.prefIsLocked("DefaultPref.char")); + + // setting the "default" value to a user pref branch should + // make prefHasUserValue return false (documented behavior) + ps.setCharPref("DefaultPref.char", "_default"); + do_check_false(pb1.prefHasUserValue("DefaultPref.char")); + + // unlocking and locking multiple times shouldn't throw + ps.unlockPref("DefaultPref.char"); + ps.lockPref("DefaultPref.char"); + ps.lockPref("DefaultPref.char"); + + //**************************************************************************// + // resetBranch test + + // NOT IMPLEMENTED YET in module/libpref. So we're not testing ! + // uncomment the following if resetBranch ever gets implemented. + /*ps.resetBranch("DefaultPref"); + do_check_eq(ps.getBoolPref("DefaultPref.bool"), true); + do_check_eq(ps.getIntPref("DefaultPref.int"), 100); + do_check_eq(ps.getCharPref("DefaultPref.char"), "_default");*/ + + //**************************************************************************// + // deleteBranch tests + + // TODO : Really, this should throw!, by documentation. + // do_check_throws(function() { + // ps.deleteBranch("UserPref.nonexistent.deleteBranch");}, Cr.NS_ERROR_UNEXPECTED); + + ps.deleteBranch("DefaultPref"); + pb = ps.getBranch("DefaultPref"); + pb1 = ps.getDefaultBranch("DefaultPref"); + + // getting prefs on deleted user branches should throw + do_check_throws(function() { + pb.getBoolPref("DefaultPref.bool");}, Cr.NS_ERROR_UNEXPECTED); + do_check_throws(function() { + pb.getIntPref("DefaultPref.int");}, Cr.NS_ERROR_UNEXPECTED); + do_check_throws(function() { + pb.getCharPref("DefaultPref.char");}, Cr.NS_ERROR_UNEXPECTED); + + // getting prefs on deleted default branches should throw + do_check_throws(function() { + pb1.getBoolPref("DefaultPref.bool");}, Cr.NS_ERROR_UNEXPECTED); + do_check_throws(function() { + pb1.getIntPref("DefaultPref.int");}, Cr.NS_ERROR_UNEXPECTED); + do_check_throws(function() { + pb1.getCharPref("DefaultPref.char");}, Cr.NS_ERROR_UNEXPECTED); + + //**************************************************************************// + // savePrefFile & readPrefFile tests + + // set some prefs + ps.setBoolPref("ReadPref.bool", true); + ps.setIntPref("ReadPref.int", 230); + ps.setCharPref("ReadPref.char", "hello"); + + // save those prefs in a file + let savePrefFile = do_get_cwd(); + savePrefFile.append("data"); + savePrefFile.append("savePref.js"); + if (savePrefFile.exists()) + savePrefFile.remove(false); + savePrefFile.create(Ci.nsIFile.NORMAL_FILE_TYPE, 0o666); + ps.savePrefFile(savePrefFile); + ps.resetPrefs(); + + // load a preexisting pref file + let prefFile = do_get_file("data/testPref.js"); + ps.readUserPrefs(prefFile); + + // former prefs should have been replaced/lost + do_check_throws(function() { + do_check_eq(pb.getBoolPref("ReadPref.bool"));}, Cr.NS_ERROR_UNEXPECTED); + do_check_throws(function() { + do_check_eq(pb.getIntPref("ReadPref.int"));}, Cr.NS_ERROR_UNEXPECTED); + do_check_throws(function() { + do_check_eq(pb.getCharPref("ReadPref.char"));}, Cr.NS_ERROR_UNEXPECTED); + + // loaded prefs should read ok. + pb = ps.getBranch("testPref."); + do_check_eq(pb.getBoolPref("bool1"), true); + do_check_eq(pb.getBoolPref("bool2"), false); + do_check_eq(pb.getIntPref("int1"), 23); + do_check_eq(pb.getIntPref("int2"), -1236); + do_check_eq(pb.getCharPref("char1"), "_testPref"); + do_check_eq(pb.getCharPref("char2"), "älskar"); + + // loading our former savePrefFile should allow us to read former prefs + ps.readUserPrefs(savePrefFile); + // cleanup the file now we don't need it + savePrefFile.remove(false); + do_check_eq(ps.getBoolPref("ReadPref.bool"), true); + do_check_eq(ps.getIntPref("ReadPref.int"), 230); + do_check_eq(ps.getCharPref("ReadPref.char"), "hello"); + + // ... and still be able to access "prior-to-readUserPrefs" preferences + do_check_eq(pb.getBoolPref("bool1"), true); + do_check_eq(pb.getBoolPref("bool2"), false); + do_check_eq(pb.getIntPref("int1"), 23); + + //**************************************************************************// + // preference Observers + + // an observer... + var observer = { + QueryInterface: function QueryInterface(aIID) { + if (aIID.equals(Ci.nsIObserver) || + aIID.equals(Ci.nsISupports)) + return this; + throw Components.results.NS_NOINTERFACE; + }, + + observe: function observe(aSubject, aTopic, aState) { + do_check_eq(aTopic, "nsPref:changed"); + do_check_eq(aState, "ReadPref.int"); + do_check_eq(ps.getIntPref(aState), 76); + ps.removeObserver("ReadPref.int", this); + + // notification received, we may go on... + do_test_finished(); + } + } + + pb2.addObserver("ReadPref.int", observer, false); + ps.setIntPref("ReadPref.int", 76); + + // test will continue upon notification... + do_test_pending(); + + // removed observer should not fire + pb2.removeObserver("ReadPref.int", observer); + ps.setIntPref("ReadPref.int", 32); + + // let's test observers once more with a non-root prefbranch + pb2.getBranch("ReadPref."); + pb2.addObserver("int", observer, false); + ps.setIntPref("ReadPref.int", 76); + + // test will complete upon notification... + do_test_pending(); +} diff --git a/modules/libpref/test/unit/test_stickyprefs.js b/modules/libpref/test/unit/test_stickyprefs.js new file mode 100644 index 000000000..c2c5a7c4b --- /dev/null +++ b/modules/libpref/test/unit/test_stickyprefs.js @@ -0,0 +1,170 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/licenses/publicdomain/ */ + +Components.utils.import("resource://gre/modules/XPCOMUtils.jsm"); +Components.utils.import("resource://gre/modules/Services.jsm"); + +const ps = Services.prefs; + +// Once we fetch the profile directory the xpcshell test harness will send +// a profile-before-change notification at shutdown. This causes the prefs +// service to flush the prefs file - and the prefs file it uses ends up being +// testPrefSticky*.js in the test dir. This upsets things in confusing ways :) +// We avoid this by ensuring our "temp" prefs.js is the current prefs file. +do_get_profile(); +do_register_cleanup(saveAndReload); + +// A little helper to reset the service and load some pref files +function resetAndLoad(filenames) { + ps.resetPrefs(); + for (let filename of filenames) { + ps.readUserPrefs(do_get_file(filename)); + } +} + +// A little helper that saves the current state to a file in the profile +// dir, then resets the service and re-reads the file it just saved. +// Used to test what gets actually written - things the pref service decided +// not to write don't exist at all after this call. +function saveAndReload() { + let file = do_get_profile(); + file.append("prefs.js"); + ps.savePrefFile(file); + + // Now reset the pref service and re-read what we saved. + ps.resetPrefs(); + ps.readUserPrefs(file); +} + +function run_test() { + run_next_test(); +} + +// A sticky pref should not be written if the value is unchanged. +add_test(function notWrittenWhenUnchanged() { + resetAndLoad(["data/testPrefSticky.js"]); + Assert.strictEqual(ps.getBoolPref("testPref.unsticky.bool"), true); + Assert.strictEqual(ps.getBoolPref("testPref.sticky.bool"), false); + + // write prefs - but we haven't changed the sticky one, so it shouldn't be written. + saveAndReload(); + // sticky should not have been written to the new file. + try { + ps.getBoolPref("testPref.sticky.bool"); + Assert.ok(false, "expected failure reading this pref"); + } catch (ex) { + Assert.ok(ex, "exception reading regular pref"); + } + run_next_test(); +}); + +// Loading a sticky_pref then a user_pref for the same pref means it should +// always be written. +add_test(function writtenOnceLoadedWithoutChange() { + // Load the same pref file *as well as* a pref file that has a user_pref for + // our sticky with the default value. It should be re-written without us + // touching it. + resetAndLoad(["data/testPrefSticky.js", "data/testPrefStickyUser.js"]); + // reset and re-read what we just wrote - it should be written. + saveAndReload(); + Assert.strictEqual(ps.getBoolPref("testPref.sticky.bool"), false, + "user_pref was written with default value"); + run_next_test(); +}); + +// If a sticky pref is explicicitly changed, even to the default, it is written. +add_test(function writtenOnceLoadedWithChangeNonDefault() { + // Load the same pref file *as well as* a pref file that has a user_pref for + // our sticky - then change the pref. It should be written. + resetAndLoad(["data/testPrefSticky.js", "data/testPrefStickyUser.js"]); + // Set a new val and check we wrote it. + ps.setBoolPref("testPref.sticky.bool", false); + saveAndReload(); + Assert.strictEqual(ps.getBoolPref("testPref.sticky.bool"), false, + "user_pref was written with custom value"); + run_next_test(); +}); + +// If a sticky pref is changed to the non-default value, it is written. +add_test(function writtenOnceLoadedWithChangeNonDefault() { + // Load the same pref file *as well as* a pref file that has a user_pref for + // our sticky - then change the pref. It should be written. + resetAndLoad(["data/testPrefSticky.js", "data/testPrefStickyUser.js"]); + // Set a new val and check we wrote it. + ps.setBoolPref("testPref.sticky.bool", true); + saveAndReload(); + Assert.strictEqual(ps.getBoolPref("testPref.sticky.bool"), true, + "user_pref was written with custom value"); + run_next_test(); +}); + +// Test that prefHasUserValue always returns true whenever there is a sticky +// value, even when that value matches the default. This is mainly for +// about:config semantics - prefs with a sticky value always remain bold and +// always offer "reset" (which fully resets and drops the sticky value as if +// the pref had never changed.) +add_test(function hasUserValue() { + // sticky pref without user value. + resetAndLoad(["data/testPrefSticky.js"]); + Assert.strictEqual(ps.getBoolPref("testPref.sticky.bool"), false); + Assert.ok(!ps.prefHasUserValue("testPref.sticky.bool"), + "should not initially reflect a user value"); + + ps.setBoolPref("testPref.sticky.bool", false); + Assert.ok(ps.prefHasUserValue("testPref.sticky.bool"), + "should reflect a user value after set to default"); + + ps.setBoolPref("testPref.sticky.bool", true); + Assert.ok(ps.prefHasUserValue("testPref.sticky.bool"), + "should reflect a user value after change to non-default"); + + ps.clearUserPref("testPref.sticky.bool"); + Assert.ok(!ps.prefHasUserValue("testPref.sticky.bool"), + "should reset to no user value"); + ps.setBoolPref("testPref.sticky.bool", false, "expected default"); + + // And make sure the pref immediately reflects a user value after load. + resetAndLoad(["data/testPrefSticky.js", "data/testPrefStickyUser.js"]); + Assert.strictEqual(ps.getBoolPref("testPref.sticky.bool"), false); + Assert.ok(ps.prefHasUserValue("testPref.sticky.bool"), + "should have a user value when loaded value is the default"); + run_next_test(); +}); + +// Test that clearUserPref removes the "sticky" value. +add_test(function clearUserPref() { + // load things such that we have a sticky value which is the same as the + // default. + resetAndLoad(["data/testPrefSticky.js", "data/testPrefStickyUser.js"]); + ps.clearUserPref("testPref.sticky.bool"); + + // Once we save prefs the sticky pref should no longer be written. + saveAndReload(); + try { + ps.getBoolPref("testPref.sticky.bool"); + Assert.ok(false, "expected failure reading this pref"); + } catch (ex) { + Assert.ok(ex, "pref doesn't have a sticky value"); + } + run_next_test(); +}); + +// Test that a pref observer gets a notification fired when a sticky pref +// has it's value changed to the same value as the default. The reason for +// this behaviour is that later we might have other code that cares about a +// pref being sticky (IOW, we notify due to the "state" of the pref changing +// even if the value has not) +add_test(function observerFires() { + // load things so there's no sticky value. + resetAndLoad(["data/testPrefSticky.js"]); + + function observe(subject, topic, data) { + Assert.equal(data, "testPref.sticky.bool"); + ps.removeObserver("testPref.sticky.bool", observe); + run_next_test(); + } + ps.addObserver("testPref.sticky.bool", observe, false); + + ps.setBoolPref("testPref.sticky.bool", ps.getBoolPref("testPref.sticky.bool")); + // and the observer will fire triggering the next text. +}); diff --git a/modules/libpref/test/unit/test_warnings.js b/modules/libpref/test/unit/test_warnings.js new file mode 100644 index 000000000..856e117b7 --- /dev/null +++ b/modules/libpref/test/unit/test_warnings.js @@ -0,0 +1,69 @@ +/* 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/. */ + +Cu.import("resource://gre/modules/Promise.jsm"); + +var cs = Cc["@mozilla.org/consoleservice;1"]. + getService(Ci.nsIConsoleService); +var ps = Cc["@mozilla.org/preferences-service;1"]. + getService(Ci.nsIPrefService); + +function makeBuffer(length) { + return new Array(length + 1).join('x'); +} + +/** + * @resolves |true| if execution proceeded without warning, + * |false| if there was a warning. + */ +function checkWarning(pref, buffer) { + let deferred = Promise.defer(); + let complete = false; + let listener = { + observe: function(event) { + let message = event.message; + if (!(message.startsWith("Warning: attempting to write") + && message.includes(pref))) { + return; + } + if (complete) { + return; + } + complete = true; + do_print("Warning while setting " + pref); + cs.unregisterListener(listener); + deferred.resolve(true); + } + }; + do_timeout(1000, function() { + if (complete) { + return; + } + complete = true; + do_print("No warning while setting " + pref); + cs.unregisterListener(listener); + deferred.resolve(false); + }); + cs.registerListener(listener); + ps.setCharPref(pref, buffer); + return deferred.promise; +} + +function run_test() { + run_next_test(); +} + +add_task(function() { + // Simple change, shouldn't cause a warning + do_print("Checking that a simple change doesn't cause a warning"); + let buf = makeBuffer(100); + let warned = yield checkWarning("string.accept", buf); + do_check_false(warned); + + // Large change, should cause a warning + do_print("Checking that a large change causes a warning"); + buf = makeBuffer(32 * 1024); + warned = yield checkWarning("string.warn", buf); + do_check_true(warned); +}); diff --git a/modules/libpref/test/unit/xpcshell.ini b/modules/libpref/test/unit/xpcshell.ini new file mode 100644 index 000000000..74c56907a --- /dev/null +++ b/modules/libpref/test/unit/xpcshell.ini @@ -0,0 +1,18 @@ +[DEFAULT] +head = head_libPrefs.js +tail = +support-files = + data/testPref.js + extdata/testExt.js + +[test_warnings.js] +[test_bug345529.js] +[test_bug506224.js] +[test_bug577950.js] +[test_bug790374.js] +[test_stickyprefs.js] +support-files = data/testPrefSticky.js data/testPrefStickyUser.js +[test_changeType.js] +[test_dirtyPrefs.js] +[test_extprefs.js] +[test_libPrefs.js] |