OLD | NEW |
1 // Copyright 2008 the V8 project authors. All rights reserved. | 1 // Copyright 2008 the V8 project authors. All rights reserved. |
2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
4 // met: | 4 // met: |
5 // | 5 // |
6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
(...skipping 13 matching lines...) Expand all Loading... |
24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | 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. | 26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
27 | 27 |
28 /** | 28 /** |
29 * This test uses assert{True,False}(... == ...) instead of | 29 * This test uses assert{True,False}(... == ...) instead of |
30 * assertEquals(..., ...) to not rely on the details of the | 30 * assertEquals(..., ...) to not rely on the details of the |
31 * implementation of assertEquals. | 31 * implementation of assertEquals. |
32 */ | 32 */ |
33 | 33 |
34 assertTrue (void 0 == void 0, "void 0 == void 0"); | 34 function testEqual(a, b) { |
35 assertTrue (null == null, "null == null"); | 35 assertTrue(a == b); |
36 assertFalse(NaN == NaN, "NaN == NaN"); | 36 assertTrue(b == a); |
37 assertFalse(NaN == 0, "NaN == 0"); | 37 assertFalse(a != b); |
38 assertFalse(0 == NaN, "0 == NaN"); | 38 assertFalse(b != a); |
39 assertFalse(NaN == Infinity, "NaN == Inf"); | 39 } |
40 assertFalse(Infinity == NaN, "Inf == NaN"); | 40 |
41 | 41 function testNotEqual(a, b) { |
42 assertTrue(Number.MAX_VALUE == Number.MAX_VALUE, "MAX == MAX"); | 42 assertFalse(a == b); |
43 assertTrue(Number.MIN_VALUE == Number.MIN_VALUE, "MIN == MIN"); | 43 assertFalse(b == a); |
44 assertTrue(Infinity == Infinity, "Inf == Inf"); | 44 assertTrue(a != b); |
45 assertTrue(-Infinity == -Infinity, "-Inf == -Inf"); | 45 assertTrue(b != a); |
46 | 46 } |
47 assertTrue(0 == 0, "0 == 0"); | 47 |
48 assertTrue(0 == -0, "0 == -0"); | 48 // Object where ToPrimitive returns value. |
49 assertTrue(-0 == 0, "-0 == 0"); | 49 function Wrapper(value) { |
50 assertTrue(-0 == -0, "-0 == -0"); | 50 this.value = value; |
51 | 51 this.valueOf = function () { return this.value; }; |
52 assertFalse(0.9 == 1, "0.9 == 1"); | 52 } |
53 assertFalse(0.999999 == 1, "0.999999 == 1"); | 53 |
54 assertFalse(0.9999999999 == 1, "0.9999999999 == 1"); | 54 // Object where ToPrimitive returns value by failover to toString when |
55 assertFalse(0.9999999999999 == 1, "0.9999999999999 == 1"); | 55 // valueOf isn't a function. |
56 | 56 function Wrapper2(value) { |
57 assertTrue('hello' == 'hello', "'hello' == 'hello'"); | 57 this.value = value; |
58 | 58 this.valueOf = null; |
59 assertTrue (true == true, "true == true"); | 59 this.toString = function () { return this.value; }; |
60 assertTrue (false == false, "false == false"); | 60 } |
61 assertFalse(true == false, "true == false"); | 61 |
62 assertFalse(false == true, "false == true"); | 62 |
63 | 63 // Compare values of same type. |
64 assertFalse(new Wrapper(null) == new Wrapper(null), "new Wrapper(null) == new
Wrapper(null)"); | 64 |
65 assertFalse(new Boolean(true) == new Boolean(true), "new Boolean(true) == new
Boolean(true)"); | 65 // Numbers are equal if same, unless NaN, which isn't equal to anything, and |
66 assertFalse(new Boolean(false) == new Boolean(false), "new Boolean(false) == new
Boolean(false)"); | 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 |
67 | 109 |
68 (function () { | 110 (function () { |
69 var x = new Wrapper(null); | 111 var x = new Wrapper(null); |
70 var y = x, z = x; | 112 var y = x, z = x; |
71 assertTrue(y == x); | 113 testEqual(y, x); |
72 })(); | 114 })(); |
73 | 115 |
74 (function () { | 116 (function () { |
75 var x = new Boolean(true); | 117 var x = new Boolean(true); |
76 var y = x, z = x; | 118 var y = x, z = x; |
77 assertTrue(y == x); | 119 testEqual(y, x); |
78 })(); | 120 })(); |
79 | 121 |
80 (function () { | 122 (function () { |
81 var x = new Boolean(false); | 123 var x = new Boolean(false); |
82 var y = x, z = x; | 124 var y = x, z = x; |
83 assertTrue(y == x); | 125 testEqual(y, x); |
84 })(); | 126 })(); |
85 | 127 |
86 assertTrue(null == void 0, "null == void 0"); | 128 // Test comparing values of different types. |
87 assertTrue(void 0 == null, "void 0 == null"); | 129 |
88 assertFalse(new Wrapper(null) == null, "new Wrapper(null) == null"); | 130 // Null and undefined are equal to each-other, and to nothing else. |
89 assertFalse(null == new Wrapper(null), "null == new Wrapper(null)"); | 131 testEqual(null, undefined); |
90 | 132 testEqual(undefined, null); |
91 assertTrue(1 == '1', "1 == '1"); | 133 |
92 assertTrue(255 == '0xff', "255 == '0xff'"); | 134 testNotEqual(null, new Wrapper(null)); |
93 assertTrue(0 == '\r', "0 == '\\r'"); | 135 testNotEqual(null, 0); |
94 assertTrue(1e19 == '1e19', "1e19 == '1e19'"); | 136 testNotEqual(null, false); |
95 | 137 testNotEqual(null, ""); |
96 assertTrue(new Boolean(true) == true, "new Boolean(true) == true"); | 138 testNotEqual(null, new Object()); |
97 assertTrue(new Boolean(false) == false, "new Boolean(false) == false"); | 139 testNotEqual(undefined, new Wrapper(undefined)); |
98 assertTrue(true == new Boolean(true), "true == new Boolean(true)"); | 140 testNotEqual(undefined, 0); |
99 assertTrue(false == new Boolean(false), "false == new Boolean(false)"); | 141 testNotEqual(undefined, false); |
100 | 142 testNotEqual(undefined, ""); |
101 assertTrue(Boolean(true) == true, "Boolean(true) == true"); | 143 testNotEqual(undefined, new Object()); |
102 assertTrue(Boolean(false) == false, "Boolean(false) == false"); | 144 |
103 assertTrue(true == Boolean(true), "true == Boolean(true)"); | 145 // Numbers compared to Strings will convert the string to a number using |
104 assertTrue(false == Boolean(false), "false == Boolean(false)"); | 146 // the internal ToNumber conversion. |
105 | 147 |
106 assertTrue(new Wrapper(true) == true, "new Wrapper(true) == true"); | 148 testEqual(1, '1'); |
107 assertTrue(new Wrapper(false) == false, "new Wrapper(false) == false"); | 149 testEqual(255, '0xff'); |
108 assertTrue(true == new Wrapper(true), "true = new Wrapper(true)"); | 150 testEqual(0, '\r'); // ToNumber ignores tailing and trailing whitespace. |
109 assertTrue(false == new Wrapper(false), "false = new Wrapper(false)"); | 151 testEqual(1e19, '1e19'); |
110 | 152 testEqual(Infinity, "Infinity"); |
111 function Wrapper(value) { | 153 |
112 this.value = value; | 154 // Booleans compared to anything else will be converted to numbers. |
113 this.valueOf = function () { return this.value; }; | 155 testEqual(false, 0); |
114 } | 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); |
OLD | NEW |