summaryrefslogtreecommitdiffstats
path: root/modules/libpref/test
diff options
context:
space:
mode:
Diffstat (limited to 'modules/libpref/test')
-rw-r--r--modules/libpref/test/unit/data/testPref.js6
-rw-r--r--modules/libpref/test/unit/data/testPrefSticky.js2
-rw-r--r--modules/libpref/test/unit/data/testPrefStickyUser.js5
-rw-r--r--modules/libpref/test/unit/extdata/testExt.js2
-rw-r--r--modules/libpref/test/unit/head_libPrefs.js45
-rw-r--r--modules/libpref/test/unit/test_bug345529.js34
-rw-r--r--modules/libpref/test/unit/test_bug506224.js29
-rw-r--r--modules/libpref/test/unit/test_bug577950.js28
-rw-r--r--modules/libpref/test/unit/test_bug790374.js55
-rw-r--r--modules/libpref/test/unit/test_changeType.js63
-rw-r--r--modules/libpref/test/unit/test_dirtyPrefs.js75
-rw-r--r--modules/libpref/test/unit/test_extprefs.js70
-rw-r--r--modules/libpref/test/unit/test_libPrefs.js392
-rw-r--r--modules/libpref/test/unit/test_stickyprefs.js170
-rw-r--r--modules/libpref/test/unit/test_warnings.js69
-rw-r--r--modules/libpref/test/unit/xpcshell.ini18
-rw-r--r--modules/libpref/test/unit_ipc/test_existing_prefs.js21
-rw-r--r--modules/libpref/test/unit_ipc/test_initial_prefs.js18
-rw-r--r--modules/libpref/test/unit_ipc/test_large_pref.js98
-rw-r--r--modules/libpref/test/unit_ipc/test_observed_prefs.js16
-rw-r--r--modules/libpref/test/unit_ipc/test_update_prefs.js38
-rw-r--r--modules/libpref/test/unit_ipc/test_user_default_prefs.js76
-rw-r--r--modules/libpref/test/unit_ipc/xpcshell.ini11
23 files changed, 1341 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]
diff --git a/modules/libpref/test/unit_ipc/test_existing_prefs.js b/modules/libpref/test/unit_ipc/test_existing_prefs.js
new file mode 100644
index 000000000..4c51c4d67
--- /dev/null
+++ b/modules/libpref/test/unit_ipc/test_existing_prefs.js
@@ -0,0 +1,21 @@
+var Ci = Components.interfaces;
+var Cc = Components.classes;
+
+function isParentProcess() {
+ let appInfo = Cc["@mozilla.org/xre/app-info;1"];
+ return (!appInfo || appInfo.getService(Ci.nsIXULRuntime).processType == Ci.nsIXULRuntime.PROCESS_TYPE_DEFAULT);
+}
+
+function run_test() {
+ if (isParentProcess() == false) {
+
+ do_load_child_test_harness();
+
+ var pb = Cc["@mozilla.org/preferences-service;1"].getService(Ci.nsIPrefBranch);
+ pb.setBoolPref("Test.IPC.bool.new", true);
+ pb.setIntPref("Test.IPC.int.new", 23);
+ pb.setCharPref("Test.IPC.char.new", "hey");
+
+ run_test_in_child("test_observed_prefs.js");
+ }
+} \ No newline at end of file
diff --git a/modules/libpref/test/unit_ipc/test_initial_prefs.js b/modules/libpref/test/unit_ipc/test_initial_prefs.js
new file mode 100644
index 000000000..62b36c694
--- /dev/null
+++ b/modules/libpref/test/unit_ipc/test_initial_prefs.js
@@ -0,0 +1,18 @@
+var Ci = Components.interfaces;
+var Cc = Components.classes;
+
+function isParentProcess() {
+ let appInfo = Cc["@mozilla.org/xre/app-info;1"];
+ return (!appInfo || appInfo.getService(Ci.nsIXULRuntime).processType == Ci.nsIXULRuntime.PROCESS_TYPE_DEFAULT);
+}
+
+function run_test() {
+ if (isParentProcess() == false) {
+ var pb = Cc["@mozilla.org/preferences-service;1"].getService(Ci.nsIPrefBranch);
+ pb.setBoolPref("Test.IPC.bool", true);
+ pb.setIntPref("Test.IPC.int", 23);
+ pb.setCharPref("Test.IPC.char", "hey");
+
+ run_test_in_child("test_existing_prefs.JS");
+ }
+} \ No newline at end of file
diff --git a/modules/libpref/test/unit_ipc/test_large_pref.js b/modules/libpref/test/unit_ipc/test_large_pref.js
new file mode 100644
index 000000000..c3c937b43
--- /dev/null
+++ b/modules/libpref/test/unit_ipc/test_large_pref.js
@@ -0,0 +1,98 @@
+/* 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/. */
+
+// Large preferences should not be set in the child process.
+// Non-string preferences are not tested here, because their behavior
+// should not be affected by this filtering.
+
+var Ci = Components.interfaces;
+var Cc = Components.classes;
+
+function isParentProcess() {
+ let appInfo = Cc["@mozilla.org/xre/app-info;1"];
+ return (!appInfo || appInfo.getService(Ci.nsIXULRuntime).processType == Ci.nsIXULRuntime.PROCESS_TYPE_DEFAULT);
+}
+
+function makeBuffer(length) {
+ let string = "x";
+ while (string.length < length) {
+ string = string + string;
+ }
+ if (string.length > length) {
+ string = string.substring(length - string.length);
+ }
+ return string;
+}
+
+// from prefapi.h
+const MAX_ADVISABLE_PREF_LENGTH = 4 * 1024;
+
+const largeString = makeBuffer(MAX_ADVISABLE_PREF_LENGTH + 1);
+const smallString = makeBuffer(4);
+
+const testValues = [
+ {name: "None", value: undefined},
+ {name: "Small", value: smallString},
+ {name: "Large", value: largeString},
+];
+
+function prefName(def, user) {
+ return "Test.IPC.default" + def.name + "User" + user.name;
+}
+
+function expectedPrefValue(def, user) {
+ if (user.value) {
+ return user.value;
+ }
+ return def.value;
+}
+
+function run_test() {
+ let pb = Cc["@mozilla.org/preferences-service;1"].getService(Ci.nsIPrefBranch);
+ let ps = Cc["@mozilla.org/preferences-service;1"].getService(Ci.nsIPrefService);
+ let defaultBranch = ps.getDefaultBranch("");
+
+ let isParent = isParentProcess();
+ if (isParent) {
+ // Set all combinations of none, small and large, for default and user prefs.
+ for (let def of testValues) {
+ for (let user of testValues) {
+ let currPref = prefName(def, user);
+ if (def.value) {
+ defaultBranch.setCharPref(currPref, def.value);
+ }
+ if (user.value) {
+ pb.setCharPref(currPref, user.value);
+ }
+ }
+ }
+
+ run_test_in_child("test_large_pref.js");
+ }
+
+ // Check that each preference is set or not set, as appropriate.
+ for (let def of testValues) {
+ for (let user of testValues) {
+ if (!def.value && !user.value) {
+ continue;
+ }
+ let pref_name = prefName(def, user);
+ if (isParent || (def.name != "Large" && user.name != "Large")) {
+ do_check_eq(pb.getCharPref(pref_name), expectedPrefValue(def, user));
+ } else {
+ // This is the child, and either the default or user value is
+ // large, so the preference should not be set.
+ let prefExists;
+ try {
+ pb.getCharPref(pref_name);
+ prefExists = true;
+ } catch(e) {
+ prefExists = false;
+ }
+ ok(!prefExists,
+ "Pref " + pref_name + " should not be set in the child");
+ }
+ }
+ }
+}
diff --git a/modules/libpref/test/unit_ipc/test_observed_prefs.js b/modules/libpref/test/unit_ipc/test_observed_prefs.js
new file mode 100644
index 000000000..c18f7f0fe
--- /dev/null
+++ b/modules/libpref/test/unit_ipc/test_observed_prefs.js
@@ -0,0 +1,16 @@
+var Ci = Components.interfaces;
+var Cc = Components.classes;
+
+function isParentProcess() {
+ let appInfo = Cc["@mozilla.org/xre/app-info;1"];
+ return (!appInfo || appInfo.getService(Ci.nsIXULRuntime).processType == Ci.nsIXULRuntime.PROCESS_TYPE_DEFAULT);
+}
+
+function run_test() {
+ if (isParentProcess() == false) {
+ var pb = Cc["@mozilla.org/preferences-service;1"].getService(Ci.nsIPrefBranch);
+ do_check_eq(pb.getBoolPref("Test.IPC.bool.new"), true);
+ do_check_eq(pb.getIntPref("Test.IPC.int.new"), 23);
+ do_check_eq(pb.getCharPref("Test.IPC.char.new"), "hey");
+ }
+} \ No newline at end of file
diff --git a/modules/libpref/test/unit_ipc/test_update_prefs.js b/modules/libpref/test/unit_ipc/test_update_prefs.js
new file mode 100644
index 000000000..7e1b0dcd7
--- /dev/null
+++ b/modules/libpref/test/unit_ipc/test_update_prefs.js
@@ -0,0 +1,38 @@
+var Ci = Components.interfaces;
+var Cc = Components.classes;
+
+function isParentProcess() {
+ let appInfo = Cc["@mozilla.org/xre/app-info;1"];
+ return (!appInfo || appInfo.getService(Ci.nsIXULRuntime).processType == Ci.nsIXULRuntime.PROCESS_TYPE_DEFAULT);
+}
+
+function run_test() {
+ if (isParentProcess()) {
+
+ do_load_child_test_harness();
+
+ var pb = Cc["@mozilla.org/preferences-service;1"].getService(Ci.nsIPrefBranch);
+
+ // these prefs are set after the child has been created.
+ pb.setBoolPref("Test.IPC.bool.new", true);
+ pb.setIntPref("Test.IPC.int.new", 23);
+ pb.setCharPref("Test.IPC.char.new", "hey");
+
+ run_test_in_child("test_observed_prefs.js", testPrefClear);
+ }
+}
+
+function testPrefClear() {
+ var pb = Cc["@mozilla.org/preferences-service;1"].getService(Ci.nsIPrefBranch);
+ pb.clearUserPref("Test.IPC.bool.new");
+
+ sendCommand(
+'var pb = Cc["@mozilla.org/preferences-service;1"].getService(Ci.nsIPrefBranch);\n'+
+'pb.prefHasUserValue("Test.IPC.bool.new");\n',
+ checkWasCleared);
+}
+
+function checkWasCleared(existsStr) {
+ do_check_eq(existsStr, "false");
+ do_test_finished();
+} \ No newline at end of file
diff --git a/modules/libpref/test/unit_ipc/test_user_default_prefs.js b/modules/libpref/test/unit_ipc/test_user_default_prefs.js
new file mode 100644
index 000000000..3b8ca28c6
--- /dev/null
+++ b/modules/libpref/test/unit_ipc/test_user_default_prefs.js
@@ -0,0 +1,76 @@
+var Ci = Components.interfaces;
+var Cc = Components.classes;
+
+var pb = Cc["@mozilla.org/preferences-service;1"].getService(Ci.nsIPrefBranch);
+
+// This pref is chosen somewhat arbitrarily --- we just need one
+// that's guaranteed to have a default value.
+const kPrefName = 'intl.accept_languages'; // of type char, which we
+ // assume below
+var initialValue = null;
+
+function check_child_pref_info_eq(continuation) {
+ sendCommand(
+ 'var pb = Components.classes["@mozilla.org/preferences-service;1"].getService(Components.interfaces.nsIPrefBranch);\n'+
+ // Returns concatenation "[value],[isUser]"
+ 'pb.getCharPref("'+ kPrefName +'")+ "," +'+
+ 'pb.prefHasUserValue("'+ kPrefName +'");',
+ function (info) {
+ let [ value, isUser ] = info.split(',');
+ do_check_eq(pb.getCharPref(kPrefName), value);
+ do_check_eq(pb.prefHasUserValue(kPrefName), isUser == "true");
+ continuation();
+ });
+}
+
+function run_test() {
+ // We finish in clean_up()
+ do_test_pending();
+
+ try {
+ if (pb.getCharPref('dom.ipc.processPrelaunch.enabled')) {
+ dump('WARNING: Content process may already have launched, so this test may not be meaningful.');
+ }
+ } catch(e) { }
+
+ initialValue = pb.getCharPref(kPrefName);
+
+ test_user_setting();
+}
+
+function test_user_setting() {
+ // We rely on setting this before the content process starts up.
+ // When it starts up, it should recognize this as a user pref, not
+ // a default pref.
+ pb.setCharPref(kPrefName, 'i-imaginarylanguage');
+ // NB: processing of the value-change notification in the child
+ // process triggered by the above set happens-before the remaining
+ // code here
+ check_child_pref_info_eq(function () {
+ do_check_eq(pb.prefHasUserValue(kPrefName), true);
+
+ test_cleared_is_default();
+ });
+}
+
+function test_cleared_is_default() {
+ pb.clearUserPref(kPrefName);
+ // NB: processing of the value-change notification in the child
+ // process triggered by the above set happens-before the remaining
+ // code here
+ check_child_pref_info_eq(function () {
+ do_check_eq(pb.prefHasUserValue(kPrefName), false);
+
+ clean_up();
+ });
+}
+
+function clean_up() {
+ pb.setCharPref(kPrefName, initialValue);
+ // NB: processing of the value-change notification in the child
+ // process triggered by the above set happens-before the remaining
+ // code here
+ check_child_pref_info_eq(function () {
+ do_test_finished();
+ });
+} \ No newline at end of file
diff --git a/modules/libpref/test/unit_ipc/xpcshell.ini b/modules/libpref/test/unit_ipc/xpcshell.ini
new file mode 100644
index 000000000..319276e68
--- /dev/null
+++ b/modules/libpref/test/unit_ipc/xpcshell.ini
@@ -0,0 +1,11 @@
+[DEFAULT]
+head =
+tail =
+skip-if = toolkit == 'android'
+
+[test_existing_prefs.js]
+[test_initial_prefs.js]
+[test_large_pref.js]
+[test_observed_prefs.js]
+[test_update_prefs.js]
+[test_user_default_prefs.js]