// http://wiki.commonjs.org/wiki/Unit_Testing/1.01//2// THIS IS NOT TESTED NOR LIKELY TO WORK OUTSIDE V8!3//4// Originally from narwhal.js (http://narwhaljs.org)5// Copyright (c) 2009 Thomas Robinson <280north.com>6//7// Permission is hereby granted, free of charge, to any person obtaining a copy8// of this software and associated documentation files (the 'Software'), to9// deal in the Software without restriction, including without limitation the10// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or11// sell copies of the Software, and to permit persons to whom the Software is12// furnished to do so, subject to the following conditions:13//14// The above copyright notice and this permission notice shall be included in15// all copies or substantial portions of the Software.16//17// THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR18// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,19// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE20// AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN21// ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION22// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.2324// when used in node, this will actually load the util module we depend on25// versus loading the builtin util module as happens otherwise26// this is a bug in node module loading as far as I am concerned27var util = require('util/');2829var pSlice = Array.prototype.slice;30var hasOwn = Object.prototype.hasOwnProperty;3132// 1. The assert module provides functions that throw33// AssertionError's when particular conditions are not met. The34// assert module must conform to the following interface.3536var assert = module.exports = ok;3738// 2. The AssertionError is defined in assert.39// new assert.AssertionError({ message: message,40// actual: actual,41// expected: expected })4243assert.AssertionError = function AssertionError(options) {44this.name = 'AssertionError';45this.actual = options.actual;46this.expected = options.expected;47this.operator = options.operator;48if (options.message) {49this.message = options.message;50this.generatedMessage = false;51} else {52this.message = getMessage(this);53this.generatedMessage = true;54}55var stackStartFunction = options.stackStartFunction || fail;5657if (Error.captureStackTrace) {58Error.captureStackTrace(this, stackStartFunction);59}60else {61// non v8 browsers so we can have a stacktrace62var err = new Error();63if (err.stack) {64var out = err.stack;6566// try to strip useless frames67var fn_name = stackStartFunction.name;68var idx = out.indexOf('\n' + fn_name);69if (idx >= 0) {70// once we have located the function frame71// we need to strip out everything before it (and its line)72var next_line = out.indexOf('\n', idx + 1);73out = out.substring(next_line + 1);74}7576this.stack = out;77}78}79};8081// assert.AssertionError instanceof Error82util.inherits(assert.AssertionError, Error);8384function replacer(key, value) {85if (util.isUndefined(value)) {86return '' + value;87}88if (util.isNumber(value) && !isFinite(value)) {89return value.toString();90}91if (util.isFunction(value) || util.isRegExp(value)) {92return value.toString();93}94return value;95}9697function truncate(s, n) {98if (util.isString(s)) {99return s.length < n ? s : s.slice(0, n);100} else {101return s;102}103}104105function getMessage(self) {106return truncate(JSON.stringify(self.actual, replacer), 128) + ' ' +107self.operator + ' ' +108truncate(JSON.stringify(self.expected, replacer), 128);109}110111// At present only the three keys mentioned above are used and112// understood by the spec. Implementations or sub modules can pass113// other keys to the AssertionError's constructor - they will be114// ignored.115116// 3. All of the following functions must throw an AssertionError117// when a corresponding condition is not met, with a message that118// may be undefined if not provided. All assertion methods provide119// both the actual and expected values to the assertion error for120// display purposes.121122function fail(actual, expected, message, operator, stackStartFunction) {123throw new assert.AssertionError({124message: message,125actual: actual,126expected: expected,127operator: operator,128stackStartFunction: stackStartFunction129});130}131132// EXTENSION! allows for well behaved errors defined elsewhere.133assert.fail = fail;134135// 4. Pure assertion tests whether a value is truthy, as determined136// by !!guard.137// assert.ok(guard, message_opt);138// This statement is equivalent to assert.equal(true, !!guard,139// message_opt);. To test strictly for the value true, use140// assert.strictEqual(true, guard, message_opt);.141142function ok(value, message) {143if (!value) fail(value, true, message, '==', assert.ok);144}145assert.ok = ok;146147// 5. The equality assertion tests shallow, coercive equality with148// ==.149// assert.equal(actual, expected, message_opt);150151assert.equal = function equal(actual, expected, message) {152if (actual != expected) fail(actual, expected, message, '==', assert.equal);153};154155// 6. The non-equality assertion tests for whether two objects are not equal156// with != assert.notEqual(actual, expected, message_opt);157158assert.notEqual = function notEqual(actual, expected, message) {159if (actual == expected) {160fail(actual, expected, message, '!=', assert.notEqual);161}162};163164// 7. The equivalence assertion tests a deep equality relation.165// assert.deepEqual(actual, expected, message_opt);166167assert.deepEqual = function deepEqual(actual, expected, message) {168if (!_deepEqual(actual, expected)) {169fail(actual, expected, message, 'deepEqual', assert.deepEqual);170}171};172173function _deepEqual(actual, expected) {174// 7.1. All identical values are equivalent, as determined by ===.175if (actual === expected) {176return true;177178} else if (util.isBuffer(actual) && util.isBuffer(expected)) {179if (actual.length != expected.length) return false;180181for (var i = 0; i < actual.length; i++) {182if (actual[i] !== expected[i]) return false;183}184185return true;186187// 7.2. If the expected value is a Date object, the actual value is188// equivalent if it is also a Date object that refers to the same time.189} else if (util.isDate(actual) && util.isDate(expected)) {190return actual.getTime() === expected.getTime();191192// 7.3 If the expected value is a RegExp object, the actual value is193// equivalent if it is also a RegExp object with the same source and194// properties (`global`, `multiline`, `lastIndex`, `ignoreCase`).195} else if (util.isRegExp(actual) && util.isRegExp(expected)) {196return actual.source === expected.source &&197actual.global === expected.global &&198actual.multiline === expected.multiline &&199actual.lastIndex === expected.lastIndex &&200actual.ignoreCase === expected.ignoreCase;201202// 7.4. Other pairs that do not both pass typeof value == 'object',203// equivalence is determined by ==.204} else if (!util.isObject(actual) && !util.isObject(expected)) {205return actual == expected;206207// 7.5 For all other Object pairs, including Array objects, equivalence is208// determined by having the same number of owned properties (as verified209// with Object.prototype.hasOwnProperty.call), the same set of keys210// (although not necessarily the same order), equivalent values for every211// corresponding key, and an identical 'prototype' property. Note: this212// accounts for both named and indexed properties on Arrays.213} else {214return objEquiv(actual, expected);215}216}217218function isArguments(object) {219return Object.prototype.toString.call(object) == '[object Arguments]';220}221222function objEquiv(a, b) {223if (util.isNullOrUndefined(a) || util.isNullOrUndefined(b))224return false;225// an identical 'prototype' property.226if (a.prototype !== b.prototype) return false;227// if one is a primitive, the other must be same228if (util.isPrimitive(a) || util.isPrimitive(b)) {229return a === b;230}231var aIsArgs = isArguments(a),232bIsArgs = isArguments(b);233if ((aIsArgs && !bIsArgs) || (!aIsArgs && bIsArgs))234return false;235if (aIsArgs) {236a = pSlice.call(a);237b = pSlice.call(b);238return _deepEqual(a, b);239}240var ka = objectKeys(a),241kb = objectKeys(b),242key, i;243// having the same number of owned properties (keys incorporates244// hasOwnProperty)245if (ka.length != kb.length)246return false;247//the same set of keys (although not necessarily the same order),248ka.sort();249kb.sort();250//~~~cheap key test251for (i = ka.length - 1; i >= 0; i--) {252if (ka[i] != kb[i])253return false;254}255//equivalent values for every corresponding key, and256//~~~possibly expensive deep test257for (i = ka.length - 1; i >= 0; i--) {258key = ka[i];259if (!_deepEqual(a[key], b[key])) return false;260}261return true;262}263264// 8. The non-equivalence assertion tests for any deep inequality.265// assert.notDeepEqual(actual, expected, message_opt);266267assert.notDeepEqual = function notDeepEqual(actual, expected, message) {268if (_deepEqual(actual, expected)) {269fail(actual, expected, message, 'notDeepEqual', assert.notDeepEqual);270}271};272273// 9. The strict equality assertion tests strict equality, as determined by ===.274// assert.strictEqual(actual, expected, message_opt);275276assert.strictEqual = function strictEqual(actual, expected, message) {277if (actual !== expected) {278fail(actual, expected, message, '===', assert.strictEqual);279}280};281282// 10. The strict non-equality assertion tests for strict inequality, as283// determined by !==. assert.notStrictEqual(actual, expected, message_opt);284285assert.notStrictEqual = function notStrictEqual(actual, expected, message) {286if (actual === expected) {287fail(actual, expected, message, '!==', assert.notStrictEqual);288}289};290291function expectedException(actual, expected) {292if (!actual || !expected) {293return false;294}295296if (Object.prototype.toString.call(expected) == '[object RegExp]') {297return expected.test(actual);298} else if (actual instanceof expected) {299return true;300} else if (expected.call({}, actual) === true) {301return true;302}303304return false;305}306307function _throws(shouldThrow, block, expected, message) {308var actual;309310if (util.isString(expected)) {311message = expected;312expected = null;313}314315try {316block();317} catch (e) {318actual = e;319}320321message = (expected && expected.name ? ' (' + expected.name + ').' : '.') +322(message ? ' ' + message : '.');323324if (shouldThrow && !actual) {325fail(actual, expected, 'Missing expected exception' + message);326}327328if (!shouldThrow && expectedException(actual, expected)) {329fail(actual, expected, 'Got unwanted exception' + message);330}331332if ((shouldThrow && actual && expected &&333!expectedException(actual, expected)) || (!shouldThrow && actual)) {334throw actual;335}336}337338// 11. Expected to throw an error:339// assert.throws(block, Error_opt, message_opt);340341assert.throws = function(block, /*optional*/error, /*optional*/message) {342_throws.apply(this, [true].concat(pSlice.call(arguments)));343};344345// EXTENSION! This is annoying to write outside this module.346assert.doesNotThrow = function(block, /*optional*/message) {347_throws.apply(this, [false].concat(pSlice.call(arguments)));348};349350assert.ifError = function(err) { if (err) {throw err;}};351352var objectKeys = Object.keys || function (obj) {353var keys = [];354for (var key in obj) {355if (hasOwn.call(obj, key)) keys.push(key);356}357return keys;358};359360361