addon-sdk/source/lib/sdk/test/assert.js

Sat, 03 Jan 2015 20:18:00 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Sat, 03 Jan 2015 20:18:00 +0100
branch
TOR_BUG_3246
changeset 7
129ffea94266
permissions
-rw-r--r--

Conditionally enable double key logic according to:
private browsing mode or privacy.thirdparty.isolate preference and
implement in GetCookieStringCommon and FindCookie where it counts...
With some reservations of how to convince FindCookie users to test
condition and pass a nullptr when disabling double key logic.

     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
     3  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     4 "use strict";
     6 module.metadata = {
     7   "stability": "unstable"
     8 };
    10 const { isFunction, isNull, isObject, isString,
    11         isRegExp, isArray, isDate, isPrimitive,
    12         isUndefined, instanceOf, source } = require("../lang/type");
    14 /**
    15  * The `AssertionError` is defined in assert.
    16  * @extends Error
    17  * @example
    18  *  new assert.AssertionError({
    19  *    message: message,
    20  *    actual: actual,
    21  *    expected: expected
    22  *  })
    23  */
    24 function AssertionError(options) {
    25   let assertionError = Object.create(AssertionError.prototype);
    27   if (isString(options))
    28     options = { message: options };
    29   if ("actual" in options)
    30     assertionError.actual = options.actual;
    31   if ("expected" in options)
    32     assertionError.expected = options.expected;
    33   if ("operator" in options)
    34     assertionError.operator = options.operator;
    36   assertionError.message = options.message;
    37   assertionError.stack = new Error().stack;
    38   return assertionError;
    39 }
    40 AssertionError.prototype = Object.create(Error.prototype, {
    41   constructor: { value: AssertionError },
    42   name: { value: "AssertionError", enumerable: true },
    43   toString: { value: function toString() {
    44     let value;
    45     if (this.message) {
    46       value = this.name + " : " + this.message;
    47     }
    48     else {
    49       value = [
    50         this.name + " : ",
    51         source(this.expected),
    52         this.operator,
    53         source(this.actual)
    54       ].join(" ");
    55     }
    56     return value;
    57   }}
    58 });
    59 exports.AssertionError = AssertionError;
    61 function Assert(logger) {
    62   let assert = Object.create(Assert.prototype, { _log: { value: logger }});
    64   assert.fail = assert.fail.bind(assert);
    65   assert.pass = assert.pass.bind(assert);
    67   return assert;
    68 }
    70 Assert.prototype = {
    71   fail: function fail(e) {
    72     if (!e || typeof(e) !== 'object') {
    73       this._log.fail(e);
    74       return;
    75     }
    76     let message = e.message;
    77     try {
    78       if ('operator' in e) {
    79         message += [
    80           " -",
    81           source(e.expected),
    82           e.operator,
    83           source(e.actual)
    84         ].join(" ");
    85       }
    86     }
    87     catch(e) {}
    88     this._log.fail(message);
    89   },
    90   pass: function pass(message) {
    91     this._log.pass(message);
    92   },
    93   error: function error(e) {
    94     this._log.exception(e);
    95   },
    96   ok: function ok(value, message) {
    97     if (!!!value) {
    98       this.fail({
    99         actual: value,
   100         expected: true,
   101         message: message,
   102         operator: "=="
   103       });
   104     }
   105     else {
   106       this.pass(message);
   107     }
   108   },
   110   /**
   111    * The equality assertion tests shallow, coercive equality with `==`.
   112    * @example
   113    *    assert.equal(1, 1, "one is one");
   114    */
   115   equal: function equal(actual, expected, message) {
   116     if (actual == expected) {
   117       this.pass(message);
   118     }
   119     else {
   120       this.fail({
   121         actual: actual,
   122         expected: expected,
   123         message: message,
   124         operator: "=="
   125       });
   126     }
   127   },
   129   /**
   130    * The non-equality assertion tests for whether two objects are not equal
   131    * with `!=`.
   132    * @example
   133    *    assert.notEqual(1, 2, "one is not two");
   134    */
   135   notEqual: function notEqual(actual, expected, message) {
   136     if (actual != expected) {
   137       this.pass(message);
   138     }
   139     else {
   140       this.fail({
   141         actual: actual,
   142         expected: expected,
   143         message: message,
   144         operator: "!=",
   145       });
   146     }
   147   },
   149   /**
   150    * The equivalence assertion tests a deep (with `===`) equality relation.
   151    * @example
   152    *    assert.deepEqual({ a: "foo" }, { a: "foo" }, "equivalent objects")
   153    */
   154    deepEqual: function deepEqual(actual, expected, message) {
   155     if (isDeepEqual(actual, expected)) {
   156       this.pass(message);
   157     }
   158     else {
   159       this.fail({
   160         actual: actual,
   161         expected: expected,
   162         message: message,
   163         operator: "deepEqual"
   164       });
   165     }
   166   },
   168   /**
   169    * The non-equivalence assertion tests for any deep (with `===`) inequality.
   170    * @example
   171    *    assert.notDeepEqual({ a: "foo" }, Object.create({ a: "foo" }),
   172    *                        "object's inherit from different prototypes");
   173    */
   174   notDeepEqual: function notDeepEqual(actual, expected, message) {
   175     if (!isDeepEqual(actual, expected)) {
   176       this.pass(message);
   177     }
   178     else {
   179       this.fail({
   180         actual: actual,
   181         expected: expected,
   182         message: message,
   183         operator: "notDeepEqual"
   184       });
   185     }
   186   },
   188   /**
   189    * The strict equality assertion tests strict equality, as determined by
   190    * `===`.
   191    * @example
   192    *    assert.strictEqual(null, null, "`null` is `null`")
   193    */
   194   strictEqual: function strictEqual(actual, expected, message) {
   195     if (actual === expected) {
   196       this.pass(message);
   197     }
   198     else {
   199       this.fail({
   200         actual: actual,
   201         expected: expected,
   202         message: message,
   203         operator: "==="
   204       });
   205     }
   206   },
   208   /**
   209    * The strict non-equality assertion tests for strict inequality, as
   210    * determined by `!==`.
   211    * @example
   212    *    assert.notStrictEqual(null, undefined, "`null` is not `undefined`");
   213    */
   214   notStrictEqual: function notStrictEqual(actual, expected, message) {
   215     if (actual !== expected) {
   216       this.pass(message);
   217     }
   218     else {
   219       this.fail({
   220         actual: actual,
   221         expected: expected,
   222         message: message,
   223         operator: "!=="
   224       })
   225     }
   226   },
   228   /**
   229    * The assertion whether or not given `block` throws an exception. If optional
   230    * `Error` argument is provided and it's type of function thrown error is
   231    * asserted to be an instance of it, if type of `Error` is string then message
   232    * of throw exception is asserted to contain it.
   233    * @param {Function} block
   234    *    Function that is expected to throw.
   235    * @param {Error|RegExp} [Error]
   236    *    Error constructor that is expected to be thrown or a string that
   237    *    must be contained by a message of the thrown exception, or a RegExp
   238    *    matching a message of the thrown exception.
   239    * @param {String} message
   240    *    Description message
   241    *
   242    * @examples
   243    *
   244    *    assert.throws(function block() {
   245    *      doSomething(4)
   246    *    }, "Object is expected", "Incorrect argument is passed");
   247    *
   248    *    assert.throws(function block() {
   249    *      Object.create(5)
   250    *    }, TypeError, "TypeError is thrown");
   251    */
   252   throws: function throws(block, Error, message) {
   253     let threw = false;
   254     let exception = null;
   256     // If third argument is not provided and second argument is a string it
   257     // means that optional `Error` argument was not passed, so we shift
   258     // arguments.
   259     if (isString(Error) && isUndefined(message)) {
   260       message = Error;
   261       Error = undefined;
   262     }
   264     // Executing given `block`.
   265     try {
   266       block();
   267     }
   268     catch (e) {
   269       threw = true;
   270       exception = e;
   271     }
   273     // If exception was thrown and `Error` argument was not passed assert is
   274     // passed.
   275     if (threw && (isUndefined(Error) ||
   276                  // If passed `Error` is RegExp using it's test method to
   277                  // assert thrown exception message.
   278                  (isRegExp(Error) && Error.test(exception.message)) ||
   279                  // If passed `Error` is a constructor function testing if
   280                  // thrown exception is an instance of it.
   281                  (isFunction(Error) && instanceOf(exception, Error))))
   282     {
   283       this.pass(message);
   284     }
   286     // Otherwise we report assertion failure.
   287     else {
   288       let failure = {
   289         message: message,
   290         operator: "throws"
   291       };
   293       if (exception)
   294         failure.actual = exception;
   296       if (Error)
   297         failure.expected = Error;
   299       this.fail(failure);
   300     }
   301   }
   302 };
   303 exports.Assert = Assert;
   305 function isDeepEqual(actual, expected) {
   307   // 7.1. All identical values are equivalent, as determined by ===.
   308   if (actual === expected) {
   309     return true;
   310   }
   312   // 7.2. If the expected value is a Date object, the actual value is
   313   // equivalent if it is also a Date object that refers to the same time.
   314   else if (isDate(actual) && isDate(expected)) {
   315     return actual.getTime() === expected.getTime();
   316   }
   318   // XXX specification bug: this should be specified
   319   else if (isPrimitive(actual) || isPrimitive(expected)) {
   320     return expected === actual;
   321   }
   323   // 7.3. Other pairs that do not both pass typeof value == "object",
   324   // equivalence is determined by ==.
   325   else if (!isObject(actual) && !isObject(expected)) {
   326     return actual == expected;
   327   }
   329   // 7.4. For all other Object pairs, including Array objects, equivalence is
   330   // determined by having the same number of owned properties (as verified
   331   // with Object.prototype.hasOwnProperty.call), the same set of keys
   332   // (although not necessarily the same order), equivalent values for every
   333   // corresponding key, and an identical "prototype" property. Note: this
   334   // accounts for both named and indexed properties on Arrays.
   335   else {
   336     return actual.prototype === expected.prototype &&
   337            isEquivalent(actual, expected);
   338   }
   339 }
   341 function isEquivalent(a, b, stack) {
   342   let aKeys = Object.keys(a);
   343   let bKeys = Object.keys(b);
   345   return aKeys.length === bKeys.length &&
   346           isArrayEquivalent(aKeys.sort(), bKeys.sort()) &&
   347           aKeys.every(function(key) {
   348             return isDeepEqual(a[key], b[key], stack)
   349           });
   350 }
   352 function isArrayEquivalent(a, b, stack) {
   353   return isArray(a) && isArray(b) &&
   354          a.every(function(value, index) {
   355            return isDeepEqual(value, b[index]);
   356          });
   357 }

mercurial