toolkit/components/contentprefs/tests/unit_cps2/head.js

Fri, 16 Jan 2015 18:13:44 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Fri, 16 Jan 2015 18:13:44 +0100
branch
TOR_BUG_9701
changeset 14
925c144e1f1f
permissions
-rw-r--r--

Integrate suggestion from review to improve consistency with existing code.

     1 /* This Source Code Form is subject to the terms of the Mozilla Public
     2  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
     3  * You can obtain one at http://mozilla.org/MPL/2.0/. */
     5 const { interfaces: Ci, classes: Cc, results: Cr, utils: Cu } = Components;
     7 Cu.import("resource://gre/modules/Services.jsm");
     9 var cps;
    10 var asyncRunner;
    11 var next;
    13 (function init() {
    14   // There has to be a profile directory before the CPS service is gotten.
    15   do_get_profile();
    16 })();
    18 function runAsyncTests(tests) {
    19   do_test_pending();
    21   cps = Cc["@mozilla.org/content-pref/service;1"].
    22         getService(Ci.nsIContentPrefService2);
    24   // Without this the private-browsing service tries to open a dialog when you
    25   // change its enabled state.
    26   Services.prefs.setBoolPref("browser.privatebrowsing.keep_current_session",
    27                              true);
    29   let s = {};
    30   Cu.import("resource://test/AsyncRunner.jsm", s);
    31   asyncRunner = new s.AsyncRunner({
    32     done: do_test_finished,
    33     error: function (err) {
    34       // xpcshell test functions like do_check_eq throw NS_ERROR_ABORT on
    35       // failure.  Ignore those and catch only uncaught exceptions.
    36       if (err !== Cr.NS_ERROR_ABORT) {
    37         if (err.stack) {
    38           err = err + "\n\nTraceback (most recent call first):\n" + err.stack +
    39                       "\nUseless do_throw stack:";
    40         }
    41         do_throw(err);
    42       }
    43     },
    44     consoleError: function (scriptErr) {
    45       // As much as possible make sure the error is related to the test.  On the
    46       // other hand if this fails to catch a test-related error, we'll hang.
    47       let filename = scriptErr.sourceName || scriptErr.toString() || "";
    48       if (/contentpref/i.test(filename))
    49         do_throw(scriptErr);
    50     }
    51   });
    53   next = asyncRunner.next.bind(asyncRunner);
    55   do_register_cleanup(function () {
    56     asyncRunner.destroy();
    57     asyncRunner = null;
    58   });
    60   tests.forEach(function (test) {
    61     function gen() {
    62       do_print("Running " + test.name);
    63       yield test();
    64       yield reset();
    65     }
    66     asyncRunner.appendIterator(gen());
    67   });
    69   // reset() ends up calling asyncRunner.next(), starting the tests.
    70   reset();
    71 }
    73 function makeCallback(callbacks) {
    74   callbacks = callbacks || {};
    75   ["handleResult", "handleError"].forEach(function (meth) {
    76     if (!callbacks[meth])
    77       callbacks[meth] = function () {
    78         do_throw(meth + " shouldn't be called.");
    79       };
    80   });
    81   if (!callbacks.handleCompletion)
    82     callbacks.handleCompletion = function (reason) {
    83       do_check_eq(reason, Ci.nsIContentPrefCallback2.COMPLETE_OK);
    84       next();
    85     };
    86   return callbacks;
    87 }
    89 function do_check_throws(fn) {
    90   let threw = false;
    91   try {
    92     fn();
    93   }
    94   catch (err) {
    95     threw = true;
    96   }
    97   do_check_true(threw);
    98 }
   100 function sendMessage(msg, callback) {
   101   let obj = callback || {};
   102   let ref = Cu.getWeakReference(obj);
   103   cps.QueryInterface(Ci.nsIObserver).observe(ref, "test:" + msg, null);
   104   return "value" in obj ? obj.value : undefined;
   105 }
   107 function reset() {
   108   sendMessage("reset", next);
   109 }
   111 function set(group, name, val, context) {
   112   cps.set(group, name, val, context, makeCallback());
   113 }
   115 function setGlobal(name, val, context) {
   116   cps.setGlobal(name, val, context, makeCallback());
   117 }
   119 function prefOK(actual, expected, strict) {
   120   do_check_true(actual instanceof Ci.nsIContentPref);
   121   do_check_eq(actual.domain, expected.domain);
   122   do_check_eq(actual.name, expected.name);
   123   if (strict)
   124     do_check_true(actual.value === expected.value);
   125   else
   126     do_check_eq(actual.value, expected.value);
   127 }
   129 function getOK(args, expectedVal, expectedGroup, strict) {
   130   if (args.length == 2)
   131     args.push(undefined);
   132   let expectedPrefs = expectedVal === undefined ? [] :
   133                       [{ domain: expectedGroup || args[0],
   134                          name: args[1],
   135                          value: expectedVal }];
   136   yield getOKEx("getByDomainAndName", args, expectedPrefs, strict);
   137 }
   139 function getSubdomainsOK(args, expectedGroupValPairs) {
   140   if (args.length == 2)
   141     args.push(undefined);
   142   let expectedPrefs = expectedGroupValPairs.map(function ([group, val]) {
   143     return { domain: group, name: args[1], value: val };
   144   });
   145   yield getOKEx("getBySubdomainAndName", args, expectedPrefs);
   146 }
   148 function getGlobalOK(args, expectedVal) {
   149   if (args.length == 1)
   150     args.push(undefined);
   151   let expectedPrefs = expectedVal === undefined ? [] :
   152                       [{ domain: null, name: args[0], value: expectedVal }];
   153   yield getOKEx("getGlobal", args, expectedPrefs);
   154 }
   156 function getOKEx(methodName, args, expectedPrefs, strict, context) {
   157   let actualPrefs = [];
   158   args.push(makeCallback({
   159     handleResult: function (pref) actualPrefs.push(pref)
   160   }));
   161   yield cps[methodName].apply(cps, args);
   162   arraysOfArraysOK([actualPrefs], [expectedPrefs], function (actual, expected) {
   163     prefOK(actual, expected, strict);
   164   });
   165 }
   167 function getCachedOK(args, expectedIsCached, expectedVal, expectedGroup,
   168                      strict) {
   169   if (args.length == 2)
   170     args.push(undefined);
   171   let expectedPref = !expectedIsCached ? null : {
   172     domain: expectedGroup || args[0],
   173     name: args[1],
   174     value: expectedVal
   175   };
   176   getCachedOKEx("getCachedByDomainAndName", args, expectedPref, strict);
   177 }
   179 function getCachedSubdomainsOK(args, expectedGroupValPairs) {
   180   if (args.length == 2)
   181     args.push(undefined);
   182   let len = {};
   183   args.push(len);
   184   let actualPrefs = cps.getCachedBySubdomainAndName.apply(cps, args);
   185   actualPrefs = actualPrefs.sort(function (a, b) {
   186     return a.domain.localeCompare(b.domain);
   187   });
   188   do_check_eq(actualPrefs.length, len.value);
   189   let expectedPrefs = expectedGroupValPairs.map(function ([group, val]) {
   190     return { domain: group, name: args[1], value: val };
   191   });
   192   arraysOfArraysOK([actualPrefs], [expectedPrefs], prefOK);
   193 }
   195 function getCachedGlobalOK(args, expectedIsCached, expectedVal) {
   196   if (args.length == 1)
   197     args.push(undefined);
   198   let expectedPref = !expectedIsCached ? null : {
   199     domain: null,
   200     name: args[0],
   201     value: expectedVal
   202   };
   203   getCachedOKEx("getCachedGlobal", args, expectedPref);
   204 }
   206 function getCachedOKEx(methodName, args, expectedPref, strict) {
   207   let actualPref = cps[methodName].apply(cps, args);
   208   if (expectedPref)
   209     prefOK(actualPref, expectedPref, strict);
   210   else
   211     do_check_true(actualPref === null);
   212 }
   214 function arraysOfArraysOK(actual, expected, cmp) {
   215   cmp = cmp || function (a, b) do_check_eq(a, b);
   216   do_check_eq(actual.length, expected.length);
   217   actual.forEach(function (actualChildArr, i) {
   218     let expectedChildArr = expected[i];
   219     do_check_eq(actualChildArr.length, expectedChildArr.length);
   220     actualChildArr.forEach(function (actualElt, j) {
   221       let expectedElt = expectedChildArr[j];
   222       cmp(actualElt, expectedElt);
   223     });
   224   });
   225 }
   227 function dbOK(expectedRows) {
   228   let db = sendMessage("db");
   229   let stmt = db.createAsyncStatement(
   230     "SELECT groups.name AS grp, settings.name AS name, prefs.value AS value " +
   231     "FROM prefs " +
   232     "LEFT JOIN groups ON groups.id = prefs.groupID " +
   233     "LEFT JOIN settings ON settings.id = prefs.settingID " +
   234     "UNION " +
   236     // These second two SELECTs get the rows of the groups and settings tables
   237     // that aren't referenced by the prefs table.  Neither should return any
   238     // rows if the component is working properly.
   239     "SELECT groups.name AS grp, NULL AS name, NULL AS value " +
   240     "FROM groups " +
   241     "WHERE id NOT IN (" +
   242       "SELECT DISTINCT groupID " +
   243       "FROM prefs " +
   244       "WHERE groupID NOTNULL" +
   245     ") " +
   246     "UNION " +
   247     "SELECT NULL AS grp, settings.name AS name, NULL AS value " +
   248     "FROM settings " +
   249     "WHERE id NOT IN (" +
   250       "SELECT DISTINCT settingID " +
   251       "FROM prefs " +
   252       "WHERE settingID NOTNULL" +
   253     ") " +
   255     "ORDER BY value ASC, grp ASC, name ASC"
   256   );
   258   let actualRows = [];
   259   let cols = ["grp", "name", "value"];
   261   db.executeAsync([stmt], 1, {
   262     handleCompletion: function (reason) {
   263       arraysOfArraysOK(actualRows, expectedRows);
   264       next();
   265     },
   266     handleResult: function (results) {
   267       let row = null;
   268       while (row = results.getNextRow()) {
   269         actualRows.push(cols.map(function (c) row.getResultByName(c)));
   270       }
   271     },
   272     handleError: function (err) {
   273       do_throw(err);
   274     }
   275   });
   276   stmt.finalize();
   277 }
   279 function on(event, names, dontRemove) {
   280   let args = {
   281     reset: function () {
   282       for (let prop in this) {
   283         if (Array.isArray(this[prop]))
   284           this[prop].splice(0, this[prop].length);
   285       }
   286     },
   287   };
   289   let observers = {};
   291   names.forEach(function (name) {
   292     let obs = {};
   293     ["onContentPrefSet", "onContentPrefRemoved"].forEach(function (meth) {
   294       obs[meth] = function () do_throw(meth + " should not be called");
   295     });
   296     obs["onContentPref" + event] = function () {
   297       args[name].push(Array.slice(arguments));
   298     };
   299     observers[name] = obs;
   300     args[name] = [];
   301     args[name].observer = obs;
   302     cps.addObserverForName(name, obs);
   303   });
   305   do_execute_soon(function () {
   306     if (!dontRemove)
   307       names.forEach(function (n) cps.removeObserverForName(n, observers[n]));
   308     next(args);
   309   });
   310 }
   312 function wait() {
   313   do_execute_soon(next);
   314 }
   316 function observerArgsOK(actualArgs, expectedArgs) {
   317   do_check_neq(actualArgs, undefined);
   318   arraysOfArraysOK(actualArgs, expectedArgs);
   319 }

mercurial