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