diff --git a/lib/assert.js b/lib/assert.js index e0720c8d10..4704d9a60e 100644 --- a/lib/assert.js +++ b/lib/assert.js @@ -36,32 +36,38 @@ var assert = exports; // new assert.AssertionError({message: message, actual: actual, expected: expected}) assert.AssertionError = function AssertionError(options) { - this.name = "AssertionError"; - this.message = options.message; - this.actual = options.actual; - this.expected = options.expected; - this.operator = options.operator; - //v8 specific - if(Error.captureStackTrace){ - Error.captureStackTrace(this,fail); - //node specific, removes the node machinery stack frames - if(typeof(__filename) !== undefined){ - var stack = this.stack.split('\n'); - for (var i = stack.length - 1; i >= 0; i--) { - if(stack[i].indexOf(__filename) != -1){ - this.stack = stack.slice(0,i+2).join('\n'); - break; - } - } + this.name = "AssertionError"; + this.message = options.message; + this.actual = options.actual; + this.expected = options.expected; + this.operator = options.operator; + + //v8 specific + if (Error.captureStackTrace) { + Error.captureStackTrace(this, fail); + //node specific, removes the node machinery stack frames + if (typeof(__filename) !== undefined) { + var stack = this.stack.split('\n'); + for (var i = stack.length - 1; i >= 0; i--) { + if (stack[i].indexOf(__filename) != -1) { + this.stack = stack.slice(0, i+2).join('\n'); + break; } + } } + } }; -assert.AssertionError.prototype.toString = function(){ - if(this.message) - return [this.name+":", this.message].join(' '); - else - return [this.name+":", JSON.stringify(this.expected ), this.operator , JSON.stringify(this.actual)].join(" "); +assert.AssertionError.prototype.toString = function() { + if (this.message) { + return [this.name+":", this.message].join(' '); + } else { + return [ this.name+":" + , JSON.stringify(this.expected ) + , this.operator + , JSON.stringify(this.actual) + ].join(" "); + } } // assert.AssertionError instanceof Error @@ -80,12 +86,12 @@ assert.AssertionError.__proto__ = Error.prototype; // display purposes. function fail(actual, expected, message, operator) { - throw new assert.AssertionError({ - message: message, - actual: actual, - expected: expected, - operator: operator - }); + throw new assert.AssertionError({ + message: message, + actual: actual, + expected: expected, + operator: operator + }); } // EXTENSION! allows for well behaved errors defined elsewhere. @@ -99,8 +105,7 @@ assert.fail = fail; // assert.strictEqual(true, guard, message_opt);. assert.ok = function ok(value, message) { - if (!!!value) - fail(value, true, message, "=="); + if (!!!value) fail(value, true, message, "=="); }; // 5. The equality assertion tests shallow, coercive equality with @@ -108,179 +113,175 @@ assert.ok = function ok(value, message) { // assert.equal(actual, expected, message_opt); assert.equal = function equal(actual, expected, message) { - if (actual != expected) - fail(actual, expected, message, "=="); + if (actual != expected) fail(actual, expected, message, "=="); }; - // 6. The non-equality assertion tests for whether two objects are not equal // with != assert.notEqual(actual, expected, message_opt); assert.notEqual = function notEqual(actual, expected, message) { - if (actual == expected) - fail(actual, expected, message, "!="); + if (actual == expected) fail(actual, expected, message, "!="); }; // 7. The equivalence assertion tests a deep equality relation. // assert.deepEqual(actual, expected, message_opt); exports.deepEqual = function deepEqual(actual, expected, message) { - if (!_deepEqual(actual, expected)) - fail(actual, expected, message, "deepEqual"); + if (!_deepEqual(actual, expected)) { + fail(actual, expected, message, "deepEqual"); + } }; function _deepEqual(actual, expected) { - // 7.1. All identical values are equivalent, as determined by ===. - if (actual === expected) { - return true; - - // 7.2. If the expected value is a Date object, the actual value is - // equivalent if it is also a Date object that refers to the same time. - } else if (actual instanceof Date - && expected instanceof Date) { - return actual.getTime() === expected.getTime(); - - // 7.3. Other pairs that do not both pass typeof value == "object", - // equivalence is determined by ==. - } else if (typeof actual != 'object' - && typeof expected != 'object') { - return actual == expected; - - // 7.4. For all other Object pairs, including Array objects, equivalence is - // determined by having the same number of owned properties (as verified - // with Object.prototype.hasOwnProperty.call), the same set of keys - // (although not necessarily the same order), equivalent values for every - // corresponding key, and an identical "prototype" property. Note: this - // accounts for both named and indexed properties on Arrays. - } else { - return objEquiv(actual, expected); - } + // 7.1. All identical values are equivalent, as determined by ===. + if (actual === expected) { + return true; + + // 7.2. If the expected value is a Date object, the actual value is + // equivalent if it is also a Date object that refers to the same time. + } else if (actual instanceof Date && expected instanceof Date) { + return actual.getTime() === expected.getTime(); + + // 7.3. Other pairs that do not both pass typeof value == "object", + // equivalence is determined by ==. + } else if (typeof actual != 'object' && typeof expected != 'object') { + return actual == expected; + + // 7.4. For all other Object pairs, including Array objects, equivalence is + // determined by having the same number of owned properties (as verified + // with Object.prototype.hasOwnProperty.call), the same set of keys + // (although not necessarily the same order), equivalent values for every + // corresponding key, and an identical "prototype" property. Note: this + // accounts for both named and indexed properties on Arrays. + } else { + return objEquiv(actual, expected); + } } function isUndefinedOrNull (value) { - return value === null || value === undefined; + return value === null || value === undefined; } -function isArguments (object){ - return Object.prototype.toString.call(object) == '[object Arguments]'; +function isArguments (object) { + return Object.prototype.toString.call(object) == '[object Arguments]'; } function objEquiv (a, b) { - if (isUndefinedOrNull(a) || isUndefinedOrNull(b)) - return false; - // an identical "prototype" property. - if (a.prototype !== b.prototype) return false; - //~~~I've managed to break Object.keys through screwy arguments passing. - // Converting to array solves the problem. - if(isArguments(a)){ - if(!isArguments(b)){ - return false; - } - a = pSlice.call(a); - b = pSlice.call(b); - return _deepEqual(a,b); - } - try{ - var ka = Object.keys(a), - kb = Object.keys(b), - key, i; - } catch (e) {//happens when one is a string literal and the other isn't - return false; + if (isUndefinedOrNull(a) || isUndefinedOrNull(b)) + return false; + // an identical "prototype" property. + if (a.prototype !== b.prototype) return false; + //~~~I've managed to break Object.keys through screwy arguments passing. + // Converting to array solves the problem. + if (isArguments(a)) { + if (!isArguments(b)) { + return false; } - // having the same number of owned properties (keys incorporates hasOwnProperty) - if(ka.length != kb.length) - return false; - //the same set of keys (although not necessarily the same order), - ka.sort(); - kb.sort(); - //~~~cheap key test - for (i = ka.length - 1; i >= 0; i--) { - if(ka[i] != kb[i]) - return false; - } - //equivalent values for every corresponding key, and - //~~~possibly expensive deep test - for (i = ka.length - 1; i >= 0; i--) { - key = ka[i]; - if(!_deepEqual(a[key], b[key] )) - return false; - } - return true; + a = pSlice.call(a); + b = pSlice.call(b); + return _deepEqual(a, b); + } + try{ + var ka = Object.keys(a), + kb = Object.keys(b), + key, i; + } catch (e) {//happens when one is a string literal and the other isn't + return false; + } + // having the same number of owned properties (keys incorporates hasOwnProperty) + if (ka.length != kb.length) + return false; + //the same set of keys (although not necessarily the same order), + ka.sort(); + kb.sort(); + //~~~cheap key test + for (i = ka.length - 1; i >= 0; i--) { + if (ka[i] != kb[i]) + return false; + } + //equivalent values for every corresponding key, and + //~~~possibly expensive deep test + for (i = ka.length - 1; i >= 0; i--) { + key = ka[i]; + if (!_deepEqual(a[key], b[key] )) + return false; + } + return true; } // 8. The non-equivalence assertion tests for any deep inequality. // assert.notDeepEqual(actual, expected, message_opt); exports.notDeepEqual = function notDeepEqual(actual, expected, message) { - if (_deepEqual(actual, expected)) - fail(actual, expected, message, "notDeepEqual"); + if (_deepEqual(actual, expected)) { + fail(actual, expected, message, "notDeepEqual"); + } }; // 9. The strict equality assertion tests strict equality, as determined by ===. // assert.strictEqual(actual, expected, message_opt); assert.strictEqual = function strictEqual(actual, expected, message) { - if (actual !== expected) - fail(actual, expected, message, "==="); + if (actual !== expected) fail(actual, expected, message, "==="); }; // 10. The strict non-equality assertion tests for strict inequality, as determined by !==. // assert.notStrictEqual(actual, expected, message_opt); assert.notStrictEqual = function notStrictEqual(actual, expected, message) { - if (actual === expected) - fail(actual, expected, message, "!=="); + if (actual === expected) fail(actual, expected, message, "!=="); }; -// 11. Expected to throw an error: -// assert.throws(block, Error_opt, message_opt); +function _throws (shouldThrow, block, err, message) { + var exception = null, + threw = false, + typematters = true; -assert.throws = function(block, /*optional*/error, /*optional*/message){ - var args = [true] - _throws.apply(this, args.concat(pSlice.call(arguments))); -} + message = message || ""; -// EXTENSION! This is annoying to write outside this module. -assert.doesNotThrow = function(block, /*optional*/error, /*optional*/message){ - var args = [false] - _throws.apply(this, args.concat(pSlice.call(arguments))); + //handle optional arguments + if (arguments.length == 3) { + if (typeof(err) == "string") { + message = err; + typematters = false; + } + } else if (arguments.length == 2) { + typematters = false; + } + + try { + block(); + } catch (e) { + threw = true; + exception = e; + } + + if (shouldThrow && !threw) { + fail( "Missing expected exception" + + (err && err.name ? " ("+err.name+")." : '.') + + (message ? " " + message : "") + ); + } + if (!shouldThrow && threw && typematters && exception instanceof err) { + fail( "Got unwanted exception" + + (err && err.name ? " ("+err.name+")." : '.') + + (message ? " " + message : "") + ); + } + if ((shouldThrow && threw && typematters && !(exception instanceof err)) || + (!shouldThrow && threw)) { + throw exception; + } } -var _throws = function (shouldThrow, block, err, message) { - var exception = null - threw = false - typematters = true; - message = message || ""; - - //handle optional arguments - if(arguments.length == 3){ - if(typeof(err) == "string"){ - message = err; - typematters = false; - } - } else if(arguments.length == 2) { - typematters = false; - } +// 11. Expected to throw an error: +// assert.throws(block, Error_opt, message_opt); - try { - block(); - } catch (e) { - threw = true; - exception = e; - } +assert.throws = function(block, /*optional*/error, /*optional*/message) { + _throws.apply(this, [true].concat(pSlice.call(arguments))); +}; - if(shouldThrow && !threw){ - fail("Missing expected exception"+ - (err && err.name ? " ("+err.name+")." : '.') + - (message ? " " + message : "")); - } - if(!shouldThrow && threw && typematters && exception instanceof err){ - fail("Got unwanted exception" + - (err && err.name ? " ("+err.name+")." : '.') + - (message ? " " + message : "")); - } - if((shouldThrow && threw && typematters && !(exception instanceof err)) || - (!shouldThrow && threw)){ - throw exception; - } +// EXTENSION! This is annoying to write outside this module. +assert.doesNotThrow = function(block, /*optional*/error, /*optional*/message) { + _throws.apply(this, [false].concat(pSlice.call(arguments))); }; diff --git a/test/mjsunit/test-assert.js b/test/mjsunit/test-assert.js index 10976fcb9a..d8d546a901 100644 --- a/test/mjsunit/test-assert.js +++ b/test/mjsunit/test-assert.js @@ -1,52 +1,69 @@ process.mixin(require("./common")); -//strangely meta, no? - var a = require('assert'); - -function makeBlock(f){ - var args = Array.prototype.slice.call(arguments,1); - return function(){ - return f.apply(this,args); - } +function makeBlock (f) { + var args = Array.prototype.slice.call(arguments,1); + return function () { + return f.apply(this,args); + }; } -assert.ok(a.AssertionError instanceof Error, "a.AssertionError instanceof Error"); +assert.ok(a.AssertionError instanceof Error, + "a.AssertionError instanceof Error"); + +assert.throws(makeBlock(a.ok, false), + a.AssertionError, "ok(false)"); -assert.throws(makeBlock(a.ok, false), a.AssertionError, "ok(false)"); -assert.doesNotThrow(makeBlock(a.ok, true), a.AssertionError, "ok(true)"); -assert.doesNotThrow(makeBlock(a.ok, "test"),"ok('test')"); +assert.doesNotThrow(makeBlock(a.ok, true), + a.AssertionError, "ok(true)"); + +assert.doesNotThrow(makeBlock(a.ok, "test"), "ok('test')"); assert.throws(makeBlock(a.equal, true, false), a.AssertionError, 'equal'); + assert.doesNotThrow(makeBlock(a.equal, null, null), 'equal'); + assert.doesNotThrow(makeBlock(a.equal, undefined, undefined), 'equal'); + assert.doesNotThrow(makeBlock(a.equal, null, undefined), 'equal'); + assert.doesNotThrow(makeBlock(a.equal, true, true), 'equal'); + assert.doesNotThrow(makeBlock(a.equal, 2, "2"), 'equal'); assert.doesNotThrow(makeBlock(a.notEqual, true, false), 'notEqual'); + assert.throws(makeBlock(a.notEqual, true, true), a.AssertionError, 'notEqual'); assert.throws(makeBlock(a.strictEqual, 2, "2"), a.AssertionError, 'strictEqual'); + assert.throws(makeBlock(a.strictEqual, null, undefined), a.AssertionError, 'strictEqual'); assert.doesNotThrow(makeBlock(a.notStrictEqual, 2, "2"), 'notStrictEqual'); -//deepEquals joy! -//7.2 -assert.doesNotThrow(makeBlock(a.deepEqual, new Date(2000,3,14), new Date(2000,3,14)), 'deepEqual date'); -assert.throws( makeBlock(a.deepEqual, new Date(), new Date(2000,3,14)), a.AssertionError, 'deepEqual date'); -//7.3 +// deepEquals joy! +// 7.2 +assert.doesNotThrow(makeBlock(a.deepEqual, new Date(2000,3,14), new Date(2000,3,14)), + 'deepEqual date'); + +assert.throws(makeBlock(a.deepEqual, new Date(), new Date(2000,3,14)), + a.AssertionError, + 'deepEqual date'); + +// 7.3 assert.doesNotThrow(makeBlock(a.deepEqual, 4, "4"), 'deepEqual == check'); assert.doesNotThrow(makeBlock(a.deepEqual, true, 1), 'deepEqual == check'); -assert.throws( makeBlock(a.deepEqual, 4, "5"), a.AssertionError, 'deepEqual == check'); -//7.4 +assert.throws(makeBlock(a.deepEqual, 4, "5"), + a.AssertionError, + 'deepEqual == check'); + +// 7.4 // having the same number of owned properties && the same set of keys assert.doesNotThrow(makeBlock(a.deepEqual, {a:4}, {a:4})); assert.doesNotThrow(makeBlock(a.deepEqual, {a:4,b:"2"}, {a:4,b:"2"})); assert.doesNotThrow(makeBlock(a.deepEqual, [4], ["4"])); -assert.throws( makeBlock(a.deepEqual, {a:4}, {a:4,b:true}), a.AssertionError); +assert.throws(makeBlock(a.deepEqual, {a:4}, {a:4,b:true}), a.AssertionError); assert.doesNotThrow(makeBlock(a.deepEqual, ["a"], {0:"a"})); //(although not necessarily the same order), assert.doesNotThrow(makeBlock(a.deepEqual, {a:4,b:"1"}, {b:"1",a:4})); @@ -55,26 +72,32 @@ var a2 = [1,2,3]; a1.a = "test"; a1.b = true; a2.b = true; -a2.a = "test" -assert.throws( makeBlock(a.deepEqual, Object.keys(a1), Object.keys(a2)), a.AssertionError); +a2.a = "test"; +assert.throws(makeBlock(a.deepEqual, + Object.keys(a1), + Object.keys(a2)), + a.AssertionError); assert.doesNotThrow(makeBlock(a.deepEqual, a1, a2)); // having an identical prototype property var nbRoot = { - toString: function(){return this.first+' '+this.last;} -} -var nameBuilder = function(first,last){ - this.first = first; - this.last = last; - return this; + toString: function () { return this.first+' '+this.last; } +}; + +function nameBuilder (first,last) { + this.first = first; + this.last = last; + return this; } nameBuilder.prototype = nbRoot; -var nameBuilder2 = function(first,last){ - this.first = first; - this.last = last; - return this; + +function nameBuilder2 (first,last) { + this.first = first; + this.last = last; + return this; } nameBuilder2.prototype = nbRoot; + var nb1 = new nameBuilder('Ryan', 'Dahl'); var nb2 = new nameBuilder2('Ryan','Dahl'); @@ -82,46 +105,52 @@ assert.doesNotThrow(makeBlock(a.deepEqual, nb1, nb2)); nameBuilder2.prototype = Object; nb2 = new nameBuilder2('Ryan','Dahl'); -assert.throws( makeBlock(a.deepEqual, nb1, nb2), a.AssertionError); +assert.throws(makeBlock(a.deepEqual, nb1, nb2), a.AssertionError); -//String literal + object blew up my implementation... -assert.throws( makeBlock(a.deepEqual, 'a', {}), a.AssertionError); +// String literal + object blew up my implementation... +assert.throws(makeBlock(a.deepEqual, 'a', {}), a.AssertionError); -//Testing the throwing -function thrower(errorConstructor){ - throw new errorConstructor('test'); +// Testing the throwing +function thrower (errorConstructor){ + throw new errorConstructor('test'); } aethrow = makeBlock(thrower, a.AssertionError); aethrow = makeBlock(thrower, a.AssertionError); -//the basic calls work -assert.throws( makeBlock(thrower, a.AssertionError), a.AssertionError, 'message'); -assert.throws( makeBlock(thrower, a.AssertionError), a.AssertionError); -assert.throws( makeBlock(thrower, a.AssertionError)); -//if not passing an error, catch all. -assert.throws( makeBlock(thrower, TypeError)); -//when passing a type, only catch errors of the appropriate type + +// the basic calls work +assert.throws(makeBlock(thrower, a.AssertionError), a.AssertionError, 'message'); +assert.throws(makeBlock(thrower, a.AssertionError), a.AssertionError); +assert.throws(makeBlock(thrower, a.AssertionError)); + +// if not passing an error, catch all. +assert.throws(makeBlock(thrower, TypeError)); + +// when passing a type, only catch errors of the appropriate type var threw = false; -try{ - a.throws( makeBlock(thrower, TypeError), a.AssertionError); -}catch (e){ - threw = true; - assert.ok(e instanceof TypeError, 'type'); +try { + a.throws(makeBlock(thrower, TypeError), a.AssertionError); +} catch (e) { + threw = true; + assert.ok(e instanceof TypeError, 'type'); } assert.equal(true,threw,'a.throws with an explicit error is eating extra errors', a.AssertionError); threw = false; -//doesNotThrow should pass through all errors -try{ - a.doesNotThrow(makeBlock(thrower, TypeError), a.AssertionError); -}catch(e){ - threw = true - assert.ok(e instanceof TypeError); + +// doesNotThrow should pass through all errors +try { + a.doesNotThrow(makeBlock(thrower, TypeError), a.AssertionError); +} catch(e) { + threw = true + assert.ok(e instanceof TypeError); } assert.equal(true,threw,'a.doesNotThrow with an explicit error is eating extra errors'); -//the key difference is that throwing our correct error makes an assertion error -try{ - a.doesNotThrow(makeBlock(thrower, TypeError), TypeError); -}catch(e){ - threw = true - assert.ok(e instanceof a.AssertionError); + +// key difference is that throwing our correct error makes an assertion error +try { + a.doesNotThrow(makeBlock(thrower, TypeError), TypeError); +} catch(e) { + threw = true + assert.ok(e instanceof a.AssertionError); } assert.equal(true,threw,'a.doesNotThrow is not catching type matching errors'); +