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 /**
     92  * Throws an exception, and prints the values in case of error.
     93  */
     94 function fail(expected, found) {
     95   // TODO(cira): Replace String with PrettyPrint for objects and arrays.
     96   var message = 'Failure: expected <' + String(expected) + '>, found <' +
     97       String(found) + '>.';
     98   throw new Error(message);
     99 }
    100 
    101 
    102 /**
    103  * Throws if two variables have different types or values.
    104  */
    105 function assertEquals(expected, found) {
    106   if (!deepEquals(expected, found)) {
    107     fail(expected, found);
    108   }
    109 }
    110 
    111 
    112 /**
    113  * Throws if value is false.
    114  */
    115 function assertTrue(value) {
    116   assertEquals(true, value)
    117 }
    118 
    119 
    120 /**
    121  * Throws if value is true.
    122  */
    123 function assertFalse(value) {
    124   assertEquals(false, value);
    125 }
    126 
    127 
    128 /**
    129  * Returns true if code throws specified exception.
    130  */
    131 function assertThrows(code, type_opt, cause_opt) {
    132   var threwException = true;
    133   try {
    134     if (typeof code == 'function') {
    135       code();
    136     } else {
    137       eval(code);
    138     }
    139     threwException = false;
    140   } catch (e) {
    141     if (typeof type_opt == 'function') {
    142       assertInstanceof(e, type_opt);
    143     }
    144     if (arguments.length >= 3) {
    145       assertEquals(e.type, cause_opt);
    146     }
    147     // Success.
    148     return;
    149   }
    150   throw new Error("Did not throw exception");
    151 }
    152 
    153 
    154 /**
    155  * Throws an exception if code throws.
    156  */
    157 function assertDoesNotThrow(code, name_opt) {
    158   try {
    159     if (typeof code == 'function') {
    160       code();
    161     } else {
    162       eval(code);
    163     }
    164   } catch (e) {
    165     fail("threw an exception: ", e.message || e, name_opt);
    166   }
    167 }
    168 
    169 
    170 /**
    171  * Throws if obj is not of given type.
    172  */
    173 function assertInstanceof(obj, type) {
    174   if (!(obj instanceof type)) {
    175     var actualTypeName = null;
    176     var actualConstructor = Object.prototypeOf(obj).constructor;
    177     if (typeof actualConstructor == "function") {
    178       actualTypeName = actualConstructor.name || String(actualConstructor);
    179     }
    180     throw new Error('Object <' + obj + '> is not an instance of <' +
    181          (type.name || type) + '>' +
    182          (actualTypeName ? ' but of < ' + actualTypeName + '>' : ''));
    183   }
    184 }
    185