Home | History | Annotate | Download | only in intl
      1 // Copyright 2013 the V8 project authors. All rights reserved.
      2 // Redistribution and use in source and binary forms, with or without
      3 // modification, are permitted provided that the following conditions are
      4 // met:
      5 //
      6 //     * Redistributions of source code must retain the above copyright
      7 //       notice, this list of conditions and the following disclaimer.
      8 //     * Redistributions in binary form must reproduce the above
      9 //       copyright notice, this list of conditions and the following
     10 //       disclaimer in the documentation and/or other materials provided
     11 //       with the distribution.
     12 //     * Neither the name of Google Inc. nor the names of its
     13 //       contributors may be used to endorse or promote products derived
     14 //       from this software without specific prior written permission.
     15 //
     16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
     18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
     19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
     20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
     21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
     22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     27 
     28 // Some methods are taken from v8/test/mjsunit/mjsunit.js
     29 
     30 /**
     31  * Compares two objects for key/value equality.
     32  * Returns true if they are equal, false otherwise.
     33  */
     34 function deepObjectEquals(a, b) {
     35   var aProps = Object.keys(a);
     36   aProps.sort();
     37   var bProps = Object.keys(b);
     38   bProps.sort();
     39   if (!deepEquals(aProps, bProps)) {
     40     return false;
     41   }
     42   for (var i = 0; i < aProps.length; i++) {
     43     if (!deepEquals(a[aProps[i]], b[aProps[i]])) {
     44       return false;
     45     }
     46   }
     47   return true;
     48 }
     49 
     50 
     51 /**
     52  * Compares two JavaScript values for type and value equality.
     53  * It checks internals of arrays and objects.
     54  */
     55 function deepEquals(a, b) {
     56   if (a === b) {
     57     // Check for -0.
     58     if (a === 0) return (1 / a) === (1 / b);
     59     return true;
     60   }
     61   if (typeof a != typeof b) return false;
     62   if (typeof a == 'number') return isNaN(a) && isNaN(b);
     63   if (typeof a !== 'object' && typeof a !== 'function') return false;
     64   // Neither a nor b is primitive.
     65   var objectClass = classOf(a);
     66   if (objectClass !== classOf(b)) return false;
     67   if (objectClass === 'RegExp') {
     68     // For RegExp, just compare pattern and flags using its toString.
     69     return (a.toString() === b.toString());
     70   }
     71   // Functions are only identical to themselves.
     72   if (objectClass === 'Function') return false;
     73   if (objectClass === 'Array') {
     74     var elementCount = 0;
     75     if (a.length != b.length) {
     76       return false;
     77     }
     78     for (var i = 0; i < a.length; i++) {
     79       if (!deepEquals(a[i], b[i])) return false;
     80     }
     81     return true;
     82   }
     83   if (objectClass == 'String' || objectClass == 'Number' ||
     84       objectClass == 'Boolean' || objectClass == 'Date') {
     85     if (a.valueOf() !== b.valueOf()) return false;
     86   }
     87   return deepObjectEquals(a, b);
     88 }
     89 
     90 /**
     91  * Throws an exception containing the user_message (if any) and the values.
     92  */
     93 function fail(expected, found, user_message = '') {
     94   // TODO(cira): Replace String with PrettyPrint for objects and arrays.
     95   var message = 'Failure' + (user_message ? ' (' + user_message + ')' : '') +
     96       ': expected <' + String(expected) + '>, found <' + String(found) + '>.';
     97   throw new Error(message);
     98 }
     99 
    100 
    101 /**
    102  * Throws if two variables have different types or values.
    103  */
    104 function assertEquals(expected, found, user_message = '') {
    105   if (!deepEquals(expected, found)) {
    106     fail(expected, found, user_message);
    107   }
    108 }
    109 
    110 
    111 /**
    112  * Throws if value is false.
    113  */
    114 function assertTrue(value, user_message = '') {
    115   assertEquals(true, value, user_message);
    116 }
    117 
    118 
    119 /**
    120  * Throws if value is true.
    121  */
    122 function assertFalse(value, user_message = '') {
    123   assertEquals(false, value, user_message);
    124 }
    125 
    126 
    127 /**
    128  * Runs code() and asserts that it throws the specified exception.
    129  */
    130 function assertThrows(code, type_opt, cause_opt) {
    131   try {
    132     if (typeof code == 'function') {
    133       code();
    134     } else {
    135       eval(code);
    136     }
    137   } catch (e) {
    138     if (typeof type_opt == 'function') {
    139       assertInstanceof(e, type_opt);
    140     }
    141     if (arguments.length >= 3) {
    142       assertEquals(cause_opt, e.type, 'thrown exception type mismatch');
    143     }
    144     // Success.
    145     return;
    146   }
    147   var expected = arguments.length >= 3 ? cause_opt :
    148       typeof type_opt == 'function' ? type_opt : 'any exception';
    149   fail(expected, 'no exception', 'expected thrown exception');
    150 }
    151 
    152 
    153 /**
    154  * Runs code() and asserts that it does now throw any exception.
    155  */
    156 function assertDoesNotThrow(code, user_message = '') {
    157   try {
    158     if (typeof code == 'function') {
    159       code();
    160     } else {
    161       eval(code);
    162     }
    163   } catch (e) {
    164     fail("no expection", "exception: " + String(e), user_message);
    165   }
    166 }
    167 
    168 
    169 /**
    170  * Throws if obj is not of given type.
    171  */
    172 function assertInstanceof(obj, type) {
    173   if (!(obj instanceof type)) {
    174     var actualTypeName = null;
    175     var actualConstructor = Object.prototypeOf(obj).constructor;
    176     if (typeof actualConstructor == "function") {
    177       actualTypeName = actualConstructor.name || String(actualConstructor);
    178     }
    179     throw new Error('Object <' + obj + '> is not an instance of <' +
    180          (type.name || type) + '>' +
    181          (actualTypeName ? ' but of < ' + actualTypeName + '>' : ''));
    182   }
    183 }
    184