Home | History | Annotate | Download | only in mjsunit
      1 // Copyright 2008 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 /**
     29  * This test uses assert{True,False}(... == ...) instead of
     30  * assertEquals(..., ...) to not rely on the details of the
     31  * implementation of assertEquals.
     32  */
     33 
     34 function testEqual(a, b) {
     35   assertTrue(a == b);
     36   assertTrue(b == a);
     37   assertFalse(a != b);
     38   assertFalse(b != a);
     39 }
     40 
     41 function testNotEqual(a, b) {
     42   assertFalse(a == b);
     43   assertFalse(b == a);
     44   assertTrue(a != b);
     45   assertTrue(b != a);
     46 }
     47 
     48 // Object where ToPrimitive returns value.
     49 function Wrapper(value) {
     50   this.value = value;
     51   this.valueOf = function () { return this.value; };
     52 }
     53 
     54 // Object where ToPrimitive returns value by failover to toString when
     55 // valueOf isn't a function.
     56 function Wrapper2(value) {
     57   this.value = value;
     58   this.valueOf = null;
     59   this.toString = function () { return this.value; };
     60 }
     61 
     62 
     63 // Compare values of same type.
     64 
     65 // Numbers are equal if same, unless NaN, which isn't equal to anything, and
     66 // +/-0 being equal.
     67 
     68 testNotEqual(NaN, NaN);
     69 testNotEqual(NaN, 0);
     70 testNotEqual(NaN, Infinity);
     71 
     72 testEqual(Number.MAX_VALUE, Number.MAX_VALUE);
     73 testEqual(Number.MIN_VALUE, Number.MIN_VALUE);
     74 testEqual(Infinity, Infinity);
     75 testEqual(-Infinity, -Infinity);
     76 
     77 testEqual(0, 0);
     78 testEqual(0, -0);
     79 testEqual(-0, -0);
     80 
     81 testNotEqual(0.9, 1);
     82 testNotEqual(0.999999, 1);
     83 testNotEqual(0.9999999999, 1);
     84 testNotEqual(0.9999999999999, 1);
     85 
     86 // Strings are equal if containing the same code points.
     87 
     88 testEqual('hello', 'hello');
     89 testEqual('hello', 'hel' + 'lo');
     90 testEqual('', '');
     91 testEqual('\u0020\x20', '  ');  // Escapes are not part of the value.
     92 
     93 // Booleans are equal if they are the same.
     94 
     95 testEqual(true, true);
     96 testEqual(false, false);
     97 testNotEqual(true, false);
     98 
     99 // Null and undefined are equal to themselves.
    100 
    101 testEqual(null, null);
    102 testEqual(undefined, undefined);
    103 
    104 // Objects are equal if they are the same object only.
    105 
    106 testEqual(Math, Math);
    107 testEqual(Object.prototype, Object.prototype);
    108 
    109 
    110 (function () {
    111   var x = new Wrapper(null);
    112   var y = x, z = x;
    113    testEqual(y, x);
    114 })();
    115 
    116 (function () {
    117   var x = new Boolean(true);
    118   var y = x, z = x;
    119    testEqual(y, x);
    120 })();
    121 
    122 (function () {
    123   var x = new Boolean(false);
    124   var y = x, z = x;
    125    testEqual(y, x);
    126 })();
    127 
    128 // Test comparing values of different types.
    129 
    130 // Null and undefined are equal to each-other, and to nothing else.
    131 testEqual(null, undefined);
    132 testEqual(undefined, null);
    133 
    134 testNotEqual(null, new Wrapper(null));
    135 testNotEqual(null, 0);
    136 testNotEqual(null, false);
    137 testNotEqual(null, "");
    138 testNotEqual(null, new Object());
    139 testNotEqual(undefined, new Wrapper(undefined));
    140 testNotEqual(undefined, 0);
    141 testNotEqual(undefined, false);
    142 testNotEqual(undefined, "");
    143 testNotEqual(undefined, new Object());
    144 
    145 // Numbers compared to Strings will convert the string to a number using
    146 // the internal ToNumber conversion.
    147 
    148 testEqual(1, '1');
    149 testEqual(255, '0xff');
    150 testEqual(0, '\r');  // ToNumber ignores tailing and trailing whitespace.
    151 testEqual(1e19, '1e19');
    152 testEqual(Infinity, "Infinity");
    153 
    154 // Booleans compared to anything else will be converted to numbers.
    155 testEqual(false, 0);
    156 testEqual(true, 1);
    157 testEqual(false, "0");  // String also converted to number.
    158 testEqual(true, "1");
    159 
    160 // Objects compared to Number or String (or Boolean, since that's converted
    161 // to Number too) is converted to primitive using ToPrimitive with NO HINT.
    162 // Having no hint means Date gets a string hint, and everything else gets
    163 // a number hint.
    164 
    165 testEqual(new Boolean(true), true);
    166 testEqual(new Boolean(true), 1);  // First to primtive boolean, then to number.
    167 testEqual(new Boolean(false), false);
    168 testEqual(new Boolean(false), 0);
    169 
    170 testEqual(new Wrapper(true), true);
    171 testEqual(new Wrapper(true), 1);
    172 testEqual(new Wrapper(false), false);
    173 testEqual(new Wrapper(false), 0);
    174 
    175 testEqual(new Wrapper2(true), true);
    176 testEqual(new Wrapper2(true), 1);
    177 testEqual(new Wrapper2(false), false);
    178 testEqual(new Wrapper2(false), 0);
    179 
    180 testEqual(new Number(1), true);
    181 testEqual(new Number(1), 1);
    182 testEqual(new Number(0), false);
    183 testEqual(new Number(0), 0);
    184 
    185 // Date objects convert to string, not number (and the string does not
    186 // convert to the number).
    187 testEqual(new Date(42), String(new Date(42)));
    188 testNotEqual(new Date(42), Number(new Date(42)));
    189 var dnow = new Date();
    190 testEqual(dnow, dnow);
    191 testEqual(dnow, String(dnow));
    192 testNotEqual(dnow, Number(dnow));
    193 
    194 // Doesn't just call toString, but uses ToPrimitive which tries toString first
    195 // and valueOf second.
    196 dnow.toString = null;
    197 testEqual(dnow, Number(dnow));
    198 dnow.valueOf = function () { return "42"; };
    199 testEqual(dnow, 42);
    200 dnow.toString = function () { return "1"; };
    201 testEqual(dnow, true);
    202 
    203 
    204 // Objects compared to other objects, or to null and undefined, are not
    205 // converted to primitive.
    206 testNotEqual(new Wrapper(null), new Wrapper(null));
    207 testNotEqual(new Boolean(true), new Boolean(true));
    208 testNotEqual(new Boolean(false), new Boolean(false));
    209 testNotEqual(new String("a"), new String("a"));
    210 testNotEqual(new Number(42), new Number(42));
    211 testNotEqual(new Date(42), new Date(42));
    212 testNotEqual(new Array(42), new Array(42));
    213 testNotEqual(new Object(), new Object());
    214 
    215 // Object that can't be converted to primitive.
    216 var badObject = {
    217   valueOf: null,
    218   toString: function() {
    219     return this;  // Not primitive.
    220   }
    221 };
    222 
    223 testEqual(badObject, badObject);
    224 testNotEqual(badObject, {});
    225 testNotEqual(badObject, null);
    226 testNotEqual(badObject, undefined);
    227 // Forcing conversion will throw.
    228 function testBadConversion(value) {
    229   assertThrows(function() { return badObject == value; });
    230   assertThrows(function() { return badObject != value; });
    231   assertThrows(function() { return value == badObject; });
    232   assertThrows(function() { return value != badObject; });
    233 }
    234 testBadConversion(0);
    235 testBadConversion("string");
    236 testBadConversion(true);
    237