tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

test_assert.js (13269B)


      1 /* Any copyright is dedicated to the Public Domain.
      2   http://creativecommons.org/publicdomain/zero/1.0/ */
      3 
      4 // Test cases borrowed and adapted from:
      5 // https://github.com/joyent/node/blob/6101eb184db77d0b11eb96e48744e57ecce4b73d/test/simple/test-assert.js
      6 // MIT license: http://opensource.org/licenses/MIT
      7 
      8 var { Assert } = ChromeUtils.importESModule(
      9  "resource://testing-common/Assert.sys.mjs"
     10 );
     11 
     12 add_task(function test_basic_asserts() {
     13  let assert = new Assert();
     14 
     15  function makeBlock(f, ...args) {
     16    return function () {
     17      return f.apply(assert, args);
     18    };
     19  }
     20 
     21  function protoCtrChain(o) {
     22    let result = [];
     23    while ((o = o.__proto__)) {
     24      result.push(o.constructor);
     25    }
     26    return result.join();
     27  }
     28 
     29  function indirectInstanceOf(obj, cls) {
     30    if (obj instanceof cls) {
     31      return true;
     32    }
     33    let clsChain = protoCtrChain(cls.prototype);
     34    let objChain = protoCtrChain(obj);
     35    return objChain.slice(-clsChain.length) === clsChain;
     36  }
     37 
     38  assert.ok(
     39    indirectInstanceOf(Assert.AssertionError.prototype, Error),
     40    "Assert.AssertionError instanceof Error"
     41  );
     42 
     43  assert.throws(
     44    makeBlock(assert.ok, false),
     45    Assert.AssertionError,
     46    "ok(false)"
     47  );
     48 
     49  assert.ok(true, "ok(true)");
     50 
     51  assert.ok("test", "ok('test')");
     52 
     53  assert.throws(
     54    makeBlock(assert.equal, true, false),
     55    Assert.AssertionError,
     56    "equal"
     57  );
     58 
     59  assert.equal(null, null, "equal");
     60 
     61  assert.equal(undefined, undefined, "equal");
     62 
     63  assert.equal(null, undefined, "equal");
     64 
     65  assert.equal(true, true, "equal");
     66 
     67  assert.notEqual(true, false, "notEqual");
     68 
     69  assert.throws(
     70    makeBlock(assert.notEqual, true, true),
     71    Assert.AssertionError,
     72    "notEqual"
     73  );
     74 
     75  assert.throws(
     76    makeBlock(assert.strictEqual, 2, "2"),
     77    Assert.AssertionError,
     78    "strictEqual"
     79  );
     80 
     81  assert.throws(
     82    makeBlock(assert.strictEqual, null, undefined),
     83    Assert.AssertionError,
     84    "strictEqual"
     85  );
     86 
     87  assert.notStrictEqual(2, "2", "notStrictEqual");
     88 
     89  // deepEquals joy!
     90  // 7.2
     91  assert.deepEqual(
     92    new Date(2000, 3, 14),
     93    new Date(2000, 3, 14),
     94    "deepEqual date"
     95  );
     96  assert.deepEqual(new Date(NaN), new Date(NaN), "deepEqual invalid dates");
     97 
     98  assert.throws(
     99    makeBlock(assert.deepEqual, new Date(), new Date(2000, 3, 14)),
    100    Assert.AssertionError,
    101    "deepEqual date"
    102  );
    103 
    104  // 7.3
    105  assert.deepEqual(/a/, /a/);
    106  assert.deepEqual(/a/g, /a/g);
    107  assert.deepEqual(/a/i, /a/i);
    108  assert.deepEqual(/a/m, /a/m);
    109  assert.deepEqual(/a/gim, /a/gim);
    110  assert.throws(makeBlock(assert.deepEqual, /ab/, /a/), Assert.AssertionError);
    111  assert.throws(makeBlock(assert.deepEqual, /a/g, /a/), Assert.AssertionError);
    112  assert.throws(makeBlock(assert.deepEqual, /a/i, /a/), Assert.AssertionError);
    113  assert.throws(makeBlock(assert.deepEqual, /a/m, /a/), Assert.AssertionError);
    114  assert.throws(
    115    makeBlock(assert.deepEqual, /a/gim, /a/im),
    116    Assert.AssertionError
    117  );
    118 
    119  let re1 = /a/;
    120  re1.lastIndex = 3;
    121  assert.throws(makeBlock(assert.deepEqual, re1, /a/), Assert.AssertionError);
    122 
    123  // 7.4
    124  assert.deepEqual(4, "4", "deepEqual == check");
    125  assert.deepEqual(true, 1, "deepEqual == check");
    126  assert.throws(
    127    makeBlock(assert.deepEqual, 4, "5"),
    128    Assert.AssertionError,
    129    "deepEqual == check"
    130  );
    131 
    132  // 7.5
    133  // having the same number of owned properties && the same set of keys
    134  assert.deepEqual({ a: 4 }, { a: 4 });
    135  assert.deepEqual({ a: 4, b: "2" }, { a: 4, b: "2" });
    136  assert.deepEqual([4], ["4"]);
    137  assert.throws(
    138    makeBlock(assert.deepEqual, { a: 4 }, { a: 4, b: true }),
    139    Assert.AssertionError
    140  );
    141  assert.deepEqual(["a"], { 0: "a" });
    142 
    143  let a1 = [1, 2, 3];
    144  let a2 = [1, 2, 3];
    145  a1.a = "test";
    146  a1.b = true;
    147  a2.b = true;
    148  a2.a = "test";
    149  assert.throws(
    150    makeBlock(assert.deepEqual, Object.keys(a1), Object.keys(a2)),
    151    Assert.AssertionError
    152  );
    153  assert.deepEqual(a1, a2);
    154 
    155  let nbRoot = {
    156    toString() {
    157      return this.first + " " + this.last;
    158    },
    159  };
    160 
    161  function nameBuilder(first, last) {
    162    this.first = first;
    163    this.last = last;
    164    return this;
    165  }
    166  nameBuilder.prototype = nbRoot;
    167 
    168  function nameBuilder2(first, last) {
    169    this.first = first;
    170    this.last = last;
    171    return this;
    172  }
    173  nameBuilder2.prototype = nbRoot;
    174 
    175  let nb1 = new nameBuilder("Ryan", "Dahl");
    176  let nb2 = new nameBuilder2("Ryan", "Dahl");
    177 
    178  assert.deepEqual(nb1, nb2);
    179 
    180  nameBuilder2.prototype = Object;
    181  nb2 = new nameBuilder2("Ryan", "Dahl");
    182  assert.throws(makeBlock(assert.deepEqual, nb1, nb2), Assert.AssertionError);
    183 
    184  // String literal + object
    185  assert.throws(makeBlock(assert.deepEqual, "a", {}), Assert.AssertionError);
    186 
    187  // Testing the throwing
    188  function thrower(errorConstructor) {
    189    throw new errorConstructor("test");
    190  }
    191  makeBlock(thrower, Assert.AssertionError);
    192  makeBlock(thrower, Assert.AssertionError);
    193 
    194  // the basic calls work
    195  assert.throws(
    196    makeBlock(thrower, Assert.AssertionError),
    197    Assert.AssertionError,
    198    "message"
    199  );
    200  assert.throws(
    201    makeBlock(thrower, Assert.AssertionError),
    202    Assert.AssertionError
    203  );
    204  assert.throws(
    205    makeBlock(thrower, Assert.AssertionError),
    206    Assert.AssertionError
    207  );
    208 
    209  // if not passing an error, catch all.
    210  assert.throws(makeBlock(thrower, TypeError), TypeError);
    211 
    212  // when passing a type, only catch errors of the appropriate type
    213  let threw = false;
    214  try {
    215    assert.throws(makeBlock(thrower, TypeError), Assert.AssertionError);
    216  } catch (e) {
    217    threw = true;
    218    assert.ok(e instanceof TypeError, "type");
    219  }
    220  assert.equal(
    221    true,
    222    threw,
    223    "Assert.throws with an explicit error is eating extra errors",
    224    Assert.AssertionError
    225  );
    226  threw = false;
    227 
    228  function ifError(err) {
    229    if (err) {
    230      throw err;
    231    }
    232  }
    233  assert.throws(function () {
    234    ifError(new Error("test error"));
    235  }, /test error/);
    236 
    237  // make sure that validating using constructor really works
    238  threw = false;
    239  try {
    240    assert.throws(function () {
    241      throw new Error({});
    242    }, Array);
    243  } catch (e) {
    244    threw = true;
    245  }
    246  assert.ok(threw, "wrong constructor validation");
    247 
    248  // use a RegExp to validate error message
    249  assert.throws(makeBlock(thrower, TypeError), /test/);
    250 
    251  // use a fn to validate error object
    252  assert.throws(makeBlock(thrower, TypeError), function (err) {
    253    if (err instanceof TypeError && /test/.test(err)) {
    254      return true;
    255    }
    256    return false;
    257  });
    258  // do the same with an arrow function
    259  assert.throws(makeBlock(thrower, TypeError), err => {
    260    if (err instanceof TypeError && /test/.test(err)) {
    261      return true;
    262    }
    263    return false;
    264  });
    265 
    266  function testAssertionMessage(actual, expected) {
    267    try {
    268      assert.equal(actual, "");
    269    } catch (e) {
    270      assert.equal(
    271        e.toString(),
    272        ["AssertionError:", expected, "==", '""'].join(" ")
    273      );
    274    }
    275  }
    276  testAssertionMessage(undefined, '"undefined"');
    277  testAssertionMessage(null, "null");
    278  testAssertionMessage(true, "true");
    279  testAssertionMessage(false, "false");
    280  testAssertionMessage(0, "0");
    281  testAssertionMessage(100, "100");
    282  testAssertionMessage(NaN, '"NaN"');
    283  testAssertionMessage(Infinity, '"Infinity"');
    284  testAssertionMessage(-Infinity, '"-Infinity"');
    285  testAssertionMessage("", '""');
    286  testAssertionMessage("foo", '"foo"');
    287  testAssertionMessage([], "[]");
    288  testAssertionMessage([1, 2, 3], "[1,2,3]");
    289  testAssertionMessage(/a/, '"/a/"');
    290  testAssertionMessage(/abc/gim, '"/abc/gim"');
    291  testAssertionMessage(function f() {}, '"function f() {}"');
    292  testAssertionMessage({}, "{}");
    293  testAssertionMessage({ a: undefined, b: null }, '{"a":"undefined","b":null}');
    294  testAssertionMessage(
    295    { a: NaN, b: Infinity, c: -Infinity },
    296    '{"a":"NaN","b":"Infinity","c":"-Infinity"}'
    297  );
    298 
    299  // https://github.com/joyent/node/issues/2893
    300  try {
    301    assert.throws(function () {
    302      ifError(null);
    303    });
    304  } catch (e) {
    305    threw = true;
    306    assert.equal(
    307      e.message,
    308      "Error: The 'expected' argument was not supplied to Assert.throws() - false == true"
    309    );
    310  }
    311  assert.ok(threw);
    312 
    313  // https://github.com/joyent/node/issues/5292
    314  try {
    315    assert.equal(1, 2);
    316  } catch (e) {
    317    assert.equal(e.toString().split("\n")[0], "AssertionError: 1 == 2");
    318  }
    319 
    320  try {
    321    assert.equal(1, 2, "oh no");
    322  } catch (e) {
    323    assert.equal(e.toString().split("\n")[0], "AssertionError: oh no - 1 == 2");
    324  }
    325 
    326  // Need to JSON.stringify so that their length is > 128 characters.
    327  let longArray0 = Array.from(Array(50), (v, i) => i);
    328  let longArray1 = longArray0.concat([51]);
    329  try {
    330    assert.deepEqual(longArray0, longArray1);
    331  } catch (e) {
    332    let message = e.toString();
    333    // Just check that they're both entirely present in the message
    334    assert.ok(message.includes(JSON.stringify(longArray0)));
    335    assert.ok(message.includes(JSON.stringify(longArray1)));
    336  }
    337 
    338  // Test XPCShell-test integration:
    339  ok(true, "OK, this went well");
    340  deepEqual(/a/g, /a/g, "deep equal should work on RegExp");
    341  deepEqual(/a/gim, /a/gim, "deep equal should work on RegExp");
    342  deepEqual(
    343    { a: 4, b: "1" },
    344    { b: "1", a: 4 },
    345    "deep equal should work on regular Object"
    346  );
    347  deepEqual(a1, a2, "deep equal should work on Array with Object properties");
    348 
    349  // Test robustness of reporting:
    350  equal(
    351    new Assert.AssertionError({
    352      actual: {
    353        toJSON() {
    354          throw new Error("bam!");
    355        },
    356      },
    357      expected: "foo",
    358      operator: "=",
    359    }).message,
    360    '[object Object] = "foo"'
    361  );
    362 
    363  let message;
    364  assert.greater(3, 2);
    365  try {
    366    assert.greater(2, 2);
    367  } catch (e) {
    368    message = e.toString().split("\n")[0];
    369  }
    370  assert.equal(message, "AssertionError: 2 > 2");
    371 
    372  assert.greaterOrEqual(2, 2);
    373  try {
    374    assert.greaterOrEqual(1, 2);
    375  } catch (e) {
    376    message = e.toString().split("\n")[0];
    377  }
    378  assert.equal(message, "AssertionError: 1 >= 2");
    379 
    380  assert.less(1, 2);
    381  assert.throws(
    382    () => assert.less(2, 2),
    383    e => e == "AssertionError: 2 < 2"
    384  );
    385 
    386  assert.lessOrEqual(2, 2);
    387  assert.throws(
    388    () => assert.lessOrEqual(2, 1),
    389    e => e == "AssertionError: 2 <= 1"
    390  );
    391 
    392  assert.throws(
    393    () => assert.greater(NaN, 0),
    394    e => e == "AssertionError: 'NaN' is not a number or date."
    395  );
    396 
    397  assert.throws(
    398    () => assert.greater(0, NaN),
    399    e => e == "AssertionError: 'NaN' is not a number or date."
    400  );
    401 
    402  let now = new Date();
    403  let firefoxReleaseDate = new Date("2004-11-09");
    404  assert.less(firefoxReleaseDate, now);
    405  assert.throws(
    406    () => assert.less(now, now),
    407    e => e == `AssertionError: "${now.toJSON()}" < "${now.toJSON()}"`
    408  );
    409 
    410  assert.lessOrEqual(now, now);
    411  assert.greaterOrEqual(now, now);
    412  assert.throws(
    413    () => assert.greaterOrEqual(firefoxReleaseDate, now),
    414    e =>
    415      e ==
    416      `AssertionError: "${firefoxReleaseDate.toJSON()}" >= "${now.toJSON()}"`
    417  );
    418 
    419  // Invalid date:
    420  assert.throws(
    421    () => assert.greater(firefoxReleaseDate, new Date("invalid")),
    422    e => e == "AssertionError: 'Invalid Date' is not a number or date."
    423  );
    424 
    425  /* ---- stringMatches ---- */
    426  assert.stringMatches("hello world", /llo\s/);
    427  assert.stringMatches("hello world", "llo\\s");
    428  assert.throws(
    429    () => assert.stringMatches("hello world", /foo/),
    430    /^AssertionError: "hello world" matches "\/foo\/"/
    431  );
    432  assert.throws(
    433    () => assert.stringMatches(5, /foo/),
    434    /^AssertionError: Expected a string for lhs, but "5" isn't a string./
    435  );
    436  assert.throws(
    437    () => assert.stringMatches("foo bar", "+"),
    438    /^AssertionError: Expected a valid regular expression for rhs, but "\+" isn't one./
    439  );
    440 
    441  /* ---- stringContains ---- */
    442  assert.stringContains("hello world", "llo");
    443  assert.throws(
    444    () => assert.stringContains(5, "foo"),
    445    /^AssertionError: Expected a string for both lhs and rhs, but either "5" or "foo" is not a string./
    446  );
    447 });
    448 
    449 add_task(async function test_rejects() {
    450  let assert = new Assert();
    451 
    452  // A helper function to test failures.
    453  async function checkRejectsFails(err, expected) {
    454    try {
    455      await assert.rejects(Promise.reject(err), expected);
    456      ok(false, "should have thrown");
    457    } catch (ex) {
    458      deepEqual(ex, err, "Assert.rejects threw the original unexpected error");
    459    }
    460  }
    461 
    462  // A "throwable" error that's not an actual Error().
    463  let SomeErrorLikeThing = function () {};
    464 
    465  // The actual tests...
    466 
    467  // An explicit error object:
    468  // An instance to check against.
    469  await assert.rejects(Promise.reject(new Error("oh no")), Error, "rejected");
    470  // A regex to match against the message.
    471  await assert.rejects(Promise.reject(new Error("oh no")), /oh no/, "rejected");
    472 
    473  // Failure cases:
    474  // An instance to check against that doesn't match.
    475  await checkRejectsFails(new Error("something else"), SomeErrorLikeThing);
    476  // A regex that doesn't match.
    477  await checkRejectsFails(new Error("something else"), /oh no/);
    478 
    479  // Check simple string messages.
    480  await assert.rejects(Promise.reject("oh no"), /oh no/, "rejected");
    481  // Wrong message.
    482  await checkRejectsFails("something else", /oh no/);
    483 
    484  // A non-rejection should also be an assertion failure:
    485  try {
    486    await assert.rejects(Promise.resolve(), /./, "ReSoLvEd");
    487    ok(false, "should have rejected");
    488  } catch (ex) {
    489    deepEqual(ex.message, "Missing expected exception ReSoLvEd");
    490  }
    491 });