diff options
Diffstat (limited to 'toolkit/components/contentprefs/tests/unit_cps2/head.js')
-rw-r--r-- | toolkit/components/contentprefs/tests/unit_cps2/head.js | 358 |
1 files changed, 358 insertions, 0 deletions
diff --git a/toolkit/components/contentprefs/tests/unit_cps2/head.js b/toolkit/components/contentprefs/tests/unit_cps2/head.js new file mode 100644 index 0000000000..3a07ad9901 --- /dev/null +++ b/toolkit/components/contentprefs/tests/unit_cps2/head.js @@ -0,0 +1,358 @@ +/* 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/. */ + +let loadContext = Cu.createLoadContext(); +let privateLoadContext = Cu.createPrivateLoadContext(); + +// There has to be a profile directory before the CPS service is gotten. +do_get_profile(); +let cps = Cc["@mozilla.org/content-pref/service;1"].getService( + Ci.nsIContentPrefService2 +); + +function makeCallback(resolve, callbacks, success = null) { + callbacks = callbacks || {}; + if (!callbacks.handleError) { + callbacks.handleError = function(error) { + do_throw("handleError call was not expected, error: " + error); + }; + } + if (!callbacks.handleResult) { + callbacks.handleResult = function() { + do_throw("handleResult call was not expected"); + }; + } + if (!callbacks.handleCompletion) { + callbacks.handleCompletion = function(reason) { + equal(reason, Ci.nsIContentPrefCallback2.COMPLETE_OK); + if (success) { + success(); + } else { + resolve(); + } + }; + } + return callbacks; +} + +async function do_check_throws(fn) { + let threw = false; + try { + await fn(); + } catch (err) { + threw = true; + } + ok(threw); +} + +function sendMessage(msg, callback) { + let obj = callback || {}; + let ref = Cu.getWeakReference(obj); + cps.QueryInterface(Ci.nsIObserver).observe(ref, "test:" + msg, null); + return "value" in obj ? obj.value : undefined; +} + +function reset() { + return new Promise(resolve => { + sendMessage("reset", resolve); + }); +} + +function setWithDate(group, name, val, timestamp, context) { + return new Promise(resolve => { + async function updateDate() { + let conn = await sendMessage("db"); + await conn.execute( + ` + UPDATE prefs SET timestamp = :timestamp + WHERE + settingID = (SELECT id FROM settings WHERE name = :name) + AND groupID = (SELECT id FROM groups WHERE name = :group) + `, + { name, group, timestamp: timestamp / 1000 } + ); + + resolve(); + } + + cps.set(group, name, val, context, makeCallback(null, null, updateDate)); + }); +} + +async function getDate(group, name, context) { + let conn = await sendMessage("db"); + let [result] = await conn.execute( + ` + SELECT timestamp FROM prefs + WHERE + settingID = (SELECT id FROM settings WHERE name = :name) + AND groupID = (SELECT id FROM groups WHERE name = :group) + `, + { name, group } + ); + + return result.getResultByName("timestamp") * 1000; +} + +function set(group, name, val, context) { + return new Promise(resolve => { + cps.set(group, name, val, context, makeCallback(resolve)); + }); +} + +function setGlobal(name, val, context) { + return new Promise(resolve => { + cps.setGlobal(name, val, context, makeCallback(resolve)); + }); +} + +function prefOK(actual, expected, strict) { + ok(actual instanceof Ci.nsIContentPref); + equal(actual.domain, expected.domain); + equal(actual.name, expected.name); + if (strict) { + strictEqual(actual.value, expected.value); + } else { + equal(actual.value, expected.value); + } +} + +async function getOK(args, expectedVal, expectedGroup, strict) { + if (args.length == 2) { + args.push(undefined); + } + let expectedPrefs = + expectedVal === undefined + ? [] + : [ + { + domain: expectedGroup || args[0], + name: args[1], + value: expectedVal, + }, + ]; + await getOKEx("getByDomainAndName", args, expectedPrefs, strict); +} + +async function getSubdomainsOK(args, expectedGroupValPairs) { + if (args.length == 2) { + args.push(undefined); + } + let expectedPrefs = expectedGroupValPairs.map(function([group, val]) { + return { domain: group, name: args[1], value: val }; + }); + await getOKEx("getBySubdomainAndName", args, expectedPrefs); +} + +async function getGlobalOK(args, expectedVal) { + if (args.length == 1) { + args.push(undefined); + } + let expectedPrefs = + expectedVal === undefined + ? [] + : [{ domain: null, name: args[0], value: expectedVal }]; + await getOKEx("getGlobal", args, expectedPrefs); +} + +async function getOKEx(methodName, args, expectedPrefs, strict, context) { + let actualPrefs = []; + await new Promise(resolve => { + args.push( + makeCallback(resolve, { + handleResult: pref => actualPrefs.push(pref), + }) + ); + cps[methodName].apply(cps, args); + }); + arraysOfArraysOK([actualPrefs], [expectedPrefs], function(actual, expected) { + prefOK(actual, expected, strict); + }); +} + +function getCachedOK( + args, + expectedIsCached, + expectedVal, + expectedGroup, + strict +) { + if (args.length == 2) { + args.push(undefined); + } + let expectedPref = !expectedIsCached + ? null + : { + domain: expectedGroup || args[0], + name: args[1], + value: expectedVal, + }; + getCachedOKEx("getCachedByDomainAndName", args, expectedPref, strict); +} + +function getCachedSubdomainsOK(args, expectedGroupValPairs) { + if (args.length == 2) { + args.push(undefined); + } + let actualPrefs = cps.getCachedBySubdomainAndName.apply(cps, args); + actualPrefs = actualPrefs.sort(function(a, b) { + return a.domain.localeCompare(b.domain); + }); + let expectedPrefs = expectedGroupValPairs.map(function([group, val]) { + return { domain: group, name: args[1], value: val }; + }); + arraysOfArraysOK([actualPrefs], [expectedPrefs], prefOK); +} + +function getCachedGlobalOK(args, expectedIsCached, expectedVal) { + if (args.length == 1) { + args.push(undefined); + } + let expectedPref = !expectedIsCached + ? null + : { + domain: null, + name: args[0], + value: expectedVal, + }; + getCachedOKEx("getCachedGlobal", args, expectedPref); +} + +function getCachedOKEx(methodName, args, expectedPref, strict) { + let actualPref = cps[methodName].apply(cps, args); + if (expectedPref) { + prefOK(actualPref, expectedPref, strict); + } else { + strictEqual(actualPref, null); + } +} + +function arraysOK(actual, expected, cmp) { + if (actual.length != expected.length) { + do_throw( + "Length is not equal: " + + JSON.stringify(actual) + + "==" + + JSON.stringify(expected) + ); + } else { + actual.forEach(function(actualElt, j) { + let expectedElt = expected[j]; + cmp(actualElt, expectedElt); + }); + } +} + +function arraysOfArraysOK(actual, expected, cmp) { + cmp = cmp || equal; + arraysOK(actual, expected, function(act, exp) { + arraysOK(act, exp, cmp); + }); +} + +async function dbOK(expectedRows) { + let conn = await sendMessage("db"); + let stmt = ` + SELECT groups.name AS grp, settings.name AS name, prefs.value AS value + FROM prefs + LEFT JOIN groups ON groups.id = prefs.groupID + LEFT JOIN settings ON settings.id = prefs.settingID + UNION + + /* + These second two SELECTs get the rows of the groups and settings tables + that aren't referenced by the prefs table. Neither should return any + rows if the component is working properly. + */ + SELECT groups.name AS grp, NULL AS name, NULL AS value + FROM groups + WHERE id NOT IN ( + SELECT DISTINCT groupID + FROM prefs + WHERE groupID NOTNULL + ) + UNION + SELECT NULL AS grp, settings.name AS name, NULL AS value + FROM settings + WHERE id NOT IN ( + SELECT DISTINCT settingID + FROM prefs + WHERE settingID NOTNULL + ) + + ORDER BY value ASC, grp ASC, name ASC + `; + + let cols = ["grp", "name", "value"]; + + let actualRows = (await conn.execute(stmt)).map(row => + cols.map(c => row.getResultByName(c)) + ); + arraysOfArraysOK(actualRows, expectedRows); +} + +function on(event, names, dontRemove) { + return onEx(event, names, dontRemove).promise; +} + +function onEx(event, names, dontRemove) { + let args = { + reset() { + for (let prop in this) { + if (Array.isArray(this[prop])) { + this[prop].splice(0, this[prop].length); + } + } + }, + }; + + let observers = {}; + let deferred = null; + let triggered = false; + + names.forEach(function(name) { + let obs = {}; + ["onContentPrefSet", "onContentPrefRemoved"].forEach(function(meth) { + obs[meth] = () => do_throw(meth + " should not be called for " + name); + }); + obs["onContentPref" + event] = function() { + args[name].push(Array.from(arguments)); + + if (!triggered) { + triggered = true; + executeSoon(function() { + if (!dontRemove) { + names.forEach(n => cps.removeObserverForName(n, observers[n])); + } + deferred.resolve(args); + }); + } + }; + observers[name] = obs; + args[name] = []; + args[name].observer = obs; + cps.addObserverForName(name, obs); + }); + + return { + observers, + promise: new Promise(resolve => { + deferred = { resolve }; + }), + }; +} + +async function schemaVersionIs(expectedVersion) { + let db = await sendMessage("db"); + equal(await db.getSchemaVersion(), expectedVersion); +} + +function wait() { + return new Promise(resolve => executeSoon(resolve)); +} + +function observerArgsOK(actualArgs, expectedArgs) { + notEqual(actualArgs, undefined); + arraysOfArraysOK(actualArgs, expectedArgs); +} |