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 function MjsUnitAssertionError(message) { 29 this.message = message; 30 } 31 32 MjsUnitAssertionError.prototype.toString = function () { 33 return this.message; 34 } 35 36 /* 37 * This file is included in all mini jsunit test cases. The test 38 * framework expects lines that signal failed tests to start with 39 * the f-word and ignore all other lines. 40 */ 41 42 function fail(expected, found, name_opt) { 43 var start; 44 if (name_opt) { 45 // Fix this when we ditch the old test runner. 46 start = "Fail" + "ure (" + name_opt + "): "; 47 } else { 48 start = "Fail" + "ure:"; 49 } 50 throw new MjsUnitAssertionError(start + " expected <" + expected + "> found <" + found + ">"); 51 } 52 53 54 function deepObjectEquals(a, b) { 55 var aProps = []; 56 for (var key in a) 57 aProps.push(key); 58 var bProps = []; 59 for (var key in b) 60 bProps.push(key); 61 aProps.sort(); 62 bProps.sort(); 63 if (!deepEquals(aProps, bProps)) 64 return false; 65 for (var i = 0; i < aProps.length; i++) { 66 if (!deepEquals(a[aProps[i]], b[aProps[i]])) 67 return false; 68 } 69 return true; 70 } 71 72 73 function deepEquals(a, b) { 74 if (a == b) return true; 75 if (typeof a == "number" && typeof b == "number" && isNaN(a) && isNaN(b)) { 76 return true; 77 } 78 if (a == null || b == null) return false; 79 if (a.constructor === RegExp || b.constructor === RegExp) { 80 return (a.constructor === b.constructor) && (a.toString === b.toString); 81 } 82 if ((typeof a) !== 'object' || (typeof b) !== 'object' || 83 (a === null) || (b === null)) 84 return false; 85 if (a.constructor === Array) { 86 if (b.constructor !== Array) 87 return false; 88 if (a.length != b.length) 89 return false; 90 for (var i = 0; i < a.length; i++) { 91 if (i in a) { 92 if (!(i in b) || !(deepEquals(a[i], b[i]))) 93 return false; 94 } else if (i in b) { 95 return false; 96 } 97 } 98 return true; 99 } else { 100 return deepObjectEquals(a, b); 101 } 102 } 103 104 105 function assertEquals(expected, found, name_opt) { 106 if (!deepEquals(found, expected)) { 107 fail(expected, found, name_opt); 108 } 109 } 110 111 112 function assertArrayEquals(expected, found, name_opt) { 113 var start = ""; 114 if (name_opt) { 115 start = name_opt + " - "; 116 } 117 assertEquals(expected.length, found.length, start + "array length"); 118 if (expected.length == found.length) { 119 for (var i = 0; i < expected.length; ++i) { 120 assertEquals(expected[i], found[i], start + "array element at index " + i); 121 } 122 } 123 } 124 125 126 function assertTrue(value, name_opt) { 127 assertEquals(true, value, name_opt); 128 } 129 130 131 function assertFalse(value, name_opt) { 132 assertEquals(false, value, name_opt); 133 } 134 135 136 function assertNaN(value, name_opt) { 137 if (!isNaN(value)) { 138 fail("NaN", value, name_opt); 139 } 140 } 141 142 143 function assertNull(value, name_opt) { 144 if (value !== null) { 145 fail("null", value, name_opt); 146 } 147 } 148 149 150 function assertNotNull(value, name_opt) { 151 if (value === null) { 152 fail("not null", value, name_opt); 153 } 154 } 155 156 157 function assertThrows(code, type_opt, cause_opt) { 158 var threwException = true; 159 try { 160 if (typeof code == 'function') { 161 code(); 162 } else { 163 eval(code); 164 } 165 threwException = false; 166 } catch (e) { 167 if (typeof type_opt == 'function') 168 assertInstanceof(e, type_opt); 169 if (arguments.length >= 3) 170 assertEquals(e.type, cause_opt); 171 // Do nothing. 172 } 173 if (!threwException) assertTrue(false, "did not throw exception"); 174 } 175 176 177 function assertInstanceof(obj, type) { 178 if (!(obj instanceof type)) { 179 assertTrue(false, "Object <" + obj + "> is not an instance of <" + type + ">"); 180 } 181 } 182 183 184 function assertDoesNotThrow(code) { 185 try { 186 if (typeof code == 'function') { 187 code(); 188 } else { 189 eval(code); 190 } 191 } catch (e) { 192 assertTrue(false, "threw an exception: " + (e.message || e)); 193 } 194 } 195 196 197 function assertUnreachable(name_opt) { 198 // Fix this when we ditch the old test runner. 199 var message = "Fail" + "ure: unreachable" 200 if (name_opt) { 201 message += " - " + name_opt; 202 } 203 throw new MjsUnitAssertionError(message); 204 } 205