tor-browser

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

testharness-helpers.js (5507B)


      1 /*
      2 * testharness-helpers contains various useful extensions to testharness.js to
      3 * allow them to be used across multiple tests before they have been
      4 * upstreamed. This file is intended to be usable from both document and worker
      5 * environments, so code should for example not rely on the DOM.
      6 */
      7 
      8 // Asserts that two objects |actual| and |expected| are weakly equal under the
      9 // following definition:
     10 //
     11 // |a| and |b| are weakly equal if any of the following are true:
     12 //   1. If |a| is not an 'object', and |a| === |b|.
     13 //   2. If |a| is an 'object', and all of the following are true:
     14 //     2.1 |a.p| is weakly equal to |b.p| for all own properties |p| of |a|.
     15 //     2.2 Every own property of |b| is an own property of |a|.
     16 //
     17 // This is a replacement for the version of assert_object_equals() in
     18 // testharness.js. The latter doesn't handle own properties correctly. I.e. if
     19 // |a.p| is not an own property, it still requires that |b.p| be an own
     20 // property.
     21 //
     22 // Note that |actual| must not contain cyclic references.
     23 self.assert_object_equals = function(actual, expected, description) {
     24  var object_stack = [];
     25 
     26  function _is_equal(actual, expected, prefix) {
     27    if (typeof actual !== 'object') {
     28      assert_equals(actual, expected, prefix);
     29      return;
     30    }
     31    assert_equals(typeof expected, 'object', prefix);
     32    assert_equals(object_stack.indexOf(actual), -1,
     33                  prefix + ' must not contain cyclic references.');
     34 
     35    object_stack.push(actual);
     36 
     37    Object.getOwnPropertyNames(expected).forEach(function(property) {
     38        assert_own_property(actual, property, prefix);
     39        _is_equal(actual[property], expected[property],
     40                  prefix + '.' + property);
     41      });
     42    Object.getOwnPropertyNames(actual).forEach(function(property) {
     43        assert_own_property(expected, property, prefix);
     44      });
     45 
     46    object_stack.pop();
     47  }
     48 
     49  function _brand(object) {
     50    return Object.prototype.toString.call(object).match(/^\[object (.*)\]$/)[1];
     51  }
     52 
     53  _is_equal(actual, expected,
     54            (description ? description + ': ' : '') + _brand(expected));
     55 };
     56 
     57 // Equivalent to assert_in_array, but uses a weaker equivalence relation
     58 // (assert_object_equals) than '==='.
     59 function assert_object_in_array(actual, expected_array, description) {
     60  assert_true(expected_array.some(function(element) {
     61      try {
     62        assert_object_equals(actual, element);
     63        return true;
     64      } catch (e) {
     65        return false;
     66      }
     67    }), description);
     68 }
     69 
     70 // Assert that the two arrays |actual| and |expected| contain the same set of
     71 // elements as determined by assert_object_equals. The order is not significant.
     72 //
     73 // |expected| is assumed to not contain any duplicates as determined by
     74 // assert_object_equals().
     75 function assert_array_equivalent(actual, expected, description) {
     76  assert_true(Array.isArray(actual), description);
     77  assert_equals(actual.length, expected.length, description);
     78  expected.forEach(function(expected_element) {
     79      // assert_in_array treats the first argument as being 'actual', and the
     80      // second as being 'expected array'. We are switching them around because
     81      // we want to be resilient against the |actual| array containing
     82      // duplicates.
     83      assert_object_in_array(expected_element, actual, description);
     84    });
     85 }
     86 
     87 // Asserts that two arrays |actual| and |expected| contain the same set of
     88 // elements as determined by assert_object_equals(). The corresponding elements
     89 // must occupy corresponding indices in their respective arrays.
     90 function assert_array_objects_equals(actual, expected, description) {
     91  assert_true(Array.isArray(actual), description);
     92  assert_equals(actual.length, expected.length, description);
     93  actual.forEach(function(value, index) {
     94      assert_object_equals(value, expected[index],
     95                           description + ' : object[' + index + ']');
     96    });
     97 }
     98 
     99 // Asserts that |object| that is an instance of some interface has the attribute
    100 // |attribute_name| following the conditions specified by WebIDL, but it's
    101 // acceptable that the attribute |attribute_name| is an own property of the
    102 // object because we're in the middle of moving the attribute to a prototype
    103 // chain.  Once we complete the transition to prototype chains,
    104 // assert_will_be_idl_attribute must be replaced with assert_idl_attribute
    105 // defined in testharness.js.
    106 //
    107 // FIXME: Remove assert_will_be_idl_attribute once we complete the transition
    108 // of moving the DOM attributes to prototype chains.  (http://crbug.com/43394)
    109 function assert_will_be_idl_attribute(object, attribute_name, description) {
    110  assert_equals(typeof object, "object", description);
    111 
    112  assert_true("hasOwnProperty" in object, description);
    113 
    114  // Do not test if |attribute_name| is not an own property because
    115  // |attribute_name| is in the middle of the transition to a prototype
    116  // chain.  (http://crbug.com/43394)
    117 
    118  assert_true(attribute_name in object, description);
    119 }
    120 
    121 // Stringifies a DOM object.  This function stringifies not only own properties
    122 // but also DOM attributes which are on a prototype chain.  Note that
    123 // JSON.stringify only stringifies own properties.
    124 function stringifyDOMObject(object)
    125 {
    126    function deepCopy(src) {
    127        if (typeof src != "object")
    128            return src;
    129        var dst = Array.isArray(src) ? [] : {};
    130        for (var property in src) {
    131            dst[property] = deepCopy(src[property]);
    132        }
    133        return dst;
    134    }
    135    return JSON.stringify(deepCopy(object));
    136 }