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.

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

mercurial