diff --git a/Makefile b/Makefile index c503d54..477723b 100644 --- a/Makefile +++ b/Makefile @@ -3,11 +3,11 @@ .PHONY: otto assets underscore TESTS := \ - FunctionDeclarationInFunction \ ~ TEST := -v --run TEST := -v --run Test\($(subst $(eval) ,\|,$(TESTS))\) +TEST := -v TEST := . test: parser inline.go diff --git a/array_test.go b/array_test.go index 4faa740..06f481b 100644 --- a/array_test.go +++ b/array_test.go @@ -1,717 +1,716 @@ package otto import ( - . "./terst" "testing" ) func TestArray(t *testing.T) { - Terst(t) + tt(t, func() { + test, _ := test() - test := runTest() + test(` + var abc = [ undefined, "Nothing happens." ]; + abc.length; + `, 2) - test(` - var abc = [ undefined, "Nothing happens." ]; - abc.length; - `, 2) + test(` + abc = ""+[0, 1, 2, 3]; + def = [].toString(); + ghi = [null, 4, "null"].toString(); + [ abc, def, ghi ]; + `, "0,1,2,3,,,4,null") - test(` - abc = ""+[0, 1, 2, 3]; - def = [].toString(); - ghi = [null, 4, "null"].toString(); - [ abc, def, ghi ]; - `, "0,1,2,3,,,4,null") + test(`new Array(0).length`, 0) - test(`new Array(0).length`, 0) + test(`new Array(11).length`, 11) - test(`new Array(11).length`, 11) + test(`new Array(11, 1).length`, 2) - test(`new Array(11, 1).length`, 2) + test(` + abc = [0, 1, 2, 3]; + abc.xyzzy = "Nothing happens."; + delete abc[1]; + var xyzzy = delete abc.xyzzy; + [ abc, xyzzy, abc.xyzzy ]; + `, "0,,2,3,true,") - test(` - abc = [0, 1, 2, 3]; - abc.xyzzy = "Nothing happens."; - delete abc[1]; - var xyzzy = delete abc.xyzzy; - [ abc, xyzzy, abc.xyzzy ]; - `, "0,,2,3,true,") + test(` + var abc = [0, 1, 2, 3, 4]; + abc.length = 2; + abc; + `, "0,1") - test(` - var abc = [0, 1, 2, 3, 4]; - abc.length = 2; - abc; - `, "0,1") + test(`raise: + [].length = 3.14159; + `, "RangeError") - test(`raise: - [].length = 3.14159; - `, "RangeError") + test(`raise: + new Array(3.14159); + `, "RangeError") - test(`raise: - new Array(3.14159); - `, "RangeError") + test(` + Object.defineProperty(Array.prototype, "0", { + value: 100, + writable: false, + configurable: true + }); + abc = [101]; + abc.hasOwnProperty("0") && abc[0] === 101; + `, true) - test(` - Object.defineProperty(Array.prototype, "0", { - value: 100, - writable: false, - configurable: true - }); - abc = [101]; - abc.hasOwnProperty("0") && abc[0] === 101; - `, true) - - test(` - abc = [,,undefined]; - [ abc.hasOwnProperty(0), abc.hasOwnProperty(1), abc.hasOwnProperty(2) ]; - `, "false,false,true") - - test(` - abc = Object.getOwnPropertyDescriptor(Array, "prototype"); - [ [ typeof Array.prototype ], - [ abc.writable, abc.enumerable, abc.configurable ] ]; - `, "object,false,false,false") + test(` + abc = [,,undefined]; + [ abc.hasOwnProperty(0), abc.hasOwnProperty(1), abc.hasOwnProperty(2) ]; + `, "false,false,true") + test(` + abc = Object.getOwnPropertyDescriptor(Array, "prototype"); + [ [ typeof Array.prototype ], + [ abc.writable, abc.enumerable, abc.configurable ] ]; + `, "object,false,false,false") + }) } func TestArray_toString(t *testing.T) { - Terst(t) + tt(t, func() { + { + test(` + Array.prototype.toString = function() { + return "Nothing happens."; + } + abc = Array.prototype.toString(); + def = [].toString(); + ghi = [null, 4, "null"].toString(); - { - test := runTest() + [ abc, def, ghi ].join(","); + `, "Nothing happens.,Nothing happens.,Nothing happens.") + } - test(` - Array.prototype.toString = function() { - return "Nothing happens."; - } - abc = Array.prototype.toString(); - def = [].toString(); - ghi = [null, 4, "null"].toString(); + { + test(` + Array.prototype.join = undefined + abc = Array.prototype.toString() + def = [].toString() + ghi = [null, 4, "null"].toString() - [ abc, def, ghi ].join(","); - `, "Nothing happens.,Nothing happens.,Nothing happens.") - } - - { - test := runTest() - - test(` - Array.prototype.join = undefined - abc = Array.prototype.toString() - def = [].toString() - ghi = [null, 4, "null"].toString() - - abc + "," + def + "," + ghi; - `, "[object Array],[object Array],[object Array]") - } + abc + "," + def + "," + ghi; + `, "[object Array],[object Array],[object Array]") + } + }) } func TestArray_toLocaleString(t *testing.T) { - Terst(t) + tt(t, func() { + test, _ := test() - defer mockUTC()() + defer mockUTC()() - test := runTest() + test(` + [ 3.14159, "abc", undefined, new Date(0) ].toLocaleString(); + `, "3.14159,abc,,1970-01-01 00:00:00") - test(` - [ 3.14159, "abc", undefined, new Date(0) ].toLocaleString(); - `, "3.14159,abc,,1970-01-01 00:00:00") - - test(`raise: - [ { toLocaleString: undefined } ].toLocaleString(); - `, "TypeError") + test(`raise: + [ { toLocaleString: undefined } ].toLocaleString(); + `, "TypeError") + }) } func TestArray_concat(t *testing.T) { - Terst(t) + tt(t, func() { + test, _ := test() - test := runTest() + test(` + abc = [0, 1, 2]; + def = [-1, -2, -3]; + ghi = abc.concat(def); + jkl = abc.concat(def, 3, 4, 5); + mno = def.concat(-4, -5, abc); - test(` - abc = [0, 1, 2]; - def = [-1, -2, -3]; - ghi = abc.concat(def); - jkl = abc.concat(def, 3, 4, 5); - mno = def.concat(-4, -5, abc); + [ ghi, jkl, mno ].join(";"); + `, "0,1,2,-1,-2,-3;0,1,2,-1,-2,-3,3,4,5;-1,-2,-3,-4,-5,0,1,2") - [ ghi, jkl, mno ].join(";"); - `, "0,1,2,-1,-2,-3;0,1,2,-1,-2,-3,3,4,5;-1,-2,-3,-4,-5,0,1,2") + test(` + var abc = [,1]; + var def = abc.concat([], [,]); - test(` - var abc = [,1]; - var def = abc.concat([], [,]); + def.getClass = Object.prototype.toString; - def.getClass = Object.prototype.toString; + [ def.getClass(), typeof def[0], def[1], typeof def[2], def.length ]; + `, "[object Array],undefined,1,undefined,3") - [ def.getClass(), typeof def[0], def[1], typeof def[2], def.length ]; - `, "[object Array],undefined,1,undefined,3") + test(` + Object.defineProperty(Array.prototype, "0", { + value: 100, + writable: false, + configurable: true + }); - test(` - Object.defineProperty(Array.prototype, "0", { - value: 100, - writable: false, - configurable: true - }); + var abc = Array.prototype.concat.call(101); - var abc = Array.prototype.concat.call(101); + var hasProperty = abc.hasOwnProperty("0"); + var instanceOfVerify = typeof abc[0] === "object"; + var verifyValue = false; + verifyValue = abc[0] == 101; - var hasProperty = abc.hasOwnProperty("0"); - var instanceOfVerify = typeof abc[0] === "object"; - var verifyValue = false; - verifyValue = abc[0] == 101; - - var verifyEnumerable = false; - for (var property in abc) { - if (property === "0" && abc.hasOwnProperty("0")) { - verifyEnumerable = true; + var verifyEnumerable = false; + for (var property in abc) { + if (property === "0" && abc.hasOwnProperty("0")) { + verifyEnumerable = true; + } } - } - var verifyWritable = false; - abc[0] = 12; - verifyWritable = abc[0] === 12; + var verifyWritable = false; + abc[0] = 12; + verifyWritable = abc[0] === 12; - var verifyConfigurable = false; - delete abc[0]; - verifyConfigurable = abc.hasOwnProperty("0"); + var verifyConfigurable = false; + delete abc[0]; + verifyConfigurable = abc.hasOwnProperty("0"); - [ hasProperty, instanceOfVerify, verifyValue, !verifyConfigurable, verifyEnumerable, verifyWritable ]; - `, "true,true,true,true,true,true") + [ hasProperty, instanceOfVerify, verifyValue, !verifyConfigurable, verifyEnumerable, verifyWritable ]; + `, "true,true,true,true,true,true") + }) } func TestArray_splice(t *testing.T) { - Terst(t) + tt(t, func() { + test, _ := test() - test := runTest() - - test(` - abc = [0, 1, 2]; - def = abc.splice(1, 2, 3, 4, 5); - ghi = [].concat(abc); - jkl = ghi.splice(17, 21, 7, 8, 9); - [ abc, def, ghi, jkl ].join(";"); - `, "0,3,4,5;1,2;0,3,4,5,7,8,9;") + test(` + abc = [0, 1, 2]; + def = abc.splice(1, 2, 3, 4, 5); + ghi = [].concat(abc); + jkl = ghi.splice(17, 21, 7, 8, 9); + [ abc, def, ghi, jkl ].join(";"); + `, "0,3,4,5;1,2;0,3,4,5,7,8,9;") + }) } func TestArray_shift(t *testing.T) { - Terst(t) + tt(t, func() { + test, _ := test() - test := runTest() + test(` + abc = [0, 1, 2]; + def = abc.shift(); + ghi = [].concat(abc); + jkl = abc.shift(); + mno = [].concat(abc); + pqr = abc.shift(); + stu = [].concat(abc); + vwx = abc.shift(); - test(` - abc = [0, 1, 2]; - def = abc.shift(); - ghi = [].concat(abc); - jkl = abc.shift(); - mno = [].concat(abc); - pqr = abc.shift(); - stu = [].concat(abc); - vwx = abc.shift(); - - [ abc, def, ghi, jkl, mno, pqr, stu, vwx ].join(";"); - `, ";0;1,2;1;2;2;;") + [ abc, def, ghi, jkl, mno, pqr, stu, vwx ].join(";"); + `, ";0;1,2;1;2;2;;") + }) } func TestArray_push(t *testing.T) { - Terst(t) + tt(t, func() { + test, _ := test() - test := runTest() + test(` + abc = [0]; + def = abc.push(1); + ghi = [].concat(abc); + jkl = abc.push(2,3,4); - test(` - abc = [0]; - def = abc.push(1); - ghi = [].concat(abc); - jkl = abc.push(2,3,4); - - [ abc, def, ghi, jkl ].join(";"); - `, "0,1,2,3,4;2;0,1;5") + [ abc, def, ghi, jkl ].join(";"); + `, "0,1,2,3,4;2;0,1;5") + }) } func TestArray_pop(t *testing.T) { - Terst(t) + tt(t, func() { + test, _ := test() - test := runTest() + test(` + abc = [0,1]; + def = abc.pop(); + ghi = [].concat(abc); + jkl = abc.pop(); + mno = [].concat(abc); + pqr = abc.pop(); - test(` - abc = [0,1]; - def = abc.pop(); - ghi = [].concat(abc); - jkl = abc.pop(); - mno = [].concat(abc); - pqr = abc.pop(); - - [ abc, def, ghi, jkl, mno, pqr ].join(";"); - `, ";1;0;0;;") + [ abc, def, ghi, jkl, mno, pqr ].join(";"); + `, ";1;0;0;;") + }) } func TestArray_slice(t *testing.T) { - Terst(t) + tt(t, func() { + test, _ := test() - test := runTest() + test(` + abc = [0,1,2,3]; + def = abc.slice(); + ghi = abc.slice(1); + jkl = abc.slice(3,-1); + mno = abc.slice(2,-1); + pqr = abc.slice(-1, -10); - test(` - abc = [0,1,2,3]; - def = abc.slice(); - ghi = abc.slice(1); - jkl = abc.slice(3,-1); - mno = abc.slice(2,-1); - pqr = abc.slice(-1, -10); + [ abc, def, ghi, jkl, mno, pqr ].join(";"); + `, "0,1,2,3;0,1,2,3;1,2,3;;2;") - [ abc, def, ghi, jkl, mno, pqr ].join(";"); - `, "0,1,2,3;0,1,2,3;1,2,3;;2;") + // Array.protoype.slice is generic + test(` + abc = { 0: 0, 1: 1, 2: 2, 3: 3 }; + abc.length = 4; + def = Array.prototype.slice.call(abc); + ghi = Array.prototype.slice.call(abc,1); + jkl = Array.prototype.slice.call(abc,3,-1); + mno = Array.prototype.slice.call(abc,2,-1); + pqr = Array.prototype.slice.call(abc,-1,-10); - // Array.protoype.slice is generic - test(` - abc = { 0: 0, 1: 1, 2: 2, 3: 3 }; - abc.length = 4; - def = Array.prototype.slice.call(abc); - ghi = Array.prototype.slice.call(abc,1); - jkl = Array.prototype.slice.call(abc,3,-1); - mno = Array.prototype.slice.call(abc,2,-1); - pqr = Array.prototype.slice.call(abc,-1,-10); - - [ abc, def, ghi, jkl, pqr ].join(";"); - `, "[object Object];0,1,2,3;1,2,3;;") + [ abc, def, ghi, jkl, pqr ].join(";"); + `, "[object Object];0,1,2,3;1,2,3;;") + }) } func TestArray_sliceArguments(t *testing.T) { - Terst(t) + tt(t, func() { + test, _ := test() - test := runTest() - - test(` - (function(){ - return Array.prototype.slice.call(arguments, 1) - })({}, 1, 2, 3); - `, "1,2,3") + test(` + (function(){ + return Array.prototype.slice.call(arguments, 1) + })({}, 1, 2, 3); + `, "1,2,3") + }) } func TestArray_unshift(t *testing.T) { - Terst(t) + tt(t, func() { + test, _ := test() - test := runTest() + test(` + abc = []; + def = abc.unshift(0); + ghi = [].concat(abc); + jkl = abc.unshift(1,2,3,4); - test(` - abc = []; - def = abc.unshift(0); - ghi = [].concat(abc); - jkl = abc.unshift(1,2,3,4); - - [ abc, def, ghi, jkl ].join(";"); - `, "1,2,3,4,0;1;0;5") + [ abc, def, ghi, jkl ].join(";"); + `, "1,2,3,4,0;1;0;5") + }) } func TestArray_reverse(t *testing.T) { - Terst(t) + tt(t, func() { + test, _ := test() - test := runTest() + test(` + abc = [0,1,2,3].reverse(); + def = [0,1,2].reverse(); - test(` - abc = [0,1,2,3].reverse(); - def = [0,1,2].reverse(); - - [ abc, def ]; - `, "3,2,1,0,2,1,0") + [ abc, def ]; + `, "3,2,1,0,2,1,0") + }) } func TestArray_sort(t *testing.T) { - Terst(t) + tt(t, func() { + test, _ := test() - test := runTest() + test(` + abc = [0,1,2,3].sort(); + def = [3,2,1,0].sort(); + ghi = [].sort(); + jkl = [0].sort(); + mno = [1,0].sort(); + pqr = [1,5,-10, 100, 8, 72, 401, 0.05].sort(); + stu = [1,5,-10, 100, 8, 72, 401, 0.05].sort(function(x, y){ + return x == y ? 0 : x < y ? -1 : 1 + }); - test(` - abc = [0,1,2,3].sort(); - def = [3,2,1,0].sort(); - ghi = [].sort(); - jkl = [0].sort(); - mno = [1,0].sort(); - pqr = [1,5,-10, 100, 8, 72, 401, 0.05].sort(); - stu = [1,5,-10, 100, 8, 72, 401, 0.05].sort(function(x, y){ - return x == y ? 0 : x < y ? -1 : 1 - }); + [ abc, def, ghi, jkl, mno, pqr, stu ].join(";"); + `, "0,1,2,3;0,1,2,3;;0;0,1;-10,0.05,1,100,401,5,72,8;-10,0.05,1,5,8,72,100,401") - [ abc, def, ghi, jkl, mno, pqr, stu ].join(";"); - `, "0,1,2,3;0,1,2,3;;0;0,1;-10,0.05,1,100,401,5,72,8;-10,0.05,1,5,8,72,100,401") - - test(`Array.prototype.sort.length`, 1) + test(`Array.prototype.sort.length`, 1) + }) } func TestArray_isArray(t *testing.T) { - Terst(t) + tt(t, func() { + test, _ := test() - test := runTest() - - test(` - [ Array.isArray.length, Array.isArray(), Array.isArray([]), Array.isArray({}) ]; - `, "1,false,true,false") - - test(`Array.isArray(Math)`, false) + test(` + [ Array.isArray.length, Array.isArray(), Array.isArray([]), Array.isArray({}) ]; + `, "1,false,true,false") + test(`Array.isArray(Math)`, false) + }) } func TestArray_indexOf(t *testing.T) { - Terst(t) + tt(t, func() { + test, _ := test() - test := runTest() + test(`['a', 'b', 'c', 'b'].indexOf('b')`, 1) - test(`['a', 'b', 'c', 'b'].indexOf('b')`, 1) + test(`['a', 'b', 'c', 'b'].indexOf('b', 2)`, 3) - test(`['a', 'b', 'c', 'b'].indexOf('b', 2)`, 3) + test(`['a', 'b', 'c', 'b'].indexOf('b', -2)`, 3) - test(`['a', 'b', 'c', 'b'].indexOf('b', -2)`, 3) + test(` + Object.prototype.indexOf = Array.prototype.indexOf; + var abc = {0: 'a', 1: 'b', 2: 'c', length: 3}; + abc.indexOf('c'); + `, 2) - test(` - Object.prototype.indexOf = Array.prototype.indexOf; - var abc = {0: 'a', 1: 'b', 2: 'c', length: 3}; - abc.indexOf('c'); - `, 2) + test(`[true].indexOf(true, "-Infinity")`, 0) - test(`[true].indexOf(true, "-Infinity")`, 0) + test(` + var target = {}; + Math[3] = target; + Math.length = 5; + Array.prototype.indexOf.call(Math, target) === 3; + `, true) - test(` - var target = {}; - Math[3] = target; - Math.length = 5; - Array.prototype.indexOf.call(Math, target) === 3; - `, true) + test(` + var _NaN = NaN; + var abc = new Array("NaN", undefined, 0, false, null, {toString:function(){return NaN}}, "false", _NaN, NaN); + abc.indexOf(NaN); + `, -1) - test(` - var _NaN = NaN; - var abc = new Array("NaN", undefined, 0, false, null, {toString:function(){return NaN}}, "false", _NaN, NaN); - abc.indexOf(NaN); - `, -1) - - test(` - var abc = {toString:function (){return 0}}; - var def = 1; - var ghi = -(4/3); - var jkl = new Array(false, undefined, null, "0", abc, -1.3333333333333, "string", -0, true, +0, def, 1, 0, false, ghi, -(4/3)); - [ jkl.indexOf(-(4/3)), jkl.indexOf(0), jkl.indexOf(-0), jkl.indexOf(1) ]; - `, "14,7,7,10") + test(` + var abc = {toString:function (){return 0}}; + var def = 1; + var ghi = -(4/3); + var jkl = new Array(false, undefined, null, "0", abc, -1.3333333333333, "string", -0, true, +0, def, 1, 0, false, ghi, -(4/3)); + [ jkl.indexOf(-(4/3)), jkl.indexOf(0), jkl.indexOf(-0), jkl.indexOf(1) ]; + `, "14,7,7,10") + }) } func TestArray_lastIndexOf(t *testing.T) { - Terst(t) + tt(t, func() { + test, _ := test() - test := runTest() - test(`['a', 'b', 'c', 'b'].lastIndexOf('b')`, "3") - test(`['a', 'b', 'c', 'b'].lastIndexOf('b', 2)`, "1") - test(`['a', 'b', 'c', 'b'].lastIndexOf('b', -2)`, "1") - test(` - Object.prototype.lastIndexOf = Array.prototype.lastIndexOf; - var abc = {0: 'a', 1: 'b', 2: 'c', 3: 'b', length: 4}; - abc.lastIndexOf('b'); - `, "3") + test(`['a', 'b', 'c', 'b'].lastIndexOf('b')`, 3) - test(` - var target = {}; - Math[3] = target; - Math.length = 5; - [ Array.prototype.lastIndexOf.call(Math, target) === 3 ]; - `, "true") + test(`['a', 'b', 'c', 'b'].lastIndexOf('b', 2)`, 1) - test(` - var _NaN = NaN; - var abc = new Array("NaN", undefined, 0, false, null, {toString:function(){return NaN}}, "false", _NaN, NaN); - [ abc.lastIndexOf(NaN) ]; - `, "-1") + test(`['a', 'b', 'c', 'b'].lastIndexOf('b', -2)`, 1) - test(` - var abc = {toString:function (){return 0}}; - var def = 1; - var ghi = -(4/3); - var jkl = new Array(false, undefined, null, "0", abc, -1.3333333333333, "string", -0, true, +0, def, 1, 0, false, ghi, -(4/3)); - [ jkl.lastIndexOf(-(4/3)), jkl.indexOf(0), jkl.indexOf(-0), jkl.indexOf(1) ]; - `, "15,7,7,10") + test(` + Object.prototype.lastIndexOf = Array.prototype.lastIndexOf; + var abc = {0: 'a', 1: 'b', 2: 'c', 3: 'b', length: 4}; + abc.lastIndexOf('b'); + `, 3) + + test(` + var target = {}; + Math[3] = target; + Math.length = 5; + [ Array.prototype.lastIndexOf.call(Math, target) === 3 ]; + `, "true") + + test(` + var _NaN = NaN; + var abc = new Array("NaN", undefined, 0, false, null, {toString:function(){return NaN}}, "false", _NaN, NaN); + abc.lastIndexOf(NaN); + `, -1) + + test(` + var abc = {toString:function (){return 0}}; + var def = 1; + var ghi = -(4/3); + var jkl = new Array(false, undefined, null, "0", abc, -1.3333333333333, "string", -0, true, +0, def, 1, 0, false, ghi, -(4/3)); + [ jkl.lastIndexOf(-(4/3)), jkl.indexOf(0), jkl.indexOf(-0), jkl.indexOf(1) ]; + `, "15,7,7,10") + }) } func TestArray_every(t *testing.T) { - Terst(t) + tt(t, func() { + test, _ := test() - test := runTest() + test(`raise: [].every()`, "TypeError") - test(`raise: [].every()`, "TypeError") + test(`raise: [].every("abc")`, "TypeError") - test(`raise: [].every("abc")`, "TypeError") + test(`[].every(function() { return false })`, true) - test(`[].every(function() { return false })`, true) + test(`[1,2,3].every(function() { return false })`, false) - test(`[1,2,3].every(function() { return false })`, false) + test(`[1,2,3].every(function() { return true })`, true) - test(`[1,2,3].every(function() { return true })`, true) + test(`[1,2,3].every(function(_, index) { if (index === 1) return true })`, false) - test(`[1,2,3].every(function(_, index) { if (index === 1) return true })`, false) + test(` + var abc = function(value, index, object) { + return ('[object Math]' !== Object.prototype.toString.call(object)); + }; - test(` - var abc = function(value, index, object) { - return ('[object Math]' !== Object.prototype.toString.call(object)); - }; + Math.length = 1; + Math[0] = 1; + !Array.prototype.every.call(Math, abc); + `, true) - Math.length = 1; - Math[0] = 1; - !Array.prototype.every.call(Math, abc); - `, true) + test(` + var def = false; - test(` - var def = false; + var abc = function(value, index, object) { + def = true; + return this === Math; + }; - var abc = function(value, index, object) { - def = true; - return this === Math; - }; + [11].every(abc, Math) && def; + `, true) - [11].every(abc, Math) && def; - `, true) + test(` + var def = false; - test(` - var def = false; + var abc = function(value, index, object) { + def = true; + return Math; + }; - var abc = function(value, index, object) { - def = true; - return Math; - }; - - [11].every(abc) && def; - `, true) + [11].every(abc) && def; + `, true) + }) } func TestArray_some(t *testing.T) { - Terst(t) + tt(t, func() { + test, _ := test() - test := runTest() + test(`raise: [].some("abc")`, "TypeError") - test(`raise: [].some("abc")`, "TypeError") + test(`[].some(function() { return true })`, false) - test(`[].some(function() { return true })`, false) + test(`[1,2,3].some(function() { return false })`, false) - test(`[1,2,3].some(function() { return false })`, false) + test(`[1,2,3].some(function() { return true })`, true) - test(`[1,2,3].some(function() { return true })`, true) + test(`[1,2,3].some(function(_, index) { if (index === 1) return true })`, true) - test(`[1,2,3].some(function(_, index) { if (index === 1) return true })`, true) + test(` + var abc = function(value, index, object) { + return ('[object Math]' !== Object.prototype.toString.call(object)); + }; - test(` - var abc = function(value, index, object) { - return ('[object Math]' !== Object.prototype.toString.call(object)); - }; + Math.length = 1; + Math[0] = 1; + !Array.prototype.some.call(Math, abc); + `, true) - Math.length = 1; - Math[0] = 1; - !Array.prototype.some.call(Math, abc); - `, true) + test(` + var abc = function(value, index, object) { + return this === Math; + }; - test(` - var abc = function(value, index, object) { - return this === Math; - }; + [11].some(abc, Math); + `, true) - [11].some(abc, Math); - `, true) + test(` + var abc = function(value, index, object) { + return Math; + }; - test(` - var abc = function(value, index, object) { - return Math; - }; - - [11].some(abc); - `, true) + [11].some(abc); + `, true) + }) } func TestArray_forEach(t *testing.T) { - Terst(t) + tt(t, func() { + test, _ := test() - test := runTest() + test(`raise: [].forEach("abc")`, "TypeError") - test(`raise: [].forEach("abc")`, "TypeError") + test(` + var abc = 0; + [].forEach(function(value) { + abc += value; + }); + abc; + `, 0) - test(` - var abc = 0; - [].forEach(function(value) { - abc += value; - }); - abc; - `, 0) + test(` + abc = 0; + var def = []; + [1,2,3].forEach(function(value, index) { + abc += value; + def.push(index); + }); + [ abc, def ]; + `, "6,0,1,2") - test(` - abc = 0; - var def = []; - [1,2,3].forEach(function(value, index) { - abc += value; - def.push(index); - }); - [ abc, def ]; - `, "6,0,1,2") + test(` + var def = false; + var abc = function(value, index, object) { + def = ('[object Math]' === Object.prototype.toString.call(object)); + }; - test(` - var def = false; - var abc = function(value, index, object) { - def = ('[object Math]' === Object.prototype.toString.call(object)); - }; + Math.length = 1; + Math[0] = 1; + Array.prototype.forEach.call(Math, abc); + def; + `, true) - Math.length = 1; - Math[0] = 1; - Array.prototype.forEach.call(Math, abc); - def; - `, true) + test(` + var def = false; + var abc = function(value, index, object) { + def = this === Math; + }; - test(` - var def = false; - var abc = function(value, index, object) { - def = this === Math; - }; - - [11].forEach(abc, Math); - def; - `, true) + [11].forEach(abc, Math); + def; + `, true) + }) } func TestArray_indexing(t *testing.T) { - Terst(t) + tt(t, func() { + test, _ := test() - test := runTest() + test(` + var abc = new Array(0, 1); + var def = abc.length; + abc[4294967296] = 10; // 2^32 => 0 + abc[4294967297] = 11; // 2^32+1 => 1 + [ def, abc.length, abc[0], abc[1], abc[4294967296] ]; + `, "2,2,0,1,10") - test(` - var abc = new Array(0, 1); - var def = abc.length; - abc[4294967296] = 10; // 2^32 => 0 - abc[4294967297] = 11; // 2^32+1 => 1 - [ def, abc.length, abc[0], abc[1], abc[4294967296] ]; - `, "2,2,0,1,10") - - test(` - abc = new Array(0, 1); - def = abc.length; - abc[4294967295] = 10; - var ghi = abc.length; - abc[4294967299] = 12; - var jkl = abc.length; - abc[4294967294] = 11; - [ def, ghi, jkl, abc.length, abc[4294967295], abc[4294967299] ]; - `, "2,2,2,4294967295,10,12") + test(` + abc = new Array(0, 1); + def = abc.length; + abc[4294967295] = 10; + var ghi = abc.length; + abc[4294967299] = 12; + var jkl = abc.length; + abc[4294967294] = 11; + [ def, ghi, jkl, abc.length, abc[4294967295], abc[4294967299] ]; + `, "2,2,2,4294967295,10,12") + }) } func TestArray_map(t *testing.T) { - Terst(t) + tt(t, func() { + test, _ := test() - test := runTest() + test(`raise: [].map("abc")`, "TypeError") - test(`raise: [].map("abc")`, "TypeError") + test(`[].map(function() { return 1 }).length`, 0) - test(`[].map(function() { return 1 }).length`, 0) + test(`[1,2,3].map(function(value) { return value * value })`, "1,4,9") - test(`[1,2,3].map(function(value) { return value * value })`, "1,4,9") + test(`[1,2,3].map(function(value) { return 1 })`, "1,1,1") - test(`[1,2,3].map(function(value) { return 1 })`, "1,1,1") + test(` + var abc = function(value, index, object) { + return ('[object Math]' === Object.prototype.toString.call(object)); + }; - test(` - var abc = function(value, index, object) { - return ('[object Math]' === Object.prototype.toString.call(object)); - }; + Math.length = 1; + Math[0] = 1; + Array.prototype.map.call(Math, abc)[0]; + `, true) - Math.length = 1; - Math[0] = 1; - Array.prototype.map.call(Math, abc)[0]; - `, true) + test(` + var abc = function(value, index, object) { + return this === Math; + }; - test(` - var abc = function(value, index, object) { - return this === Math; - }; - - [11].map(abc, Math)[0]; - `, true) + [11].map(abc, Math)[0]; + `, true) + }) } func TestArray_filter(t *testing.T) { - Terst(t) + tt(t, func() { + test, _ := test() - test := runTest() + test(`raise: [].filter("abc")`, "TypeError") - test(`raise: [].filter("abc")`, "TypeError") + test(`[].filter(function() { return 1 }).length`, 0) - test(`[].filter(function() { return 1 }).length`, 0) + test(`[1,2,3].filter(function() { return false }).length`, 0) - test(`[1,2,3].filter(function() { return false }).length`, 0) - - test(`[1,2,3].filter(function() { return true })`, "1,2,3") + test(`[1,2,3].filter(function() { return true })`, "1,2,3") + }) } func TestArray_reduce(t *testing.T) { - Terst(t) + tt(t, func() { + test, _ := test() - test := runTest() + test(`raise: [].reduce("abc")`, "TypeError") - test(`raise: [].reduce("abc")`, "TypeError") + test(`raise: [].reduce(function() {})`, "TypeError") - test(`raise: [].reduce(function() {})`, "TypeError") + test(`[].reduce(function() {}, 0)`, 0) - test(`[].reduce(function() {}, 0)`, 0) + test(`[].reduce(function() {}, undefined)`, "undefined") - test(`[].reduce(function() {}, undefined)`, "undefined") + test(`['a','b','c'].reduce(function(result, value) { return result+', '+value })`, "a, b, c") - test(`['a','b','c'].reduce(function(result, value) { return result+', '+value })`, "a, b, c") + test(`[1,2,3].reduce(function(result, value) { return result + value }, 4)`, 10) - test(`[1,2,3].reduce(function(result, value) { return result + value }, 4)`, 10) - - test(`[1,2,3].reduce(function(result, value) { return result + value })`, 6) + test(`[1,2,3].reduce(function(result, value) { return result + value })`, 6) + }) } func TestArray_reduceRight(t *testing.T) { - Terst(t) + tt(t, func() { + test, _ := test() - test := runTest() + test(`raise: [].reduceRight("abc")`, "TypeError") - test(`raise: [].reduceRight("abc")`, "TypeError") + test(`raise: [].reduceRight(function() {})`, "TypeError") - test(`raise: [].reduceRight(function() {})`, "TypeError") + test(`[].reduceRight(function() {}, 0)`, 0) - test(`[].reduceRight(function() {}, 0)`, 0) + test(`[].reduceRight(function() {}, undefined)`, "undefined") - test(`[].reduceRight(function() {}, undefined)`, "undefined") + test(`['a','b','c'].reduceRight(function(result, value) { return result+', '+value })`, "c, b, a") - test(`['a','b','c'].reduceRight(function(result, value) { return result+', '+value })`, "c, b, a") + test(`[1,2,3].reduceRight(function(result, value) { return result + value }, 4)`, 10) - test(`[1,2,3].reduceRight(function(result, value) { return result + value }, 4)`, 10) - - test(`[1,2,3].reduceRight(function(result, value) { return result + value })`, 6) + test(`[1,2,3].reduceRight(function(result, value) { return result + value })`, 6) + }) } func TestArray_defineOwnProperty(t *testing.T) { - Terst(t) + tt(t, func() { + test, _ := test() - test := runTest() - test(` - var abc = []; - Object.defineProperty(abc, "length", { - writable: false - }); - abc.length; - `, 0) + test(` + var abc = []; + Object.defineProperty(abc, "length", { + writable: false + }); + abc.length; + `, 0) - test(`raise: - var abc = []; - var exception; - Object.defineProperty(abc, "length", { - writable: false - }); - Object.defineProperty(abc, "length", { - writable: true - }); - `, "TypeError") + test(`raise: + var abc = []; + var exception; + Object.defineProperty(abc, "length", { + writable: false + }); + Object.defineProperty(abc, "length", { + writable: true + }); + `, "TypeError") + }) } func TestArray_new(t *testing.T) { - Terst(t) + tt(t, func() { + test, _ := test() - test := runTest() - test(` - var abc = new Array(null); - var def = new Array(undefined); - [ abc.length, abc[0] === null, def.length, def[0] === undefined ] - `, "1,true,1,true") + test(` + var abc = new Array(null); + var def = new Array(undefined); + [ abc.length, abc[0] === null, def.length, def[0] === undefined ] + `, "1,true,1,true") - test(` - var abc = new Array(new Number(0)); - var def = new Array(new Number(4294967295)); - [ abc.length, typeof abc[0], abc[0] == 0, def.length, typeof def[0], def[0] == 4294967295 ] - `, "1,object,true,1,object,true") + test(` + var abc = new Array(new Number(0)); + var def = new Array(new Number(4294967295)); + [ abc.length, typeof abc[0], abc[0] == 0, def.length, typeof def[0], def[0] == 4294967295 ] + `, "1,object,true,1,object,true") + }) } diff --git a/bug_test.go b/bug_test.go index b9f2801..0ee484d 100644 --- a/bug_test.go +++ b/bug_test.go @@ -1,426 +1,433 @@ package otto import ( - . "./terst" "testing" "time" ) func Test_262(t *testing.T) { - Terst(t) + tt(t, func() { + test, _ := test() - // 11.13.1-1-1 - test := runTest() - - test(`raise: - eval("42 = 42;"); - `, "ReferenceError: Invalid left-hand side in assignment") + // 11.13.1-1-1 + test(`raise: + eval("42 = 42;"); + `, "ReferenceError: Invalid left-hand side in assignment") + }) } func Test_issue5(t *testing.T) { - Terst(t) + tt(t, func() { + test, _ := test() - test := runTest() - - test(`'abc' === 'def'`, false) - test(`'\t' === '\r'`, false) + test(`'abc' === 'def'`, false) + test(`'\t' === '\r'`, false) + }) } func Test_issue13(t *testing.T) { - Terst(t) + tt(t, func() { + test, tester := test() + vm := tester.vm - otto, test := runTestWithOtto() + value, err := vm.ToValue(map[string]interface{}{ + "string": "Xyzzy", + "number": 42, + "array": []string{"def", "ghi"}, + }) + if err != nil { + t.Error(err) + t.FailNow() + } - value, err := otto.ToValue(map[string]interface{}{ - "string": "Xyzzy", - "number": 42, - "array": []string{"def", "ghi"}, - }) - if err != nil { - FailNow(err) - } + fn, err := vm.Object(` + (function(value){ + return ""+[value.string, value.number, value.array] + }) + `) + if err != nil { + t.Error(err) + t.FailNow() + } - fn, err := otto.Object(` - (function(value){ - return ""+[value.string, value.number, value.array] - }) - `) - if err != nil { - FailNow(err) - } + result, err := fn.Value().Call(fn.Value(), value) + if err != nil { + t.Error(err) + t.FailNow() + } + is(result.toString(), "Xyzzy,42,def,ghi") - result, err := fn.Value().Call(fn.Value(), value) - if err != nil { - FailNow(err) - } - Is(result.toString(), "Xyzzy,42,def,ghi") - - anything := struct { - Abc interface{} - }{ - Abc: map[string]interface{}{ - "def": []interface{}{ - []interface{}{ - "a", "b", "c", "", "d", "e", - }, - map[string]interface{}{ - "jkl": "Nothing happens.", + anything := struct { + Abc interface{} + }{ + Abc: map[string]interface{}{ + "def": []interface{}{ + []interface{}{ + "a", "b", "c", "", "d", "e", + }, + map[string]interface{}{ + "jkl": "Nothing happens.", + }, }, + "ghi": -1, }, - "ghi": -1, - }, - } + } - otto.Set("anything", anything) - test(` - [ - anything, - "~", - anything.Abc, - "~", - anything.Abc.def, - "~", - anything.Abc.def[1].jkl, - "~", - anything.Abc.ghi, - ]; - `, "[object Object],~,[object Object],~,a,b,c,,d,e,[object Object],~,Nothing happens.,~,-1", - ) + vm.Set("anything", anything) + test(` + [ + anything, + "~", + anything.Abc, + "~", + anything.Abc.def, + "~", + anything.Abc.def[1].jkl, + "~", + anything.Abc.ghi, + ]; + `, "[object Object],~,[object Object],~,a,b,c,,d,e,[object Object],~,Nothing happens.,~,-1") + }) } func Test_issue16(t *testing.T) { - Terst(t) + tt(t, func() { + test, vm := test() - otto, test := runTestWithOtto() + test(` + var def = { + "abc": ["abc"], + "xyz": ["xyz"] + }; + def.abc.concat(def.xyz); + `, "abc,xyz") - test(` - var def = { - "abc": ["abc"], - "xyz": ["xyz"] - }; - def.abc.concat(def.xyz); - `, "abc,xyz") + vm.Set("ghi", []string{"jkl", "mno"}) - otto.Set("ghi", []string{"jkl", "mno"}) + test(` + def.abc.concat(def.xyz).concat(ghi); + `, "abc,xyz,jkl,mno") - test(` - def.abc.concat(def.xyz).concat(ghi); - `, "abc,xyz,jkl,mno") + test(` + ghi.concat(def.abc.concat(def.xyz)); + `, "jkl,mno,abc,xyz") - test(` - ghi.concat(def.abc.concat(def.xyz)); - `, "jkl,mno,abc,xyz") + vm.Set("pqr", []interface{}{"jkl", 42, 3.14159, true}) - otto.Set("pqr", []interface{}{"jkl", 42, 3.14159, true}) + test(` + pqr.concat(ghi, def.abc, def, def.xyz); + `, "jkl,42,3.14159,true,jkl,mno,abc,[object Object],xyz") - test(` - pqr.concat(ghi, def.abc, def, def.xyz); - `, "jkl,42,3.14159,true,jkl,mno,abc,[object Object],xyz") - - test(` - pqr.concat(ghi, def.abc, def, def.xyz).length; - `, 9) + test(` + pqr.concat(ghi, def.abc, def, def.xyz).length; + `, 9) + }) } func Test_issue21(t *testing.T) { - Terst(t) + tt(t, func() { + vm1 := New() + vm1.Run(` + abc = {} + abc.ghi = "Nothing happens."; + var jkl = 0; + abc.def = function() { + jkl += 1; + return 1; + } + `) + abc, err := vm1.Get("abc") + is(err, nil) - otto1 := New() - otto1.Run(` - abc = {} - abc.ghi = "Nothing happens."; - var jkl = 0; - abc.def = function() { - jkl += 1; - return 1; - } - `) - abc, err := otto1.Get("abc") - Is(err, nil) + vm2 := New() + vm2.Set("cba", abc) + _, err = vm2.Run(` + var pqr = 0; + cba.mno = function() { + pqr -= 1; + return 1; + } + cba.def(); + cba.def(); + cba.def(); + `) + is(err, nil) - otto2 := New() - otto2.Set("cba", abc) - _, err = otto2.Run(` - var pqr = 0; - cba.mno = function() { - pqr -= 1; - return 1; - } - cba.def(); - cba.def(); - cba.def(); - `) - Is(err, nil) + jkl, err := vm1.Get("jkl") + is(err, nil) + is(jkl, 3) - jkl, err := otto1.Get("jkl") - Is(err, nil) - is(jkl, 3) + _, err = vm1.Run(` + abc.mno(); + abc.mno(); + abc.mno(); + `) + is(err, nil) - _, err = otto1.Run(` - abc.mno(); - abc.mno(); - abc.mno(); - `) - Is(err, nil) - - pqr, err := otto2.Get("pqr") - Is(err, nil) - is(pqr, -3) + pqr, err := vm2.Get("pqr") + is(err, nil) + is(pqr, -3) + }) } func Test_issue24(t *testing.T) { - Terst(t) + tt(t, func() { + _, vm := test() - otto, _ := runTestWithOtto() - - { - otto.Set("abc", []string{"abc", "def", "ghi"}) - value, err := otto.Get("abc") - Is(err, nil) - export, _ := value.Export() { - value, valid := export.([]string) - Is(valid, true) + vm.Set("abc", []string{"abc", "def", "ghi"}) + value, err := vm.Get("abc") + is(err, nil) + export, _ := value.Export() + { + value, valid := export.([]string) + is(valid, true) - Is(value[0], "abc") - Is(value[2], "ghi") + is(value[0], "abc") + is(value[2], "ghi") + } } - } - { - otto.Set("abc", [...]string{"abc", "def", "ghi"}) - value, err := otto.Get("abc") - Is(err, nil) - export, _ := value.Export() { - value, valid := export.([3]string) - Is(valid, true) + vm.Set("abc", [...]string{"abc", "def", "ghi"}) + value, err := vm.Get("abc") + is(err, nil) + export, _ := value.Export() + { + value, valid := export.([3]string) + is(valid, true) - Is(value[0], "abc") - Is(value[2], "ghi") + is(value[0], "abc") + is(value[2], "ghi") + } } - } - { - otto.Set("abc", &[...]string{"abc", "def", "ghi"}) - value, err := otto.Get("abc") - Is(err, nil) - export, _ := value.Export() { - value, valid := export.(*[3]string) - Is(valid, true) + vm.Set("abc", &[...]string{"abc", "def", "ghi"}) + value, err := vm.Get("abc") + is(err, nil) + export, _ := value.Export() + { + value, valid := export.(*[3]string) + is(valid, true) - Is(value[0], "abc") - Is(value[2], "ghi") + is(value[0], "abc") + is(value[2], "ghi") + } } - } - { - otto.Set("abc", map[int]string{0: "abc", 1: "def", 2: "ghi"}) - value, err := otto.Get("abc") - Is(err, nil) - export, _ := value.Export() { - value, valid := export.(map[int]string) - Is(valid, true) + vm.Set("abc", map[int]string{0: "abc", 1: "def", 2: "ghi"}) + value, err := vm.Get("abc") + is(err, nil) + export, _ := value.Export() + { + value, valid := export.(map[int]string) + is(valid, true) - Is(value[0], "abc") - Is(value[2], "ghi") + is(value[0], "abc") + is(value[2], "ghi") + } } - } - { - otto.Set("abc", testStruct{Abc: true, Ghi: "Nothing happens."}) - value, err := otto.Get("abc") - Is(err, nil) - export, _ := value.Export() { - value, valid := export.(testStruct) - Is(valid, true) + vm.Set("abc", testStruct{Abc: true, Ghi: "Nothing happens."}) + value, err := vm.Get("abc") + is(err, nil) + export, _ := value.Export() + { + value, valid := export.(testStruct) + is(valid, true) - Is(value.Abc, true) - Is(value.Ghi, "Nothing happens.") + is(value.Abc, true) + is(value.Ghi, "Nothing happens.") + } } - } - { - otto.Set("abc", &testStruct{Abc: true, Ghi: "Nothing happens."}) - value, err := otto.Get("abc") - Is(err, nil) - export, _ := value.Export() { - value, valid := export.(*testStruct) - Is(valid, true) + vm.Set("abc", &testStruct{Abc: true, Ghi: "Nothing happens."}) + value, err := vm.Get("abc") + is(err, nil) + export, _ := value.Export() + { + value, valid := export.(*testStruct) + is(valid, true) - Is(value.Abc, true) - Is(value.Ghi, "Nothing happens.") + is(value.Abc, true) + is(value.Ghi, "Nothing happens.") + } } - } + }) } func Test_issue39(t *testing.T) { - Terst(t) + tt(t, func() { + test, _ := test() - test := runTest() + test(` + var abc = 0, def = [], ghi = function() { + if (abc < 10) return ++abc; + return undefined; + } + for (var jkl; (jkl = ghi());) def.push(jkl); + def; + `, "1,2,3,4,5,6,7,8,9,10") - test(` - var abc = 0, def = [], ghi = function() { - if (abc < 10) return ++abc; - return undefined; - } - for (var jkl; (jkl = ghi());) def.push(jkl); - def; - `, "1,2,3,4,5,6,7,8,9,10") - - test(` - var abc = ["1", "2", "3", "4"]; - var def = []; - for (var ghi; (ghi = abc.shift());) { - def.push(ghi); - } - def; - `, "1,2,3,4") + test(` + var abc = ["1", "2", "3", "4"]; + var def = []; + for (var ghi; (ghi = abc.shift());) { + def.push(ghi); + } + def; + `, "1,2,3,4") + }) } func Test_issue64(t *testing.T) { - Terst(t) + tt(t, func() { + test, vm := test() - defer mockTimeLocal(time.UTC)() + defer mockTimeLocal(time.UTC)() - otto, test := runTestWithOtto() + abc := map[string]interface{}{ + "time": time.Unix(0, 0), + } + vm.Set("abc", abc) - abc := map[string]interface{}{ - "time": time.Unix(0, 0), - } - otto.Set("abc", abc) + def := struct { + Public string + private string + }{ + "Public", "private", + } + vm.Set("def", def) - def := struct { - Public string - private string - }{ - "Public", "private", - } - otto.Set("def", def) + test(`"sec" in abc.time`, false) - test(`"sec" in abc.time`, false) + test(` + [ "Public" in def, "private" in def, def.Public, def.private ]; + `, "true,false,Public,") - test(` - [ "Public" in def, "private" in def, def.Public, def.private ]; - `, "true,false,Public,") - - test(`JSON.stringify(abc)`, `{"time":"1970-01-01T00:00:00Z"}`) + test(`JSON.stringify(abc)`, `{"time":"1970-01-01T00:00:00Z"}`) + }) } func Test_7_3_1(t *testing.T) { - Terst(t) + tt(t, func() { + test(` - test := runTest() - test(` - eval("var test7_3_1\u2028abc = 66;"); - [ abc, typeof test7_3_1 ]; - `, "66,undefined") + eval("var test7_3_1\u2028abc = 66;"); + [ abc, typeof test7_3_1 ]; + `, "66,undefined") + }) } func Test_7_3_3(t *testing.T) { - Terst(t) - - test := runTest() - test(`raise: - eval("//\u2028 =;"); - `, "SyntaxError: Unexpected token =") + tt(t, func() { + test(`raise: + eval("//\u2028 =;"); + `, "SyntaxError: Unexpected token =") + }) } func Test_S7_3_A2_1_T1(t *testing.T) { - Terst(t) + tt(t, func() { + test, _ := test() - test := runTest() - test(`raise: - eval("'\u000Astr\u000Aing\u000A'") - `, "SyntaxError: Unexpected token ILLEGAL") + test(`raise: + eval("'\u000Astr\u000Aing\u000A'") + `, "SyntaxError: Unexpected token ILLEGAL") + }) } func Test_S7_8_3_A2_1_T1(t *testing.T) { - Terst(t) + tt(t, func() { + test, _ := test() - test := runTest() - test(` - [ .0 === 0.0, .0, .1 === 0.1, .1 ] - `, "true,0,true,0.1") + test(` + [ .0 === 0.0, .0, .1 === 0.1, .1 ] + `, "true,0,true,0.1") + }) } func Test_S7_8_4_A4_2_T3(t *testing.T) { - Terst(t) + tt(t, func() { + test, _ := test() - test := runTest() - test(` - "\a" - `, "a") + test(` + "\a" + `, "a") + }) } func Test_S7_9_A1(t *testing.T) { - Terst(t) + tt(t, func() { + test, _ := test() - test := runTest() - test(` - var def; - abc: for (var i = 0; i <= 0; i++) { - for (var j = 0; j <= 1; j++) { - if (j === 0) { - continue abc; - } else { - def = true; + test(` + var def; + abc: for (var i = 0; i <= 0; i++) { + for (var j = 0; j <= 1; j++) { + if (j === 0) { + continue abc; + } else { + def = true; + } } } - } - [ def, i, j ]; - `, ",1,0") + [ def, i, j ]; + `, ",1,0") + }) } func Test_S7_9_A3(t *testing.T) { - Terst(t) + tt(t, func() { + test, _ := test() - test := runTest() - test(` - (function(){ - return - 1; - })() - `, "undefined") + test(` + (function(){ + return + 1; + })() + `, "undefined") + }) } func Test_7_3_10(t *testing.T) { - Terst(t) + tt(t, func() { + test, _ := test() - test := runTest() - test(` - eval("var \u0061\u0062\u0063 = 3.14159;"); - abc; - `, 3.14159) - test(` - abc = undefined; - eval("var \\u0061\\u0062\\u0063 = 3.14159;"); - abc; - `, 3.14159) + test(` + eval("var \u0061\u0062\u0063 = 3.14159;"); + abc; + `, 3.14159) + + test(` + abc = undefined; + eval("var \\u0061\\u0062\\u0063 = 3.14159;"); + abc; + `, 3.14159) + }) } func Test_bug(t *testing.T) { - Terst(t) + tt(t, func() { + test, _ := test() - test := runTest() - - // 10.4.2-1-5 - test(` - "abc\ + // 10.4.2-1-5 + test(` + "abc\ def" - `, "abcdef") + `, "abcdef") - test(` - eval("'abc';\ - 'def'") - `, "def") + test(` + eval("'abc';\ + 'def'") + `, "def") - // S12.6.1_A10 - test(` + // S12.6.1_A10 + test(` var abc = 0; do { if(typeof(def) === "function"){ @@ -434,63 +441,64 @@ def" abc; `, 1) - // S12.7_A7 - test(`raise: - abc: - while (true) { - eval("continue abc"); - } - `, "SyntaxError: Undefined label 'abc'") - - // S15.1.2.1_A3.3_T3 - test(`raise: - eval("return"); - `, "SyntaxError: Illegal return statement") - - // 15.2.3.3-2-33 - test(` - var abc = { "AB\n\\cd": 1 }; - Object.getOwnPropertyDescriptor(abc, "AB\n\\cd").value; - `, 1) - - // S15.3_A2_T1 - test(`raise: - Function.call(this, "var x / = 1;"); - `, "SyntaxError: Unexpected token /") - - // ? - test(` - (function(){ - var abc = []; - (function(){ - abc.push(0); - abc.push(1); - })(undefined); - if ((function(){ return true; })()) { - (function(){ - abc.push(2); - })(); + // S12.7_A7 + test(`raise: + abc: + while (true) { + eval("continue abc"); } - return abc; - })(); - `, "0,1,2") + `, "SyntaxError: Undefined label 'abc'") - if false { - // 15.9.5.43-0-10 - // Should be an invalid date + // S15.1.2.1_A3.3_T3 + test(`raise: + eval("return"); + `, "SyntaxError: Illegal return statement") + + // 15.2.3.3-2-33 test(` - date = new Date(1970, 0, -99999999, 0, 0, 0, 1); - `, "") - } + var abc = { "AB\n\\cd": 1 }; + Object.getOwnPropertyDescriptor(abc, "AB\n\\cd").value; + `, 1) - // S7.8.3_A1.2_T1 - test(` - [ 0e1, 1e1, 2e1, 3e1, 4e1, 5e1, 6e1, 7e1, 8e1, 9e1 ]; - `, "0,10,20,30,40,50,60,70,80,90") + // S15.3_A2_T1 + test(`raise: + Function.call(this, "var x / = 1;"); + `, "SyntaxError: Unexpected token /") - // S15.10.2.7_A3_T2 - test(` - var abc = /\s+abc\s+/.exec("\t abc def"); - [ abc.length, abc.index, abc.input, abc ]; - `, "1,0,\t abc def,\t abc ") + // ? + test(` + (function(){ + var abc = []; + (function(){ + abc.push(0); + abc.push(1); + })(undefined); + if ((function(){ return true; })()) { + (function(){ + abc.push(2); + })(); + } + return abc; + })(); + `, "0,1,2") + + if false { + // 15.9.5.43-0-10 + // Should be an invalid date + test(` + date = new Date(1970, 0, -99999999, 0, 0, 0, 1); + `, "") + } + + // S7.8.3_A1.2_T1 + test(` + [ 0e1, 1e1, 2e1, 3e1, 4e1, 5e1, 6e1, 7e1, 8e1, 9e1 ]; + `, "0,10,20,30,40,50,60,70,80,90") + + // S15.10.2.7_A3_T2 + test(` + var abc = /\s+abc\s+/.exec("\t abc def"); + [ abc.length, abc.index, abc.input, abc ]; + `, "1,0,\t abc def,\t abc ") + }) } diff --git a/builtin_test.go b/builtin_test.go index 3d4c1bb..f5be00a 100644 --- a/builtin_test.go +++ b/builtin_test.go @@ -1,134 +1,136 @@ package otto import ( - . "./terst" "testing" ) func TestString_substr(t *testing.T) { - Terst(t) + tt(t, func() { + test, _ := test() - test := runTest() - test(` - [ - "abc".substr(0,1), // "a" - "abc".substr(0,2), // "ab" - "abc".substr(0,3), // "abc" - "abc".substr(0,4), // "abc" - "abc".substr(0,9), // "abc" - ]; - `, "a,ab,abc,abc,abc") + test(` + [ + "abc".substr(0,1), // "a" + "abc".substr(0,2), // "ab" + "abc".substr(0,3), // "abc" + "abc".substr(0,4), // "abc" + "abc".substr(0,9), // "abc" + ]; + `, "a,ab,abc,abc,abc") - test(` - [ - "abc".substr(1,1), // "b" - "abc".substr(1,2), // "bc" - "abc".substr(1,3), // "bc" - "abc".substr(1,4), // "bc" - "abc".substr(1,9), // "bc" - ]; - `, "b,bc,bc,bc,bc") + test(` + [ + "abc".substr(1,1), // "b" + "abc".substr(1,2), // "bc" + "abc".substr(1,3), // "bc" + "abc".substr(1,4), // "bc" + "abc".substr(1,9), // "bc" + ]; + `, "b,bc,bc,bc,bc") - test(` - [ - "abc".substr(2,1), // "c" - "abc".substr(2,2), // "c" - "abc".substr(2,3), // "c" - "abc".substr(2,4), // "c" - "abc".substr(2,9), // "c" - ]; - `, "c,c,c,c,c") + test(` + [ + "abc".substr(2,1), // "c" + "abc".substr(2,2), // "c" + "abc".substr(2,3), // "c" + "abc".substr(2,4), // "c" + "abc".substr(2,9), // "c" + ]; + `, "c,c,c,c,c") - test(` - [ - "abc".substr(3,1), // "" - "abc".substr(3,2), // "" - "abc".substr(3,3), // "" - "abc".substr(3,4), // "" - "abc".substr(3,9), // "" - ]; - `, ",,,,") + test(` + [ + "abc".substr(3,1), // "" + "abc".substr(3,2), // "" + "abc".substr(3,3), // "" + "abc".substr(3,4), // "" + "abc".substr(3,9), // "" + ]; + `, ",,,,") - test(` - [ - "abc".substr(0), // "abc" - "abc".substr(1), // "bc" - "abc".substr(2), // "c" - "abc".substr(3), // "" - "abc".substr(9), // "" - ]; - `, "abc,bc,c,,") + test(` + [ + "abc".substr(0), // "abc" + "abc".substr(1), // "bc" + "abc".substr(2), // "c" + "abc".substr(3), // "" + "abc".substr(9), // "" + ]; + `, "abc,bc,c,,") - test(` - [ - "abc".substr(-9), // "abc" - "abc".substr(-3), // "abc" - "abc".substr(-2), // "bc" - "abc".substr(-1), // "c" - ]; - `, "abc,abc,bc,c") + test(` + [ + "abc".substr(-9), // "abc" + "abc".substr(-3), // "abc" + "abc".substr(-2), // "bc" + "abc".substr(-1), // "c" + ]; + `, "abc,abc,bc,c") - test(` - [ - "abc".substr(-9, 1), // "a" - "abc".substr(-3, 1), // "a" - "abc".substr(-2, 1), // "b" - "abc".substr(-1, 1), // "c" - "abc".substr(-1, 2), // "c" - ]; - `, "a,a,b,c,c") + test(` + [ + "abc".substr(-9, 1), // "a" + "abc".substr(-3, 1), // "a" + "abc".substr(-2, 1), // "b" + "abc".substr(-1, 1), // "c" + "abc".substr(-1, 2), // "c" + ]; + `, "a,a,b,c,c") - test(`"abcd".substr(3, 5)`, "d") + test(`"abcd".substr(3, 5)`, "d") + }) } func Test_builtin_escape(t *testing.T) { - Terst(t) + tt(t, func() { + is(builtin_escape("abc"), "abc") - Is(builtin_escape("abc"), "abc") + is(builtin_escape("="), "%3D") - Is(builtin_escape("="), "%3D") + is(builtin_escape("abc=%+32"), "abc%3D%25+32") - Is(builtin_escape("abc=%+32"), "abc%3D%25+32") - - Is(builtin_escape("世界"), "%u4E16%u754C") + is(builtin_escape("世界"), "%u4E16%u754C") + }) } func Test_builtin_unescape(t *testing.T) { - Terst(t) + tt(t, func() { + is(builtin_unescape("abc"), "abc") - Is(builtin_unescape("abc"), "abc") + is(builtin_unescape("=%3D"), "==") - Is(builtin_unescape("=%3D"), "==") + is(builtin_unescape("abc%3D%25+32"), "abc=%+32") - Is(builtin_unescape("abc%3D%25+32"), "abc=%+32") - - Is(builtin_unescape("%u4E16%u754C"), "世界") + is(builtin_unescape("%u4E16%u754C"), "世界") + }) } func TestGlobal_escape(t *testing.T) { - Terst(t) + tt(t, func() { + test, _ := test() - test := runTest() - test(` - [ - escape("abc"), // "abc" - escape("="), // "%3D" - escape("abc=%+32"), // "abc%3D%25+32" - escape("\u4e16\u754c"), // "%u4E16%u754C" - ]; - `, "abc,%3D,abc%3D%25+32,%u4E16%u754C") + test(` + [ + escape("abc"), // "abc" + escape("="), // "%3D" + escape("abc=%+32"), // "abc%3D%25+32" + escape("\u4e16\u754c"), // "%u4E16%u754C" + ]; + `, "abc,%3D,abc%3D%25+32,%u4E16%u754C") + }) } func TestGlobal_unescape(t *testing.T) { - Terst(t) + tt(t, func() { + test, _ := test() - test := runTest() - test(` - [ - unescape("abc"), // "abc" - unescape("=%3D"), // "==" - unescape("abc%3D%25+32"), // "abc=%+32" - unescape("%u4E16%u754C"), // "世界" - ]; - `, "abc,==,abc=%+32,世界") + test(` + [ + unescape("abc"), // "abc" + unescape("=%3D"), // "==" + unescape("abc%3D%25+32"), // "abc=%+32" + unescape("%u4E16%u754C"), // "世界" + ]; + `, "abc,==,abc=%+32,世界") + }) } diff --git a/cmpl_test.go b/cmpl_test.go index fc7602d..01ee86e 100644 --- a/cmpl_test.go +++ b/cmpl_test.go @@ -1,54 +1,54 @@ package otto import ( - . "./terst" "testing" "github.com/robertkrimen/otto/parser" ) func Test_cmpl(t *testing.T) { - Terst(t) + tt(t, func() { + vm := New() - vm := New() - - test := func(src string, expect ...interface{}) { - program, err := parser.ParseFile(nil, "", src, 0) - Is(err, nil) - { - program := cmpl_parse(program) - value := vm.runtime.cmpl_evaluate_nodeProgram(program) - if len(expect) > 0 { - is(value, expect[0]) + test := func(src string, expect ...interface{}) { + program, err := parser.ParseFile(nil, "", src, 0) + is(err, nil) + { + program := cmpl_parse(program) + value := vm.runtime.cmpl_evaluate_nodeProgram(program) + if len(expect) > 0 { + is(value, expect[0]) + } } } - } - test(``, Value{}) + test(``, Value{}) - test(`var abc = 1; abc;`, 1) + test(`var abc = 1; abc;`, 1) - test(`var abc = 1 + 1; abc;`, 2) + test(`var abc = 1 + 1; abc;`, 2) - test(`1 + 2;`, 3) + test(`1 + 2;`, 3) + }) } func TestParse_cmpl(t *testing.T) { - Terst(t) + tt(t, func() { - test := func(src string) { - program, err := parser.ParseFile(nil, "", src, 0) - Is(err, nil) - IsNot(cmpl_parse(program), nil) - } + test := func(src string) { + program, err := parser.ParseFile(nil, "", src, 0) + is(err, nil) + is(cmpl_parse(program), "!=", nil) + } - test(``) + test(``) - test(`var abc = 1; abc;`) + test(`var abc = 1; abc;`) - test(` - function abc() { - return; - } - `) + test(` + function abc() { + return; + } + `) + }) } diff --git a/date_test.go b/date_test.go index eb24e33..18ab528 100644 --- a/date_test.go +++ b/date_test.go @@ -1,482 +1,478 @@ package otto import ( - . "./terst" - "fmt" + "math" "testing" - Time "time" + "time" ) -func mockTimeLocal(location *Time.Location) func() { - local := Time.Local - Time.Local = location +func mockTimeLocal(location *time.Location) func() { + local := time.Local + time.Local = location return func() { - Time.Local = local + time.Local = local } } // Passing or failing should not be dependent on what time zone we're in func mockUTC() func() { - return mockTimeLocal(Time.UTC) + return mockTimeLocal(time.UTC) } func TestDate(t *testing.T) { - Terst(t) + tt(t, func() { + test, _ := test() - defer mockUTC()() + defer mockUTC()() - test := runTest() + time0 := time.Unix(1348616313, 47*1000*1000).Local() - time := Time.Unix(1348616313, 47*1000*1000).Local() - check := func(run string, value int) { - test(run, fmt.Sprintf("%d", value)) - } + test(`Date`, "function Date() { [native code] }") + test(`new Date(0).toUTCString()`, "Thu, 01 Jan 1970 00:00:00 UTC") + test(`new Date(0).toGMTString()`, "Thu, 01 Jan 1970 00:00:00 GMT") + if false { + // TODO toLocale{Date,Time}String + test(`new Date(0).toLocaleString()`, "") + test(`new Date(0).toLocaleDateString()`, "") + test(`new Date(0).toLocaleTimeString()`, "") + } + test(`new Date(1348616313).getTime()`, 1348616313) + test(`new Date(1348616313).toUTCString()`, "Fri, 16 Jan 1970 14:36:56 UTC") + test(`abc = new Date(1348616313047); abc.toUTCString()`, "Tue, 25 Sep 2012 23:38:33 UTC") + test(`abc.getYear()`, time0.Year()-1900) + test(`abc.getFullYear()`, time0.Year()) + test(`abc.getUTCFullYear()`, 2012) + test(`abc.getMonth()`, int(time0.Month())-1) // Remember, the JavaScript month is 0-based + test(`abc.getUTCMonth()`, 8) + test(`abc.getDate()`, time0.Day()) + test(`abc.getUTCDate()`, 25) + test(`abc.getDay()`, int(time0.Weekday())) + test(`abc.getUTCDay()`, 2) + test(`abc.getHours()`, time0.Hour()) + test(`abc.getUTCHours()`, 23) + test(`abc.getMinutes()`, time0.Minute()) + test(`abc.getUTCMinutes()`, 38) + test(`abc.getSeconds()`, time0.Second()) + test(`abc.getUTCSeconds()`, 33) + test(`abc.getMilliseconds()`, time0.Nanosecond()/(1000*1000)) // In honor of the 47% + test(`abc.getUTCMilliseconds()`, 47) + _, offset := time0.Zone() + test(`abc.getTimezoneOffset()`, offset/-60) - test(`Date`, "function Date() { [native code] }") - test(`new Date(0).toUTCString()`, "Thu, 01 Jan 1970 00:00:00 UTC") - test(`new Date(0).toGMTString()`, "Thu, 01 Jan 1970 00:00:00 GMT") - if false { - // TODO toLocale{Date,Time}String - test(`new Date(0).toLocaleString()`, "") - test(`new Date(0).toLocaleDateString()`, "") - test(`new Date(0).toLocaleTimeString()`, "") - } - test(`new Date(1348616313).getTime()`, "1348616313") - test(`new Date(1348616313).toUTCString()`, "Fri, 16 Jan 1970 14:36:56 UTC") - test(`abc = new Date(1348616313047); abc.toUTCString()`, "Tue, 25 Sep 2012 23:38:33 UTC") - check(`abc.getYear()`, time.Year()-1900) - check(`abc.getFullYear()`, time.Year()) - check(`abc.getUTCFullYear()`, 2012) - check(`abc.getMonth()`, int(time.Month())-1) // Remember, the JavaScript month is 0-based - check(`abc.getUTCMonth()`, 8) - check(`abc.getDate()`, time.Day()) - check(`abc.getUTCDate()`, 25) - check(`abc.getDay()`, int(time.Weekday())) - check(`abc.getUTCDay()`, 2) - check(`abc.getHours()`, time.Hour()) - check(`abc.getUTCHours()`, 23) - check(`abc.getMinutes()`, time.Minute()) - check(`abc.getUTCMinutes()`, 38) - check(`abc.getSeconds()`, time.Second()) - check(`abc.getUTCSeconds()`, 33) - check(`abc.getMilliseconds()`, time.Nanosecond()/(1000*1000)) // In honor of the 47% - check(`abc.getUTCMilliseconds()`, 47) - _, offset := time.Zone() - check(`abc.getTimezoneOffset()`, offset/-60) + test(`new Date("Xyzzy").getTime()`, math.NaN()) - test(`new Date("Xyzzy").getTime()`, "NaN") + test(`abc.setFullYear(2011); abc.toUTCString()`, "Sun, 25 Sep 2011 23:38:33 UTC") + test(`new Date(12564504e5).toUTCString()`, "Sun, 25 Oct 2009 06:00:00 UTC") + test(`new Date(2009, 9, 25).toUTCString()`, "Sun, 25 Oct 2009 00:00:00 UTC") + test(`+(new Date(2009, 9, 25))`, 1256428800000) - test(`abc.setFullYear(2011); abc.toUTCString()`, "Sun, 25 Sep 2011 23:38:33 UTC") - test(`new Date(12564504e5).toUTCString()`, "Sun, 25 Oct 2009 06:00:00 UTC") - test(`new Date(2009, 9, 25).toUTCString()`, "Sun, 25 Oct 2009 00:00:00 UTC") - test(`+(new Date(2009, 9, 25))`, "1256428800000") + format := "Mon, 2 Jan 2006 15:04:05 MST" - format := "Mon, 2 Jan 2006 15:04:05 MST" + time1 := time.Unix(1256450400, 0) + time0 = time.Date(time1.Year(), time1.Month(), time1.Day(), time1.Hour(), time1.Minute(), time1.Second(), time1.Nanosecond(), time1.Location()).UTC() - tme := Time.Unix(1256450400, 0) - time = Time.Date(tme.Year(), tme.Month(), tme.Day(), tme.Hour(), tme.Minute(), tme.Second(), tme.Nanosecond(), tme.Location()).UTC() + time0 = time.Date(time1.Year(), time1.Month(), time1.Day(), time1.Hour(), time1.Minute(), time1.Second(), 2001*1000*1000, time1.Location()).UTC() + test(`abc = new Date(12564504e5); abc.setMilliseconds(2001); abc.toUTCString()`, time0.Format(format)) - time = Time.Date(tme.Year(), tme.Month(), tme.Day(), tme.Hour(), tme.Minute(), tme.Second(), 2001*1000*1000, tme.Location()).UTC() - test(`abc = new Date(12564504e5); abc.setMilliseconds(2001); abc.toUTCString()`, time.Format(format)) + time0 = time.Date(time1.Year(), time1.Month(), time1.Day(), time1.Hour(), time1.Minute(), 61, time1.Nanosecond(), time1.Location()).UTC() + test(`abc = new Date(12564504e5); abc.setSeconds("61"); abc.toUTCString()`, time0.Format(format)) - time = Time.Date(tme.Year(), tme.Month(), tme.Day(), tme.Hour(), tme.Minute(), 61, tme.Nanosecond(), tme.Location()).UTC() - test(`abc = new Date(12564504e5); abc.setSeconds("61"); abc.toUTCString()`, time.Format(format)) + time0 = time.Date(time1.Year(), time1.Month(), time1.Day(), time1.Hour(), 61, time1.Second(), time1.Nanosecond(), time1.Location()).UTC() + test(`abc = new Date(12564504e5); abc.setMinutes("61"); abc.toUTCString()`, time0.Format(format)) - time = Time.Date(tme.Year(), tme.Month(), tme.Day(), tme.Hour(), 61, tme.Second(), tme.Nanosecond(), tme.Location()).UTC() - test(`abc = new Date(12564504e5); abc.setMinutes("61"); abc.toUTCString()`, time.Format(format)) + time0 = time.Date(time1.Year(), time1.Month(), time1.Day(), 5, time1.Minute(), time1.Second(), time1.Nanosecond(), time1.Location()).UTC() + test(`abc = new Date(12564504e5); abc.setHours("5"); abc.toUTCString()`, time0.Format(format)) - time = Time.Date(tme.Year(), tme.Month(), tme.Day(), 5, tme.Minute(), tme.Second(), tme.Nanosecond(), tme.Location()).UTC() - test(`abc = new Date(12564504e5); abc.setHours("5"); abc.toUTCString()`, time.Format(format)) + time0 = time.Date(time1.Year(), time1.Month(), 26, time1.Hour(), time1.Minute(), time1.Second(), time1.Nanosecond(), time1.Location()).UTC() + test(`abc = new Date(12564504e5); abc.setDate("26"); abc.toUTCString()`, time0.Format(format)) - time = Time.Date(tme.Year(), tme.Month(), 26, tme.Hour(), tme.Minute(), tme.Second(), tme.Nanosecond(), tme.Location()).UTC() - test(`abc = new Date(12564504e5); abc.setDate("26"); abc.toUTCString()`, time.Format(format)) + time0 = time.Date(time1.Year(), 10, time1.Day(), time1.Hour(), time1.Minute(), time1.Second(), time1.Nanosecond(), time1.Location()).UTC() + test(`abc = new Date(12564504e5); abc.setMonth(9); abc.toUTCString()`, time0.Format(format)) + test(`abc = new Date(12564504e5); abc.setMonth("09"); abc.toUTCString()`, time0.Format(format)) - time = Time.Date(tme.Year(), 10, tme.Day(), tme.Hour(), tme.Minute(), tme.Second(), tme.Nanosecond(), tme.Location()).UTC() - test(`abc = new Date(12564504e5); abc.setMonth(9); abc.toUTCString()`, time.Format(format)) - test(`abc = new Date(12564504e5); abc.setMonth("09"); abc.toUTCString()`, time.Format(format)) + time0 = time.Date(time1.Year(), 11, time1.Day(), time1.Hour(), time1.Minute(), time1.Second(), time1.Nanosecond(), time1.Location()).UTC() + test(`abc = new Date(12564504e5); abc.setMonth("10"); abc.toUTCString()`, time0.Format(format)) - time = Time.Date(tme.Year(), 11, tme.Day(), tme.Hour(), tme.Minute(), tme.Second(), tme.Nanosecond(), tme.Location()).UTC() - test(`abc = new Date(12564504e5); abc.setMonth("10"); abc.toUTCString()`, time.Format(format)) + time0 = time.Date(2010, time1.Month(), time1.Day(), time1.Hour(), time1.Minute(), time1.Second(), time1.Nanosecond(), time1.Location()).UTC() + test(`abc = new Date(12564504e5); abc.setFullYear(2010); abc.toUTCString()`, time0.Format(format)) - time = Time.Date(2010, tme.Month(), tme.Day(), tme.Hour(), tme.Minute(), tme.Second(), tme.Nanosecond(), tme.Location()).UTC() - test(`abc = new Date(12564504e5); abc.setFullYear(2010); abc.toUTCString()`, time.Format(format)) + test(`new Date("2001-01-01T10:01:02.000").getTime()`, 978343262000) - test(`new Date("2001-01-01T10:01:02.000").getTime()`, "978343262000") + // Date() + test(`typeof Date()`, "string") + test(`typeof Date(2006, 1, 2)`, "string") - // Date() - test(`typeof Date()`, "string") - test(`typeof Date(2006, 1, 2)`, "string") + test(` + abc = Object.getOwnPropertyDescriptor(Date, "parse"); + [ abc.value === Date.parse, abc.writable, abc.enumerable, abc.configurable ]; + `, "true,true,false,true") - test(` - abc = Object.getOwnPropertyDescriptor(Date, "parse"); - [ abc.value === Date.parse, abc.writable, abc.enumerable, abc.configurable ]; - `, "true,true,false,true") + test(` + abc = Object.getOwnPropertyDescriptor(Date.prototype, "toTimeString"); + [ abc.value === Date.prototype.toTimeString, abc.writable, abc.enumerable, abc.configurable ]; + `, "true,true,false,true") - test(` - abc = Object.getOwnPropertyDescriptor(Date.prototype, "toTimeString"); - [ abc.value === Date.prototype.toTimeString, abc.writable, abc.enumerable, abc.configurable ]; - `, "true,true,false,true") - - test(` - var abc = Object.getOwnPropertyDescriptor(Date, "prototype"); - [ [ typeof Date.prototype ], - [ abc.writable, abc.enumerable, abc.configurable ] ]; - `, "object,false,false,false") + test(` + var abc = Object.getOwnPropertyDescriptor(Date, "prototype"); + [ [ typeof Date.prototype ], + [ abc.writable, abc.enumerable, abc.configurable ] ]; + `, "object,false,false,false") + }) } func TestDate_parse(t *testing.T) { - Terst(t) + tt(t, func() { + test, _ := test() - defer mockUTC()() + defer mockUTC()() - test := runTest() + test(`Date.parse("2001-01-01T10:01:02.000")`, 978343262000) - test(`Date.parse("2001-01-01T10:01:02.000")`, "978343262000") + test(`Date.parse("2006-01-02T15:04:05.000")`, 1136214245000) - test(`Date.parse("2006-01-02T15:04:05.000")`, "1136214245000") + test(`Date.parse("2006")`, 1136073600000) - test(`Date.parse("2006")`, "1136073600000") + test(`Date.parse("1970-01-16T14:36:56+00:00")`, 1348616000) - test(`Date.parse("1970-01-16T14:36:56+00:00")`, "1348616000") + test(`Date.parse("1970-01-16T14:36:56.313+00:00")`, 1348616313) - test(`Date.parse("1970-01-16T14:36:56.313+00:00")`, "1348616313") + test(`Date.parse("1970-01-16T14:36:56.000")`, 1348616000) - test(`Date.parse("1970-01-16T14:36:56.000")`, "1348616000") - - test(`Date.parse.length`, 1) + test(`Date.parse.length`, 1) + }) } func TestDate_UTC(t *testing.T) { - Terst(t) + tt(t, func() { + test, _ := test() - defer mockUTC()() + defer mockUTC()() - test := runTest() + test(`Date.UTC(2009, 9, 25)`, 1256428800000) - test(`Date.UTC(2009, 9, 25)`, "1256428800000") - - test(`Date.UTC.length`, 7) + test(`Date.UTC.length`, 7) + }) } func TestDate_now(t *testing.T) { - Terst(t) + tt(t, func() { + test, _ := test() - defer mockUTC()() + defer mockUTC()() - test := runTest() + // FIXME I think this too risky + test(`+(""+Date.now()).substr(0, 10)`, float64(epochToInteger(timeToEpoch(time.Now()))/1000)) - // FIXME I think this too risky - test(`+(""+Date.now()).substr(0, 10)`, float64(epochToInteger(timeToEpoch(Time.Now()))/1000)) - - test(`Date.now() - Date.now(1,2,3) < 24 * 60 * 60`, true) + test(`Date.now() - Date.now(1,2,3) < 24 * 60 * 60`, true) + }) } func TestDate_toISOString(t *testing.T) { - Terst(t) + tt(t, func() { + test, _ := test() - defer mockUTC()() + defer mockUTC()() - test := runTest() - - test(`new Date(0).toISOString()`, "1970-01-01T00:00:00.000Z") + test(`new Date(0).toISOString()`, "1970-01-01T00:00:00.000Z") + }) } func TestDate_toJSON(t *testing.T) { - Terst(t) + tt(t, func() { + test, _ := test() - defer mockUTC()() + defer mockUTC()() - test := runTest() - - test(`new Date(0).toJSON()`, "1970-01-01T00:00:00.000Z") + test(`new Date(0).toJSON()`, "1970-01-01T00:00:00.000Z") + }) } func TestDate_setYear(t *testing.T) { - Terst(t) + tt(t, func() { + test, _ := test() - defer mockUTC()() + defer mockUTC()() - test := runTest() + test(`new Date(12564504e5).setYear(96)`, 846223200000) - test(`new Date(12564504e5).setYear(96)`, 846223200000) + test(`new Date(12564504e5).setYear(1996)`, 846223200000) - test(`new Date(12564504e5).setYear(1996)`, 846223200000) - - test(`new Date(12564504e5).setYear(2000)`, 972453600000) + test(`new Date(12564504e5).setYear(2000)`, 972453600000) + }) } func TestDateDefaultValue(t *testing.T) { - Terst(t) + tt(t, func() { + test, _ := test() - defer mockUTC()() + defer mockUTC()() - test := runTest() - - test(` + test(` var date = new Date(); date + 0 === date.toString() + "0"; `, true) + }) } func TestDate_April1978(t *testing.T) { - Terst(t) + tt(t, func() { + test, _ := test() - defer mockUTC()() + defer mockUTC()() - test := runTest() - - test(` - var abc = new Date(1978,3); - [ abc.getYear(), abc.getMonth(), abc.valueOf() ]; - `, "78,3,260236800000") + test(` + var abc = new Date(1978,3); + [ abc.getYear(), abc.getMonth(), abc.valueOf() ]; + `, "78,3,260236800000") + }) } func TestDate_setMilliseconds(t *testing.T) { - Terst(t) + tt(t, func() { + test, _ := test() - defer mockUTC()() + defer mockUTC()() - test := runTest() - - test(` - abc = new Date(); - def = abc.setMilliseconds(); - [ abc, def ]; - `, "Invalid Date,NaN") + test(` + abc = new Date(); + def = abc.setMilliseconds(); + [ abc, def ]; + `, "Invalid Date,NaN") + }) } func TestDate_new(t *testing.T) { - Terst(t) - // FIXME? // This is probably incorrect, due to differences in Go date/time handling // versus ECMA date/time handling, but we'll leave this here for // future reference return - defer mockUTC()() + tt(t, func() { + test, _ := test() - test := runTest() + defer mockUTC()() - test(` - [ - new Date(1899, 11).valueOf(), - new Date(1899, 12).valueOf(), - new Date(1900, 0).valueOf() - ] - `, "-2211638400000,-2208960000000,-2208960000000") + test(` + [ + new Date(1899, 11).valueOf(), + new Date(1899, 12).valueOf(), + new Date(1900, 0).valueOf() + ] + `, "-2211638400000,-2208960000000,-2208960000000") + }) } func TestDateComparison(t *testing.T) { - Terst(t) + tt(t, func() { + test, _ := test() - defer mockUTC()() + defer mockUTC()() - test := runTest() - - test(` - var now0 = Date.now(); - var now1 = (new Date()).toString(); - [ now0 === now1, Math.abs(now0 - Date.parse(now1)) <= 1000 ]; - `, "false,true") + test(` + var now0 = Date.now(); + var now1 = (new Date()).toString(); + [ now0 === now1, Math.abs(now0 - Date.parse(now1)) <= 1000 ]; + `, "false,true") + }) } func TestDate_setSeconds(t *testing.T) { - Terst(t) + tt(t, func() { + test, _ := test() - defer mockUTC()() + defer mockUTC()() - test := runTest() + test(` + abc = new Date(1980, 10); + def = new Date(abc); - test(` - abc = new Date(1980, 10); - def = new Date(abc); + abc.setSeconds(10, 12); - abc.setSeconds(10, 12); + def.setSeconds(10); + def.setMilliseconds(12); - def.setSeconds(10); - def.setMilliseconds(12); + abc.valueOf() === def.valueOf(); + `, true) - abc.valueOf() === def.valueOf(); - `, true) + test(` + abc = new Date(1980, 10); + def = new Date(abc); - test(` - abc = new Date(1980, 10); - def = new Date(abc); + abc.setUTCSeconds(10, 12); - abc.setUTCSeconds(10, 12); + def.setUTCSeconds(10); + def.setUTCMilliseconds(12); - def.setUTCSeconds(10); - def.setUTCMilliseconds(12); + abc.valueOf() === def.valueOf(); + `, true) - abc.valueOf() === def.valueOf(); - `, true) - - test(`Date.prototype.setSeconds.length`, 2) - test(`Date.prototype.setUTCSeconds.length`, 2) + test(`Date.prototype.setSeconds.length`, 2) + test(`Date.prototype.setUTCSeconds.length`, 2) + }) } func TestDate_setMinutes(t *testing.T) { - Terst(t) + tt(t, func() { + test, _ := test() - defer mockUTC()() + defer mockUTC()() - test := runTest() + test(` + abc = new Date(1980, 10); + def = new Date(abc); - test(` - abc = new Date(1980, 10); - def = new Date(abc); + abc.setMinutes(8, 10, 12); - abc.setMinutes(8, 10, 12); + def.setMinutes(8); + def.setSeconds(10); + def.setMilliseconds(12); - def.setMinutes(8); - def.setSeconds(10); - def.setMilliseconds(12); + abc.valueOf() === def.valueOf(); + `, true) - abc.valueOf() === def.valueOf(); - `, true) + test(` + abc = new Date(1980, 10); + def = new Date(abc); - test(` - abc = new Date(1980, 10); - def = new Date(abc); + abc.setUTCMinutes(8, 10, 12); - abc.setUTCMinutes(8, 10, 12); + def.setUTCMinutes(8); + def.setUTCSeconds(10); + def.setUTCMilliseconds(12); - def.setUTCMinutes(8); - def.setUTCSeconds(10); - def.setUTCMilliseconds(12); + abc.valueOf() === def.valueOf(); + `, true) - abc.valueOf() === def.valueOf(); - `, true) - - test(`Date.prototype.setMinutes.length`, 3) - test(`Date.prototype.setUTCMinutes.length`, 3) + test(`Date.prototype.setMinutes.length`, 3) + test(`Date.prototype.setUTCMinutes.length`, 3) + }) } func TestDate_setHours(t *testing.T) { - Terst(t) + tt(t, func() { + test, _ := test() - defer mockUTC()() + defer mockUTC()() - test := runTest() + test(` + abc = new Date(1980, 10); + def = new Date(abc); - test(` - abc = new Date(1980, 10); - def = new Date(abc); + abc.setHours(6, 8, 10, 12); - abc.setHours(6, 8, 10, 12); + def.setHours(6); + def.setMinutes(8); + def.setSeconds(10); + def.setMilliseconds(12); - def.setHours(6); - def.setMinutes(8); - def.setSeconds(10); - def.setMilliseconds(12); + abc.valueOf() === def.valueOf(); + `, true) - abc.valueOf() === def.valueOf(); - `, true) + test(` + abc = new Date(1980, 10); + def = new Date(abc); - test(` - abc = new Date(1980, 10); - def = new Date(abc); + abc.setUTCHours(6, 8, 10, 12); - abc.setUTCHours(6, 8, 10, 12); + def.setUTCHours(6); + def.setUTCMinutes(8); + def.setUTCSeconds(10); + def.setUTCMilliseconds(12); - def.setUTCHours(6); - def.setUTCMinutes(8); - def.setUTCSeconds(10); - def.setUTCMilliseconds(12); + abc.valueOf() === def.valueOf(); + `, true) - abc.valueOf() === def.valueOf(); - `, true) - - test(`Date.prototype.setHours.length`, 4) - test(`Date.prototype.setUTCHours.length`, 4) + test(`Date.prototype.setHours.length`, 4) + test(`Date.prototype.setUTCHours.length`, 4) + }) } func TestDate_setMonth(t *testing.T) { - Terst(t) + tt(t, func() { + test, _ := test() - defer mockUTC()() + defer mockUTC()() - test := runTest() + test(` + abc = new Date(1980, 10); + def = new Date(abc); - test(` - abc = new Date(1980, 10); - def = new Date(abc); + abc.setMonth(6, 8); - abc.setMonth(6, 8); + def.setMonth(6); + def.setDate(8); - def.setMonth(6); - def.setDate(8); + abc.valueOf() === def.valueOf(); + `, true) - abc.valueOf() === def.valueOf(); - `, true) + test(` + abc = new Date(1980, 10); + def = new Date(abc); - test(` - abc = new Date(1980, 10); - def = new Date(abc); + abc.setUTCMonth(6, 8); - abc.setUTCMonth(6, 8); + def.setUTCMonth(6); + def.setUTCDate(8); - def.setUTCMonth(6); - def.setUTCDate(8); + abc.valueOf() === def.valueOf(); + `, true) - abc.valueOf() === def.valueOf(); - `, true) - - test(`Date.prototype.setMonth.length`, 2) - test(`Date.prototype.setUTCMonth.length`, 2) + test(`Date.prototype.setMonth.length`, 2) + test(`Date.prototype.setUTCMonth.length`, 2) + }) } func TestDate_setFullYear(t *testing.T) { - Terst(t) + tt(t, func() { + test, _ := test() - defer mockUTC()() + defer mockUTC()() - test := runTest() + test(` + abc = new Date(1980, 10); + def = new Date(abc); - test(` - abc = new Date(1980, 10); - def = new Date(abc); + abc.setFullYear(1981, 6, 8); - abc.setFullYear(1981, 6, 8); + def.setFullYear(1981); + def.setMonth(6); + def.setDate(8); - def.setFullYear(1981); - def.setMonth(6); - def.setDate(8); + abc.valueOf() === def.valueOf(); + `, true) - abc.valueOf() === def.valueOf(); - `, true) + test(` + abc = new Date(1980, 10); + def = new Date(abc); - test(` - abc = new Date(1980, 10); - def = new Date(abc); + abc.setUTCFullYear(1981, 6, 8); - abc.setUTCFullYear(1981, 6, 8); + def.setUTCFullYear(1981); + def.setUTCMonth(6); + def.setUTCDate(8); - def.setUTCFullYear(1981); - def.setUTCMonth(6); - def.setUTCDate(8); + abc.valueOf() === def.valueOf(); + `, true) - abc.valueOf() === def.valueOf(); - `, true) - - test(`Date.prototype.setFullYear.length`, 3) - test(`Date.prototype.setUTCFullYear.length`, 3) + test(`Date.prototype.setFullYear.length`, 3) + test(`Date.prototype.setUTCFullYear.length`, 3) + }) } func TestDate_setTime(t *testing.T) { - Terst(t) + tt(t, func() { + test, _ := test() - defer mockUTC()() + defer mockUTC()() - test := runTest() + test(` + var abc = new Date(1999, 6, 1); + var def = new Date(); + def.setTime(abc.getTime()); + [ def, abc.valueOf() == def.valueOf() ]; + `, "Thu, 01 Jul 1999 00:00:00 UTC,true") - test(` - var abc = new Date(1999, 6, 1); - var def = new Date(); - def.setTime(abc.getTime()); - [ def, abc.valueOf() == def.valueOf() ]; - `, "Thu, 01 Jul 1999 00:00:00 UTC,true") - - test(`Date.prototype.setTime.length`, 1) + test(`Date.prototype.setTime.length`, 1) + }) } diff --git a/error_test.go b/error_test.go index 0364147..d0580c6 100644 --- a/error_test.go +++ b/error_test.go @@ -1,63 +1,62 @@ package otto import ( - . "./terst" "testing" ) func TestError(t *testing.T) { - Terst(t) + tt(t, func() { + test, _ := test() - test := runTest() - - test(` - [ Error.prototype.name, Error.prototype.message, Error.prototype.hasOwnProperty("message") ]; - `, "Error,,true") + test(` + [ Error.prototype.name, Error.prototype.message, Error.prototype.hasOwnProperty("message") ]; + `, "Error,,true") + }) } func TestError_instanceof(t *testing.T) { - Terst(t) + tt(t, func() { + test, _ := test() - test := runTest() - - test(`(new TypeError()) instanceof Error`, true) + test(`(new TypeError()) instanceof Error`, true) + }) } func TestPanicValue(t *testing.T) { - Terst(t) + tt(t, func() { + test, vm := test() - test := runTest() + vm.Set("abc", func(call FunctionCall) Value { + value, err := call.Otto.Run(`({ def: 3.14159 })`) + is(err, nil) + panic(value) + }) - failSet("abc", func(call FunctionCall) Value { - value, err := call.Otto.Run(`({ def: 3.14159 })`) - Is(err, nil) - panic(value) + test(` + try { + abc(); + } + catch (err) { + error = err; + } + [ error instanceof Error, error.message, error.def ]; + `, "false,,3.14159") }) - - test(` - try { - abc(); - } - catch (err) { - error = err; - } - [ error instanceof Error, error.message, error.def ]; - `, "false,,3.14159") } func Test_catchPanic(t *testing.T) { - Terst(t) + tt(t, func() { + vm := New() - otto, _ := runTestWithOtto() + _, err := vm.Run(` + A syntax error that + does not define + var; + abc; + `) + is(err, "!=", nil) - _, err := otto.Run(` - A syntax error that - does not define - var; - abc; - `) - IsNot(err, nil) - - _, err = otto.Call(`abc.def`, nil) - IsNot(err, nil) + _, err = vm.Call(`abc.def`, nil) + is(err, "!=", nil) + }) } diff --git a/function_test.go b/function_test.go index 9b95d5d..bd43802 100644 --- a/function_test.go +++ b/function_test.go @@ -1,192 +1,191 @@ package otto import ( - . "./terst" "testing" ) func TestFunction(t *testing.T) { - Terst(t) + tt(t, func() { + test, _ := test() - test := runTest() - - test(` - var abc = Object.getOwnPropertyDescriptor(Function, "prototype"); - [ [ typeof Function.prototype, typeof Function.prototype.length, Function.prototype.length ], - [ abc.writable, abc.enumerable, abc.configurable ] ]; - `, "function,number,0,false,false,false") + test(` + var abc = Object.getOwnPropertyDescriptor(Function, "prototype"); + [ [ typeof Function.prototype, typeof Function.prototype.length, Function.prototype.length ], + [ abc.writable, abc.enumerable, abc.configurable ] ]; + `, "function,number,0,false,false,false") + }) } func Test_argumentList2parameterList(t *testing.T) { - Terst(t) - - Is(argumentList2parameterList([]Value{toValue("abc, def"), toValue("ghi")}), []string{"abc", "def", "ghi"}) + tt(t, func() { + is(argumentList2parameterList([]Value{toValue("abc, def"), toValue("ghi")}), []string{"abc", "def", "ghi"}) + }) } func TestFunction_new(t *testing.T) { - Terst(t) + tt(t, func() { + test, _ := test() - test := runTest() + test(`raise: + new Function({}); + `, "SyntaxError: Unexpected identifier") - test(`raise: - new Function({}); - `, "SyntaxError: Unexpected identifier") + test(` + var abc = Function("def, ghi", "jkl", "return def+ghi+jkl"); + [ typeof abc, abc instanceof Function, abc("ab", "ba", 1) ]; + `, "function,true,abba1") - test(` - var abc = Function("def, ghi", "jkl", "return def+ghi+jkl"); - [ typeof abc, abc instanceof Function, abc("ab", "ba", 1) ]; - `, "function,true,abba1") + test(`raise: + var abc = { + toString: function() { throw 1; } + }; + var def = { + toString: function() { throw 2; } + }; + var ghi = new Function(abc, def); + ghi; + `, "1") - test(`raise: - var abc = { - toString: function() { throw 1; } - }; - var def = { - toString: function() { throw 2; } - }; - var ghi = new Function(abc, def); - ghi; - `, "1") + // S15.3.2.1_A3_T10 + test(`raise: + var abc = { + toString: function() { return "z;x"; } + }; + var def = "return this"; + var ghi = new Function(abc, def); + ghi; + `, "SyntaxError: Unexpected token ;") - // S15.3.2.1_A3_T10 - test(`raise: - var abc = { - toString: function() { return "z;x"; } - }; - var def = "return this"; - var ghi = new Function(abc, def); - ghi; - `, "SyntaxError: Unexpected token ;") - - test(`raise: - var abc; - var def = "return true"; - var ghi = new Function(null, def); - ghi; - `, "SyntaxError: Unexpected token null") + test(`raise: + var abc; + var def = "return true"; + var ghi = new Function(null, def); + ghi; + `, "SyntaxError: Unexpected token null") + }) } func TestFunction_apply(t *testing.T) { - Terst(t) + tt(t, func() { + test, _ := test() - test := runTest() - - test(`Function.prototype.apply.length`, 2) - test(`String.prototype.substring.apply("abc", [1, 11])`, "bc") + test(`Function.prototype.apply.length`, 2) + test(`String.prototype.substring.apply("abc", [1, 11])`, "bc") + }) } func TestFunction_call(t *testing.T) { - Terst(t) + tt(t, func() { + test, _ := test() - test := runTest() - - test(`Function.prototype.call.length`, 1) - test(`String.prototype.substring.call("abc", 1, 11)`, "bc") + test(`Function.prototype.call.length`, 1) + test(`String.prototype.substring.call("abc", 1, 11)`, "bc") + }) } func TestFunctionArguments(t *testing.T) { - Terst(t) + tt(t, func() { + test, _ := test() - test := runTest() + // Should not be able to delete arguments + test(` + function abc(def, arguments){ + delete def; + return def; + } + abc(1); + `, 1) - // Should not be able to delete arguments - test(` - function abc(def, arguments){ - delete def; - return def; - } - abc(1); - `, 1) + // Again, should not be able to delete arguments + test(` + function abc(def){ + delete def; + return def; + } + abc(1); + `, 1) - // Again, should not be able to delete arguments - test(` - function abc(def){ - delete def; - return def; - } - abc(1); - `, 1) + // Test typeof of a function argument + test(` + function abc(def, ghi, jkl){ + return typeof jkl + } + abc("1st", "2nd", "3rd", "4th", "5th"); + `, "string") - // Test typeof of a function argument - test(` - function abc(def, ghi, jkl){ - return typeof jkl - } - abc("1st", "2nd", "3rd", "4th", "5th"); - `, "string") - - test(` - function abc(def, ghi, jkl){ - arguments[0] = 3.14; - arguments[1] = 'Nothing happens'; - arguments[2] = 42; - if (3.14 === def && 'Nothing happens' === ghi && 42 === jkl) - return true; - } - abc(-1, 4.2, 314); - `, true) + test(` + function abc(def, ghi, jkl){ + arguments[0] = 3.14; + arguments[1] = 'Nothing happens'; + arguments[2] = 42; + if (3.14 === def && 'Nothing happens' === ghi && 42 === jkl) + return true; + } + abc(-1, 4.2, 314); + `, true) + }) } func TestFunctionDeclarationInFunction(t *testing.T) { - Terst(t) + tt(t, func() { + test, _ := test() - // Function declarations happen AFTER parameter/argument declarations - // That is, a function declared within a function will shadow/overwrite - // declared parameters - test := runTest() + // Function declarations happen AFTER parameter/argument declarations + // That is, a function declared within a function will shadow/overwrite + // declared parameters - test(` - function abc(def){ - return def; - function def(){ - return 1; + test(` + function abc(def){ + return def; + function def(){ + return 1; + } } - } - typeof abc(); - `, "function") + typeof abc(); + `, "function") + }) } func TestArguments_defineOwnProperty(t *testing.T) { - Terst(t) + tt(t, func() { + test, _ := test() - test := runTest() - - test(` - var abc; - var def = true; - var ghi = {}; - (function (a, b, c) { - Object.defineProperty(arguments, "0", { - value: 42, - writable: false, - enumerable: false, - configurable: false - }); - Object.defineProperty(arguments, "1", { - value: 3.14, - configurable: true, - enumerable: true - }); - abc = Object.getOwnPropertyDescriptor(arguments, "0"); - for (var name in arguments) { - ghi[name] = (ghi[name] || 0) + 1; - if (name === "0") { - def = false; + test(` + var abc; + var def = true; + var ghi = {}; + (function (a, b, c) { + Object.defineProperty(arguments, "0", { + value: 42, + writable: false, + enumerable: false, + configurable: false + }); + Object.defineProperty(arguments, "1", { + value: 3.14, + configurable: true, + enumerable: true + }); + abc = Object.getOwnPropertyDescriptor(arguments, "0"); + for (var name in arguments) { + ghi[name] = (ghi[name] || 0) + 1; + if (name === "0") { + def = false; + } } - } - }(0, 1, 2)); - [ abc.value, abc.writable, abc.enumerable, abc.configurable, def, ghi["1"] ]; - `, "42,false,false,false,true,1") + }(0, 1, 2)); + [ abc.value, abc.writable, abc.enumerable, abc.configurable, def, ghi["1"] ]; + `, "42,false,false,false,true,1") + }) } func TestFunction_bind(t *testing.T) { - Terst(t) + tt(t, func() { + test, _ := test() - defer mockUTC()() + defer mockUTC()() - test := runTest() - - test(` + test(` abc = function(){ return "abc"; }; @@ -194,79 +193,80 @@ func TestFunction_bind(t *testing.T) { [ typeof def.prototype, typeof def.hasOwnProperty, def.hasOwnProperty("caller"), def.hasOwnProperty("arguments"), def() ]; `, "object,function,true,true,abc") - test(` - abc = function(){ - return arguments[1]; - }; - def = abc.bind(undefined, "abc"); - ghi = abc.bind(undefined, "abc", "ghi"); - [ def(), def("def"), ghi("def") ]; - `, ",def,ghi") + test(` + abc = function(){ + return arguments[1]; + }; + def = abc.bind(undefined, "abc"); + ghi = abc.bind(undefined, "abc", "ghi"); + [ def(), def("def"), ghi("def") ]; + `, ",def,ghi") - test(` - var abc = function () {}; - var ghi; - try { - Object.defineProperty(Function.prototype, "xyzzy", { - value: 1001, - writable: true, - enumerable: true, - configurable: true - }); - var def = abc.bind({}); - ghi = !def.hasOwnProperty("xyzzy") && ghi.xyzzy === 1001; - } finally { - delete Function.prototype.xyzzy; - } - [ ghi ]; - `, "true") + test(` + var abc = function () {}; + var ghi; + try { + Object.defineProperty(Function.prototype, "xyzzy", { + value: 1001, + writable: true, + enumerable: true, + configurable: true + }); + var def = abc.bind({}); + ghi = !def.hasOwnProperty("xyzzy") && ghi.xyzzy === 1001; + } finally { + delete Function.prototype.xyzzy; + } + [ ghi ]; + `, "true") - test(` - var abc = function (def, ghi) {}; - var jkl = abc.bind({}); - var mno = abc.bind({}, 1, 2); - [ jkl.length, mno.length ]; - `, "2,0") + test(` + var abc = function (def, ghi) {}; + var jkl = abc.bind({}); + var mno = abc.bind({}, 1, 2); + [ jkl.length, mno.length ]; + `, "2,0") - test(`raise: - Math.bind(); - `, "TypeError: undefined is not a function") + test(`raise: + Math.bind(); + `, "TypeError: undefined is not a function") - test(` - function construct(fn, arguments) { - var bound = Function.prototype.bind.apply(fn, [null].concat(arguments)); - return new bound(); - } - var abc = construct(Date, [1957, 4, 27]); - Object.prototype.toString.call(abc); - `, "[object Date]") + test(` + function construct(fn, arguments) { + var bound = Function.prototype.bind.apply(fn, [null].concat(arguments)); + return new bound(); + } + var abc = construct(Date, [1957, 4, 27]); + Object.prototype.toString.call(abc); + `, "[object Date]") - test(` - var fn = function (x, y, z) { - var result = {}; - result.abc = x + y + z; - result.def = arguments[0] === "a" && arguments.length === 3; - return result; - }; - var newFn = Function.prototype.bind.call(fn, {}, "a", "b", "c"); - var result = new newFn(); - [ result.hasOwnProperty("abc"), result.hasOwnProperty("def"), result.abc, result.def ]; - `, "true,true,abc,true") + test(` + var fn = function (x, y, z) { + var result = {}; + result.abc = x + y + z; + result.def = arguments[0] === "a" && arguments.length === 3; + return result; + }; + var newFn = Function.prototype.bind.call(fn, {}, "a", "b", "c"); + var result = new newFn(); + [ result.hasOwnProperty("abc"), result.hasOwnProperty("def"), result.abc, result.def ]; + `, "true,true,abc,true") + }) } func TestFunction_toString(t *testing.T) { - Terst(t) + tt(t, func() { + test, _ := test() - test := runTest() + test(`raise: + Function.prototype.toString.call(undefined); + `, "TypeError") - test(`raise: - Function.prototype.toString.call(undefined); - `, "TypeError") - - test(` - abc = function() { return -1 ; + test(` + abc = function() { return -1 ; } - 1; - abc.toString(); - `, "function() { return -1 ;\n}") + 1; + abc.toString(); + `, "function() { return -1 ;\n}") + }) } diff --git a/global_test.go b/global_test.go index 7fcfab8..c5204e5 100644 --- a/global_test.go +++ b/global_test.go @@ -1,7 +1,6 @@ package otto import ( - . "./terst" "fmt" "math" "strings" @@ -9,344 +8,345 @@ import ( ) func TestGlobal(t *testing.T) { - Terst(t) + tt(t, func() { + test, vm := test() - vm, test := runTestWithOtto() - runtime := vm.runtime + runtime := vm.vm.runtime - { - call := func(object interface{}, src string, argumentList ...interface{}) Value { - var tgt *Object - switch object := object.(type) { - case Value: - tgt = object.Object() - case *Object: - tgt = object - case *_object: - tgt = toValue_object(object).Object() - default: - panic("Here be dragons.") + { + call := func(object interface{}, src string, argumentList ...interface{}) Value { + var tgt *Object + switch object := object.(type) { + case Value: + tgt = object.Object() + case *Object: + tgt = object + case *_object: + tgt = toValue_object(object).Object() + default: + panic("Here be dragons.") + } + value, err := tgt.Call(src, argumentList...) + is(err, nil) + return value } - value, err := tgt.Call(src, argumentList...) - Is(err, nil) - return value + + value := runtime.localGet("Object")._object().Call(UndefinedValue(), []Value{toValue(runtime.newObject())}) + is(value.IsObject(), true) + is(value, "[object Object]") + is(value._object().prototype == runtime.Global.ObjectPrototype, true) + is(value._object().prototype == runtime.Global.Object.get("prototype")._object(), true) + is(value._object().get("toString"), "function toString() { [native code] }") + is(call(value.Object(), "hasOwnProperty", "hasOwnProperty"), false) + + is(call(value._object().get("toString")._object().prototype, "toString"), "function () { [native code] }") // TODO Is this right? + is(value._object().get("toString")._object().get("toString"), "function toString() { [native code] }") + is(value._object().get("toString")._object().get("toString")._object(), "function toString() { [native code] }") + + is(call(value._object(), "propertyIsEnumerable", "isPrototypeOf"), false) + value._object().put("xyzzy", toValue_string("Nothing happens."), false) + is(call(value, "propertyIsEnumerable", "isPrototypeOf"), false) + is(call(value, "propertyIsEnumerable", "xyzzy"), true) + is(value._object().get("xyzzy"), "Nothing happens.") + + is(call(runtime.localGet("Object"), "isPrototypeOf", value), false) + is(call(runtime.localGet("Object")._object().get("prototype"), "isPrototypeOf", value), true) + is(call(runtime.localGet("Function"), "isPrototypeOf", value), false) + + is(runtime.newObject().prototype == runtime.Global.Object.get("prototype")._object(), true) + + abc := runtime.newBoolean(toValue_bool(true)) + is(toValue_object(abc), "true") // TODO Call primitive? + + def := runtime.localGet("Boolean")._object().Construct(UndefinedValue(), []Value{}) + is(def, "false") // TODO Call primitive? } - value := runtime.localGet("Object")._object().Call(UndefinedValue(), []Value{toValue(runtime.newObject())}) - Is(value.IsObject(), true) - Is(value, "[object Object]") - Is(value._object().prototype == runtime.Global.ObjectPrototype, true) - Is(value._object().prototype == runtime.Global.Object.get("prototype")._object(), true) - Is(value._object().get("toString"), "function toString() { [native code] }") - is(call(value.Object(), "hasOwnProperty", "hasOwnProperty"), false) + test(`new Number().constructor == Number`, true) - is(call(value._object().get("toString")._object().prototype, "toString"), "function () { [native code] }") // TODO Is this right? - Is(value._object().get("toString")._object().get("toString"), "function toString() { [native code] }") - Is(value._object().get("toString")._object().get("toString")._object(), "function toString() { [native code] }") + test(`this.hasOwnProperty`, "function hasOwnProperty() { [native code] }") - is(call(value._object(), "propertyIsEnumerable", "isPrototypeOf"), false) - value._object().put("xyzzy", toValue_string("Nothing happens."), false) - is(call(value, "propertyIsEnumerable", "isPrototypeOf"), false) - is(call(value, "propertyIsEnumerable", "xyzzy"), true) - Is(value._object().get("xyzzy"), "Nothing happens.") + test(`eval.length === 1`, true) + test(`eval.prototype === undefined`, true) + test(`raise: new eval()`, "TypeError: function eval() { [native code] } is not a constructor") - is(call(runtime.localGet("Object"), "isPrototypeOf", value), false) - is(call(runtime.localGet("Object")._object().get("prototype"), "isPrototypeOf", value), true) - is(call(runtime.localGet("Function"), "isPrototypeOf", value), false) + test(` + [ + [ delete undefined, undefined ], + [ delete NaN, NaN ], + [ delete Infinity, Infinity ], + ]; + `, "false,,false,NaN,false,Infinity") - Is(runtime.newObject().prototype == runtime.Global.Object.get("prototype")._object(), true) + test(` + Object.getOwnPropertyNames(Function('return this')()).sort(); + `, "Array,Boolean,Date,Error,EvalError,Function,Infinity,JSON,Math,NaN,Number,Object,RangeError,ReferenceError,RegExp,String,SyntaxError,TypeError,URIError,console,decodeURI,decodeURIComponent,encodeURI,encodeURIComponent,escape,eval,isFinite,isNaN,parseFloat,parseInt,undefined,unescape") - abc := runtime.newBoolean(toValue_bool(true)) - Is(toValue_object(abc), "true") // TODO Call primitive? + // __defineGetter__,__defineSetter__,__lookupGetter__,__lookupSetter__,constructor,hasOwnProperty,isPrototypeOf,propertyIsEnumerable,toLocaleString,toString,valueOf + test(` + Object.getOwnPropertyNames(Object.prototype).sort(); + `, "constructor,hasOwnProperty,isPrototypeOf,propertyIsEnumerable,toLocaleString,toString,valueOf") - def := runtime.localGet("Boolean")._object().Construct(UndefinedValue(), []Value{}) - Is(def, "false") // TODO Call primitive? - } + // arguments,caller,length,name,prototype + test(` + Object.getOwnPropertyNames(EvalError).sort(); + `, "length,prototype") - test(`new Number().constructor == Number`, true) + test(` + var abc = []; + var def = [EvalError, RangeError, ReferenceError, SyntaxError, TypeError, URIError]; + for (constructor in def) { + abc.push(def[constructor] === def[constructor].prototype.constructor); + } + def = [Array, Boolean, Date, Function, Number, Object, RegExp, String, SyntaxError]; + for (constructor in def) { + abc.push(def[constructor] === def[constructor].prototype.constructor); + } + abc; + `, "true,true,true,true,true,true,true,true,true,true,true,true,true,true,true") - test(`this.hasOwnProperty`, "function hasOwnProperty() { [native code] }") + test(` + [ Array.prototype.constructor === Array, Array.constructor === Function ]; + `, "true,true") - test(`eval.length === 1`, true) - test(`eval.prototype === undefined`, true) - test(`raise: new eval()`, "TypeError: function eval() { [native code] } is not a constructor") + test(` + [ Number.prototype.constructor === Number, Number.constructor === Function ]; + `, "true,true") - test(` - [ - [ delete undefined, undefined ], - [ delete NaN, NaN ], - [ delete Infinity, Infinity ], - ]; - `, "false,,false,NaN,false,Infinity") - - test(` - Object.getOwnPropertyNames(Function('return this')()).sort(); - `, "Array,Boolean,Date,Error,EvalError,Function,Infinity,JSON,Math,NaN,Number,Object,RangeError,ReferenceError,RegExp,String,SyntaxError,TypeError,URIError,console,decodeURI,decodeURIComponent,encodeURI,encodeURIComponent,escape,eval,isFinite,isNaN,parseFloat,parseInt,undefined,unescape") - - // __defineGetter__,__defineSetter__,__lookupGetter__,__lookupSetter__,constructor,hasOwnProperty,isPrototypeOf,propertyIsEnumerable,toLocaleString,toString,valueOf - test(` - Object.getOwnPropertyNames(Object.prototype).sort(); - `, "constructor,hasOwnProperty,isPrototypeOf,propertyIsEnumerable,toLocaleString,toString,valueOf") - - // arguments,caller,length,name,prototype - test(` - Object.getOwnPropertyNames(EvalError).sort(); - `, "length,prototype") - - test(` - var abc = []; - var def = [EvalError, RangeError, ReferenceError, SyntaxError, TypeError, URIError]; - for (constructor in def) { - abc.push(def[constructor] === def[constructor].prototype.constructor); - } - def = [Array, Boolean, Date, Function, Number, Object, RegExp, String, SyntaxError]; - for (constructor in def) { - abc.push(def[constructor] === def[constructor].prototype.constructor); - } - abc; - `, "true,true,true,true,true,true,true,true,true,true,true,true,true,true,true") - - test(` - [ Array.prototype.constructor === Array, Array.constructor === Function ]; - `, "true,true") - - test(` - [ Number.prototype.constructor === Number, Number.constructor === Function ]; - `, "true,true") - - test(` - [ Function.prototype.constructor === Function, Function.constructor === Function ]; - `, "true,true") + test(` + [ Function.prototype.constructor === Function, Function.constructor === Function ]; + `, "true,true") + }) } func TestGlobalLength(t *testing.T) { - Terst(t) + tt(t, func() { + test, _ := test() - test := runTest() - - test(` - [ Object.length, Function.length, RegExp.length, Math.length ]; - `, "1,1,2,") + test(` + [ Object.length, Function.length, RegExp.length, Math.length ]; + `, "1,1,2,") + }) } func TestGlobalError(t *testing.T) { - Terst(t) + tt(t, func() { + test, _ := test() - test := runTest() + test(` + [ TypeError.length, TypeError(), TypeError("Nothing happens.") ]; + `, "1,TypeError,TypeError: Nothing happens.") - test(` - [ TypeError.length, TypeError(), TypeError("Nothing happens.") ]; - `, "1,TypeError,TypeError: Nothing happens.") - - test(` - [ URIError.length, URIError(), URIError("Nothing happens.") ]; - `, "1,URIError,URIError: Nothing happens.") + test(` + [ URIError.length, URIError(), URIError("Nothing happens.") ]; + `, "1,URIError,URIError: Nothing happens.") + }) } func TestGlobalReadOnly(t *testing.T) { - Terst(t) + tt(t, func() { + test, _ := test() - test := runTest() + test(`Number.POSITIVE_INFINITY`, math.Inf(1)) - test(`Number.POSITIVE_INFINITY`, math.Inf(1)) + test(` + Number.POSITIVE_INFINITY = 1; + `, 1) - test(` - Number.POSITIVE_INFINITY = 1; - `, 1) + test(`Number.POSITIVE_INFINITY`, math.Inf(1)) - test(`Number.POSITIVE_INFINITY`, math.Inf(1)) - - test(` - Number.POSITIVE_INFINITY = 1; - Number.POSITIVE_INFINITY; - `, math.Inf(1)) + test(` + Number.POSITIVE_INFINITY = 1; + Number.POSITIVE_INFINITY; + `, math.Inf(1)) + }) } func Test_isNaN(t *testing.T) { - Terst(t) + tt(t, func() { + test, _ := test() - test := runTest() + test(`isNaN(0)`, false) + test(`isNaN("Xyzzy")`, true) + test(`isNaN()`, true) + test(`isNaN(NaN)`, true) + test(`isNaN(Infinity)`, false) - test(`isNaN(0)`, false) - test(`isNaN("Xyzzy")`, true) - test(`isNaN()`, true) - test(`isNaN(NaN)`, true) - test(`isNaN(Infinity)`, false) - - test(`isNaN.length === 1`, true) - test(`isNaN.prototype === undefined`, true) + test(`isNaN.length === 1`, true) + test(`isNaN.prototype === undefined`, true) + }) } func Test_isFinite(t *testing.T) { - Terst(t) + tt(t, func() { + test, _ := test() - test := runTest() + test(`isFinite(0)`, true) + test(`isFinite("Xyzzy")`, false) + test(`isFinite()`, false) + test(`isFinite(NaN)`, false) + test(`isFinite(Infinity)`, false) + test(`isFinite(new Number(451));`, true) - test(`isFinite(0)`, true) - test(`isFinite("Xyzzy")`, false) - test(`isFinite()`, false) - test(`isFinite(NaN)`, false) - test(`isFinite(Infinity)`, false) - test(`isFinite(new Number(451));`, true) - - test(`isFinite.length === 1`, true) - test(`isFinite.prototype === undefined`, true) + test(`isFinite.length === 1`, true) + test(`isFinite.prototype === undefined`, true) + }) } func Test_parseInt(t *testing.T) { - Terst(t) + tt(t, func() { + test, _ := test() - test := runTest() + test(`parseInt("0")`, 0) + test(`parseInt("11")`, 11) + test(`parseInt(" 11")`, 11) + test(`parseInt("11 ")`, 11) + test(`parseInt(" 11 ")`, 11) + test(`parseInt(" 11\n")`, 11) + test(`parseInt(" 11\n", 16)`, 17) - test(`parseInt("0")`, 0) - test(`parseInt("11")`, 11) - test(`parseInt(" 11")`, 11) - test(`parseInt("11 ")`, 11) - test(`parseInt(" 11 ")`, 11) - test(`parseInt(" 11\n")`, 11) - test(`parseInt(" 11\n", 16)`, 17) + test(`parseInt("Xyzzy")`, _NaN) - test(`parseInt("Xyzzy")`, "NaN") + test(`parseInt(" 0x11\n", 16)`, 17) + test(`parseInt("0x0aXyzzy", 16)`, 10) + test(`parseInt("0x1", 0)`, 1) + test(`parseInt("0x10000000000000000000", 16)`, float64(75557863725914323419136)) - test(`parseInt(" 0x11\n", 16)`, 17) - test(`parseInt("0x0aXyzzy", 16)`, 10) - test(`parseInt("0x1", 0)`, 1) - test(`parseInt("0x10000000000000000000", 16)`, float64(75557863725914323419136)) - - test(`parseInt.length === 2`, true) - test(`parseInt.prototype === undefined`, true) + test(`parseInt.length === 2`, true) + test(`parseInt.prototype === undefined`, true) + }) } func Test_parseFloat(t *testing.T) { - Terst(t) + tt(t, func() { + test, _ := test() - test := runTest() + test(`parseFloat("0")`, 0) + test(`parseFloat("11")`, 11) + test(`parseFloat(" 11")`, 11) + test(`parseFloat("11 ")`, 11) + test(`parseFloat(" 11 ")`, 11) + test(`parseFloat(" 11\n")`, 11) + test(`parseFloat(" 11\n", 16)`, 11) + test(`parseFloat("11.1")`, 11.1) - test(`parseFloat("0")`, 0) - test(`parseFloat("11")`, 11) - test(`parseFloat(" 11")`, 11) - test(`parseFloat("11 ")`, 11) - test(`parseFloat(" 11 ")`, 11) - test(`parseFloat(" 11\n")`, 11) - test(`parseFloat(" 11\n", 16)`, 11) - test(`parseFloat("11.1")`, 11.1) + test(`parseFloat("Xyzzy")`, _NaN) - test(`parseFloat("Xyzzy")`, "NaN") + test(`parseFloat(" 0x11\n", 16)`, 0) + test(`parseFloat("0x0a")`, 0) + test(`parseFloat("0x0aXyzzy")`, 0) + test(`parseFloat("Infinity")`, _Infinity) + test(`parseFloat("infinity")`, _NaN) + test(`parseFloat("0x")`, 0) + test(`parseFloat("11x")`, 11) + test(`parseFloat("Infinity1")`, _Infinity) - test(`parseFloat(" 0x11\n", 16)`, 0) - test(`parseFloat("0x0a")`, 0) - test(`parseFloat("0x0aXyzzy")`, 0) - test(`parseFloat("Infinity")`, "Infinity") - test(`parseFloat("infinity")`, "NaN") - test(`parseFloat("0x")`, 0) - test(`parseFloat("11x")`, 11) - test(`parseFloat("Infinity1")`, "Infinity") - - test(`parseFloat.length === 1`, true) - test(`parseFloat.prototype === undefined`, true) + test(`parseFloat.length === 1`, true) + test(`parseFloat.prototype === undefined`, true) + }) } func Test_encodeURI(t *testing.T) { - Terst(t) + tt(t, func() { + test, _ := test() - test := runTest() + test(`encodeURI("http://example.com/ Nothing happens.")`, "http://example.com/%20Nothing%20happens.") + test(`encodeURI("http://example.com/ _^#")`, "http://example.com/%20_%5E#") + test(`encodeURI(String.fromCharCode("0xE000"))`, "%EE%80%80") + test(`encodeURI(String.fromCharCode("0xFFFD"))`, "%EF%BF%BD") + test(`raise: encodeURI(String.fromCharCode("0xDC00"))`, "URIError: URI malformed") - test(`encodeURI("http://example.com/ Nothing happens.")`, "http://example.com/%20Nothing%20happens.") - test(`encodeURI("http://example.com/ _^#")`, "http://example.com/%20_%5E#") - test(`encodeURI(String.fromCharCode("0xE000"))`, "%EE%80%80") - test(`encodeURI(String.fromCharCode("0xFFFD"))`, "%EF%BF%BD") - test(`raise: encodeURI(String.fromCharCode("0xDC00"))`, "URIError: URI malformed") - - test(`encodeURI.length === 1`, true) - test(`encodeURI.prototype === undefined`, true) + test(`encodeURI.length === 1`, true) + test(`encodeURI.prototype === undefined`, true) + }) } func Test_encodeURIComponent(t *testing.T) { - Terst(t) + tt(t, func() { + test, _ := test() - test := runTest() - - test(`encodeURIComponent("http://example.com/ Nothing happens.")`, "http%3A%2F%2Fexample.com%2F%20Nothing%20happens.") - test(`encodeURIComponent("http://example.com/ _^#")`, "http%3A%2F%2Fexample.com%2F%20_%5E%23") + test(`encodeURIComponent("http://example.com/ Nothing happens.")`, "http%3A%2F%2Fexample.com%2F%20Nothing%20happens.") + test(`encodeURIComponent("http://example.com/ _^#")`, "http%3A%2F%2Fexample.com%2F%20_%5E%23") + }) } func Test_decodeURI(t *testing.T) { - Terst(t) + tt(t, func() { + test, _ := test() - test := runTest() + test(`decodeURI(encodeURI("http://example.com/ Nothing happens."))`, "http://example.com/ Nothing happens.") + test(`decodeURI(encodeURI("http://example.com/ _^#"))`, "http://example.com/ _^#") + test(`raise: decodeURI("http://example.com/ _^#%")`, "URIError: URI malformed") + test(`raise: decodeURI("%DF%7F")`, "URIError: URI malformed") + for _, check := range strings.Fields("+ %3B %2F %3F %3A %40 %26 %3D %2B %24 %2C %23") { + test(fmt.Sprintf(`decodeURI("%s")`, check), check) + } - test(`decodeURI(encodeURI("http://example.com/ Nothing happens."))`, "http://example.com/ Nothing happens.") - test(`decodeURI(encodeURI("http://example.com/ _^#"))`, "http://example.com/ _^#") - test(`raise: decodeURI("http://example.com/ _^#%")`, "URIError: URI malformed") - test(`raise: decodeURI("%DF%7F")`, "URIError: URI malformed") - for _, check := range strings.Fields("+ %3B %2F %3F %3A %40 %26 %3D %2B %24 %2C %23") { - test(fmt.Sprintf(`decodeURI("%s")`, check), check) - } - - test(`decodeURI.length === 1`, true) - test(`decodeURI.prototype === undefined`, true) + test(`decodeURI.length === 1`, true) + test(`decodeURI.prototype === undefined`, true) + }) } func Test_decodeURIComponent(t *testing.T) { - Terst(t) + tt(t, func() { + test, _ := test() - test := runTest() + test(`decodeURIComponent(encodeURI("http://example.com/ Nothing happens."))`, "http://example.com/ Nothing happens.") + test(`decodeURIComponent(encodeURI("http://example.com/ _^#"))`, "http://example.com/ _^#") - test(`decodeURIComponent(encodeURI("http://example.com/ Nothing happens."))`, "http://example.com/ Nothing happens.") - test(`decodeURIComponent(encodeURI("http://example.com/ _^#"))`, "http://example.com/ _^#") + test(`decodeURIComponent.length === 1`, true) + test(`decodeURIComponent.prototype === undefined`, true) - test(`decodeURIComponent.length === 1`, true) - test(`decodeURIComponent.prototype === undefined`, true) - - test(` + test(` var global = Function('return this')(); var abc = Object.getOwnPropertyDescriptor(global, "decodeURIComponent"); [ abc.value === global.decodeURIComponent, abc.writable, abc.enumerable, abc.configurable ]; `, "true,true,false,true") + }) } func TestGlobal_skipEnumeration(t *testing.T) { - Terst(t) + tt(t, func() { + test, _ := test() - test := runTest() - - test(` - var found = []; - for (var test in this) { - if (false || - test === 'NaN' || - test === 'undefined' || - test === 'Infinity' || - false) { - found.push(test) + test(` + var found = []; + for (var test in this) { + if (false || + test === 'NaN' || + test === 'undefined' || + test === 'Infinity' || + false) { + found.push(test) + } } - } - found.length; - `, 0) + found.length; + `, 0) - test(` - var found = []; - for (var test in this) { - if (false || - test === 'Object' || - test === 'Function' || - test === 'String' || - test === 'Number' || - test === 'Array' || - test === 'Boolean' || - test === 'Date' || - test === 'RegExp' || - test === 'Error' || - test === 'EvalError' || - test === 'RangeError' || - test === 'ReferenceError' || - test === 'SyntaxError' || - test === 'TypeError' || - test === 'URIError' || - false) { - found.push(test) + test(` + var found = []; + for (var test in this) { + if (false || + test === 'Object' || + test === 'Function' || + test === 'String' || + test === 'Number' || + test === 'Array' || + test === 'Boolean' || + test === 'Date' || + test === 'RegExp' || + test === 'Error' || + test === 'EvalError' || + test === 'RangeError' || + test === 'ReferenceError' || + test === 'SyntaxError' || + test === 'TypeError' || + test === 'URIError' || + false) { + found.push(test) + } } - } - found.length; - `, 0) + found.length; + `, 0) + }) } diff --git a/json_test.go b/json_test.go index eab3ecc..4dd2ed7 100644 --- a/json_test.go +++ b/json_test.go @@ -1,184 +1,183 @@ package otto import ( - . "./terst" "testing" ) func BenchmarkJSON_parse(b *testing.B) { - otto := New() + vm := New() for i := 0; i < b.N; i++ { - otto.Run(`JSON.parse("1")`) - otto.Run(`JSON.parse("[1,2,3]")`) - otto.Run(`JSON.parse('{"a":{"x":100,"y":110},"b":[10,20,30],"c":"zazazaza"}')`) - otto.Run(`JSON.parse("[1,2,3]", function(k, v) { return undefined })`) + vm.Run(`JSON.parse("1")`) + vm.Run(`JSON.parse("[1,2,3]")`) + vm.Run(`JSON.parse('{"a":{"x":100,"y":110},"b":[10,20,30],"c":"zazazaza"}')`) + vm.Run(`JSON.parse("[1,2,3]", function(k, v) { return undefined })`) } } func TestJSON_parse(t *testing.T) { - Terst(t) + tt(t, func() { + test, _ := test() - test := runTest() + test(` + JSON.parse("1"); + `, 1) - test(` - JSON.parse("1"); - `, 1) + test(` + JSON.parse("null"); + `, "null") // TODO Can we make this nil? - test(` - JSON.parse("null"); - `, "null") // TODO Can we make this nil? + test(` + var abc = JSON.parse('"a\uFFFFbc"'); + [ abc[0], abc[2], abc[3], abc.length ]; + `, "a,b,c,4") - test(` - var abc = JSON.parse('"a\uFFFFbc"'); - [ abc[0], abc[2], abc[3], abc.length ]; - `, "a,b,c,4") + test(` + JSON.parse("[1, 2, 3]"); + `, "1,2,3") - test(` - JSON.parse("[1, 2, 3]"); - `, "1,2,3") + test(` + JSON.parse('{ "abc": 1, "def":2 }').abc; + `, 1) - test(` - JSON.parse('{ "abc": 1, "def":2 }').abc; - `, 1) + test(` + JSON.parse('{ "abc": { "x": 100, "y": 110 }, "def": [ 10, 20 ,30 ], "ghi": "zazazaza" }').def; + `, "10,20,30") - test(` - JSON.parse('{ "abc": { "x": 100, "y": 110 }, "def": [ 10, 20 ,30 ], "ghi": "zazazaza" }').def; - `, "10,20,30") + test(`raise: + JSON.parse("12\t\r\n 34"); + `, "SyntaxError: invalid character '3' after top-level value") - test(`raise: - JSON.parse("12\t\r\n 34"); - `, "SyntaxError: invalid character '3' after top-level value") + test(` + JSON.parse("[1, 2, 3]", function() { return undefined }); + `, "undefined") - test(` - JSON.parse("[1, 2, 3]", function() { return undefined }); - `, "undefined") + test(`raise: + JSON.parse(""); + `, "SyntaxError: unexpected end of JSON input") - test(`raise: - JSON.parse(""); - `, "SyntaxError: unexpected end of JSON input") + test(`raise: + JSON.parse("[1, 2, 3"); + `, "SyntaxError: unexpected end of JSON input") - test(`raise: - JSON.parse("[1, 2, 3"); - `, "SyntaxError: unexpected end of JSON input") + test(`raise: + JSON.parse("[1, 2, ; abc=10"); + `, "SyntaxError: invalid character ';' looking for beginning of value") - test(`raise: - JSON.parse("[1, 2, ; abc=10"); - `, "SyntaxError: invalid character ';' looking for beginning of value") - - test(`raise: - JSON.parse("[1, 2, function(){}]"); - `, "SyntaxError: invalid character 'u' in literal false (expecting 'a')") + test(`raise: + JSON.parse("[1, 2, function(){}]"); + `, "SyntaxError: invalid character 'u' in literal false (expecting 'a')") + }) } func TestJSON_stringify(t *testing.T) { - Terst(t) + tt(t, func() { + test, _ := test() - defer mockUTC()() + defer mockUTC()() - test := runTest() + test(` + JSON.stringify(function(){}); + `, "undefined") - test(` - JSON.stringify(function(){}); - `, "undefined") + test(` + JSON.stringify(new Boolean(false)); + `, "false") - test(` - JSON.stringify(new Boolean(false)); - `, "false") + test(` + JSON.stringify({a1: {b1: [1,2,3,4], b2: {c1: 1, c2: 2}}, a2: 'a2'}, null, -5); + `, `{"a1":{"b1":[1,2,3,4],"b2":{"c1":1,"c2":2}},"a2":"a2"}`) - test(` - JSON.stringify({a1: {b1: [1,2,3,4], b2: {c1: 1, c2: 2}}, a2: 'a2'}, null, -5); - `, `{"a1":{"b1":[1,2,3,4],"b2":{"c1":1,"c2":2}},"a2":"a2"}`) + test(` + JSON.stringify(undefined); + `, "undefined") - test(` - JSON.stringify(undefined); - `, "undefined") + test(` + JSON.stringify(1); + `, "1") - test(` - JSON.stringify(1); - `, "1") + test(` + JSON.stringify("abc def"); + `, "\"abc def\"") - test(` - JSON.stringify("abc def"); - `, "\"abc def\"") + test(` + JSON.stringify(3.14159); + `, "3.14159") - test(` - JSON.stringify(3.14159); - `, "3.14159") + test(` + JSON.stringify([]); + `, "[]") - test(` - JSON.stringify([]); - `, "[]") + test(` + JSON.stringify([1, 2, 3]); + `, "[1,2,3]") - test(` - JSON.stringify([1, 2, 3]); - `, "[1,2,3]") + test(` + JSON.stringify([true, false, null]); + `, "[true,false,null]") - test(` - JSON.stringify([true, false, null]); - `, "[true,false,null]") + test(` + JSON.stringify({ + abc: { x: 100, y: 110 }, + def: [ 10, 20, 30 ], + ghi: "zazazaza" + }); + `, `{"abc":{"x":100,"y":110},"def":[10,20,30],"ghi":"zazazaza"}`) - test(` - JSON.stringify({ - abc: { x: 100, y: 110 }, - def: [ 10, 20, 30 ], - ghi: "zazazaza" - }); - `, `{"abc":{"x":100,"y":110},"def":[10,20,30],"ghi":"zazazaza"}`) + test(` + JSON.stringify([ + 'e', + {pluribus: 'unum'} + ], null, '\t'); + `, "[\n\t\"e\",\n\t{\n\t\t\"pluribus\": \"unum\"\n\t}\n]") - test(` - JSON.stringify([ - 'e', - {pluribus: 'unum'} - ], null, '\t'); - `, "[\n\t\"e\",\n\t{\n\t\t\"pluribus\": \"unum\"\n\t}\n]") + test(` + JSON.stringify(new Date(0)); + `, `"1970-01-01T00:00:00.000Z"`) - test(` - JSON.stringify(new Date(0)); - `, `"1970-01-01T00:00:00.000Z"`) + test(` + JSON.stringify([ new Date(0) ], function(key, value){ + return this[key] instanceof Date ? 'Date(' + this[key] + ')' : value + }); + `, `["Date(Thu, 01 Jan 1970 00:00:00 UTC)"]`) - test(` - JSON.stringify([ new Date(0) ], function(key, value){ - return this[key] instanceof Date ? 'Date(' + this[key] + ')' : value - }); - `, `["Date(Thu, 01 Jan 1970 00:00:00 UTC)"]`) + test(` + JSON.stringify({ + abc: 1, + def: 2, + ghi: 3 + }, ['abc','def']); + `, `{"abc":1,"def":2}`) - test(` - JSON.stringify({ - abc: 1, - def: 2, - ghi: 3 - }, ['abc','def']); - `, `{"abc":1,"def":2}`) + test(`raise: + var abc = { + def: null + }; + abc.def = abc; + JSON.stringify(abc) + `, "TypeError: Converting circular structure to JSON") - test(`raise: - var abc = { - def: null - }; - abc.def = abc; - JSON.stringify(abc) - `, "TypeError: Converting circular structure to JSON") + test(`raise: + var abc= [ null ]; + abc[0] = abc; + JSON.stringify(abc); + `, "TypeError: Converting circular structure to JSON") - test(`raise: - var abc= [ null ]; - abc[0] = abc; - JSON.stringify(abc); - `, "TypeError: Converting circular structure to JSON") + test(`raise: + var abc = { + def: {} + }; + abc.def.ghi = abc; + JSON.stringify(abc) + `, "TypeError: Converting circular structure to JSON") - test(`raise: - var abc = { - def: {} - }; - abc.def.ghi = abc; - JSON.stringify(abc) - `, "TypeError: Converting circular structure to JSON") - - test(` - var ghi = { "pi": 3.14159 }; - var abc = { - def: {} - }; - abc.ghi = ghi; - abc.def.ghi = ghi; - JSON.stringify(abc); - `, `{"def":{"ghi":{"pi":3.14159}},"ghi":{"pi":3.14159}}`) + test(` + var ghi = { "pi": 3.14159 }; + var abc = { + def: {} + }; + abc.ghi = ghi; + abc.def.ghi = ghi; + JSON.stringify(abc); + `, `{"def":{"ghi":{"pi":3.14159}},"ghi":{"pi":3.14159}}`) + }) } diff --git a/math_test.go b/math_test.go index 50dbb13..499998b 100644 --- a/math_test.go +++ b/math_test.go @@ -1,284 +1,303 @@ package otto import ( - . "./terst" + "math" "testing" ) +var _NaN = math.NaN() +var _Infinity = math.Inf(1) + func TestMath_toString(t *testing.T) { - Terst(t) + tt(t, func() { + test, _ := test() - test := runTest() - - test(`Math.toString()`, "[object Math]") + test(`Math.toString()`, "[object Math]") + }) } func TestMath_abs(t *testing.T) { - Terst(t) + tt(t, func() { + test, _ := test() - test := runTest() + test(`Math.abs(NaN)`, _NaN) + test(`Math.abs(2)`, 2) + test(`Math.abs(-2)`, 2) + test(`Math.abs(-Infinity)`, _Infinity) - test(`Math.abs(NaN)`, "NaN") - test(`Math.abs(2)`, "2") - test(`Math.abs(-2)`, "2") - test(`Math.abs(-Infinity)`, "Infinity") + test(`Math.acos(0.5)`, 1.0471975511965976) - test(`Math.acos(0.5)`, "1.0471975511965976") - - test(`Math.abs('-1')`, "1") - test(`Math.abs(-2)`, "2") - test(`Math.abs(null)`, "0") - test(`Math.abs("string")`, "NaN") - test(`Math.abs()`, "NaN") + test(`Math.abs('-1')`, 1) + test(`Math.abs(-2)`, 2) + test(`Math.abs(null)`, 0) + test(`Math.abs("string")`, _NaN) + test(`Math.abs()`, _NaN) + }) } func TestMath_acos(t *testing.T) { - Terst(t) + tt(t, func() { + test, _ := test() - test := runTest() - test(`Math.acos(NaN)`, "NaN") - test(`Math.acos(2)`, "NaN") - test(`Math.acos(-2)`, "NaN") - test(`1/Math.acos(1)`, "Infinity") + test(`Math.acos(NaN)`, _NaN) + test(`Math.acos(2)`, _NaN) + test(`Math.acos(-2)`, _NaN) + test(`1/Math.acos(1)`, _Infinity) - test(`Math.acos(0.5)`, "1.0471975511965976") + test(`Math.acos(0.5)`, 1.0471975511965976) + }) } func TestMath_asin(t *testing.T) { - Terst(t) + tt(t, func() { + test, _ := test() - test := runTest() - test(`Math.asin(NaN)`, "NaN") - test(`Math.asin(2)`, "NaN") - test(`Math.asin(-2)`, "NaN") - test(`1/Math.asin(0)`, "Infinity") - test(`1/Math.asin(-0)`, "-Infinity") + test(`Math.asin(NaN)`, _NaN) + test(`Math.asin(2)`, _NaN) + test(`Math.asin(-2)`, _NaN) + test(`1/Math.asin(0)`, _Infinity) + test(`1/Math.asin(-0)`, -_Infinity) - test(`Math.asin(0.5)`, "0.5235987755982989") + test(`Math.asin(0.5)`, 0.5235987755982989) + }) } func TestMath_atan(t *testing.T) { - Terst(t) + tt(t, func() { + test, _ := test() - test := runTest() - test(`Math.atan(NaN)`, "NaN") - test(`1/Math.atan(0)`, "Infinity") - test(`1/Math.atan(-0)`, "-Infinity") - test(`Math.atan(Infinity)`, "1.5707963267948966") - test(`Math.atan(-Infinity)`, "-1.5707963267948966") + test(`Math.atan(NaN)`, _NaN) + test(`1/Math.atan(0)`, _Infinity) + test(`1/Math.atan(-0)`, -_Infinity) + test(`Math.atan(Infinity)`, 1.5707963267948966) + test(`Math.atan(-Infinity)`, -1.5707963267948966) - // freebsd/386 1.03 => 0.4636476090008061 - // darwin 1.03 => 0.46364760900080604 - test(`Math.atan(0.5).toPrecision(10)`, "0.463647609") + // freebsd/386 1.03 => 0.4636476090008061 + // darwin 1.03 => 0.46364760900080604 + test(`Math.atan(0.5).toPrecision(10)`, "0.463647609") + }) } func TestMath_atan2(t *testing.T) { - Terst(t) + tt(t, func() { + test, _ := test() - test := runTest() - test(`Math.atan2()`, "NaN") - test(`Math.atan2(NaN)`, "NaN") - test(`Math.atan2(0, NaN)`, "NaN") + test(`Math.atan2()`, _NaN) + test(`Math.atan2(NaN)`, _NaN) + test(`Math.atan2(0, NaN)`, _NaN) - test(`Math.atan2(1, 0)`, "1.5707963267948966") - test(`Math.atan2(1, -0)`, "1.5707963267948966") + test(`Math.atan2(1, 0)`, 1.5707963267948966) + test(`Math.atan2(1, -0)`, 1.5707963267948966) - test(`1/Math.atan2(0, 1)`, "Infinity") - test(`1/Math.atan2(0, 0)`, "Infinity") - test(`Math.atan2(0, -0)`, "3.141592653589793") - test(`Math.atan2(0, -1)`, "3.141592653589793") + test(`1/Math.atan2(0, 1)`, _Infinity) + test(`1/Math.atan2(0, 0)`, _Infinity) + test(`Math.atan2(0, -0)`, 3.141592653589793) + test(`Math.atan2(0, -1)`, 3.141592653589793) - test(`1/Math.atan2(-0, 1)`, "-Infinity") - test(`1/Math.atan2(-0, 0)`, "-Infinity") - test(`Math.atan2(-0, -0)`, "-3.141592653589793") - test(`Math.atan2(-0, -1)`, "-3.141592653589793") + test(`1/Math.atan2(-0, 1)`, -_Infinity) + test(`1/Math.atan2(-0, 0)`, -_Infinity) + test(`Math.atan2(-0, -0)`, -3.141592653589793) + test(`Math.atan2(-0, -1)`, -3.141592653589793) - test(`Math.atan2(-1, 0)`, "-1.5707963267948966") - test(`Math.atan2(-1, -0)`, "-1.5707963267948966") + test(`Math.atan2(-1, 0)`, -1.5707963267948966) + test(`Math.atan2(-1, -0)`, -1.5707963267948966) - test(`1/Math.atan2(1, Infinity)`, "Infinity") - test(`Math.atan2(1, -Infinity)`, "3.141592653589793") - test(`1/Math.atan2(-1, Infinity)`, "-Infinity") - test(`Math.atan2(-1, -Infinity)`, "-3.141592653589793") + test(`1/Math.atan2(1, Infinity)`, _Infinity) + test(`Math.atan2(1, -Infinity)`, 3.141592653589793) + test(`1/Math.atan2(-1, Infinity)`, -_Infinity) + test(`Math.atan2(-1, -Infinity)`, -3.141592653589793) - test(`Math.atan2(Infinity, 1)`, "1.5707963267948966") - test(`Math.atan2(-Infinity, 1)`, "-1.5707963267948966") + test(`Math.atan2(Infinity, 1)`, 1.5707963267948966) + test(`Math.atan2(-Infinity, 1)`, -1.5707963267948966) - test(`Math.atan2(Infinity, Infinity)`, "0.7853981633974483") - test(`Math.atan2(Infinity, -Infinity)`, "2.356194490192345") - test(`Math.atan2(-Infinity, Infinity)`, "-0.7853981633974483") - test(`Math.atan2(-Infinity, -Infinity)`, "-2.356194490192345") + test(`Math.atan2(Infinity, Infinity)`, 0.7853981633974483) + test(`Math.atan2(Infinity, -Infinity)`, 2.356194490192345) + test(`Math.atan2(-Infinity, Infinity)`, -0.7853981633974483) + test(`Math.atan2(-Infinity, -Infinity)`, -2.356194490192345) + }) } func TestMath_ceil(t *testing.T) { - Terst(t) + tt(t, func() { + test, _ := test() - test := runTest() - test(`Math.ceil(NaN)`, "NaN") - test(`Math.ceil(+0)`, "0") - test(`1/Math.ceil(-0)`, "-Infinity") - test(`Math.ceil(Infinity)`, "Infinity") - test(`Math.ceil(-Infinity)`, "-Infinity") - test(`1/Math.ceil(-0.5)`, "-Infinity") + test(`Math.ceil(NaN)`, _NaN) + test(`Math.ceil(+0)`, 0) + test(`1/Math.ceil(-0)`, -_Infinity) + test(`Math.ceil(Infinity)`, _Infinity) + test(`Math.ceil(-Infinity)`, -_Infinity) + test(`1/Math.ceil(-0.5)`, -_Infinity) - test(`Math.ceil(-11)`, "-11") - test(`Math.ceil(-0.5)`, "0") - test(`Math.ceil(1.5)`, "2") + test(`Math.ceil(-11)`, -11) + test(`Math.ceil(-0.5)`, 0) + test(`Math.ceil(1.5)`, 2) + }) } func TestMath_cos(t *testing.T) { - Terst(t) + tt(t, func() { + test, _ := test() - test := runTest() - test(`Math.cos(NaN)`, "NaN") - test(`Math.cos(+0)`, "1") - test(`Math.cos(-0)`, "1") - test(`Math.cos(Infinity)`, "NaN") - test(`Math.cos(-Infinity)`, "NaN") + test(`Math.cos(NaN)`, _NaN) + test(`Math.cos(+0)`, 1) + test(`Math.cos(-0)`, 1) + test(`Math.cos(Infinity)`, _NaN) + test(`Math.cos(-Infinity)`, _NaN) - test(`Math.cos(0.5)`, "0.8775825618903728") + test(`Math.cos(0.5)`, 0.8775825618903728) + }) } func TestMath_exp(t *testing.T) { - Terst(t) + tt(t, func() { + test, _ := test() - test := runTest() - test(`Math.exp(NaN)`, "NaN") - test(`Math.exp(+0)`, "1") - test(`Math.exp(-0)`, "1") - test(`Math.exp(Infinity)`, "Infinity") - test(`Math.exp(-Infinity)`, "0") + test(`Math.exp(NaN)`, _NaN) + test(`Math.exp(+0)`, 1) + test(`Math.exp(-0)`, 1) + test(`Math.exp(Infinity)`, _Infinity) + test(`Math.exp(-Infinity)`, 0) + }) } func TestMath_floor(t *testing.T) { - Terst(t) + tt(t, func() { + test, _ := test() - test := runTest() - test(`Math.floor(NaN)`, "NaN") - test(`Math.floor(+0)`, "0") - test(`1/Math.floor(-0)`, "-Infinity") - test(`Math.floor(Infinity)`, "Infinity") - test(`Math.floor(-Infinity)`, "-Infinity") + test(`Math.floor(NaN)`, _NaN) + test(`Math.floor(+0)`, 0) + test(`1/Math.floor(-0)`, -_Infinity) + test(`Math.floor(Infinity)`, _Infinity) + test(`Math.floor(-Infinity)`, -_Infinity) - test(`Math.floor(-11)`, "-11") - test(`Math.floor(-0.5)`, "-1") - test(`Math.floor(1.5)`, "1") + test(`Math.floor(-11)`, -11) + test(`Math.floor(-0.5)`, -1) + test(`Math.floor(1.5)`, 1) + }) } func TestMath_log(t *testing.T) { - Terst(t) + tt(t, func() { + test, _ := test() - test := runTest() - test(`Math.log(NaN)`, "NaN") - test(`Math.log(-1)`, "NaN") - test(`Math.log(+0)`, "-Infinity") - test(`Math.log(-0)`, "-Infinity") - test(`1/Math.log(1)`, "Infinity") - test(`Math.log(Infinity)`, "Infinity") + test(`Math.log(NaN)`, _NaN) + test(`Math.log(-1)`, _NaN) + test(`Math.log(+0)`, -_Infinity) + test(`Math.log(-0)`, -_Infinity) + test(`1/Math.log(1)`, _Infinity) + test(`Math.log(Infinity)`, _Infinity) - test(`Math.log(0.5)`, "-0.6931471805599453") + test(`Math.log(0.5)`, -0.6931471805599453) + }) } func TestMath_max(t *testing.T) { - Terst(t) + tt(t, func() { + test, _ := test() - test := runTest() - test(`Math.max(-11, -1, 0, 1, 2, 3, 11)`, "11") + test(`Math.max(-11, -1, 0, 1, 2, 3, 11)`, 11) + }) } func TestMath_min(t *testing.T) { - Terst(t) + tt(t, func() { + test, _ := test() - test := runTest() - test(`Math.min(-11, -1, 0, 1, 2, 3, 11)`, "-11") + test(`Math.min(-11, -1, 0, 1, 2, 3, 11)`, -11) + }) } func TestMath_pow(t *testing.T) { - Terst(t) + tt(t, func() { + test, _ := test() - test := runTest() - test(`Math.pow(0, NaN)`, "NaN") - test(`Math.pow(0, 0)`, "1") - test(`Math.pow(NaN, 0)`, "1") - test(`Math.pow(0, -0)`, "1") - test(`Math.pow(NaN, -0)`, "1") - test(`Math.pow(NaN, 1)`, "NaN") - test(`Math.pow(2, Infinity)`, "Infinity") - test(`1/Math.pow(2, -Infinity)`, "Infinity") - test(`Math.pow(1, Infinity)`, "NaN") - test(`Math.pow(1, -Infinity)`, "NaN") - test(`1/Math.pow(0.1, Infinity)`, "Infinity") - test(`Math.pow(0.1, -Infinity)`, "Infinity") - test(`Math.pow(Infinity, 1)`, "Infinity") - test(`1/Math.pow(Infinity, -1)`, "Infinity") - test(`Math.pow(-Infinity, 1)`, "-Infinity") - test(`Math.pow(-Infinity, 2)`, "Infinity") - test(`1/Math.pow(-Infinity, -1)`, "-Infinity") - test(`1/Math.pow(-Infinity, -2)`, "Infinity") - test(`1/Math.pow(0, 1)`, "Infinity") - test(`Math.pow(0, -1)`, "Infinity") - test(`1/Math.pow(-0, 1)`, "-Infinity") - test(`1/Math.pow(-0, 2)`, "Infinity") - test(`Math.pow(-0, -1)`, "-Infinity") - test(`Math.pow(-0, -2)`, "Infinity") - test(`Math.pow(-1, 0.1)`, "NaN") + test(`Math.pow(0, NaN)`, _NaN) + test(`Math.pow(0, 0)`, 1) + test(`Math.pow(NaN, 0)`, 1) + test(`Math.pow(0, -0)`, 1) + test(`Math.pow(NaN, -0)`, 1) + test(`Math.pow(NaN, 1)`, _NaN) + test(`Math.pow(2, Infinity)`, _Infinity) + test(`1/Math.pow(2, -Infinity)`, _Infinity) + test(`Math.pow(1, Infinity)`, _NaN) + test(`Math.pow(1, -Infinity)`, _NaN) + test(`1/Math.pow(0.1, Infinity)`, _Infinity) + test(`Math.pow(0.1, -Infinity)`, _Infinity) + test(`Math.pow(Infinity, 1)`, _Infinity) + test(`1/Math.pow(Infinity, -1)`, _Infinity) + test(`Math.pow(-Infinity, 1)`, -_Infinity) + test(`Math.pow(-Infinity, 2)`, _Infinity) + test(`1/Math.pow(-Infinity, -1)`, -_Infinity) + test(`1/Math.pow(-Infinity, -2)`, _Infinity) + test(`1/Math.pow(0, 1)`, _Infinity) + test(`Math.pow(0, -1)`, _Infinity) + test(`1/Math.pow(-0, 1)`, -_Infinity) + test(`1/Math.pow(-0, 2)`, _Infinity) + test(`Math.pow(-0, -1)`, -_Infinity) + test(`Math.pow(-0, -2)`, _Infinity) + test(`Math.pow(-1, 0.1)`, _NaN) - test(` - [ Math.pow(-1, +Infinity), Math.pow(1, Infinity) ]; - `, "NaN,NaN") + test(` + [ Math.pow(-1, +Infinity), Math.pow(1, Infinity) ]; + `, "NaN,NaN") + }) } func TestMath_round(t *testing.T) { - Terst(t) + tt(t, func() { + test, _ := test() - test := runTest() - test(`Math.round(NaN)`, "NaN") - test(`1/Math.round(0)`, "Infinity") - test(`1/Math.round(-0)`, "-Infinity") - test(`Math.round(Infinity)`, "Infinity") - test(`Math.round(-Infinity)`, "-Infinity") - test(`1/Math.round(0.1)`, "Infinity") - test(`1/Math.round(-0.1)`, "-Infinity") + test(`Math.round(NaN)`, _NaN) + test(`1/Math.round(0)`, _Infinity) + test(`1/Math.round(-0)`, -_Infinity) + test(`Math.round(Infinity)`, _Infinity) + test(`Math.round(-Infinity)`, -_Infinity) + test(`1/Math.round(0.1)`, _Infinity) + test(`1/Math.round(-0.1)`, -_Infinity) - test(`Math.round(3.5)`, "4") - test(`Math.round(-3.5)`, "-3") + test(`Math.round(3.5)`, 4) + test(`Math.round(-3.5)`, -3) + }) } func TestMath_sin(t *testing.T) { - Terst(t) + tt(t, func() { + test, _ := test() - test := runTest() - test(`Math.sin(NaN)`, "NaN") - test(`1/Math.sin(+0)`, "Infinity") - test(`1/Math.sin(-0)`, "-Infinity") - test(`Math.sin(Infinity)`, "NaN") - test(`Math.sin(-Infinity)`, "NaN") + test(`Math.sin(NaN)`, _NaN) + test(`1/Math.sin(+0)`, _Infinity) + test(`1/Math.sin(-0)`, -_Infinity) + test(`Math.sin(Infinity)`, _NaN) + test(`Math.sin(-Infinity)`, _NaN) - test(`Math.sin(0.5)`, "0.479425538604203") + test(`Math.sin(0.5)`, 0.479425538604203) + }) } func TestMath_sqrt(t *testing.T) { - Terst(t) + tt(t, func() { + test, _ := test() - test := runTest() - test(`Math.sqrt(NaN)`, "NaN") - test(`Math.sqrt(-1)`, "NaN") - test(`1/Math.sqrt(+0)`, "Infinity") - test(`1/Math.sqrt(-0)`, "-Infinity") - test(`Math.sqrt(Infinity)`, "Infinity") + test(`Math.sqrt(NaN)`, _NaN) + test(`Math.sqrt(-1)`, _NaN) + test(`1/Math.sqrt(+0)`, _Infinity) + test(`1/Math.sqrt(-0)`, -_Infinity) + test(`Math.sqrt(Infinity)`, _Infinity) - test(`Math.sqrt(2)`, "1.4142135623730951") + test(`Math.sqrt(2)`, 1.4142135623730951) + }) } func TestMath_tan(t *testing.T) { - Terst(t) + tt(t, func() { + test, _ := test() - test := runTest() - test(`Math.tan(NaN)`, "NaN") - test(`1/Math.tan(+0)`, "Infinity") - test(`1/Math.tan(-0)`, "-Infinity") - test(`Math.tan(Infinity)`, "NaN") - test(`Math.tan(-Infinity)`, "NaN") + test(`Math.tan(NaN)`, _NaN) + test(`1/Math.tan(+0)`, _Infinity) + test(`1/Math.tan(-0)`, -_Infinity) + test(`Math.tan(Infinity)`, _NaN) + test(`Math.tan(-Infinity)`, _NaN) - test(`Math.tan(0.5)`, "0.5463024898437905") + test(`Math.tan(0.5)`, 0.5463024898437905) + }) } diff --git a/number_test.go b/number_test.go index e81764b..f3790e0 100644 --- a/number_test.go +++ b/number_test.go @@ -1,168 +1,167 @@ package otto import ( - . "./terst" "testing" ) func TestNumber(t *testing.T) { - Terst(t) + tt(t, func() { + test, _ := test() - test := runTest() - - test(` - var abc = Object.getOwnPropertyDescriptor(Number, "prototype"); - [ [ typeof Number.prototype ], - [ abc.writable, abc.enumerable, abc.configurable ] ]; - `, "object,false,false,false") + test(` + var abc = Object.getOwnPropertyDescriptor(Number, "prototype"); + [ [ typeof Number.prototype ], + [ abc.writable, abc.enumerable, abc.configurable ] ]; + `, "object,false,false,false") + }) } func TestNumber_toString(t *testing.T) { - Terst(t) + tt(t, func() { + test, _ := test() - test := runTest() + test(` + new Number(451).toString(); + `, "451") - test(` - new Number(451).toString(); - `, "451") + test(` + new Number(451).toString(10); + `, "451") - test(` - new Number(451).toString(10); - `, "451") + test(` + new Number(451).toString(8); + `, "703") - test(` - new Number(451).toString(8); - `, "703") + test(`raise: + new Number(451).toString(1); + `, "RangeError: RangeError: toString() radix must be between 2 and 36") - test(`raise: - new Number(451).toString(1); - `, "RangeError: RangeError: toString() radix must be between 2 and 36") + test(`raise: + new Number(451).toString(Infinity); + `, "RangeError: RangeError: toString() radix must be between 2 and 36") - test(`raise: - new Number(451).toString(Infinity); - `, "RangeError: RangeError: toString() radix must be between 2 and 36") + test(` + new Number(NaN).toString() + `, "NaN") - test(` - new Number(NaN).toString() - `, "NaN") + test(` + new Number(Infinity).toString() + `, "Infinity") - test(` - new Number(Infinity).toString() - `, "Infinity") + test(` + new Number(Infinity).toString(16) + `, "Infinity") - test(` - new Number(Infinity).toString(16) - `, "Infinity") - - test(` - [ - Number.prototype.toString(undefined), - new Number().toString(undefined), - new Number(0).toString(undefined), - new Number(-1).toString(undefined), - new Number(1).toString(undefined), - new Number(Number.NaN).toString(undefined), - new Number(Number.POSITIVE_INFINITY).toString(undefined), - new Number(Number.NEGATIVE_INFINITY).toString(undefined) - ] - `, "0,0,0,-1,1,NaN,Infinity,-Infinity") + test(` + [ + Number.prototype.toString(undefined), + new Number().toString(undefined), + new Number(0).toString(undefined), + new Number(-1).toString(undefined), + new Number(1).toString(undefined), + new Number(Number.NaN).toString(undefined), + new Number(Number.POSITIVE_INFINITY).toString(undefined), + new Number(Number.NEGATIVE_INFINITY).toString(undefined) + ] + `, "0,0,0,-1,1,NaN,Infinity,-Infinity") + }) } func TestNumber_toFixed(t *testing.T) { - Terst(t) + tt(t, func() { + test, _ := test() - test := runTest() + test(`new Number(451).toFixed(2)`, "451.00") + test(`12345.6789.toFixed()`, "12346") + test(`12345.6789.toFixed(1)`, "12345.7") + test(`12345.6789.toFixed(6)`, "12345.678900") + test(`(1.23e-20).toFixed(2)`, "0.00") + test(`2.34.toFixed(1)`, "2.3") // FIXME Wtf? "2.3" + test(`-2.34.toFixed(1)`, -2.3) // FIXME Wtf? -2.3 + test(`(-2.34).toFixed(1)`, "-2.3") - test(`new Number(451).toFixed(2)`, "451.00") - test(`12345.6789.toFixed()`, "12346") - test(`12345.6789.toFixed(1)`, "12345.7") - test(`12345.6789.toFixed(6)`, "12345.678900") - test(`(1.23e-20).toFixed(2)`, "0.00") - test(`2.34.toFixed(1)`, "2.3") - test(`-2.34.toFixed(1)`, "-2.3") - test(`(-2.34).toFixed(1)`, "-2.3") + test(`raise: + new Number("a").toFixed(Number.POSITIVE_INFINITY); + `, "RangeError: toFixed() precision must be between 0 and 20") - test(`raise: - new Number("a").toFixed(Number.POSITIVE_INFINITY); - `, "RangeError: toFixed() precision must be between 0 and 20") + test(` + [ + new Number(1e21).toFixed(), + new Number(1e21).toFixed(0), + new Number(1e21).toFixed(1), + new Number(1e21).toFixed(1.1), + new Number(1e21).toFixed(0.9), + new Number(1e21).toFixed("1"), + new Number(1e21).toFixed("1.1"), + new Number(1e21).toFixed("0.9"), + new Number(1e21).toFixed(Number.NaN), + new Number(1e21).toFixed("some string") + ]; + `, "1e+21,1e+21,1e+21,1e+21,1e+21,1e+21,1e+21,1e+21,1e+21,1e+21") - test(` - [ - new Number(1e21).toFixed(), - new Number(1e21).toFixed(0), - new Number(1e21).toFixed(1), - new Number(1e21).toFixed(1.1), - new Number(1e21).toFixed(0.9), - new Number(1e21).toFixed("1"), - new Number(1e21).toFixed("1.1"), - new Number(1e21).toFixed("0.9"), - new Number(1e21).toFixed(Number.NaN), - new Number(1e21).toFixed("some string") - ]; - `, "1e+21,1e+21,1e+21,1e+21,1e+21,1e+21,1e+21,1e+21,1e+21,1e+21") - - test(`raise: - new Number(1e21).toFixed(Number.POSITIVE_INFINITY); - `, "RangeError: toFixed() precision must be between 0 and 20") + test(`raise: + new Number(1e21).toFixed(Number.POSITIVE_INFINITY); + `, "RangeError: toFixed() precision must be between 0 and 20") + }) } func TestNumber_toExponential(t *testing.T) { - Terst(t) + tt(t, func() { + test, _ := test() - test := runTest() - - test(`new Number(451).toExponential(2)`, "4.51e+02") - test(`77.1234.toExponential()`, "7.71234e+01") - test(`77.1234.toExponential(4)`, "7.7123e+01") - test(`77.1234.toExponential(2)`, "7.71e+01") - test(`77 .toExponential()`, "7.7e+01") + test(`new Number(451).toExponential(2)`, "4.51e+02") + test(`77.1234.toExponential()`, "7.71234e+01") + test(`77.1234.toExponential(4)`, "7.7123e+01") + test(`77.1234.toExponential(2)`, "7.71e+01") + test(`77 .toExponential()`, "7.7e+01") + }) } func TestNumber_toPrecision(t *testing.T) { - Terst(t) + tt(t, func() { + test, _ := test() - test := runTest() - - test(`new Number(451).toPrecision()`, "451") - test(`new Number(451).toPrecision(1)`, "5e+02") - test(`5.123456.toPrecision()`, "5.123456") - test(`5.123456.toPrecision(5)`, "5.1235") - test(`5.123456.toPrecision(2)`, "5.1") - test(`5.123456.toPrecision(1)`, "5") + test(`new Number(451).toPrecision()`, "451") + test(`new Number(451).toPrecision(1)`, "5e+02") + test(`5.123456.toPrecision()`, "5.123456") + test(`5.123456.toPrecision(5)`, "5.1235") + test(`5.123456.toPrecision(2)`, "5.1") + test(`5.123456.toPrecision(1)`, "5") + }) } func TestNumber_toLocaleString(t *testing.T) { - Terst(t) + tt(t, func() { + test, _ := test() - test := runTest() - - test(` - [ - new Number(451).toLocaleString(), - new Number(451).toLocaleString(10), - new Number(451).toLocaleString(8) - ]; - `, "451,451,703") + test(` + [ + new Number(451).toLocaleString(), + new Number(451).toLocaleString(10), + new Number(451).toLocaleString(8) + ]; + `, "451,451,703") + }) } func Test_toInteger(t *testing.T) { - Terst(t) + tt(t, func() { + integer := toInteger(toValue(0.0)) + is(integer.valid(), true) + is(integer.exact(), true) - integer := toInteger(toValue(0.0)) - Is(integer.valid(), true) - Is(integer.exact(), true) - - integer = toInteger(toValue(3.14159)) - Is(integer.valid(), true) - Is(integer.exact(), false) + integer = toInteger(toValue(3.14159)) + is(integer.valid(), true) + is(integer.exact(), false) + }) } func Test_NaN(t *testing.T) { - Terst(t) + tt(t, func() { + test, _ := test() - test := runTest() - - test(` - [ NaN === NaN, NaN == NaN ]; - `, "false,false") + test(` + [ NaN === NaN, NaN == NaN ]; + `, "false,false") + }) } diff --git a/object_test.go b/object_test.go index 155d0ae..d1e9068 100644 --- a/object_test.go +++ b/object_test.go @@ -1,228 +1,243 @@ package otto import ( - . "./terst" "testing" ) func TestObject_(t *testing.T) { - Terst(t) + tt(t, func() { + test, _ := test() - object := newObject(nil, "") - IsTrue(object != nil) + object := newObject(nil, "") + is(object != nil, true) - object.put("xyzzy", toValue("Nothing happens."), true) - Is(object.get("xyzzy"), "Nothing happens.") + object.put("xyzzy", toValue("Nothing happens."), true) + is(object.get("xyzzy"), "Nothing happens.") - test := runTest() - test(` - var abc = Object.getOwnPropertyDescriptor(Object, "prototype"); - [ [ typeof Object.prototype, abc.writable, abc.enumerable, abc.configurable ], - ]; - `, "object,false,false,false") + test(` + var abc = Object.getOwnPropertyDescriptor(Object, "prototype"); + [ [ typeof Object.prototype, abc.writable, abc.enumerable, abc.configurable ], + ]; + `, "object,false,false,false") + }) } func TestStringObject(t *testing.T) { - Terst(t) - - object := New().runtime.newStringObject(toValue("xyzzy")) - Is(object.get("1"), "y") - Is(object.get("10"), "undefined") - Is(object.get("2"), "z") + tt(t, func() { + object := New().runtime.newStringObject(toValue("xyzzy")) + is(object.get("1"), "y") + is(object.get("10"), "undefined") + is(object.get("2"), "z") + }) } func TestObject_getPrototypeOf(t *testing.T) { - Terst(t) + tt(t, func() { + test, _ := test() - test := runTest() - test(` - abc = {}; - def = Object.getPrototypeOf(abc); - ghi = Object.getPrototypeOf(def); - [abc,def,ghi,ghi+""]; - `, "[object Object],[object Object],,null") + test(` + abc = {}; + def = Object.getPrototypeOf(abc); + ghi = Object.getPrototypeOf(def); + [abc,def,ghi,ghi+""]; + `, "[object Object],[object Object],,null") - test(` - abc = Object.getOwnPropertyDescriptor(Object, "getPrototypeOf"); - [ abc.value === Object.getPrototypeOf, abc.writable, abc.enumerable, abc.configurable ]; - `, "true,true,false,true") + test(` + abc = Object.getOwnPropertyDescriptor(Object, "getPrototypeOf"); + [ abc.value === Object.getPrototypeOf, abc.writable, abc.enumerable, abc.configurable ]; + `, "true,true,false,true") + }) } func TestObject_new(t *testing.T) { - Terst(t) + tt(t, func() { + test, _ := test() - test := runTest() - test(` - [ new Object("abc"), new Object(2+2) ]; - `, "abc,4") + test(` + [ new Object("abc"), new Object(2+2) ]; + `, "abc,4") + }) } func TestObject_create(t *testing.T) { - Terst(t) + tt(t, func() { + test, _ := test() - test := runTest() - test(`raise: Object.create()`, "TypeError") - test(` - var abc = Object.create(null) - var def = Object.create({x: 10, y: 20}) - var ghi = Object.create(Object.prototype) + test(`raise: Object.create()`, "TypeError") - var jkl = Object.create({x: 10, y: 20}, { - z: { - value: 30, - writable: true - }, - // sum: { - // get: function() { - // return this.x + this.y + this.z - // } - // } - }); - [ abc.prototype, def.x, def.y, ghi, jkl.x, jkl.y, jkl.z ] - `, ",10,20,[object Object],10,20,30") + test(` + var abc = Object.create(null) + var def = Object.create({x: 10, y: 20}) + var ghi = Object.create(Object.prototype) - test(` - var properties = {}; - Object.defineProperty(properties, "abc", { - value: {}, - enumerable: false - }); - var mno = Object.create({}, properties); - mno.hasOwnProperty("abc"); - `, "false") + var jkl = Object.create({x: 10, y: 20}, { + z: { + value: 30, + writable: true + }, + // sum: { + // get: function() { + // return this.x + this.y + this.z + // } + // } + }); + [ abc.prototype, def.x, def.y, ghi, jkl.x, jkl.y, jkl.z ] + `, ",10,20,[object Object],10,20,30") + + test(` + var properties = {}; + Object.defineProperty(properties, "abc", { + value: {}, + enumerable: false + }); + var mno = Object.create({}, properties); + mno.hasOwnProperty("abc"); + `, false) + }) } func TestObject_toLocaleString(t *testing.T) { - Terst(t) + tt(t, func() { + test, _ := test() - test := runTest() - test(` - ({}).toLocaleString(); - `, "[object Object]") + test(` + ({}).toLocaleString(); + `, "[object Object]") - test(` - object = { - toString: function() { - return "Nothing happens."; - } - }; - object.toLocaleString(); - `, "Nothing happens.") + test(` + object = { + toString: function() { + return "Nothing happens."; + } + }; + object.toLocaleString(); + `, "Nothing happens.") + }) } func TestObject_isExtensible(t *testing.T) { - Terst(t) + tt(t, func() { + test, _ := test() - test := runTest() - test(`raise: - Object.isExtensible(); - `, "TypeError") - test(`raise: - Object.isExtensible({}); - `, "true") + test(`raise: + Object.isExtensible(); + `, "TypeError") - test(`Object.isExtensible.length`, "1") - test(`Object.isExtensible.prototype`, "undefined") + // FIXME terst, Why raise? + test(`raise: + Object.isExtensible({}); + `, true) + + test(`Object.isExtensible.length`, 1) + test(`Object.isExtensible.prototype`, "undefined") + }) } func TestObject_preventExtensions(t *testing.T) { - Terst(t) + tt(t, func() { + test, _ := test() - test := runTest() - test(`raise: - Object.preventExtensions() - `, "TypeError") + test(`raise: + Object.preventExtensions() + `, "TypeError") - test(`raise: - var abc = { def: true }; - var ghi = Object.preventExtensions(abc); - [ ghi.def === true, Object.isExtensible(abc), Object.isExtensible(ghi) ]; - `, "true,false,false") + test(`raise: + var abc = { def: true }; + var ghi = Object.preventExtensions(abc); + [ ghi.def === true, Object.isExtensible(abc), Object.isExtensible(ghi) ]; + `, "true,false,false") - test(` - var abc = new String(); - var def = Object.isExtensible(abc); - Object.preventExtensions(abc); - var ghi = false; - try { - Object.defineProperty(abc, "0", { value: "~" }); - } catch (err) { - ghi = err instanceof TypeError; - } - [ def, ghi, abc.hasOwnProperty("0"), typeof abc[0] ]; - `, "true,true,false,undefined") + test(` + var abc = new String(); + var def = Object.isExtensible(abc); + Object.preventExtensions(abc); + var ghi = false; + try { + Object.defineProperty(abc, "0", { value: "~" }); + } catch (err) { + ghi = err instanceof TypeError; + } + [ def, ghi, abc.hasOwnProperty("0"), typeof abc[0] ]; + `, "true,true,false,undefined") - test(`Object.preventExtensions.length`, "1") - test(`Object.preventExtensions.prototype`, "undefined") + test(`Object.preventExtensions.length`, 1) + test(`Object.preventExtensions.prototype`, "undefined") + }) } func TestObject_isSealed(t *testing.T) { - Terst(t) + tt(t, func() { + test, _ := test() - test := runTest() - test(`Object.isSealed.length`, "1") - test(`Object.isSealed.prototype`, "undefined") + test(`Object.isSealed.length`, 1) + test(`Object.isSealed.prototype`, "undefined") + }) } func TestObject_seal(t *testing.T) { - Terst(t) + tt(t, func() { + test, _ := test() - test := runTest() - test(`raise: Object.seal()`, "TypeError") - test(` - var abc = {a:1,b:1,c:3}; - var sealed = Object.isSealed(abc); - Object.seal(abc); - [sealed, Object.isSealed(abc)]; - `, "false,true") - test(` - var abc = {a:1,b:1,c:3}; - var sealed = Object.isSealed(abc); - var caught = false; - Object.seal(abc); - abc.b = 5; - Object.defineProperty(abc, "a", {value:4}); - try { - Object.defineProperty(abc, "a", {value:42,enumerable:false}); - } catch (e) { - caught = e instanceof TypeError; - } - [sealed, Object.isSealed(abc), caught, abc.a, abc.b]; - `, "false,true,true,4,5") + test(`raise: Object.seal()`, "TypeError") - test(`Object.seal.length`, "1") - test(`Object.seal.prototype`, "undefined") + test(` + var abc = {a:1,b:1,c:3}; + var sealed = Object.isSealed(abc); + Object.seal(abc); + [sealed, Object.isSealed(abc)]; + `, "false,true") + + test(` + var abc = {a:1,b:1,c:3}; + var sealed = Object.isSealed(abc); + var caught = false; + Object.seal(abc); + abc.b = 5; + Object.defineProperty(abc, "a", {value:4}); + try { + Object.defineProperty(abc, "a", {value:42,enumerable:false}); + } catch (e) { + caught = e instanceof TypeError; + } + [sealed, Object.isSealed(abc), caught, abc.a, abc.b]; + `, "false,true,true,4,5") + + test(`Object.seal.length`, 1) + test(`Object.seal.prototype`, "undefined") + }) } func TestObject_isFrozen(t *testing.T) { - Terst(t) + tt(t, func() { + test, _ := test() - test := runTest() - test(`raise: Object.isFrozen()`, "TypeError") - test(`Object.isFrozen(Object.preventExtensions({a:1}))`, "false") - test(`Object.isFrozen({})`, "false") + test(`raise: Object.isFrozen()`, "TypeError") + test(`Object.isFrozen(Object.preventExtensions({a:1}))`, false) + test(`Object.isFrozen({})`, false) - test(` - var abc = {}; - Object.defineProperty(abc, "def", { - value: "def", - writable: true, - configurable: false - }); - Object.preventExtensions(abc); - !Object.isFrozen(abc); - `, "true") + test(` + var abc = {}; + Object.defineProperty(abc, "def", { + value: "def", + writable: true, + configurable: false + }); + Object.preventExtensions(abc); + !Object.isFrozen(abc); + `, true) - test(`Object.isFrozen.length`, "1") - test(`Object.isFrozen.prototype`, "undefined") + test(`Object.isFrozen.length`, 1) + test(`Object.isFrozen.prototype`, "undefined") + }) } func TestObject_freeze(t *testing.T) { - Terst(t) + tt(t, func() { + test, _ := test() - test := runTest() - test(`raise: Object.freeze()`, "TypeError") - test(` + test(`raise: Object.freeze()`, "TypeError") + + test(` var abc = {a:1,b:2,c:3}; var frozen = Object.isFrozen(abc); Object.freeze(abc); @@ -230,7 +245,7 @@ func TestObject_freeze(t *testing.T) { [frozen, Object.isFrozen(abc), abc.b]; `, "false,true,2") - test(` + test(` var abc = {a:1,b:2,c:3}; var frozen = Object.isFrozen(abc); var caught = false; @@ -244,382 +259,381 @@ func TestObject_freeze(t *testing.T) { [frozen, Object.isFrozen(abc), caught, abc.a, abc.b]; `, "false,true,true,1,2") - test(`Object.freeze.length`, "1") - test(`Object.freeze.prototype`, "undefined") + test(`Object.freeze.length`, 1) + test(`Object.freeze.prototype`, "undefined") + }) } func TestObject_defineProperty(t *testing.T) { - Terst(t) + tt(t, func() { + test, _ := test() - test := runTest() - test(` - (function(abc, def, ghi){ - Object.defineProperty(arguments, "0", { - enumerable: false + test(` + (function(abc, def, ghi){ + Object.defineProperty(arguments, "0", { + enumerable: false + }); + return true; + })(0, 1, 2); + `, true) + + test(` + var abc = {}; + abc.def = 3.14; // Default: writable: true, enumerable: true, configurable: true + + Object.defineProperty(abc, "def", { + value: 42 }); - return true; - })(0, 1, 2); - `, - "true", - ) - test(` - var abc = {}; - abc.def = 3.14; // Default: writable: true, enumerable: true, configurable: true + var ghi = Object.getOwnPropertyDescriptor(abc, "def"); + [ ghi.value, ghi.writable, ghi.enumerable, ghi.configurable ]; + `, "42,true,true,true") - Object.defineProperty(abc, "def", { - value: 42 - }); + // Test that we handle the case of DefineOwnProperty + // where [[Writable]] is something but [[Value]] is not + test(` + var abc = []; + Object.defineProperty(abc, "0", { writable: false }); + 0 in abc; + `, true) - var ghi = Object.getOwnPropertyDescriptor(abc, "def"); - [ ghi.value, ghi.writable, ghi.enumerable, ghi.configurable ]; - `, "42,true,true,true") - - // Test that we handle the case of DefineOwnProperty - // where [[Writable]] is something but [[Value]] is not - test(` - var abc = []; - Object.defineProperty(abc, "0", { writable: false }); - 0 in abc; - `, "true") - - // Test that we handle the case of DefineOwnProperty - // where [[Writable]] is something but [[Value]] is not - // (and the property originally had something for [[Value]] - test(` - abc = { - def: 42 - }; - Object.defineProperty(abc, "def", { writable: false }); - abc.def; - `, "42") + // Test that we handle the case of DefineOwnProperty + // where [[Writable]] is something but [[Value]] is not + // (and the property originally had something for [[Value]] + test(` + abc = { + def: 42 + }; + Object.defineProperty(abc, "def", { writable: false }); + abc.def; + `, 42) + }) } func TestObject_keys(t *testing.T) { - Terst(t) + tt(t, func() { + test, _ := test() - test := runTest() + test(`Object.keys({ abc:undefined, def:undefined })`, "abc,def") - test(`Object.keys({ abc:undefined, def:undefined })`, "abc,def") + test(` + function abc() { + this.abc = undefined; + this.def = undefined; + } + Object.keys(new abc()) + `, "abc,def") - test(` - function abc() { - this.abc = undefined; - this.def = undefined; - } - Object.keys(new abc()) - `, "abc,def") + test(` + function def() { + this.ghi = undefined; + } + def.prototype = new abc(); + Object.keys(new def()); + `, "ghi") - test(` - function def() { - this.ghi = undefined; - } - def.prototype = new abc(); - Object.keys(new def()); - `, "ghi") + test(` + var ghi = Object.create( + { + abc: undefined, + def: undefined + }, + { + ghi: { value: undefined, enumerable: true }, + jkl: { value: undefined, enumerable: false } + } + ); + Object.keys(ghi); + `, "ghi") - test(` - var ghi = Object.create( - { - abc: undefined, - def: undefined - }, - { - ghi: { value: undefined, enumerable: true }, - jkl: { value: undefined, enumerable: false } - } - ); - Object.keys(ghi); - `, "ghi") + test(` + (function(abc, def, ghi){ + return Object.keys(arguments) + })(undefined, undefined); + `, "0,1") - test(` - (function(abc, def, ghi){ - return Object.keys(arguments) - })(undefined, undefined); - `, "0,1") - - test(` - (function(abc, def, ghi){ - return Object.keys(arguments) - })(undefined, undefined, undefined, undefined); - `, "0,1,2,3") + test(` + (function(abc, def, ghi){ + return Object.keys(arguments) + })(undefined, undefined, undefined, undefined); + `, "0,1,2,3") + }) } func TestObject_getOwnPropertyNames(t *testing.T) { - Terst(t) + tt(t, func() { + test, _ := test() - test := runTest() + test(`Object.getOwnPropertyNames({ abc:undefined, def:undefined })`, "abc,def") - test(`Object.getOwnPropertyNames({ abc:undefined, def:undefined })`, "abc,def") - - test(` - var ghi = Object.create( - { - abc: undefined, - def: undefined - }, - { - ghi: { value: undefined, enumerable: true }, - jkl: { value: undefined, enumerable: false } - } - ); - Object.getOwnPropertyNames(ghi) - `, "ghi,jkl") + test(` + var ghi = Object.create( + { + abc: undefined, + def: undefined + }, + { + ghi: { value: undefined, enumerable: true }, + jkl: { value: undefined, enumerable: false } + } + ); + Object.getOwnPropertyNames(ghi) + `, "ghi,jkl") + }) } func TestObjectGetterSetter(t *testing.T) { - Terst(t) + tt(t, func() { + test, _ := test() - test := runTest() - - test(`raise: - Object.create({}, { - abc: { - get: function(){ - return "true"; - }, - writable: true - } - }).abc; - `, "TypeError") - - test(`raise: - Object.create({}, { - abc: { - get: function(){ - return "true"; - }, - writable: false - } - }).abc; - `, "TypeError") - - test(` - Object.create({}, { - abc: { - get: function(){ - return "true"; + test(`raise: + Object.create({}, { + abc: { + get: function(){ + return "true"; + }, + writable: true } - } - }).abc; - `, "true") + }).abc; + `, "TypeError") - test(` - Object.create({xyz:true},{abc:{get:function(){return this.xyx}}}).abc; - Object.create({ - xyz: true - }, { - abc: { - get: function(){ - return this.xyz; + test(`raise: + Object.create({}, { + abc: { + get: function(){ + return "true"; + }, + writable: false } - } - }).abc; - `, "true") + }).abc; + `, "TypeError") - test(` - var abc = false; - var def = Object.create({}, { - xyz: { - set: function(value) { - abc = value; - } - } - }); - def.xyz = true; - [ abc ]; - `, "true") + test(` + Object.create({}, { + abc: { + get: function(){ + return "true"; + } + } + }).abc; + `, "true") - test(` - var abc = {}; - Object.defineProperty(abc, "def", { - value: "xyzzy", - configurable: true - }); - Object.preventExtensions(abc); - Object.defineProperty(abc, "def", { - get: function() { - return 5; - } - }); - var def = Object.getOwnPropertyDescriptor(abc, "def"); - [ abc.def, typeof def.get, typeof def.set, typeof def.value, def.configurable, def.enumerable, typeof def.writable ]; - `, "5,function,undefined,undefined,true,false,undefined") + test(` + Object.create({xyz:true},{abc:{get:function(){return this.xyx}}}).abc; + Object.create({ + xyz: true + }, { + abc: { + get: function(){ + return this.xyz; + } + } + }).abc; + `, true) - test(` - var abc = {}; - Object.defineProperty(abc, "def", { - get: function() { - return 5; - } - configurable: true - }); - Object.preventExtensions(abc); - Object.defineProperty(abc, "def", { - value: "xyzzy", - }); - var def = Object.getOwnPropertyDescriptor(abc, "def"); - [ abc.def, typeof def.get, typeof def.set, def.value, def.configurable, def.enumerable, def.writable ]; - `, "xyzzy,undefined,undefined,xyzzy,true,false,false") - - test(` - var abc = {}; - - function _get0() { - return 10; - } - - function _set(value) { - abc.def = value; - } - - Object.defineProperty(abc, "ghi", { - get: _get0, - set: _set, - configurable: true - }); - - function _get1() { - return 20; - } - - Object.defineProperty(abc, "ghi", { - get: _get0 - }); - - var descriptor = Object.getOwnPropertyDescriptor(abc, "ghi"); - [ typeof descriptor.set ]; - `, "function") - - test(`raise: - var abc = []; - Object.defineProperty(abc, "length", { - get: function () { - return 2; - } - }); - `, "TypeError") - - test(` - var abc = {}; - - var getter = function() { - return 1; - } - - Object.defineProperty(abc, "def", { - get: getter, - configurable: false - }); - - var jkl = undefined; - try { - Object.defineProperty(abc, "def", { - get: undefined + test(` + var abc = false; + var def = Object.create({}, { + xyz: { + set: function(value) { + abc = value; + } + } }); - } - catch (err) { - jkl = err; - } - var ghi = Object.getOwnPropertyDescriptor(abc, "def"); - [ jkl instanceof TypeError, ghi.get === getter, ghi.configurable, ghi.enumerable ]; - `, "true,true,false,false") + def.xyz = true; + [ abc ]; + `, "true") - test(` - var abc = {}; - - var getter = function() { - return 1; - }; - - Object.defineProperty(abc, "def", { - get: getter - }); - - Object.defineProperty(abc, "def", { - set: undefined - }); - - var ghi = Object.getOwnPropertyDescriptor(abc, "def"); - [ ghi.get === getter, ghi.set === undefined, ghi.configurable, ghi.enumerable ]; - `, "true,true,false,false") - - test(` - var abc = {}; - - var getter = function() { - return 1; - }; - - Object.defineProperty(abc, "def", { - get: getter - }); - - var jkl = undefined; - try { + test(` + var abc = {}; Object.defineProperty(abc, "def", { - set: function() {} + value: "xyzzy", + configurable: true }); - } - catch (err) { - jkl = err; - } + Object.preventExtensions(abc); + Object.defineProperty(abc, "def", { + get: function() { + return 5; + } + }); + var def = Object.getOwnPropertyDescriptor(abc, "def"); + [ abc.def, typeof def.get, typeof def.set, typeof def.value, def.configurable, def.enumerable, typeof def.writable ]; + `, "5,function,undefined,undefined,true,false,undefined") - var ghi = Object.getOwnPropertyDescriptor(abc, "def"); - [ jkl instanceof TypeError, ghi.get === getter, ghi.set, ghi.configurable, ghi.enumerable ]; - `, "true,true,,false,false") + test(` + var abc = {}; + Object.defineProperty(abc, "def", { + get: function() { + return 5; + } + configurable: true + }); + Object.preventExtensions(abc); + Object.defineProperty(abc, "def", { + value: "xyzzy", + }); + var def = Object.getOwnPropertyDescriptor(abc, "def"); + [ abc.def, typeof def.get, typeof def.set, def.value, def.configurable, def.enumerable, def.writable ]; + `, "xyzzy,undefined,undefined,xyzzy,true,false,false") - test(` - var abc = {}; - var def = "xyzzy"; + test(` + var abc = {}; - Object.defineProperty(abc, "ghi", { - get: undefined, - set: function(value) { - def = value; - }, - enumerable: true, - configurable: true - }); + function _get0() { + return 10; + } - var hasOwn = abc.hasOwnProperty("ghi"); - var descriptor = Object.getOwnPropertyDescriptor(abc, "ghi"); + function _set(value) { + abc.def = value; + } - [ hasOwn, typeof descriptor.get ]; - `, "true,undefined") + Object.defineProperty(abc, "ghi", { + get: _get0, + set: _set, + configurable: true + }); - test(` - var abc = "xyzzy"; - Object.defineProperty(Array.prototype, "abc", { - get: function () { - return abc; - }, - set: function (value) { - abc = value; - }, - enumerable: true, - configurable: true - }); - var def = []; - def.abc = 3.14159; - [ def.hasOwnProperty("abc"), def.abc, abc ]; - `, "false,3.14159,3.14159") + function _get1() { + return 20; + } + Object.defineProperty(abc, "ghi", { + get: _get0 + }); + + var descriptor = Object.getOwnPropertyDescriptor(abc, "ghi"); + [ typeof descriptor.set ]; + `, "function") + + test(`raise: + var abc = []; + Object.defineProperty(abc, "length", { + get: function () { + return 2; + } + }); + `, "TypeError") + + test(` + var abc = {}; + + var getter = function() { + return 1; + } + + Object.defineProperty(abc, "def", { + get: getter, + configurable: false + }); + + var jkl = undefined; + try { + Object.defineProperty(abc, "def", { + get: undefined + }); + } + catch (err) { + jkl = err; + } + var ghi = Object.getOwnPropertyDescriptor(abc, "def"); + [ jkl instanceof TypeError, ghi.get === getter, ghi.configurable, ghi.enumerable ]; + `, "true,true,false,false") + + test(` + var abc = {}; + + var getter = function() { + return 1; + }; + + Object.defineProperty(abc, "def", { + get: getter + }); + + Object.defineProperty(abc, "def", { + set: undefined + }); + + var ghi = Object.getOwnPropertyDescriptor(abc, "def"); + [ ghi.get === getter, ghi.set === undefined, ghi.configurable, ghi.enumerable ]; + `, "true,true,false,false") + + test(` + var abc = {}; + + var getter = function() { + return 1; + }; + + Object.defineProperty(abc, "def", { + get: getter + }); + + var jkl = undefined; + try { + Object.defineProperty(abc, "def", { + set: function() {} + }); + } + catch (err) { + jkl = err; + } + + var ghi = Object.getOwnPropertyDescriptor(abc, "def"); + [ jkl instanceof TypeError, ghi.get === getter, ghi.set, ghi.configurable, ghi.enumerable ]; + `, "true,true,,false,false") + + test(` + var abc = {}; + var def = "xyzzy"; + + Object.defineProperty(abc, "ghi", { + get: undefined, + set: function(value) { + def = value; + }, + enumerable: true, + configurable: true + }); + + var hasOwn = abc.hasOwnProperty("ghi"); + var descriptor = Object.getOwnPropertyDescriptor(abc, "ghi"); + + [ hasOwn, typeof descriptor.get ]; + `, "true,undefined") + + test(` + var abc = "xyzzy"; + Object.defineProperty(Array.prototype, "abc", { + get: function () { + return abc; + }, + set: function (value) { + abc = value; + }, + enumerable: true, + configurable: true + }); + var def = []; + def.abc = 3.14159; + [ def.hasOwnProperty("abc"), def.abc, abc ]; + `, "false,3.14159,3.14159") + }) } func TestProperty(t *testing.T) { - Terst(t) + tt(t, func() { + property := _property{} + property.writeOn() + is(property.writeSet(), true) - property := _property{} - property.writeOn() - Is(property.writeSet(), true) + property.writeClear() + is(property.writeSet(), false) - property.writeClear() - Is(property.writeSet(), false) + property.writeOff() + is(property.writeSet(), true) - property.writeOff() - Is(property.writeSet(), true) - - property.writeClear() - Is(property.writeSet(), false) + property.writeClear() + is(property.writeSet(), false) + }) } diff --git a/otto_error_test.go b/otto_error_test.go index fa6af05..90863ca 100644 --- a/otto_error_test.go +++ b/otto_error_test.go @@ -1,49 +1,48 @@ package otto import ( - . "./terst" "testing" ) func TestOttoError(t *testing.T) { - Terst(t) + tt(t, func() { + vm := New() - Otto := New() + _, err := vm.Run(`throw "Xyzzy"`) + is(err, "Xyzzy") - _, err := Otto.Run(`throw "Xyzzy"`) - Is(err, "Xyzzy") + _, err = vm.Run(`throw new TypeError()`) + is(err, "TypeError") - _, err = Otto.Run(`throw new TypeError()`) - Is(err, "TypeError") + _, err = vm.Run(`throw new TypeError("Nothing happens.")`) + is(err, "TypeError: Nothing happens.") - _, err = Otto.Run(`throw new TypeError("Nothing happens.")`) - Is(err, "TypeError: Nothing happens.") + _, err = ToValue([]byte{}) + is(err, "TypeError: Invalid value (slice): Missing runtime: [] ([]uint8)") - _, err = ToValue([]byte{}) - Is(err, "TypeError: Invalid value (slice): Missing runtime: [] ([]uint8)") + _, err = vm.Run(` + (function(){ + return abcdef.length + })() + `) + is(err, "ReferenceError: abcdef is not defined") - _, err = Otto.Run(` - (function(){ - return abcdef.length - })() - `) - Is(err, "ReferenceError: abcdef is not defined") + _, err = vm.Run(` + function start() { + } - _, err = Otto.Run(` - function start() { - } + start() - start() + xyzzy() + `) + is(err, "ReferenceError: xyzzy is not defined") - xyzzy() - `) - Is(err, "ReferenceError: xyzzy is not defined") + _, err = vm.Run(` + // Just a comment - _, err = Otto.Run(` - // Just a comment - - xyzzy - `) - Is(err, "ReferenceError: xyzzy is not defined") + xyzzy + `) + is(err, "ReferenceError: xyzzy is not defined") + }) } diff --git a/otto_test.go b/otto_test.go index a055f11..bacdda7 100644 --- a/otto_test.go +++ b/otto_test.go @@ -1,1428 +1,1319 @@ package otto import ( - . "./terst" "bytes" - "fmt" "io" - "math" - "strings" "testing" "github.com/robertkrimen/otto/parser" ) -var ( - _newOttoClone = false - _newOtto = map[string]*Otto{} - - _runTestWithOtto = struct { - Otto *Otto - test func(string, ...interface{}) Value - }{} -) - -func newOtto(kind string, setup func(otto *Otto)) *Otto { - if _newOttoClone { - otto := _newOtto[kind] - if otto == nil { - otto = New() - if setup != nil { - setup(otto) - } - _newOtto[kind] = otto - } - return otto.clone() - } - otto := New() - if setup != nil { - setup(otto) - } - return otto -} - -func is(got Value, expect interface{}) bool { - switch expect := expect.(type) { - case float32, float64: - switch got.value.(type) { - case float32, float64: - return Is( - fmt.Sprintf("%g", expect), - fmt.Sprintf("%g", got.value), - ) - case uint, uint8, uint16, uint32, uint64, int, int8, int16, int32, int64: - return Is( - fmt.Sprintf("%g", expect), - fmt.Sprintf("%d", got.value), - ) - } - case uint, uint8, uint16, uint32, uint64, int, int8, int16, int32, int64: - switch got.value.(type) { - case float32, float64: - return Is( - fmt.Sprintf("%d", expect), - fmt.Sprintf("%g", got.value), - ) - case uint, uint8, uint16, uint32, uint64, int, int8, int16, int32, int64: - return Is( - fmt.Sprintf("%d", expect), - fmt.Sprintf("%d", got.value), - ) - } - case string: - switch value := got.value.(type) { - case string: - return Is(value, expect) - } - case bool: - switch value := got.value.(type) { - case bool: - return Is(value, expect) - } - } - return Is(got, expect) -} - -func failSet(name string, value interface{}) Value { - err := _runTestWithOtto.Otto.Set(name, value) - Is(err, nil) - if err != nil { - Terst().TestingT.FailNow() - } - return _runTestWithOtto.Otto.getValue(name) -} - -func runTestWithOtto() (*Otto, func(string, ...interface{}) Value) { - cache := &_runTestWithOtto - Otto := newOtto("", nil) - test := func(name string, expect ...interface{}) Value { - raise := false - defer func() { - if caught := recover(); caught != nil { - if exception, ok := caught.(*_exception); ok { - caught = exception.eject() - } - if raise { - if len(expect) > 0 { - Is(caught, expect[0]) - } - } else { - dbg("Panic, caught:", caught) - panic(caught) - } - } - }() - var value Value - var err error - if isIdentifier(name) { - value = Otto.getValue(name) - } else { - source := name - index := strings.Index(source, "raise:") - if index == 0 { - raise = true - source = source[6:] - source = strings.TrimLeft(source, " ") - } - value, err = Otto.runtime.cmpl_run(source) - if err != nil { - panic(err) - } - } - value = Otto.runtime.GetValue(value) - if len(expect) > 0 { - is(value, expect[0]) - } - return value - } - cache.Otto = Otto - cache.test = test - return Otto, test -} - -func runTest() func(string, ...interface{}) Value { - _, test := runTestWithOtto() - return test -} - func TestOtto(t *testing.T) { - Terst(t) + tt(t, func() { + test, _ := test() - test := runTest() - test("xyzzy = 2", "2") - test("xyzzy + 2", "4") - test("xyzzy += 16", "18") - test("xyzzy", "18") - test(` - (function(){ - return 1 - })() - `, "1") - test(` - (function(){ - return 1 - }).call(this) - `, "1") - test(` - (function(){ - var result - (function(){ - result = -1 - })() - return result - })() - `, "-1") - test(` - var abc = 1 - abc || (abc = -1) - abc - `, "1") - test(` - var abc = (function(){ 1 === 1 })(); - abc; - `, "undefined") + test("xyzzy = 2", 2) + + test("xyzzy + 2", 4) + + test("xyzzy += 16", 18) + + test("xyzzy", 18) + + test(` + (function(){ + return 1 + })() + `, 1) + + test(` + (function(){ + return 1 + }).call(this) + `, 1) + + test(` + (function(){ + var result + (function(){ + result = -1 + })() + return result + })() + `, -1) + + test(` + var abc = 1 + abc || (abc = -1) + abc + `, 1) + + test(` + var abc = (function(){ 1 === 1 })(); + abc; + `, "undefined") + }) } func TestFunction__(t *testing.T) { - Terst(t) + tt(t, func() { + test, _ := test() - test := runTest() - - test(` - function abc() { - return 1; - }; - abc(); - `, "1") + test(` + function abc() { + return 1; + }; + abc(); + `, 1) + }) } func TestIf(t *testing.T) { - Terst(t) + tt(t, func() { + test, _ := test() - test := runTest() + test(` + abc = undefined; + def = undefined; + if (true) abc = 1 + else abc = 2; + if (false) { + def = 3; + } + else def = 4; - test(` - abc = undefined; - def = undefined; - if (true) abc = 1 - else abc = 2; - if (false) { - def = 3; - } - else def = 4; + [ abc, def ]; + `, "1,4") - [ abc, def ]; - `, "1,4") + test(` + if (1) { + abc = 1; + } + else { + abc = 0; + } + abc; + `, 1) - test(` - if (1) { - abc = 1; - } - else { - abc = 0; - } - [ abc ]; - `, "1") + test(` + if (0) { + abc = 1; + } + else { + abc = 0; + } + abc; + `, 0) - test(` - if (0) { - abc = 1; - } - else { - abc = 0; - } - [ abc ]; - `) + test(` + abc = 0; + if (0) { + abc = 1; + } + abc; + `, 0) - test(` - abc = 0; - if (0) { - abc = 1; - } - [ abc ]; - `, "0") - - test(` - abc = 0; - if (abc) { - abc = 1; - } - [ abc ]; - `, "0") + test(` + abc = 0; + if (abc) { + abc = 1; + } + abc; + `, 0) + }) } func TestSequence(t *testing.T) { - Terst(t) + tt(t, func() { + test, _ := test() - test := runTest() - - test(` - 1, 2, 3; - `, "3") + test(` + 1, 2, 3; + `, 3) + }) } func TestCall(t *testing.T) { - Terst(t) + tt(t, func() { + test, _ := test() - test := runTest() - - test(` - [ Math.pow(3, 2) ]; - `, "9") + test(` + Math.pow(3, 2); + `, 9) + }) } func TestMember(t *testing.T) { - Terst(t) + tt(t, func() { + test, _ := test() - test := runTest() - - test(` - abc = [ 0, 1, 2 ]; - def = { - "abc": 0, - "def": 1, - "ghi": 2, - }; - [ abc[2], def.abc, abc[1], def.def ]; - `, "2,0,1,1") + test(` + abc = [ 0, 1, 2 ]; + def = { + "abc": 0, + "def": 1, + "ghi": 2, + }; + [ abc[2], def.abc, abc[1], def.def ]; + `, "2,0,1,1") + }) } func Test_this(t *testing.T) { - Terst(t) + tt(t, func() { + test, _ := test() - test := runTest() - - test(` - [ typeof this ]; - `, "object") + test(` + typeof this; + `, "object") + }) } func TestWhile(t *testing.T) { - Terst(t) + tt(t, func() { + test, _ := test() - test := runTest() - - test(` - limit = 4 - abc = 0 - while (limit) { - abc = abc + 1 - limit = limit - 1 - } - abc; - `, "4") + test(` + limit = 4 + abc = 0 + while (limit) { + abc = abc + 1 + limit = limit - 1 + } + abc; + `, 4) + }) } func TestSwitch_break(t *testing.T) { - Terst(t) + tt(t, func() { + test, _ := test() - test := runTest() + test(` + var abc = true; + var ghi = "Xyzzy"; + while (abc) { + switch ('def') { + case 'def': + break; + } + ghi = "Nothing happens."; + abc = false; + } + ghi; + `, "Nothing happens.") - test(` - var abc = true; - var ghi = "Xyzzy"; - while (abc) { - switch ('def') { - case 'def': - break; - } - ghi = "Nothing happens."; - abc = false; - } - ghi; - `, "Nothing happens.") + test(` + var abc = true; + var ghi = "Xyzzy"; + WHILE: + while (abc) { + switch ('def') { + case 'def': + break WHILE; + } + ghi = "Nothing happens." + abc = false + } + ghi; + `, "Xyzzy") - test(` - var abc = true; - var ghi = "Xyzzy"; - WHILE: - while (abc) { - switch ('def') { - case 'def': - break WHILE; - } - ghi = "Nothing happens." - abc = false - } - ghi; - `, "Xyzzy") + test(` + var ghi = "Xyzzy"; + FOR: + for (;;) { + switch ('def') { + case 'def': + break FOR; + ghi = ""; + } + ghi = "Nothing happens."; + } + ghi; + `, "Xyzzy") - test(` - var ghi = "Xyzzy"; - FOR: - for (;;) { - switch ('def') { - case 'def': - break FOR; - ghi = ""; - } - ghi = "Nothing happens."; - } - ghi; - `, "Xyzzy") + test(` + var ghi = "Xyzzy"; + FOR: + for (var jkl in {}) { + switch ('def') { + case 'def': + break FOR; + ghi = "Something happens."; + } + ghi = "Nothing happens."; + } + ghi; + `, "Xyzzy") - test(` - var ghi = "Xyzzy"; - FOR: - for (var jkl in {}) { - switch ('def') { - case 'def': - break FOR; - ghi = "Something happens."; - } - ghi = "Nothing happens."; - } - ghi; - `, "Xyzzy") - - test(` - var ghi = "Xyzzy"; - function jkl() { - switch ('def') { - case 'def': - break; - ghi = ""; - } - ghi = "Nothing happens."; - } - while (abc) { - jkl(); - abc = false; - ghi = "Something happens."; - } - ghi; - `, "Something happens.") + test(` + var ghi = "Xyzzy"; + function jkl() { + switch ('def') { + case 'def': + break; + ghi = ""; + } + ghi = "Nothing happens."; + } + while (abc) { + jkl(); + abc = false; + ghi = "Something happens."; + } + ghi; + `, "Something happens.") + }) } func TestTryFinally(t *testing.T) { - Terst(t) + tt(t, func() { + test, _ := test() - test := runTest() - - test(` - var abc; - try { - abc = 1; - } - finally { - abc = 2; - } - abc; - `, "2") - - test(` - var abc = false, def = 0; - do { - def += 1; - if (def > 100) { - break; - } - try { - continue; - } - finally { - abc = true; - } - } - while(!abc && def < 10) - def; - `, "1") - - test(` - var abc = false, def = 0, ghi = 0; - do { - def += 1; - if (def > 100) { - break; - } - try { - throw 0; - } - catch (jkl) { - continue; - } - finally { - abc = true; - ghi = 11; - } - ghi -= 1; - } - while(!abc && def < 10) - ghi; - `, "11") - - test(` - var abc = 0, def = 0; - do { + test(` + var abc; try { - abc += 1; - throw "ghi"; + abc = 1; } finally { - def = 1; - continue; - } - def -= 1; - } - while (abc < 2) - [ abc, def ]; - `, "2,1") + abc = 2; + } + abc; + `, 2) + + test(` + var abc = false, def = 0; + do { + def += 1; + if (def > 100) { + break; + } + try { + continue; + } + finally { + abc = true; + } + } + while(!abc && def < 10) + def; + `, 1) + + test(` + var abc = false, def = 0, ghi = 0; + do { + def += 1; + if (def > 100) { + break; + } + try { + throw 0; + } + catch (jkl) { + continue; + } + finally { + abc = true; + ghi = 11; + } + ghi -= 1; + } + while(!abc && def < 10) + ghi; + `, 11) + + test(` + var abc = 0, def = 0; + do { + try { + abc += 1; + throw "ghi"; + } + finally { + def = 1; + continue; + } + def -= 1; + } + while (abc < 2) + [ abc, def ]; + `, "2,1") + }) } func TestTryCatch(t *testing.T) { - Terst(t) + tt(t, func() { + test, _ := test() - test := runTest() + test(` + var abc = 1; + try { + throw 4; + abc = -1; + } + catch (xyzzy) { + abc += xyzzy + 1; + } + abc; + `, 6) - test(` - var abc = 1; - try { - throw 4; - abc = -1; - } - catch (xyzzy) { - abc += xyzzy + 1; - } - abc; - `, "6") - - test(` - abc = 1; - var def; - try { - try { - throw 4; - abc = -1; - } - catch (xyzzy) { - abc += xyzzy + 1; - throw 64; - } - } - catch (xyzzy) { - def = xyzzy; - abc = -2; - } - [ def, abc ]; - `, "64,-2") + test(` + abc = 1; + var def; + try { + try { + throw 4; + abc = -1; + } + catch (xyzzy) { + abc += xyzzy + 1; + throw 64; + } + } + catch (xyzzy) { + def = xyzzy; + abc = -2; + } + [ def, abc ]; + `, "64,-2") + }) } func TestWith(t *testing.T) { - Terst(t) + tt(t, func() { + test, _ := test() - test := runTest() + test(` + var def; + with({ abc: 9 }) { + def = abc; + } + def; + `, 9) - test(` - var def; - with({ abc: 9 }) { - def = abc; - } - def; - `, "9") - - test(` - var def; - with({ abc: function(){ - return 11; - } }) { - def = abc(); - } - def; - `, "11") + test(` + var def; + with({ abc: function(){ + return 11; + } }) { + def = abc(); + } + def; + `, 11) + }) } func TestSwitch(t *testing.T) { - Terst(t) + tt(t, func() { + test, _ := test() - test := runTest() + test(` + var abc = 0; + switch (0) { + default: + abc += 1; + case 1: + abc += 2; + case 2: + abc += 4; + case 3: + abc += 8; + } + abc; + `, 15) - test(` - var abc = 0; - switch (0) { - default: - abc += 1; - case 1: - abc += 2; - case 2: - abc += 4; - case 3: - abc += 8; - } - abc; - `, "15") + test(` + abc = 0; + switch (3) { + default: + abc += 1; + case 1: + abc += 2; + case 2: + abc += 4; + case 3: + abc += 8; + } + abc; + `, 8) - test(` - abc = 0; - switch (3) { - default: - abc += 1; - case 1: - abc += 2; - case 2: - abc += 4; - case 3: - abc += 8; - } - abc; - `, "8") - - test(` - abc = 0; - switch (60) { - case 1: - abc += 2; - case 2: - abc += 4; - case 3: - abc += 8; - } - abc; - `, "0") + test(` + abc = 0; + switch (60) { + case 1: + abc += 2; + case 2: + abc += 4; + case 3: + abc += 8; + } + abc; + `, 0) + }) } func TestForIn(t *testing.T) { - Terst(t) + tt(t, func() { + test, _ := test() - test := runTest() + test(` + var abc; + for (property in { a: 1 }) { + abc = property; + } + abc; + `, "a") - test(` - var abc; - for (property in { a: 1 }) { - abc = property; - } - abc; - `, "a") - - test(` - var ghi; - for (property in new String("xyzzy")) { - ghi = property; - } - ghi; - `, "4") + test(` + var ghi; + for (property in new String("xyzzy")) { + ghi = property; + } + ghi; + `, "4") + }) } func TestFor(t *testing.T) { - Terst(t) + tt(t, func() { + test, _ := test() - test := runTest() + test(` + var abc = 7; + for (i = 0; i < 3; i += 1) { + abc += 1; + } + abc; + `, 10) - test(` - var abc = 7; - for (i = 0; i < 3; i += 1) { - abc += 1; - } - abc; - `, "10") + test(` + abc = 7; + for (i = 0; i < 3; i += 1) { + abc += 1; + if (i == 1) { + break; + } + } + abc; + `, 9) - test(` - abc = 7; - for (i = 0; i < 3; i += 1) { - abc += 1; - if (i == 1) { - break; - } - } - abc; - `, "9") + test(` + abc = 7; + for (i = 0; i < 3; i += 1) { + if (i == 2) { + continue; + } + abc += 1; + } + abc; + `, 9) - test(` - abc = 7; - for (i = 0; i < 3; i += 1) { - if (i == 2) { - continue; - } - abc += 1; - } - abc; - `, "9") + test(` + abc = 0; + for (;;) { + abc += 1; + if (abc == 3) + break; + } + abc; + `, 3) - test(` - abc = 0; - for (;;) { - abc += 1; - if (abc == 3) - break; - } - abc; - `, "3") + test(` + for (abc = 0; ;) { + abc += 1; + if (abc == 3) + break; + } + abc; + `, 3) - test(` - for (abc = 0; ;) { - abc += 1; - if (abc == 3) - break; - } - abc; - `, "3") - - test(` - for (abc = 0; ; abc += 1) { - abc += 1; - if (abc == 3) - break; - } - abc; - `, "3") + test(` + for (abc = 0; ; abc += 1) { + abc += 1; + if (abc == 3) + break; + } + abc; + `, 3) + }) } func TestLabelled(t *testing.T) { - Terst(t) + tt(t, func() { + test, _ := test() - test := runTest() + // TODO Add emergency break - // TODO Add emergency break - - test(` - xyzzy: for (var abc = 0; abc <= 0; abc++) { - for (var def = 0; def <= 1; def++) { - if (def === 0) { - continue xyzzy; - } else { + test(` + xyzzy: for (var abc = 0; abc <= 0; abc++) { + for (var def = 0; def <= 1; def++) { + if (def === 0) { + continue xyzzy; + } else { + } + } } - } - } - `) + `) - test(` - abc = 0 - def: - while (true) { + test(` + abc = 0 + def: while (true) { - abc = abc + 1 - if (abc > 11) { - break def; + while (true) { + abc = abc + 1 + if (abc > 11) { + break def; + } } } - } - [ abc ]; - `, "12") + abc; + `, 12) - test(` - abc = 0 - def: - do { + test(` + abc = 0 + def: do { - abc = abc + 1 - if (abc > 11) { - break def; - } + do { + abc = abc + 1 + if (abc > 11) { + break def; + } + } while (true) } while (true) - } while (true) - [ abc ]; - `, "12") + abc; + `, 12) + }) } func TestConditional(t *testing.T) { - Terst(t) + tt(t, func() { + test, _ := test() - test := runTest() - - test(` - [ true ? false : true, true ? 1 : 0, false ? 3.14159 : "abc" ]; - `, "false,1,abc") + test(` + [ true ? false : true, true ? 1 : 0, false ? 3.14159 : "abc" ]; + `, "false,1,abc") + }) } func TestArrayLiteral(t *testing.T) { - Terst(t) + tt(t, func() { + test, _ := test() - test := runTest() - - test(` - [ 1, , 3.14159 ]; - `, "1,,3.14159") + test(` + [ 1, , 3.14159 ]; + `, "1,,3.14159") + }) } func TestAssignment(t *testing.T) { - Terst(t) + tt(t, func() { + test, _ := test() - test := runTest() + test(` + var abc = 1; + abc; + `, 1) - test(` - var abc = 1; - abc; - `, "1") - - test(` - abc += 2; - abc; - `, "3") + test(` + abc += 2; + abc; + `, 3) + }) } func TestBinaryOperation(t *testing.T) { - Terst(t) + tt(t, func() { + test, _ := test() - test := runTest() - test(`0 == 1`, "false") - test(`1 == "1"`, "true") - test(`0 === 1`, "false") - test(`1 === "1"`, "false") - test(`"1" === "1"`, "true") + test(`0 == 1`, false) + test(`1 == "1"`, true) + test(`0 === 1`, false) + test(`1 === "1"`, false) + test(`"1" === "1"`, true) + }) } func Test_typeof(t *testing.T) { - Terst(t) + tt(t, func() { + test, _ := test() - test := runTest() - test(`typeof abc`, "undefined") - test(`typeof abc === 'undefined'`, "true") - test(`typeof {}`, "object") - test(`typeof null`, "object") + test(`typeof abc`, "undefined") + test(`typeof abc === 'undefined'`, true) + test(`typeof {}`, "object") + test(`typeof null`, "object") + }) } func Test_PrimitiveValueObjectValue(t *testing.T) { - Terst(t) + tt(t, func() { + test, _ := test() - test := runTest() - Number11 := test(`new Number(11)`) - Is(toFloat(Number11), "11") + Number11 := test(`new Number(11)`) + is(toFloat(Number11), 11) + }) } func Test_eval(t *testing.T) { - Terst(t) + tt(t, func() { + test, _ := test() - test := runTest() + // FIXME terst, Is this correct? + test(` + var abc = 1; + `, "undefined") - test(` - var abc = 1; - `) + test(` + eval("abc += 1"); + `, 2) - test(` - eval("abc += 1"); - `, "2") + test(` + (function(){ + var abc = 11; + eval("abc += 1"); + return abc; + })(); + `, 12) + test(`abc`, 2) - test(` - (function(){ - var abc = 11; - eval("abc += 1"); - return abc; - })(); - `, "12") - test(`abc`, "2") + test(` + (function(){ + try { + eval("var prop = \\u2029;"); + return false; + } catch (abc) { + return [ abc instanceof SyntaxError, abc.toString() ]; + } + })(); + `, "true,SyntaxError: Unexpected token ILLEGAL") - test(` - (function(){ - try { - eval("var prop = \\u2029;"); - return false; - } catch (abc) { - return [ abc instanceof SyntaxError, abc.toString() ]; - } - })(); - `, "true,SyntaxError: Unexpected token ILLEGAL") - - test(` - function abc(){ - this.THIS = eval("this"); - } - var def = new abc(); - def === def.THIS; - `, "true") + test(` + function abc(){ + this.THIS = eval("this"); + } + var def = new abc(); + def === def.THIS; + `, true) + }) } func Test_evalDirectIndirect(t *testing.T) { - Terst(t) + tt(t, func() { + test, _ := test() - test := runTest() - test(` - var abc = "global"; - (function(){ - try { - var _eval = eval; - var abc = "function"; - if ( - _eval("\'global\' === abc") === true && // eval (Indirect) - eval("\'function\' === abc") === true // eval (Direct) - ) { - return true; + test(` + var abc = "global"; + (function(){ + try { + var _eval = eval; + var abc = "function"; + if ( + _eval("\'global\' === abc") === true && // eval (Indirect) + eval("\'function\' === abc") === true // eval (Direct) + ) { + return true; + } + return false; + } finally { + delete this.abc; } - return false; - } finally { - delete this.abc; - } - })() - `, "true") + })() + `, true) + }) } func TestError_URIError(t *testing.T) { - Terst(t) + tt(t, func() { + test, _ := test() - test := runTest() - test(`new URIError() instanceof URIError`, "true") - test(` - var abc - try { - decodeURI("http://example.com/ _^#%") - } - catch (def) { - abc = def instanceof URIError - } - abc - `, "true") + test(`new URIError() instanceof URIError`, true) + + test(` + var abc + try { + decodeURI("http://example.com/ _^#%") + } + catch (def) { + abc = def instanceof URIError + } + abc + `, true) + }) } func TestTo(t *testing.T) { - Terst(t) + tt(t, func() { + test, _ := test() - test := runTest() + { + value, _ := test(`"11"`).ToFloat() + is(value, float64(11)) + } - { - value, _ := test(`"11"`).ToFloat() - Is(value, float64(11)) - } + { + value, _ := test(`"11"`).ToInteger() + is(value, int64(11)) - { - value, _ := test(`"11"`).ToInteger() - Is(value, int64(11)) - - value, _ = test(`1.1`).ToInteger() - Is(value, int64(1)) - } + value, _ = test(`1.1`).ToInteger() + is(value, int64(1)) + } + }) } func TestShouldError(t *testing.T) { - Terst(t) + tt(t, func() { + test, _ := test() - test := runTest() - test(`raise: - xyzzy - throw new TypeError("Nothing happens.") - `, "ReferenceError: xyzzy is not defined") + test(`raise: + xyzzy + throw new TypeError("Nothing happens.") + `, "ReferenceError: xyzzy is not defined") + }) } func TestAPI(t *testing.T) { - Terst(t) + tt(t, func() { + test, vm := test() - Otto, test := runTestWithOtto() - test(` - String.prototype.xyzzy = function(){ - return this.length + 11 + (arguments[0] || 0) - } - abc = new String("xyzzy") - def = "Nothing happens." - abc.xyzzy() - `, "16") - abc, _ := Otto.Get("abc") - def, _ := Otto.Get("def") - object := abc.Object() - result, _ := object.Call("xyzzy") - Is(result, "16") - result, _ = object.Call("xyzzy", 1) - Is(result, "17") - value, _ := object.Get("xyzzy") - result, _ = value.Call(def) - Is(result, "27") - result, _ = value.Call(def, 3) - Is(result, "30") - object = value.Object() // Object xyzzy - result, _ = object.Value().Call(def, 3) - Is(result, "30") + test(` + String.prototype.xyzzy = function(){ + return this.length + 11 + (arguments[0] || 0) + } + abc = new String("xyzzy") + def = "Nothing happens." + abc.xyzzy() + `, 16) + abc, _ := vm.Get("abc") + def, _ := vm.Get("def") + object := abc.Object() + result, _ := object.Call("xyzzy") + is(result, 16) + result, _ = object.Call("xyzzy", 1) + is(result, 17) + value, _ := object.Get("xyzzy") + result, _ = value.Call(def) + is(result, 27) + result, _ = value.Call(def, 3) + is(result, 30) + object = value.Object() // Object xyzzy + result, _ = object.Value().Call(def, 3) + is(result, 30) - test(` - abc = { - 'abc': 1, - 'def': false, - 3.14159: NaN, - }; - abc['abc']; - `, "1") - abc, err := Otto.Get("abc") - Is(err, nil) - object = abc.Object() // Object abc - value, err = object.Get("abc") - Is(err, nil) - Is(value, "1") - Is(object.Keys(), []string{"abc", "def", "3.14159"}) + test(` + abc = { + 'abc': 1, + 'def': false, + 3.14159: NaN, + }; + abc['abc']; + `, 1) + abc, err := vm.Get("abc") + is(err, nil) + object = abc.Object() // Object abc + value, err = object.Get("abc") + is(err, nil) + is(value, 1) + is(object.Keys(), []string{"abc", "def", "3.14159"}) - test(` - abc = [ 0, 1, 2, 3.14159, "abc", , ]; - abc.def = true; - `) - abc, err = Otto.Get("abc") - Is(err, nil) - object = abc.Object() // Object abc - Is(object.Keys(), []string{"0", "1", "2", "3", "4", "def"}) + test(` + abc = [ 0, 1, 2, 3.14159, "abc", , ]; + abc.def = true; + `) + abc, err = vm.Get("abc") + is(err, nil) + object = abc.Object() // Object abc + is(object.Keys(), []string{"0", "1", "2", "3", "4", "def"}) + }) } func TestUnicode(t *testing.T) { - Terst(t) + tt(t, func() { + test, _ := test() - test := runTest() - test(`var abc = eval("\"a\uFFFFa\"");`) - test(`abc.length`, "3") - test(`abc != "aa"`, "true") - test("abc[1] === \"\uFFFF\"", "true") + test(`var abc = eval("\"a\uFFFFa\"");`, "undefined") + + test(`abc.length`, 3) + + test(`abc != "aa"`, true) + + test("abc[1] === \"\uFFFF\"", true) + }) } func TestDotMember(t *testing.T) { - Terst(t) + tt(t, func() { + test, _ := test() - test := runTest() + test(` + abc = { + ghi: 11, + } + abc.def = "Xyzzy" + abc.null = "Nothing happens." + `) + test(`abc.def`, "Xyzzy") + test(`abc.null`, "Nothing happens.") + test(`abc.ghi`, 11) - test(` - abc = { - ghi: 11, - } - abc.def = "Xyzzy" - abc.null = "Nothing happens." - `) - test(`abc.def`, "Xyzzy") - test(`abc.null`, "Nothing happens.") - test(`abc.ghi`, "11") - - test(` - abc = { - null: 11, - } - `) - test(`abc.def`, "undefined") - test(`abc.null`, "11") - test(`abc.ghi`, "undefined") + test(` + abc = { + null: 11, + } + `) + test(`abc.def`, "undefined") + test(`abc.null`, 11) + test(`abc.ghi`, "undefined") + }) } func Test_stringToFloat(t *testing.T) { - Terst(t) + tt(t, func() { - Is(stringToFloat("10e10000"), math.Inf(1)) - Is(stringToFloat("10e10_."), "NaN") + is(stringToFloat("10e10000"), _Infinity) + is(stringToFloat("10e10_."), _NaN) + }) } func Test_delete(t *testing.T) { - Terst(t) + tt(t, func() { + test, _ := test() - test := runTest() + test(` + delete 42; + `, true) - test(` - delete 42; - `, "true") + test(` + var abc = delete $_undefined_$; + abc = abc && delete ($_undefined_$); + abc; + `, true) - test(` - var abc = delete $_undefined_$; - abc = abc && delete ($_undefined_$); - abc; - `, "true") - - // delete should not trigger get() - test(` - var abc = { - get def() { - throw "Test_delete: delete should not trigger get()" - } - }; - delete abc.def - `, true) + // delete should not trigger get() + test(` + var abc = { + get def() { + throw "Test_delete: delete should not trigger get()" + } + }; + delete abc.def + `, true) + }) } func TestObject_defineOwnProperty(t *testing.T) { - Terst(t) + tt(t, func() { + test, _ := test() - test := runTest() + test(` + var object = {}; - test(` - var object = {}; + var descriptor = new Boolean(false); + descriptor.configurable = true; - var descriptor = new Boolean(false); - descriptor.configurable = true; + Object.defineProperties(object, { + property: descriptor + }); - Object.defineProperties(object, { - property: descriptor - }); + var abc = object.hasOwnProperty("property"); + delete object.property; + var def = object.hasOwnProperty("property"); - var abc = object.hasOwnProperty("property"); - delete object.property; - var def = object.hasOwnProperty("property"); + [ abc, def ]; + `, "true,false") - [ abc, def ]; - `, "true,false") + test(` + var object = [0, 1, 2]; + Object.defineProperty(object, "0", { + value: 42, + writable: false, + enumerable: false, + configurable: false + }); + var abc = Object.getOwnPropertyDescriptor(object, "0"); + [ abc.value, abc.writable, abc.enumerable, abc.configurable ]; + `, "42,false,false,false") - test(` - var object = [0, 1, 2]; - Object.defineProperty(object, "0", { - value: 42, - writable: false, - enumerable: false, - configurable: false - }); - var abc = Object.getOwnPropertyDescriptor(object, "0"); - [ abc.value, abc.writable, abc.enumerable, abc.configurable ]; - `, "42,false,false,false") - - test(` - var abc = { "xyzzy": 42 }; - var def = Object.defineProperties(abc, ""); - abc === def; - `, "true") + test(` + var abc = { "xyzzy": 42 }; + var def = Object.defineProperties(abc, ""); + abc === def; + `, true) + }) } func Test_assignmentEvaluationOrder(t *testing.T) { - Terst(t) + tt(t, func() { + test, _ := test() - test := runTest() - //test(` - // var abc = 0; - // ((abc = 1) & abc); - //`, "1") + test(` + var abc = 0; + ((abc = 1) & abc); + `, 1) - test(` - var abc = 0; - (abc & (abc = 1)); - `, "0") + test(` + var abc = 0; + (abc & (abc = 1)); + `, 0) + }) } func TestOttoCall(t *testing.T) { - Terst(t) + tt(t, func() { + vm := New() - otto, _ := runTestWithOtto() - _, err := otto.Run(` - var abc = { - ghi: 1, - def: function(def){ - var ghi = 0; - if (this.ghi) { - ghi = this.ghi; + _, err := vm.Run(` + var abc = { + ghi: 1, + def: function(def){ + var ghi = 0; + if (this.ghi) { + ghi = this.ghi; + } + return "def: " + (def + 3.14159 + ghi); } - return "def: " + (def + 3.14159 + ghi); - } - }; - `) - Is(err, nil) + }; + `) + is(err, nil) - value, err := otto.Call(`abc.def`, nil, 2) - Is(err, nil) - Is(value, "def: 6.14159") + value, err := vm.Call(`abc.def`, nil, 2) + is(err, nil) + is(value, "def: 6.14159") - value, err = otto.Call(`abc.def`, "", 2) - Is(err, nil) - Is(value, "def: 5.14159") + value, err = vm.Call(`abc.def`, "", 2) + is(err, nil) + is(value, "def: 5.14159") - // Do not attempt to do a ToValue on a this of nil - value, err = otto.Call(`jkl.def`, nil, 1, 2, 3) - IsNot(err, nil) - Is(value, "undefined") + // Do not attempt to do a ToValue on a this of nil + value, err = vm.Call(`jkl.def`, nil, 1, 2, 3) + is(err, "!=", nil) + is(value, "undefined") - value, err = otto.Call(`[ 1, 2, 3, undefined, 4 ].concat`, nil, 5, 6, 7, "abc") - Is(err, nil) - Is(value, "1,2,3,,4,5,6,7,abc") + value, err = vm.Call(`[ 1, 2, 3, undefined, 4 ].concat`, nil, 5, 6, 7, "abc") + is(err, nil) + is(value, "1,2,3,,4,5,6,7,abc") + }) } func TestOttoCall_new(t *testing.T) { - Terst(t) + tt(t, func() { + test, vm := test() - _, test := runTestWithOtto() - - failSet("abc", func(call FunctionCall) Value { - value, err := call.Otto.Call(`new Object`, nil, "Nothing happens.") - Is(err, nil) - return value + vm.Set("abc", func(call FunctionCall) Value { + value, err := call.Otto.Call(`new Object`, nil, "Nothing happens.") + is(err, nil) + return value + }) + test(` + def = abc(); + [ def, def instanceof String ]; + `, "Nothing happens.,true") }) - test(` - def = abc(); - [ def, def instanceof String ]; - `, "Nothing happens.,true") } func TestOttoCall_throw(t *testing.T) { - Terst(t) - // FIXME? (Been broken for a while) // Looks like this has been broken for a while... what // behavior do we want here? return - _, test := runTestWithOtto() + tt(t, func() { + test, vm := test() - failSet("abc", func(call FunctionCall) Value { - if false { - call.Otto.Call(`throw eval`, nil, "({ def: 3.14159 })") - } - call.Otto.Call(`throw Error`, nil, "abcdef") - return UndefinedValue() - }) - // TODO try { abc(); } catch (err) { error = err } - // Possible unrelated error case: - // If error is not declared beforehand, is later referencing it a ReferenceError? - // Should the catch { } declare error in the outer scope? - test(` - var error; - try { - abc(); - } - catch (err) { - error = err; - } - [ error instanceof Error, error.message, error.def ]; - `, "true,abcdef,") + vm.Set("abc", func(call FunctionCall) Value { + if false { + call.Otto.Call(`throw eval`, nil, "({ def: 3.14159 })") + } + call.Otto.Call(`throw Error`, nil, "abcdef") + return UndefinedValue() + }) + // TODO try { abc(); } catch (err) { error = err } + // Possible unrelated error case: + // If error is not declared beforehand, is later referencing it a ReferenceError? + // Should the catch { } declare error in the outer scope? + test(` + var error; + try { + abc(); + } + catch (err) { + error = err; + } + [ error instanceof Error, error.message, error.def ]; + `, "true,abcdef,") - failSet("def", func(call FunctionCall) Value { - call.Otto.Call(`throw new Object`, nil, 3.14159) - return UndefinedValue() + vm.Set("def", func(call FunctionCall) Value { + call.Otto.Call(`throw new Object`, nil, 3.14159) + return UndefinedValue() + }) + test(` + try { + def(); + } + catch (err) { + error = err; + } + [ error instanceof Error, error.message, error.def, typeof error, error, error instanceof Number ]; + `, "false,,,object,3.14159,true") }) - test(` - try { - def(); - } - catch (err) { - error = err; - } - [ error instanceof Error, error.message, error.def, typeof error, error, error instanceof Number ]; - `, "false,,,object,3.14159,true") } func TestOttoCopy(t *testing.T) { - Terst(t) + tt(t, func() { + vm0 := New() + vm0.Run(` + var abc = function() { + return "Xyzzy"; + }; - otto0 := New() - otto0.Run(` - var abc = function() { - return "Xyzzy"; - }; + function def() { + return abc() + (0 + {}); + } + `) - function def() { - return abc() + (0 + {}); - } - `) + value, err := vm0.Run(` + def(); + `) + is(err, nil) + is(value, "Xyzzy0[object Object]") - value, err := otto0.Run(` - def(); - `) - Is(err, nil) - Is(value, "Xyzzy0[object Object]") + vm1 := vm0.Copy() + value, err = vm1.Run(` + def(); + `) + is(err, nil) + is(value, "Xyzzy0[object Object]") - otto1 := otto0.Copy() - value, err = otto1.Run(` - def(); - `) - Is(err, nil) - Is(value, "Xyzzy0[object Object]") + vm1.Run(` + abc = function() { + return 3.14159; + }; + `) + value, err = vm1.Run(` + def(); + `) + is(err, nil) + is(value, "3.141590[object Object]") - otto1.Run(` - abc = function() { - return 3.14159; - }; - `) - value, err = otto1.Run(` - def(); - `) - Is(err, nil) - Is(value, "3.141590[object Object]") - - value, err = otto0.Run(` - def(); - `) - Is(err, nil) - Is(value, "Xyzzy0[object Object]") + value, err = vm0.Run(` + def(); + `) + is(err, nil) + is(value, "Xyzzy0[object Object]") + }) } func TestOttoCall_clone(t *testing.T) { - Terst(t) + tt(t, func() { + vm := New().clone() + rt := vm.runtime - otto := New().clone() + { + // FIXME terst, Check how this comparison is done + is(rt.Global.Array.prototype, rt.Global.FunctionPrototype) + is(rt.Global.ArrayPrototype, "!=", nil) + is(rt.Global.Array.runtime, rt) + is(rt.Global.Array.prototype.runtime, rt) + is(rt.Global.Array.get("prototype")._object().runtime, rt) + } - { - Is(otto.runtime.Global.Array.prototype, otto.runtime.Global.FunctionPrototype) - IsNot(otto.runtime.Global.ArrayPrototype, nil) - Is(otto.runtime.Global.Array.runtime, otto.runtime) - Is(otto.runtime.Global.Array.prototype.runtime, otto.runtime) - Is(otto.runtime.Global.Array.get("prototype")._object().runtime, otto.runtime) - } + { + value, err := vm.Run(`[ 1, 2, 3 ].toString()`) + is(err, nil) + is(value, "1,2,3") + } - { - value, err := otto.Run(`[ 1, 2, 3 ].toString()`) - Is(err, nil) - Is(value, "1,2,3") - } + { + value, err := vm.Run(`[ 1, 2, 3 ]`) + is(err, nil) + is(value, "1,2,3") + object := value._object() + is(object, "!=", nil) + is(object.prototype, rt.Global.ArrayPrototype) - { - value, err := otto.Run(`[ 1, 2, 3 ]`) - Is(err, nil) - Is(value, "1,2,3") - object := value._object() - IsNot(object, nil) - Is(object.prototype, otto.runtime.Global.ArrayPrototype) + value, err = vm.Run(`Array.prototype`) + is(err, nil) + object = value._object() + is(object.runtime, rt) + is(object, "!=", nil) + is(object, rt.Global.ArrayPrototype) + } - value, err = otto.Run(`Array.prototype`) - Is(err, nil) - object = value._object() - Is(object.runtime, otto.runtime) - IsNot(object, nil) - Is(object, otto.runtime.Global.ArrayPrototype) - } + { + otto1 := New() + _, err := otto1.Run(` + var abc = 1; + var def = 2; + `) + is(err, nil) - { - otto1 := New() - _, err := otto1.Run(` - var abc = 1; - var def = 2; - `) - Is(err, nil) + otto2 := otto1.clone() + value, err := otto2.Run(`abc += 1; abc;`) + is(err, nil) + is(value, 2) - otto2 := otto1.clone() - value, err := otto2.Run(`abc += 1; abc;`) - Is(err, nil) - Is(value, "2") + value, err = otto1.Run(`abc += 4; abc;`) + is(err, nil) + is(value, 5) + } - value, err = otto1.Run(`abc += 4; abc;`) - Is(err, nil) - Is(value, "5") - } - - { - otto1 := New() - _, err := otto1.Run(` - var abc = 1; - var def = function(value) { - abc += value; - return abc; - } - `) - Is(err, nil) - - otto2 := otto1.clone() - value, err := otto2.Run(`def(1)`) - Is(err, nil) - Is(value, "2") - - value, err = otto1.Run(`def(4)`) - Is(err, nil) - Is(value, "5") - } - - { - otto1 := New() - _, err := otto1.Run(` - var abc = { - ghi: 1, - jkl: function(value) { - this.ghi += value; - return this.ghi; + { + vm1 := New() + _, err := vm1.Run(` + var abc = 1; + var def = function(value) { + abc += value; + return abc; } - }; - var def = { - abc: abc - }; - `) - Is(err, nil) + `) + is(err, nil) - otto2 := otto1.clone() - value, err := otto2.Run(`def.abc.jkl(1)`) - Is(err, nil) - Is(value, "2") + vm2 := vm1.clone() + value, err := vm2.Run(`def(1)`) + is(err, nil) + is(value, 2) - value, err = otto1.Run(`def.abc.jkl(4)`) - Is(err, nil) - Is(value, "5") - } + value, err = vm1.Run(`def(4)`) + is(err, nil) + is(value, 5) + } - { - otto1 := New() - _, err := otto1.Run(` - var abc = function() { return "abc"; }; - var def = function() { return "def"; }; - `) - Is(err, nil) + { + vm1 := New() + _, err := vm1.Run(` + var abc = { + ghi: 1, + jkl: function(value) { + this.ghi += value; + return this.ghi; + } + }; + var def = { + abc: abc + }; + `) + is(err, nil) - otto2 := otto1.clone() - value, err := otto2.Run(` - [ abc.toString(), def.toString() ]; - `) - Is(value, `function() { return "abc"; },function() { return "def"; }`) + otto2 := vm1.clone() + value, err := otto2.Run(`def.abc.jkl(1)`) + is(err, nil) + is(value, 2) - _, err = otto2.Run(` - var def = function() { return "ghi"; }; - `) - Is(err, nil) + value, err = vm1.Run(`def.abc.jkl(4)`) + is(err, nil) + is(value, 5) + } - value, err = otto1.Run(` - [ abc.toString(), def.toString() ]; - `) - Is(value, `function() { return "abc"; },function() { return "def"; }`) + { + vm1 := New() + _, err := vm1.Run(` + var abc = function() { return "abc"; }; + var def = function() { return "def"; }; + `) + is(err, nil) - value, err = otto2.Run(` - [ abc.toString(), def.toString() ]; - `) - Is(value, `function() { return "abc"; },function() { return "ghi"; }`) - } + vm2 := vm1.clone() + value, err := vm2.Run(` + [ abc.toString(), def.toString() ]; + `) + is(value, `function() { return "abc"; },function() { return "def"; }`) + _, err = vm2.Run(` + var def = function() { return "ghi"; }; + `) + is(err, nil) + + value, err = vm1.Run(` + [ abc.toString(), def.toString() ]; + `) + is(value, `function() { return "abc"; },function() { return "def"; }`) + + value, err = vm2.Run(` + [ abc.toString(), def.toString() ]; + `) + is(value, `function() { return "abc"; },function() { return "ghi"; }`) + } + + }) } func TestOttoRun(t *testing.T) { - Terst(t) + tt(t, func() { + vm := New() - vm := New() + program, err := parser.ParseFile(nil, "", "", 0) + is(err, nil) + value, err := vm.Run(program) + is(err, nil) + is(value, UndefinedValue()) - program, err := parser.ParseFile(nil, "", "", 0) - Is(err, nil) - value, err := vm.Run(program) - Is(err, nil) - Is(value, UndefinedValue()) + program, err = parser.ParseFile(nil, "", "2 + 2", 0) + is(err, nil) + value, err = vm.Run(program) + is(err, nil) + is(value, 4) + value, err = vm.Run(program) + is(err, nil) + is(value, 4) - program, err = parser.ParseFile(nil, "", "2 + 2", 0) - Is(err, nil) - value, err = vm.Run(program) - Is(err, nil) - is(value, 4) - value, err = vm.Run(program) - Is(err, nil) - is(value, 4) + program, err = parser.ParseFile(nil, "", "var abc; if (!abc) abc = 0; abc += 2; abc;", 0) + value, err = vm.Run(program) + is(err, nil) + is(value, 2) + value, err = vm.Run(program) + is(err, nil) + is(value, 4) + value, err = vm.Run(program) + is(err, nil) + is(value, 6) - program, err = parser.ParseFile(nil, "", "var abc; if (!abc) abc = 0; abc += 2; abc;", 0) - value, err = vm.Run(program) - Is(err, nil) - is(value, 2) - value, err = vm.Run(program) - Is(err, nil) - is(value, 4) - value, err = vm.Run(program) - Is(err, nil) - is(value, 6) + { + src := []byte("var abc; if (!abc) abc = 0; abc += 2; abc;") + value, err = vm.Run(src) + is(err, nil) + is(value, 8) - { - src := []byte("var abc; if (!abc) abc = 0; abc += 2; abc;") - value, err = vm.Run(src) - Is(err, nil) - is(value, 8) + value, err = vm.Run(bytes.NewBuffer(src)) + is(err, nil) + is(value, 10) - value, err = vm.Run(bytes.NewBuffer(src)) - Is(err, nil) - is(value, 10) + value, err = vm.Run(io.Reader(bytes.NewBuffer(src))) + is(err, nil) + is(value, 12) + } - value, err = vm.Run(io.Reader(bytes.NewBuffer(src))) - Is(err, nil) - is(value, 12) - } + { + script, err := vm.Compile("", `var abc; if (!abc) abc = 0; abc += 2; abc;`) + is(err, nil) - { - script, err := vm.Compile("", `var abc; if (!abc) abc = 0; abc += 2; abc;`) - Is(err, nil) + value, err = vm.Run(script) + is(err, nil) + is(value, 14) - value, err = vm.Run(script) - Is(err, nil) - is(value, 14) + value, err = vm.Run(script) + is(err, nil) + is(value, 16) - value, err = vm.Run(script) - Is(err, nil) - is(value, 16) - - Is(script.String(), "// \nvar abc; if (!abc) abc = 0; abc += 2; abc;") - } + is(script.String(), "// \nvar abc; if (!abc) abc = 0; abc += 2; abc;") + } + }) } func Test_objectLength(t *testing.T) { - Terst(t) + tt(t, func() { + _, vm := test() - otto, _ := runTestWithOtto() - value := failSet("abc", []string{"jkl", "mno"}) - Is(objectLength(value._object()), 2) + value := vm.Set("abc", []string{"jkl", "mno"}) + is(objectLength(value._object()), 2) - value, _ = otto.Run(`[1, 2, 3]`) - Is(objectLength(value._object()), 3) + value, _ = vm.Run(`[1, 2, 3]`) + is(objectLength(value._object()), 3) - value, _ = otto.Run(`new String("abcdefghi")`) - Is(objectLength(value._object()), 9) + value, _ = vm.Run(`new String("abcdefghi")`) + is(objectLength(value._object()), 9) - value, _ = otto.Run(`"abcdefghi"`) - Is(objectLength(value._object()), 0) + value, _ = vm.Run(`"abcdefghi"`) + is(objectLength(value._object()), 0) + }) } func BenchmarkNew(b *testing.B) { @@ -1432,25 +1323,9 @@ func BenchmarkNew(b *testing.B) { } func BenchmarkClone(b *testing.B) { - otto := New() + vm := New() b.ResetTimer() for i := 0; i < b.N; i++ { - otto.clone() + vm.clone() } } - -//func BenchmarkNew_(b *testing.B) { -// for i := 0; i < b.N; i++ { -// otto := New() -// otto.Run(underscore.Source()) -// } -//} - -//func BenchmarkClone_(b *testing.B) { -// otto := New() -// otto.Run(underscore.Source()) -// b.ResetTimer() -// for i := 0; i < b.N; i++ { -// otto.clone() -// } -//} diff --git a/panic_test.go b/panic_test.go index 04dffd5..06f0a64 100644 --- a/panic_test.go +++ b/panic_test.go @@ -1,41 +1,40 @@ package otto import ( - . "./terst" "testing" ) func Test_panic(t *testing.T) { - Terst(t) + tt(t, func() { + test, _ := test() - test := runTest() + // Test that property.value is set to something if writable is set + // to something + test(` + var abc = []; + Object.defineProperty(abc, "0", { writable: false }); + Object.defineProperty(abc, "0", { writable: false }); + "0" in abc; + `, true) - // Test that property.value is set to something if writable is set - // to something - test(` - var abc = []; - Object.defineProperty(abc, "0", { writable: false }); - Object.defineProperty(abc, "0", { writable: false }); - "0" in abc; - `, true) + test(`raise: + var abc = []; + Object.defineProperty(abc, "0", { writable: false }); + Object.defineProperty(abc, "0", { value: false, writable: false }); + `, "TypeError") - test(`raise: - var abc = []; - Object.defineProperty(abc, "0", { writable: false }); - Object.defineProperty(abc, "0", { value: false, writable: false }); - `, "TypeError") + // Test that a regular expression can contain \c0410 (CYRILLIC CAPITAL LETTER A) + // without panicking + test(` + var abc = 0x0410; + var def = String.fromCharCode(abc); + new RegExp("\\c" + def).exec(def); + `, "null") - // Test that a regular expression can contain \c0410 (CYRILLIC CAPITAL LETTER A) - // without panicking - test(` - var abc = 0x0410; - var def = String.fromCharCode(abc); - new RegExp("\\c" + def).exec(def); - `, "null") - - // Test transforming a transformable regular expression without a panic - test(` - new RegExp("\\u0000"); - new RegExp("\\undefined").test("undefined"); - `, true) + // Test transforming a transformable regular expression without a panic + test(` + new RegExp("\\u0000"); + new RegExp("\\undefined").test("undefined"); + `, true) + }) } diff --git a/parser/lexer_test.go b/parser/lexer_test.go index 2e4b614..37eb7a4 100644 --- a/parser/lexer_test.go +++ b/parser/lexer_test.go @@ -1,375 +1,380 @@ package parser import ( - . "../terst" + "../terst" "testing" + "github.com/robertkrimen/otto/file" "github.com/robertkrimen/otto/token" ) +var tt = terst.Terst +var is = terst.Is + func TestLexer(t *testing.T) { - Terst(t) + tt(t, func() { + setup := func(src string) *_parser { + parser := newParser("", src) + return parser + } - setup := func(src string) *_parser { - parser := newParser("", src) - return parser - } - - test := func(src string, test ...interface{}) { - parser := setup(src) - for len(test) > 0 { - tkn, literal, idx := parser.scan() - if len(test) > 0 { - Is(tkn, test[0].(token.Token)) - test = test[1:] - } - if len(test) > 0 { - Is(literal, test[0].(string)) - test = test[1:] - } - if len(test) > 0 { - Is(idx, test[0].(int)) - test = test[1:] + test := func(src string, test ...interface{}) { + parser := setup(src) + for len(test) > 0 { + tkn, literal, idx := parser.scan() + if len(test) > 0 { + is(tkn, test[0].(token.Token)) + test = test[1:] + } + if len(test) > 0 { + is(literal, test[0].(string)) + test = test[1:] + } + if len(test) > 0 { + // FIXME terst, Fix this so that cast to file.Idx is not necessary? + is(idx, file.Idx(test[0].(int))) + test = test[1:] + } } } - } - test("", - token.EOF, "", 1, - ) + test("", + token.EOF, "", 1, + ) - test("1", - token.NUMBER, "1", 1, - token.EOF, "", 2, - ) + test("1", + token.NUMBER, "1", 1, + token.EOF, "", 2, + ) - test(".0", - token.NUMBER, ".0", 1, - token.EOF, "", 3, - ) + test(".0", + token.NUMBER, ".0", 1, + token.EOF, "", 3, + ) - test("abc", - token.IDENTIFIER, "abc", 1, - token.EOF, "", 4, - ) + test("abc", + token.IDENTIFIER, "abc", 1, + token.EOF, "", 4, + ) - test("abc(1)", - token.IDENTIFIER, "abc", 1, - token.LEFT_PARENTHESIS, "", 4, - token.NUMBER, "1", 5, - token.RIGHT_PARENTHESIS, "", 6, - token.EOF, "", 7, - ) + test("abc(1)", + token.IDENTIFIER, "abc", 1, + token.LEFT_PARENTHESIS, "", 4, + token.NUMBER, "1", 5, + token.RIGHT_PARENTHESIS, "", 6, + token.EOF, "", 7, + ) - test(".", - token.PERIOD, "", 1, - token.EOF, "", 2, - ) + test(".", + token.PERIOD, "", 1, + token.EOF, "", 2, + ) - test("===.", - token.STRICT_EQUAL, "", 1, - token.PERIOD, "", 4, - token.EOF, "", 5, - ) + test("===.", + token.STRICT_EQUAL, "", 1, + token.PERIOD, "", 4, + token.EOF, "", 5, + ) - test(">>>=.0", - token.UNSIGNED_SHIFT_RIGHT_ASSIGN, "", 1, - token.NUMBER, ".0", 5, - token.EOF, "", 7, - ) + test(">>>=.0", + token.UNSIGNED_SHIFT_RIGHT_ASSIGN, "", 1, + token.NUMBER, ".0", 5, + token.EOF, "", 7, + ) - test(">>>=0.0.", - token.UNSIGNED_SHIFT_RIGHT_ASSIGN, "", 1, - token.NUMBER, "0.0", 5, - token.PERIOD, "", 8, - token.EOF, "", 9, - ) + test(">>>=0.0.", + token.UNSIGNED_SHIFT_RIGHT_ASSIGN, "", 1, + token.NUMBER, "0.0", 5, + token.PERIOD, "", 8, + token.EOF, "", 9, + ) - test("\"abc\"", - token.STRING, "\"abc\"", 1, - token.EOF, "", 6, - ) + test("\"abc\"", + token.STRING, "\"abc\"", 1, + token.EOF, "", 6, + ) - test("abc = //", - token.IDENTIFIER, "abc", 1, - token.ASSIGN, "", 5, - token.EOF, "", 9, - ) + test("abc = //", + token.IDENTIFIER, "abc", 1, + token.ASSIGN, "", 5, + token.EOF, "", 9, + ) - test("abc = 1 / 2", - token.IDENTIFIER, "abc", 1, - token.ASSIGN, "", 5, - token.NUMBER, "1", 7, - token.SLASH, "", 9, - token.NUMBER, "2", 11, - token.EOF, "", 12, - ) + test("abc = 1 / 2", + token.IDENTIFIER, "abc", 1, + token.ASSIGN, "", 5, + token.NUMBER, "1", 7, + token.SLASH, "", 9, + token.NUMBER, "2", 11, + token.EOF, "", 12, + ) - test("xyzzy = 'Nothing happens.'", - token.IDENTIFIER, "xyzzy", 1, - token.ASSIGN, "", 7, - token.STRING, "'Nothing happens.'", 9, - token.EOF, "", 27, - ) + test("xyzzy = 'Nothing happens.'", + token.IDENTIFIER, "xyzzy", 1, + token.ASSIGN, "", 7, + token.STRING, "'Nothing happens.'", 9, + token.EOF, "", 27, + ) - test("abc = !false", - token.IDENTIFIER, "abc", 1, - token.ASSIGN, "", 5, - token.NOT, "", 7, - token.BOOLEAN, "false", 8, - token.EOF, "", 13, - ) + test("abc = !false", + token.IDENTIFIER, "abc", 1, + token.ASSIGN, "", 5, + token.NOT, "", 7, + token.BOOLEAN, "false", 8, + token.EOF, "", 13, + ) - test("abc = !!true", - token.IDENTIFIER, "abc", 1, - token.ASSIGN, "", 5, - token.NOT, "", 7, - token.NOT, "", 8, - token.BOOLEAN, "true", 9, - token.EOF, "", 13, - ) + test("abc = !!true", + token.IDENTIFIER, "abc", 1, + token.ASSIGN, "", 5, + token.NOT, "", 7, + token.NOT, "", 8, + token.BOOLEAN, "true", 9, + token.EOF, "", 13, + ) - test("abc *= 1", - token.IDENTIFIER, "abc", 1, - token.MULTIPLY_ASSIGN, "", 5, - token.NUMBER, "1", 8, - token.EOF, "", 9, - ) + test("abc *= 1", + token.IDENTIFIER, "abc", 1, + token.MULTIPLY_ASSIGN, "", 5, + token.NUMBER, "1", 8, + token.EOF, "", 9, + ) - test("if 1 else", - token.IF, "if", 1, - token.NUMBER, "1", 4, - token.ELSE, "else", 6, - token.EOF, "", 10, - ) + test("if 1 else", + token.IF, "if", 1, + token.NUMBER, "1", 4, + token.ELSE, "else", 6, + token.EOF, "", 10, + ) - test("null", - token.NULL, "null", 1, - token.EOF, "", 5, - ) + test("null", + token.NULL, "null", 1, + token.EOF, "", 5, + ) - test(`"\u007a\x79\u000a\x78"`, - token.STRING, "\"\\u007a\\x79\\u000a\\x78\"", 1, - token.EOF, "", 23, - ) + test(`"\u007a\x79\u000a\x78"`, + token.STRING, "\"\\u007a\\x79\\u000a\\x78\"", 1, + token.EOF, "", 23, + ) - test(`"[First line \ + test(`"[First line \ Second line \ Third line\ . ]" `, - token.STRING, "\"[First line \\\nSecond line \\\n Third line\\\n. ]\"", 1, - token.EOF, "", 53, - ) + token.STRING, "\"[First line \\\nSecond line \\\n Third line\\\n. ]\"", 1, + token.EOF, "", 53, + ) - test("/", - token.SLASH, "", 1, - token.EOF, "", 2, - ) + test("/", + token.SLASH, "", 1, + token.EOF, "", 2, + ) - test("var abc = \"abc\uFFFFabc\"", - token.VAR, "var", 1, - token.IDENTIFIER, "abc", 5, - token.ASSIGN, "", 9, - token.STRING, "\"abc\uFFFFabc\"", 11, - token.EOF, "", 22, - ) + test("var abc = \"abc\uFFFFabc\"", + token.VAR, "var", 1, + token.IDENTIFIER, "abc", 5, + token.ASSIGN, "", 9, + token.STRING, "\"abc\uFFFFabc\"", 11, + token.EOF, "", 22, + ) - test(`'\t' === '\r'`, - token.STRING, "'\\t'", 1, - token.STRICT_EQUAL, "", 6, - token.STRING, "'\\r'", 10, - token.EOF, "", 14, - ) + test(`'\t' === '\r'`, + token.STRING, "'\\t'", 1, + token.STRICT_EQUAL, "", 6, + token.STRING, "'\\r'", 10, + token.EOF, "", 14, + ) - test(`var \u0024 = 1`, - token.VAR, "var", 1, - token.IDENTIFIER, "$", 5, - token.ASSIGN, "", 12, - token.NUMBER, "1", 14, - token.EOF, "", 15, - ) + test(`var \u0024 = 1`, + token.VAR, "var", 1, + token.IDENTIFIER, "$", 5, + token.ASSIGN, "", 12, + token.NUMBER, "1", 14, + token.EOF, "", 15, + ) - test("10e10000", - token.NUMBER, "10e10000", 1, - token.EOF, "", 9, - ) + test("10e10000", + token.NUMBER, "10e10000", 1, + token.EOF, "", 9, + ) - test(`var if var class`, - token.VAR, "var", 1, - token.IF, "if", 5, - token.VAR, "var", 8, - token.KEYWORD, "class", 12, - token.EOF, "", 17, - ) + test(`var if var class`, + token.VAR, "var", 1, + token.IF, "if", 5, + token.VAR, "var", 8, + token.KEYWORD, "class", 12, + token.EOF, "", 17, + ) - test(`-0`, - token.MINUS, "", 1, - token.NUMBER, "0", 2, - token.EOF, "", 3, - ) + test(`-0`, + token.MINUS, "", 1, + token.NUMBER, "0", 2, + token.EOF, "", 3, + ) - test(`.01`, - token.NUMBER, ".01", 1, - token.EOF, "", 4, - ) + test(`.01`, + token.NUMBER, ".01", 1, + token.EOF, "", 4, + ) - test(`.01e+2`, - token.NUMBER, ".01e+2", 1, - token.EOF, "", 7, - ) + test(`.01e+2`, + token.NUMBER, ".01e+2", 1, + token.EOF, "", 7, + ) - test(";", - token.SEMICOLON, "", 1, - token.EOF, "", 2, - ) + test(";", + token.SEMICOLON, "", 1, + token.EOF, "", 2, + ) - test(";;", - token.SEMICOLON, "", 1, - token.SEMICOLON, "", 2, - token.EOF, "", 3, - ) + test(";;", + token.SEMICOLON, "", 1, + token.SEMICOLON, "", 2, + token.EOF, "", 3, + ) - test("//", - token.EOF, "", 3, - ) + test("//", + token.EOF, "", 3, + ) - test(";;//", - token.SEMICOLON, "", 1, - token.SEMICOLON, "", 2, - token.EOF, "", 5, - ) + test(";;//", + token.SEMICOLON, "", 1, + token.SEMICOLON, "", 2, + token.EOF, "", 5, + ) - test("1", - token.NUMBER, "1", 1, - ) + test("1", + token.NUMBER, "1", 1, + ) - test("12 123", - token.NUMBER, "12", 1, - token.NUMBER, "123", 4, - ) + test("12 123", + token.NUMBER, "12", 1, + token.NUMBER, "123", 4, + ) - test("1.2 12.3", - token.NUMBER, "1.2", 1, - token.NUMBER, "12.3", 5, - ) + test("1.2 12.3", + token.NUMBER, "1.2", 1, + token.NUMBER, "12.3", 5, + ) - test("/ /=", - token.SLASH, "", 1, - token.QUOTIENT_ASSIGN, "", 3, - ) + test("/ /=", + token.SLASH, "", 1, + token.QUOTIENT_ASSIGN, "", 3, + ) - test(`"abc"`, - token.STRING, `"abc"`, 1, - ) + test(`"abc"`, + token.STRING, `"abc"`, 1, + ) - test(`'abc'`, - token.STRING, `'abc'`, 1, - ) + test(`'abc'`, + token.STRING, `'abc'`, 1, + ) - test("++", - token.INCREMENT, "", 1, - ) + test("++", + token.INCREMENT, "", 1, + ) - test(">", - token.GREATER, "", 1, - ) + test(">", + token.GREATER, "", 1, + ) - test(">=", - token.GREATER_OR_EQUAL, "", 1, - ) + test(">=", + token.GREATER_OR_EQUAL, "", 1, + ) - test(">>", - token.SHIFT_RIGHT, "", 1, - ) + test(">>", + token.SHIFT_RIGHT, "", 1, + ) - test(">>=", - token.SHIFT_RIGHT_ASSIGN, "", 1, - ) + test(">>=", + token.SHIFT_RIGHT_ASSIGN, "", 1, + ) - test(">>>", - token.UNSIGNED_SHIFT_RIGHT, "", 1, - ) + test(">>>", + token.UNSIGNED_SHIFT_RIGHT, "", 1, + ) - test(">>>=", - token.UNSIGNED_SHIFT_RIGHT_ASSIGN, "", 1, - ) + test(">>>=", + token.UNSIGNED_SHIFT_RIGHT_ASSIGN, "", 1, + ) - test("1 \"abc\"", - token.NUMBER, "1", 1, - token.STRING, "\"abc\"", 3, - ) + test("1 \"abc\"", + token.NUMBER, "1", 1, + token.STRING, "\"abc\"", 3, + ) - test(",", - token.COMMA, "", 1, - ) + test(",", + token.COMMA, "", 1, + ) - test("1, \"abc\"", - token.NUMBER, "1", 1, - token.COMMA, "", 2, - token.STRING, "\"abc\"", 4, - ) + test("1, \"abc\"", + token.NUMBER, "1", 1, + token.COMMA, "", 2, + token.STRING, "\"abc\"", 4, + ) - test("new abc(1, 3.14159);", - token.NEW, "new", 1, - token.IDENTIFIER, "abc", 5, - token.LEFT_PARENTHESIS, "", 8, - token.NUMBER, "1", 9, - token.COMMA, "", 10, - token.NUMBER, "3.14159", 12, - token.RIGHT_PARENTHESIS, "", 19, - token.SEMICOLON, "", 20, - ) + test("new abc(1, 3.14159);", + token.NEW, "new", 1, + token.IDENTIFIER, "abc", 5, + token.LEFT_PARENTHESIS, "", 8, + token.NUMBER, "1", 9, + token.COMMA, "", 10, + token.NUMBER, "3.14159", 12, + token.RIGHT_PARENTHESIS, "", 19, + token.SEMICOLON, "", 20, + ) - test("1 == \"1\"", - token.NUMBER, "1", 1, - token.EQUAL, "", 3, - token.STRING, "\"1\"", 6, - ) + test("1 == \"1\"", + token.NUMBER, "1", 1, + token.EQUAL, "", 3, + token.STRING, "\"1\"", 6, + ) - test("1\n[]\n", - token.NUMBER, "1", 1, - token.LEFT_BRACKET, "", 3, - token.RIGHT_BRACKET, "", 4, - ) + test("1\n[]\n", + token.NUMBER, "1", 1, + token.LEFT_BRACKET, "", 3, + token.RIGHT_BRACKET, "", 4, + ) - test("1\ufeff[]\ufeff", - token.NUMBER, "1", 1, - token.LEFT_BRACKET, "", 5, - token.RIGHT_BRACKET, "", 6, - ) + test("1\ufeff[]\ufeff", + token.NUMBER, "1", 1, + token.LEFT_BRACKET, "", 5, + token.RIGHT_BRACKET, "", 6, + ) - // ILLEGAL + // ILLEGAL - test(`3ea`, - token.ILLEGAL, "3e", 1, - token.IDENTIFIER, "a", 3, - token.EOF, "", 4, - ) + test(`3ea`, + token.ILLEGAL, "3e", 1, + token.IDENTIFIER, "a", 3, + token.EOF, "", 4, + ) - test(`3in`, - token.ILLEGAL, "3", 1, - token.IN, "in", 2, - token.EOF, "", 4, - ) + test(`3in`, + token.ILLEGAL, "3", 1, + token.IN, "in", 2, + token.EOF, "", 4, + ) - test("\"Hello\nWorld\"", - token.ILLEGAL, "", 1, - token.IDENTIFIER, "World", 8, - token.ILLEGAL, "", 13, - token.EOF, "", 14, - ) + test("\"Hello\nWorld\"", + token.ILLEGAL, "", 1, + token.IDENTIFIER, "World", 8, + token.ILLEGAL, "", 13, + token.EOF, "", 14, + ) - test("\u203f = 10", - token.ILLEGAL, "", 1, - token.ASSIGN, "", 5, - token.NUMBER, "10", 7, - token.EOF, "", 9, - ) + test("\u203f = 10", + token.ILLEGAL, "", 1, + token.ASSIGN, "", 5, + token.NUMBER, "10", 7, + token.EOF, "", 9, + ) - test(`"\x0G"`, - token.STRING, "\"\\x0G\"", 1, - token.EOF, "", 7, - ) + test(`"\x0G"`, + token.STRING, "\"\\x0G\"", 1, + token.EOF, "", 7, + ) + }) } diff --git a/parser/marshal_test.go b/parser/marshal_test.go index dbb67f3..f54cd2d 100644 --- a/parser/marshal_test.go +++ b/parser/marshal_test.go @@ -1,7 +1,6 @@ package parser import ( - . "../terst" "bytes" "encoding/json" "fmt" @@ -13,7 +12,6 @@ import ( "github.com/robertkrimen/otto/ast" ) -//func marshal(name string, children ...interface{}) map[string]interface{} { func marshal(name string, children ...interface{}) interface{} { if len(children) == 1 { if name == "" { @@ -194,47 +192,47 @@ func testMarshal(node interface{}) string { } func TestParserAST(t *testing.T) { - Terst(t) + tt(t, func() { - test := func(inputOutput string) { - match := matchBeforeAfterSeparator.FindStringIndex(inputOutput) - input := strings.TrimSpace(inputOutput[0:match[0]]) - wantOutput := strings.TrimSpace(inputOutput[match[1]:]) - _, program, err := testParse(input) - Is(err, nil) - haveOutput := testMarshal(program) - tmp0, tmp1 := bytes.Buffer{}, bytes.Buffer{} - json.Indent(&tmp0, []byte(haveOutput), "\t\t", " ") - json.Indent(&tmp1, []byte(wantOutput), "\t\t", " ") - Is("\n\t\t"+tmp0.String(), "\n\t\t"+tmp1.String()) - } + test := func(inputOutput string) { + match := matchBeforeAfterSeparator.FindStringIndex(inputOutput) + input := strings.TrimSpace(inputOutput[0:match[0]]) + wantOutput := strings.TrimSpace(inputOutput[match[1]:]) + _, program, err := testParse(input) + is(err, nil) + haveOutput := testMarshal(program) + tmp0, tmp1 := bytes.Buffer{}, bytes.Buffer{} + json.Indent(&tmp0, []byte(haveOutput), "\t\t", " ") + json.Indent(&tmp1, []byte(wantOutput), "\t\t", " ") + is("\n\t\t"+tmp0.String(), "\n\t\t"+tmp1.String()) + } - test(` - --- + test(` + --- [] - `) + `) - test(` - ; - --- + test(` + ; + --- [ "EmptyStatement" ] - `) + `) - test(` - ;;; - --- + test(` + ;;; + --- [ "EmptyStatement", "EmptyStatement", "EmptyStatement" ] - `) + `) - test(` - 1; true; abc; "abc"; null; - --- + test(` + 1; true; abc; "abc"; null; + --- [ { "Literal": 1 @@ -252,11 +250,11 @@ func TestParserAST(t *testing.T) { "Literal": null } ] - `) + `) - test(` - { 1; null; 3.14159; ; } - --- + test(` + { 1; null; 3.14159; ; } + --- [ { "BlockStatement": [ @@ -273,11 +271,11 @@ func TestParserAST(t *testing.T) { ] } ] - `) + `) - test(` - new abc(); - --- + test(` + new abc(); + --- [ { "New": { @@ -288,11 +286,11 @@ func TestParserAST(t *testing.T) { } } ] - `) + `) - test(` - new abc(1, 3.14159) - --- + test(` + new abc(1, 3.14159) + --- [ { "New": { @@ -310,11 +308,11 @@ func TestParserAST(t *testing.T) { } } ] - `) + `) - test(` - true ? false : true - --- + test(` + true ? false : true + --- [ { "Conditional": { @@ -330,11 +328,11 @@ func TestParserAST(t *testing.T) { } } ] - `) + `) - test(` - true || false - --- + test(` + true || false + --- [ { "BinaryExpression": { @@ -348,11 +346,11 @@ func TestParserAST(t *testing.T) { } } ] - `) + `) - test(` - 0 + { abc: true } - --- + test(` + 0 + { abc: true } + --- [ { "BinaryExpression": { @@ -373,11 +371,11 @@ func TestParserAST(t *testing.T) { } } ] - `) + `) - test(` - 1 == "1" - --- + test(` + 1 == "1" + --- [ { "BinaryExpression": { @@ -391,11 +389,11 @@ func TestParserAST(t *testing.T) { } } ] - `) + `) - test(` - abc(1) - --- + test(` + abc(1) + --- [ { "Call": { @@ -410,10 +408,11 @@ func TestParserAST(t *testing.T) { } } ] - `) - test(` - Math.pow(3, 2) - --- + `) + + test(` + Math.pow(3, 2) + --- [ { "Call": { @@ -436,11 +435,11 @@ func TestParserAST(t *testing.T) { } } ] - `) + `) - test(` - 1, 2, 3 - --- + test(` + 1, 2, 3 + --- [ { "Sequence": [ @@ -456,22 +455,22 @@ func TestParserAST(t *testing.T) { ] } ] - `) + `) - test(` - / abc / gim; - --- + test(` + / abc / gim; + --- [ { "Literal": "/ abc / gim" } ] - `) + `) - test(` - if (0) - 1; - --- + test(` + if (0) + 1; + --- [ { "If": { @@ -484,13 +483,13 @@ func TestParserAST(t *testing.T) { } } ] - `) + `) - test(` - 0+function(){ - return; - } - --- + test(` + 0+function(){ + return; + } + --- [ { "BinaryExpression": { @@ -510,21 +509,21 @@ func TestParserAST(t *testing.T) { } } ] - `) + `) - test(` - xyzzy // Ignore it - // Ignore this - // And this - /* And all.. + test(` + xyzzy // Ignore it + // Ignore this + // And this + /* And all.. - ... of this! - */ - "Nothing happens." - // And finally this - --- + ... of this! + */ + "Nothing happens." + // And finally this + --- [ { "Identifier": "xyzzy" @@ -533,11 +532,11 @@ func TestParserAST(t *testing.T) { "Literal": "\"Nothing happens.\"" } ] - `) + `) - test(` - ((x & (x = 1)) !== 0) - --- + test(` + ((x & (x = 1)) !== 0) + --- [ { "BinaryExpression": { @@ -566,11 +565,11 @@ func TestParserAST(t *testing.T) { } } ] - `) + `) - test(` - { abc: 'def' } - --- + test(` + { abc: 'def' } + --- [ { "BlockStatement": [ @@ -585,12 +584,12 @@ func TestParserAST(t *testing.T) { ] } ] - `) + `) - test(` - // This is not an object, this is a string literal with a label! - ({ abc: 'def' }) - --- + test(` + // This is not an object, this is a string literal with a label! + ({ abc: 'def' }) + --- [ { "Object": [ @@ -603,11 +602,11 @@ func TestParserAST(t *testing.T) { ] } ] - `) + `) - test(` - [,] - --- + test(` + [,] + --- [ { "Array": [ @@ -615,11 +614,11 @@ func TestParserAST(t *testing.T) { ] } ] - `) + `) - test(` - [,,] - --- + test(` + [,,] + --- [ { "Array": [ @@ -628,11 +627,11 @@ func TestParserAST(t *testing.T) { ] } ] - `) + `) - test(` - ({ get abc() {} }) - --- + test(` + ({ get abc() {} }) + --- [ { "Object": [ @@ -647,11 +646,11 @@ func TestParserAST(t *testing.T) { ] } ] - `) + `) - test(` - /abc/.source - --- + test(` + /abc/.source + --- [ { "Dot": { @@ -662,13 +661,13 @@ func TestParserAST(t *testing.T) { } } ] - `) + `) - test(` - xyzzy + test(` + xyzzy - throw new TypeError("Nothing happens.") - --- + throw new TypeError("Nothing happens.") + --- [ { "Identifier": "xyzzy" @@ -690,16 +689,16 @@ func TestParserAST(t *testing.T) { ] `) - // When run, this will call a type error to be thrown - // This is essentially the same as: - // - // var abc = 1(function(){})() - // - test(` - var abc = 1 - (function(){ - })() - --- + // When run, this will call a type error to be thrown + // This is essentially the same as: + // + // var abc = 1(function(){})() + // + test(` + var abc = 1 + (function(){ + })() + --- [ { "Var": [ @@ -728,22 +727,22 @@ func TestParserAST(t *testing.T) { ] } ] - `) + `) - test(` - "use strict" - --- + test(` + "use strict" + --- [ { "Literal": "\"use strict\"" } ] - `) + `) - test(` - "use strict" - abc = 1 + 2 + 11 - --- + test(` + "use strict" + abc = 1 + 2 + 11 + --- [ { "Literal": "\"use strict\"" @@ -775,11 +774,11 @@ func TestParserAST(t *testing.T) { } } ] - `) + `) - test(` - abc = function() { 'use strict' } - --- + test(` + abc = function() { 'use strict' } + --- [ { "Assign": { @@ -798,12 +797,12 @@ func TestParserAST(t *testing.T) { } } ] - `) + `) - test(` - for (var abc in def) { - } - --- + test(` + for (var abc in def) { + } + --- [ { "ForIn": { @@ -820,14 +819,14 @@ func TestParserAST(t *testing.T) { } } ] - `) + `) - test(` - abc = { - '"': "'", - "'": '"', - } - --- + test(` + abc = { + '"': "'", + "'": '"', + } + --- [ { "Assign": { @@ -853,14 +852,14 @@ func TestParserAST(t *testing.T) { } } ] - `) + `) - return + return - test(` - if (!abc && abc.jkl(def) && abc[0] === +abc[0] && abc.length < ghi) { - } - --- + test(` + if (!abc && abc.jkl(def) && abc[0] === +abc[0] && abc.length < ghi) { + } + --- [ { "If": { @@ -926,5 +925,6 @@ func TestParserAST(t *testing.T) { } } ] - `) + `) + }) } diff --git a/parser/parser_test.go b/parser/parser_test.go index adabb06..8f94577 100644 --- a/parser/parser_test.go +++ b/parser/parser_test.go @@ -1,13 +1,13 @@ package parser import ( - . "../terst" "errors" "regexp" "strings" "testing" "github.com/robertkrimen/otto/ast" + "github.com/robertkrimen/otto/file" ) func firstErr(err error) error { @@ -41,965 +41,964 @@ func testParse(src string) (parser *_parser, program *ast.Program, err error) { } func TestParseFile(t *testing.T) { - Terst(t) + tt(t, func() { + _, err := ParseFile(nil, "", `/abc/`, 0) + is(err, nil) - _, err := ParseFile(nil, "", `/abc/`, 0) - Is(err, nil) + _, err = ParseFile(nil, "", `/(?!def)abc/`, IgnoreRegExpErrors) + is(err, nil) - _, err = ParseFile(nil, "", `/(?!def)abc/`, IgnoreRegExpErrors) - Is(err, nil) + _, err = ParseFile(nil, "", `/(?!def)abc/`, 0) + is(err, "(anonymous): Line 1:1 Invalid regular expression: re2: Invalid (?!) ") - _, err = ParseFile(nil, "", `/(?!def)abc/`, 0) - Is(err, "(anonymous): Line 1:1 Invalid regular expression: re2: Invalid (?!) ") - - _, err = ParseFile(nil, "", `/(?!def)abc/; return`, IgnoreRegExpErrors) - Is(err, "(anonymous): Line 1:15 Illegal return statement") + _, err = ParseFile(nil, "", `/(?!def)abc/; return`, IgnoreRegExpErrors) + is(err, "(anonymous): Line 1:15 Illegal return statement") + }) } func TestParseFunction(t *testing.T) { - Terst(t) + tt(t, func() { + test := func(prm, bdy string, expect interface{}) *ast.FunctionLiteral { + function, err := ParseFunction(prm, bdy) + is(firstErr(err), expect) + return function + } - test := func(prm, bdy string, expect interface{}) *ast.FunctionLiteral { - function, err := ParseFunction(prm, bdy) - Is(firstErr(err), expect) - return function - } + test("a, b,c,d", "", nil) - test("a, b,c,d", "", nil) + test("a, b;,c,d", "", "(anonymous): Line 1:15 Unexpected token ;") - test("a, b;,c,d", "", "(anonymous): Line 1:15 Unexpected token ;") + test("this", "", "(anonymous): Line 1:11 Unexpected token this") - test("this", "", "(anonymous): Line 1:11 Unexpected token this") + test("a, b, c, null", "", "(anonymous): Line 1:20 Unexpected token null") - test("a, b, c, null", "", "(anonymous): Line 1:20 Unexpected token null") + test("a, b,c,d", "return;", nil) - test("a, b,c,d", "return;", nil) + test("a, b,c,d", "break;", "(anonymous): Line 2:1 Illegal break statement") - test("a, b,c,d", "break;", "(anonymous): Line 2:1 Illegal break statement") - - test("a, b,c,d", "{}", nil) + test("a, b,c,d", "{}", nil) + }) } func TestParserErr(t *testing.T) { - Terst(t) + tt(t, func() { + test := func(input string, expect interface{}) (*ast.Program, *_parser) { + parser := newParser("", input) + program, err := parser.parse() + is(firstErr(err), expect) + return program, parser + } - test := func(input string, expect interface{}) (*ast.Program, *_parser) { - parser := newParser("", input) - program, err := parser.parse() - Is(firstErr(err), expect) - return program, parser - } + program, parser := test("", nil) - program, parser := test("", nil) - - program, parser = test(` + program, parser = test(` var abc; break; do { } while(true); `, "(anonymous): Line 3:9 Illegal break statement") - { - stmt := program.Body[1].(*ast.BadStatement) - Is(parser.position(stmt.From).Column, 9) - Is(parser.position(stmt.To).Column, 16) - Is(parser.slice(stmt.From, stmt.To), "break; ") - } + { + stmt := program.Body[1].(*ast.BadStatement) + is(parser.position(stmt.From).Column, 9) + is(parser.position(stmt.To).Column, 16) + is(parser.slice(stmt.From, stmt.To), "break; ") + } - test("{", "(anonymous): Line 1:2 Unexpected end of input") + test("{", "(anonymous): Line 1:2 Unexpected end of input") - test("}", "(anonymous): Line 1:1 Unexpected token }") + test("}", "(anonymous): Line 1:1 Unexpected token }") - test("3ea", "(anonymous): Line 1:1 Unexpected token ILLEGAL") + test("3ea", "(anonymous): Line 1:1 Unexpected token ILLEGAL") - test("3in", "(anonymous): Line 1:1 Unexpected token ILLEGAL") + test("3in", "(anonymous): Line 1:1 Unexpected token ILLEGAL") - test("3in []", "(anonymous): Line 1:1 Unexpected token ILLEGAL") + test("3in []", "(anonymous): Line 1:1 Unexpected token ILLEGAL") - test("3e", "(anonymous): Line 1:1 Unexpected token ILLEGAL") + test("3e", "(anonymous): Line 1:1 Unexpected token ILLEGAL") - test("3e+", "(anonymous): Line 1:1 Unexpected token ILLEGAL") + test("3e+", "(anonymous): Line 1:1 Unexpected token ILLEGAL") - test("3e-", "(anonymous): Line 1:1 Unexpected token ILLEGAL") + test("3e-", "(anonymous): Line 1:1 Unexpected token ILLEGAL") - test("3x", "(anonymous): Line 1:1 Unexpected token ILLEGAL") + test("3x", "(anonymous): Line 1:1 Unexpected token ILLEGAL") - test("3x0", "(anonymous): Line 1:1 Unexpected token ILLEGAL") + test("3x0", "(anonymous): Line 1:1 Unexpected token ILLEGAL") - test("0x", "(anonymous): Line 1:1 Unexpected token ILLEGAL") + test("0x", "(anonymous): Line 1:1 Unexpected token ILLEGAL") - test("09", "(anonymous): Line 1:1 Unexpected token ILLEGAL") + test("09", "(anonymous): Line 1:1 Unexpected token ILLEGAL") - test("018", "(anonymous): Line 1:1 Unexpected token ILLEGAL") + test("018", "(anonymous): Line 1:1 Unexpected token ILLEGAL") - test("01.0", "(anonymous): Line 1:3 Unexpected number") + test("01.0", "(anonymous): Line 1:3 Unexpected number") - test("01a", "(anonymous): Line 1:1 Unexpected token ILLEGAL") + test("01a", "(anonymous): Line 1:1 Unexpected token ILLEGAL") - test("0x3in[]", "(anonymous): Line 1:1 Unexpected token ILLEGAL") + test("0x3in[]", "(anonymous): Line 1:1 Unexpected token ILLEGAL") - test("\"Hello\nWorld\"", "(anonymous): Line 1:1 Unexpected token ILLEGAL") + test("\"Hello\nWorld\"", "(anonymous): Line 1:1 Unexpected token ILLEGAL") - test("\u203f = 10", "(anonymous): Line 1:1 Unexpected token ILLEGAL") + test("\u203f = 10", "(anonymous): Line 1:1 Unexpected token ILLEGAL") - test("x\\", "(anonymous): Line 1:1 Unexpected token ILLEGAL") + test("x\\", "(anonymous): Line 1:1 Unexpected token ILLEGAL") - test("x\\\\", "(anonymous): Line 1:1 Unexpected token ILLEGAL") + test("x\\\\", "(anonymous): Line 1:1 Unexpected token ILLEGAL") - test("x\\u005c", "(anonymous): Line 1:1 Unexpected token ILLEGAL") + test("x\\u005c", "(anonymous): Line 1:1 Unexpected token ILLEGAL") - test("x\\u002a", "(anonymous): Line 1:1 Unexpected token ILLEGAL") + test("x\\u002a", "(anonymous): Line 1:1 Unexpected token ILLEGAL") - test("x\\\\u002a", "(anonymous): Line 1:1 Unexpected token ILLEGAL") + test("x\\\\u002a", "(anonymous): Line 1:1 Unexpected token ILLEGAL") - test("/\n", "(anonymous): Line 1:1 Invalid regular expression: missing /") + test("/\n", "(anonymous): Line 1:1 Invalid regular expression: missing /") - test("var x = /(s/g", "(anonymous): Line 1:9 Invalid regular expression: Unterminated group") + test("var x = /(s/g", "(anonymous): Line 1:9 Invalid regular expression: Unterminated group") - test("0 = 1", "(anonymous): Line 1:1 Invalid left-hand side in assignment") + test("0 = 1", "(anonymous): Line 1:1 Invalid left-hand side in assignment") - test("func() = 1", "(anonymous): Line 1:1 Invalid left-hand side in assignment") + test("func() = 1", "(anonymous): Line 1:1 Invalid left-hand side in assignment") - test("(1 + 1) = 2", "(anonymous): Line 1:2 Invalid left-hand side in assignment") + test("(1 + 1) = 2", "(anonymous): Line 1:2 Invalid left-hand side in assignment") - test("1++", "(anonymous): Line 1:2 Invalid left-hand side in assignment") + test("1++", "(anonymous): Line 1:2 Invalid left-hand side in assignment") - test("1--", "(anonymous): Line 1:2 Invalid left-hand side in assignment") + test("1--", "(anonymous): Line 1:2 Invalid left-hand side in assignment") - test("--1", "(anonymous): Line 1:1 Invalid left-hand side in assignment") + test("--1", "(anonymous): Line 1:1 Invalid left-hand side in assignment") - test("for((1 + 1) in abc) def();", "(anonymous): Line 1:1 Invalid left-hand side in for-in") + test("for((1 + 1) in abc) def();", "(anonymous): Line 1:1 Invalid left-hand side in for-in") - test("[", "(anonymous): Line 1:2 Unexpected end of input") + test("[", "(anonymous): Line 1:2 Unexpected end of input") - test("[,", "(anonymous): Line 1:3 Unexpected end of input") + test("[,", "(anonymous): Line 1:3 Unexpected end of input") - test("1 + {", "(anonymous): Line 1:6 Unexpected end of input") + test("1 + {", "(anonymous): Line 1:6 Unexpected end of input") - test("1 + { abc:abc", "(anonymous): Line 1:14 Unexpected end of input") + test("1 + { abc:abc", "(anonymous): Line 1:14 Unexpected end of input") - test("1 + { abc:abc,", "(anonymous): Line 1:15 Unexpected end of input") + test("1 + { abc:abc,", "(anonymous): Line 1:15 Unexpected end of input") - test("var abc = /\n/", "(anonymous): Line 1:11 Invalid regular expression: missing /") + test("var abc = /\n/", "(anonymous): Line 1:11 Invalid regular expression: missing /") - test("var abc = \"\n", "(anonymous): Line 1:11 Unexpected token ILLEGAL") + test("var abc = \"\n", "(anonymous): Line 1:11 Unexpected token ILLEGAL") - test("var if = 0", "(anonymous): Line 1:5 Unexpected token if") + test("var if = 0", "(anonymous): Line 1:5 Unexpected token if") - test("abc + 0 = 1", "(anonymous): Line 1:1 Invalid left-hand side in assignment") + test("abc + 0 = 1", "(anonymous): Line 1:1 Invalid left-hand side in assignment") - test("+abc = 1", "(anonymous): Line 1:1 Invalid left-hand side in assignment") + test("+abc = 1", "(anonymous): Line 1:1 Invalid left-hand side in assignment") - test("1 + (", "(anonymous): Line 1:6 Unexpected end of input") + test("1 + (", "(anonymous): Line 1:6 Unexpected end of input") - test("\n\n\n{", "(anonymous): Line 4:2 Unexpected end of input") + test("\n\n\n{", "(anonymous): Line 4:2 Unexpected end of input") - test("\n/* Some multiline\ncomment */\n)", "(anonymous): Line 4:1 Unexpected token )") + test("\n/* Some multiline\ncomment */\n)", "(anonymous): Line 4:1 Unexpected token )") - // TODO - //{ set 1 } - //{ get 2 } - //({ set: s(if) { } }) - //({ set s(.) { } }) - //({ set: s() { } }) - //({ set: s(a, b) { } }) - //({ get: g(d) { } }) - //({ get i() { }, i: 42 }) - //({ i: 42, get i() { } }) - //({ set i(x) { }, i: 42 }) - //({ i: 42, set i(x) { } }) - //({ get i() { }, get i() { } }) - //({ set i(x) { }, set i(x) { } }) + // TODO + //{ set 1 } + //{ get 2 } + //({ set: s(if) { } }) + //({ set s(.) { } }) + //({ set: s() { } }) + //({ set: s(a, b) { } }) + //({ get: g(d) { } }) + //({ get i() { }, i: 42 }) + //({ i: 42, get i() { } }) + //({ set i(x) { }, i: 42 }) + //({ i: 42, set i(x) { } }) + //({ get i() { }, get i() { } }) + //({ set i(x) { }, set i(x) { } }) - test("function abc(if) {}", "(anonymous): Line 1:14 Unexpected token if") + test("function abc(if) {}", "(anonymous): Line 1:14 Unexpected token if") - test("function abc(true) {}", "(anonymous): Line 1:14 Unexpected token true") + test("function abc(true) {}", "(anonymous): Line 1:14 Unexpected token true") - test("function abc(false) {}", "(anonymous): Line 1:14 Unexpected token false") + test("function abc(false) {}", "(anonymous): Line 1:14 Unexpected token false") - test("function abc(null) {}", "(anonymous): Line 1:14 Unexpected token null") + test("function abc(null) {}", "(anonymous): Line 1:14 Unexpected token null") - test("function null() {}", "(anonymous): Line 1:10 Unexpected token null") + test("function null() {}", "(anonymous): Line 1:10 Unexpected token null") - test("function true() {}", "(anonymous): Line 1:10 Unexpected token true") + test("function true() {}", "(anonymous): Line 1:10 Unexpected token true") - test("function false() {}", "(anonymous): Line 1:10 Unexpected token false") + test("function false() {}", "(anonymous): Line 1:10 Unexpected token false") - test("function if() {}", "(anonymous): Line 1:10 Unexpected token if") + test("function if() {}", "(anonymous): Line 1:10 Unexpected token if") - test("a b;", "(anonymous): Line 1:3 Unexpected identifier") + test("a b;", "(anonymous): Line 1:3 Unexpected identifier") - test("if.a", "(anonymous): Line 1:3 Unexpected token .") + test("if.a", "(anonymous): Line 1:3 Unexpected token .") - test("a if", "(anonymous): Line 1:3 Unexpected token if") + test("a if", "(anonymous): Line 1:3 Unexpected token if") - test("a class", "(anonymous): Line 1:3 Unexpected reserved word") + test("a class", "(anonymous): Line 1:3 Unexpected reserved word") - test("break\n", "(anonymous): Line 1:1 Illegal break statement") + test("break\n", "(anonymous): Line 1:1 Illegal break statement") - test("break 1;", "(anonymous): Line 1:7 Unexpected number") + test("break 1;", "(anonymous): Line 1:7 Unexpected number") - test("for (;;) { break 1; }", "(anonymous): Line 1:18 Unexpected number") + test("for (;;) { break 1; }", "(anonymous): Line 1:18 Unexpected number") - test("continue\n", "(anonymous): Line 1:1 Illegal continue statement") + test("continue\n", "(anonymous): Line 1:1 Illegal continue statement") - test("continue 1;", "(anonymous): Line 1:10 Unexpected number") + test("continue 1;", "(anonymous): Line 1:10 Unexpected number") - test("for (;;) { continue 1; }", "(anonymous): Line 1:21 Unexpected number") + test("for (;;) { continue 1; }", "(anonymous): Line 1:21 Unexpected number") - test("throw", "(anonymous): Line 1:1 Unexpected end of input") + test("throw", "(anonymous): Line 1:1 Unexpected end of input") - test("throw;", "(anonymous): Line 1:6 Unexpected token ;") + test("throw;", "(anonymous): Line 1:6 Unexpected token ;") - test("throw \n", "(anonymous): Line 1:1 Unexpected end of input") + test("throw \n", "(anonymous): Line 1:1 Unexpected end of input") - test("for (var abc, def in {});", "(anonymous): Line 1:19 Unexpected token in") + test("for (var abc, def in {});", "(anonymous): Line 1:19 Unexpected token in") - test("for ((abc in {});;);", nil) + test("for ((abc in {});;);", nil) - test("for ((abc in {}));", "(anonymous): Line 1:17 Unexpected token )") + test("for ((abc in {}));", "(anonymous): Line 1:17 Unexpected token )") - test("for (+abc in {});", "(anonymous): Line 1:1 Invalid left-hand side in for-in") + test("for (+abc in {});", "(anonymous): Line 1:1 Invalid left-hand side in for-in") - test("if (false)", "(anonymous): Line 1:11 Unexpected end of input") + test("if (false)", "(anonymous): Line 1:11 Unexpected end of input") - test("if (false) abc(); else", "(anonymous): Line 1:23 Unexpected end of input") + test("if (false) abc(); else", "(anonymous): Line 1:23 Unexpected end of input") - test("do", "(anonymous): Line 1:3 Unexpected end of input") + test("do", "(anonymous): Line 1:3 Unexpected end of input") - test("while (false)", "(anonymous): Line 1:14 Unexpected end of input") + test("while (false)", "(anonymous): Line 1:14 Unexpected end of input") - test("for (;;)", "(anonymous): Line 1:9 Unexpected end of input") + test("for (;;)", "(anonymous): Line 1:9 Unexpected end of input") - test("with (abc)", "(anonymous): Line 1:11 Unexpected end of input") + test("with (abc)", "(anonymous): Line 1:11 Unexpected end of input") - test("try {}", "(anonymous): Line 1:1 Missing catch or finally after try") + test("try {}", "(anonymous): Line 1:1 Missing catch or finally after try") - test("try {} catch {}", "(anonymous): Line 1:14 Unexpected token {") + test("try {} catch {}", "(anonymous): Line 1:14 Unexpected token {") - test("try {} catch () {}", "(anonymous): Line 1:15 Unexpected token )") + test("try {} catch () {}", "(anonymous): Line 1:15 Unexpected token )") - test("\u203f = 1", "(anonymous): Line 1:1 Unexpected token ILLEGAL") + test("\u203f = 1", "(anonymous): Line 1:1 Unexpected token ILLEGAL") - // TODO - // const x = 12, y; - // const x, y = 12; - // const x; - // if(true) let a = 1; - // if(true) const a = 1; + // TODO + // const x = 12, y; + // const x, y = 12; + // const x; + // if(true) let a = 1; + // if(true) const a = 1; - test(`new abc()."def"`, "(anonymous): Line 1:11 Unexpected string") + test(`new abc()."def"`, "(anonymous): Line 1:11 Unexpected string") - test("/*", "(anonymous): Line 1:3 Unexpected end of input") + test("/*", "(anonymous): Line 1:3 Unexpected end of input") - test("/**", "(anonymous): Line 1:4 Unexpected end of input") + test("/**", "(anonymous): Line 1:4 Unexpected end of input") - test("/*\n\n\n", "(anonymous): Line 4:1 Unexpected end of input") + test("/*\n\n\n", "(anonymous): Line 4:1 Unexpected end of input") - test("/*\n\n\n*", "(anonymous): Line 4:2 Unexpected end of input") + test("/*\n\n\n*", "(anonymous): Line 4:2 Unexpected end of input") - test("/*abc", "(anonymous): Line 1:6 Unexpected end of input") + test("/*abc", "(anonymous): Line 1:6 Unexpected end of input") - test("/*abc *", "(anonymous): Line 1:9 Unexpected end of input") + test("/*abc *", "(anonymous): Line 1:9 Unexpected end of input") - test("\n]", "(anonymous): Line 2:1 Unexpected token ]") + test("\n]", "(anonymous): Line 2:1 Unexpected token ]") - test("\r\n]", "(anonymous): Line 2:1 Unexpected token ]") + test("\r\n]", "(anonymous): Line 2:1 Unexpected token ]") - test("\n\r]", "(anonymous): Line 3:1 Unexpected token ]") + test("\n\r]", "(anonymous): Line 3:1 Unexpected token ]") - test("//\r\n]", "(anonymous): Line 2:1 Unexpected token ]") + test("//\r\n]", "(anonymous): Line 2:1 Unexpected token ]") - test("//\n\r]", "(anonymous): Line 3:1 Unexpected token ]") + test("//\n\r]", "(anonymous): Line 3:1 Unexpected token ]") - test("/abc\\\n/", "(anonymous): Line 1:1 Invalid regular expression: missing /") + test("/abc\\\n/", "(anonymous): Line 1:1 Invalid regular expression: missing /") - test("//\r \n]", "(anonymous): Line 3:1 Unexpected token ]") + test("//\r \n]", "(anonymous): Line 3:1 Unexpected token ]") - test("/*\r\n*/]", "(anonymous): Line 2:3 Unexpected token ]") + test("/*\r\n*/]", "(anonymous): Line 2:3 Unexpected token ]") - test("/*\r \n*/]", "(anonymous): Line 3:3 Unexpected token ]") + test("/*\r \n*/]", "(anonymous): Line 3:3 Unexpected token ]") - test("\\\\", "(anonymous): Line 1:1 Unexpected token ILLEGAL") + test("\\\\", "(anonymous): Line 1:1 Unexpected token ILLEGAL") - test("\\u005c", "(anonymous): Line 1:1 Unexpected token ILLEGAL") + test("\\u005c", "(anonymous): Line 1:1 Unexpected token ILLEGAL") - test("\\abc", "(anonymous): Line 1:1 Unexpected token ILLEGAL") + test("\\abc", "(anonymous): Line 1:1 Unexpected token ILLEGAL") - test("\\u0000", "(anonymous): Line 1:1 Unexpected token ILLEGAL") + test("\\u0000", "(anonymous): Line 1:1 Unexpected token ILLEGAL") - test("\\u200c = []", "(anonymous): Line 1:1 Unexpected token ILLEGAL") + test("\\u200c = []", "(anonymous): Line 1:1 Unexpected token ILLEGAL") - test("\\u200D = []", "(anonymous): Line 1:1 Unexpected token ILLEGAL") + test("\\u200D = []", "(anonymous): Line 1:1 Unexpected token ILLEGAL") - test(`"\`, "(anonymous): Line 1:1 Unexpected token ILLEGAL") + test(`"\`, "(anonymous): Line 1:1 Unexpected token ILLEGAL") - test(`"\u`, "(anonymous): Line 1:1 Unexpected token ILLEGAL") + test(`"\u`, "(anonymous): Line 1:1 Unexpected token ILLEGAL") - test("return", "(anonymous): Line 1:1 Illegal return statement") + test("return", "(anonymous): Line 1:1 Illegal return statement") - test("continue", "(anonymous): Line 1:1 Illegal continue statement") + test("continue", "(anonymous): Line 1:1 Illegal continue statement") - test("break", "(anonymous): Line 1:1 Illegal break statement") + test("break", "(anonymous): Line 1:1 Illegal break statement") - test("switch (abc) { default: continue; }", "(anonymous): Line 1:25 Illegal continue statement") + test("switch (abc) { default: continue; }", "(anonymous): Line 1:25 Illegal continue statement") - test("do { abc } *", "(anonymous): Line 1:12 Unexpected token *") + test("do { abc } *", "(anonymous): Line 1:12 Unexpected token *") - test("while (true) { break abc; }", "(anonymous): Line 1:16 Undefined label 'abc'") + test("while (true) { break abc; }", "(anonymous): Line 1:16 Undefined label 'abc'") - test("while (true) { continue abc; }", "(anonymous): Line 1:16 Undefined label 'abc'") + test("while (true) { continue abc; }", "(anonymous): Line 1:16 Undefined label 'abc'") - test("abc: while (true) { (function(){ break abc; }); }", "(anonymous): Line 1:34 Undefined label 'abc'") + test("abc: while (true) { (function(){ break abc; }); }", "(anonymous): Line 1:34 Undefined label 'abc'") - test("abc: while (true) { (function(){ abc: break abc; }); }", nil) + test("abc: while (true) { (function(){ abc: break abc; }); }", nil) - test("abc: while (true) { (function(){ continue abc; }); }", "(anonymous): Line 1:34 Undefined label 'abc'") + test("abc: while (true) { (function(){ continue abc; }); }", "(anonymous): Line 1:34 Undefined label 'abc'") - test(`abc: if (0) break abc; else {}`, nil) + test(`abc: if (0) break abc; else {}`, nil) - test(`abc: if (0) { break abc; } else {}`, nil) + test(`abc: if (0) { break abc; } else {}`, nil) - test(`abc: if (0) { break abc } else {}`, nil) + test(`abc: if (0) { break abc } else {}`, nil) - test("abc: while (true) { abc: while (true) {} }", "(anonymous): Line 1:21 Label 'abc' already exists") + test("abc: while (true) { abc: while (true) {} }", "(anonymous): Line 1:21 Label 'abc' already exists") - if false { - // TODO When strict mode is implemented - test("(function () { 'use strict'; delete abc; }())", "") - } + if false { + // TODO When strict mode is implemented + test("(function () { 'use strict'; delete abc; }())", "") + } - test("_: _: while (true) {]", "(anonymous): Line 1:4 Label '_' already exists") + test("_: _: while (true) {]", "(anonymous): Line 1:4 Label '_' already exists") - test("_:\n_:\nwhile (true) {]", "(anonymous): Line 2:1 Label '_' already exists") + test("_:\n_:\nwhile (true) {]", "(anonymous): Line 2:1 Label '_' already exists") - test("_:\n _:\nwhile (true) {]", "(anonymous): Line 2:4 Label '_' already exists") + test("_:\n _:\nwhile (true) {]", "(anonymous): Line 2:4 Label '_' already exists") - test("/Xyzzy(?!Nothing happens)/", - "(anonymous): Line 1:1 Invalid regular expression: re2: Invalid (?!) ") + test("/Xyzzy(?!Nothing happens)/", + "(anonymous): Line 1:1 Invalid regular expression: re2: Invalid (?!) ") - test("function(){}", "(anonymous): Line 1:9 Unexpected token (") + test("function(){}", "(anonymous): Line 1:9 Unexpected token (") - test("\n/*/", "(anonymous): Line 2:4 Unexpected end of input") + test("\n/*/", "(anonymous): Line 2:4 Unexpected end of input") - test("/*/.source", "(anonymous): Line 1:11 Unexpected end of input") + test("/*/.source", "(anonymous): Line 1:11 Unexpected end of input") - test("/\\1/.source", "(anonymous): Line 1:1 Invalid regular expression: re2: Invalid \\1 ") + test("/\\1/.source", "(anonymous): Line 1:1 Invalid regular expression: re2: Invalid \\1 ") - test("var class", "(anonymous): Line 1:5 Unexpected reserved word") + test("var class", "(anonymous): Line 1:5 Unexpected reserved word") - test("var if", "(anonymous): Line 1:5 Unexpected token if") + test("var if", "(anonymous): Line 1:5 Unexpected token if") - test("object Object", "(anonymous): Line 1:8 Unexpected identifier") + test("object Object", "(anonymous): Line 1:8 Unexpected identifier") - test("[object Object]", "(anonymous): Line 1:9 Unexpected identifier") + test("[object Object]", "(anonymous): Line 1:9 Unexpected identifier") - test("\\u0xyz", "(anonymous): Line 1:1 Unexpected token ILLEGAL") + test("\\u0xyz", "(anonymous): Line 1:1 Unexpected token ILLEGAL") - test(`for (var abc, def in {}) {}`, "(anonymous): Line 1:19 Unexpected token in") + test(`for (var abc, def in {}) {}`, "(anonymous): Line 1:19 Unexpected token in") - test(`for (abc, def in {}) {}`, "(anonymous): Line 1:1 Invalid left-hand side in for-in") + test(`for (abc, def in {}) {}`, "(anonymous): Line 1:1 Invalid left-hand side in for-in") - test(`for (var abc=def, ghi=("abc" in {}); true;) {}`, nil) + test(`for (var abc=def, ghi=("abc" in {}); true;) {}`, nil) - { - // Semicolon insertion + { + // Semicolon insertion - test("this\nif (1);", nil) + test("this\nif (1);", nil) - test("while (1) { break\nif (1); }", nil) + test("while (1) { break\nif (1); }", nil) - test("throw\nif (1);", "(anonymous): Line 1:1 Illegal newline after throw") + test("throw\nif (1);", "(anonymous): Line 1:1 Illegal newline after throw") - test("(function(){ return\nif (1); })", nil) + test("(function(){ return\nif (1); })", nil) - test("while (1) { continue\nif (1); }", nil) + test("while (1) { continue\nif (1); }", nil) - test("debugger\nif (1);", nil) - } + test("debugger\nif (1);", nil) + } - { // Reserved words + { // Reserved words - test("class", "(anonymous): Line 1:1 Unexpected reserved word") - test("abc.class = 1", nil) - test("var class;", "(anonymous): Line 1:5 Unexpected reserved word") + test("class", "(anonymous): Line 1:1 Unexpected reserved word") + test("abc.class = 1", nil) + test("var class;", "(anonymous): Line 1:5 Unexpected reserved word") - test("const", "(anonymous): Line 1:1 Unexpected reserved word") - test("abc.const = 1", nil) - test("var const;", "(anonymous): Line 1:5 Unexpected reserved word") + test("const", "(anonymous): Line 1:1 Unexpected reserved word") + test("abc.const = 1", nil) + test("var const;", "(anonymous): Line 1:5 Unexpected reserved word") - test("enum", "(anonymous): Line 1:1 Unexpected reserved word") - test("abc.enum = 1", nil) - test("var enum;", "(anonymous): Line 1:5 Unexpected reserved word") + test("enum", "(anonymous): Line 1:1 Unexpected reserved word") + test("abc.enum = 1", nil) + test("var enum;", "(anonymous): Line 1:5 Unexpected reserved word") - test("export", "(anonymous): Line 1:1 Unexpected reserved word") - test("abc.export = 1", nil) - test("var export;", "(anonymous): Line 1:5 Unexpected reserved word") + test("export", "(anonymous): Line 1:1 Unexpected reserved word") + test("abc.export = 1", nil) + test("var export;", "(anonymous): Line 1:5 Unexpected reserved word") - test("extends", "(anonymous): Line 1:1 Unexpected reserved word") - test("abc.extends = 1", nil) - test("var extends;", "(anonymous): Line 1:5 Unexpected reserved word") + test("extends", "(anonymous): Line 1:1 Unexpected reserved word") + test("abc.extends = 1", nil) + test("var extends;", "(anonymous): Line 1:5 Unexpected reserved word") - test("import", "(anonymous): Line 1:1 Unexpected reserved word") - test("abc.import = 1", nil) - test("var import;", "(anonymous): Line 1:5 Unexpected reserved word") + test("import", "(anonymous): Line 1:1 Unexpected reserved word") + test("abc.import = 1", nil) + test("var import;", "(anonymous): Line 1:5 Unexpected reserved word") - test("super", "(anonymous): Line 1:1 Unexpected reserved word") - test("abc.super = 1", nil) - test("var super;", "(anonymous): Line 1:5 Unexpected reserved word") - } + test("super", "(anonymous): Line 1:1 Unexpected reserved word") + test("abc.super = 1", nil) + test("var super;", "(anonymous): Line 1:5 Unexpected reserved word") + } - { // Reserved words (strict) + { // Reserved words (strict) - test(`implements`, nil) - test(`abc.implements = 1`, nil) - test(`var implements;`, nil) + test(`implements`, nil) + test(`abc.implements = 1`, nil) + test(`var implements;`, nil) - test(`interface`, nil) - test(`abc.interface = 1`, nil) - test(`var interface;`, nil) + test(`interface`, nil) + test(`abc.interface = 1`, nil) + test(`var interface;`, nil) - test(`let`, nil) - test(`abc.let = 1`, nil) - test(`var let;`, nil) + test(`let`, nil) + test(`abc.let = 1`, nil) + test(`var let;`, nil) - test(`package`, nil) - test(`abc.package = 1`, nil) - test(`var package;`, nil) + test(`package`, nil) + test(`abc.package = 1`, nil) + test(`var package;`, nil) - test(`private`, nil) - test(`abc.private = 1`, nil) - test(`var private;`, nil) + test(`private`, nil) + test(`abc.private = 1`, nil) + test(`var private;`, nil) - test(`protected`, nil) - test(`abc.protected = 1`, nil) - test(`var protected;`, nil) + test(`protected`, nil) + test(`abc.protected = 1`, nil) + test(`var protected;`, nil) - test(`public`, nil) - test(`abc.public = 1`, nil) - test(`var public;`, nil) + test(`public`, nil) + test(`abc.public = 1`, nil) + test(`var public;`, nil) - test(`static`, nil) - test(`abc.static = 1`, nil) - test(`var static;`, nil) + test(`static`, nil) + test(`abc.static = 1`, nil) + test(`var static;`, nil) - test(`yield`, nil) - test(`abc.yield = 1`, nil) - test(`var yield;`, nil) - } + test(`yield`, nil) + test(`abc.yield = 1`, nil) + test(`var yield;`, nil) + } + }) } func TestParser(t *testing.T) { - Terst(t) + tt(t, func() { + test := func(source string, chk interface{}) *ast.Program { + _, program, err := testParse(source) + is(firstErr(err), chk) + return program + } - test := func(source string, chk interface{}) *ast.Program { - _, program, err := testParse(source) - Is(firstErr(err), chk) - return program - } + test(` + abc + -- + [] + `, "(anonymous): Line 3:13 Invalid left-hand side in assignment") - test(` - abc - -- - [] - `, "(anonymous): Line 3:9 Invalid left-hand side in assignment") + test(` + abc-- + [] + `, nil) - test(` - abc-- - [] - `, nil) + test("1\n[]\n", "(anonymous): Line 2:2 Unexpected token ]") - test("1\n[]\n", "(anonymous): Line 2:2 Unexpected token ]") + test(` + function abc() { + } + abc() + `, nil) - test(` - function abc() { - } - abc() - `, nil) + program := test("", nil) - program := test("", nil) + test("//", nil) - test("//", nil) + test("/* */", nil) - test("/* */", nil) + test("/** **/", nil) - test("/** **/", nil) + test("/*****/", nil) - test("/*****/", nil) + test("/*", "(anonymous): Line 1:3 Unexpected end of input") - test("/*", "(anonymous): Line 1:3 Unexpected end of input") + test("#", "(anonymous): Line 1:1 Unexpected token ILLEGAL") - test("#", "(anonymous): Line 1:1 Unexpected token ILLEGAL") + test("/**/#", "(anonymous): Line 1:5 Unexpected token ILLEGAL") - test("/**/#", "(anonymous): Line 1:5 Unexpected token ILLEGAL") + test("new +", "(anonymous): Line 1:5 Unexpected token +") - test("new +", "(anonymous): Line 1:5 Unexpected token +") + program = test(";", nil) + is(len(program.Body), 1) + is(program.Body[0].(*ast.EmptyStatement).Semicolon, file.Idx(1)) - program = test(";", nil) - Is(len(program.Body), 1) - Is(program.Body[0].(*ast.EmptyStatement).Semicolon, "1") + program = test(";;", nil) + is(len(program.Body), 2) + is(program.Body[0].(*ast.EmptyStatement).Semicolon, file.Idx(1)) + is(program.Body[1].(*ast.EmptyStatement).Semicolon, file.Idx(2)) - program = test(";;", nil) - Is(len(program.Body), 2) - Is(program.Body[0].(*ast.EmptyStatement).Semicolon, "1") - Is(program.Body[1].(*ast.EmptyStatement).Semicolon, "2") + program = test("1.2", nil) + is(len(program.Body), 1) + is(program.Body[0].(*ast.ExpressionStatement).Expression.(*ast.NumberLiteral).Literal, "1.2") - program = test("1.2", nil) - Is(len(program.Body), 1) - Is(program.Body[0].(*ast.ExpressionStatement).Expression.(*ast.NumberLiteral).Literal, "1.2") + program = test("/* */1.2", nil) + is(len(program.Body), 1) + is(program.Body[0].(*ast.ExpressionStatement).Expression.(*ast.NumberLiteral).Literal, "1.2") - program = test("/* */1.2", nil) - Is(len(program.Body), 1) - Is(program.Body[0].(*ast.ExpressionStatement).Expression.(*ast.NumberLiteral).Literal, "1.2") + program = test("\n", nil) + is(len(program.Body), 0) - program = test("\n", nil) - Is(len(program.Body), 0) + test(` + if (0) { + abc = 0 + } + else abc = 0 + `, nil) - test(` - if (0) { - abc = 0 - } - else abc = 0 - `, nil) + test("if (0) abc = 0 else abc = 0", "(anonymous): Line 1:16 Unexpected token else") - test("if (0) abc = 0 else abc = 0", "(anonymous): Line 1:16 Unexpected token else") + test(` + if (0) { + abc = 0 + } else abc = 0 + `, nil) - test(` - if (0) { - abc = 0 - } else abc = 0 - `, nil) + test(` + if (0) { + abc = 1 + } else { + } + `, nil) - test(` - if (0) { - abc = 1 - } else { - } - `, nil) - - test(` - do { - } while (true) - `, nil) - - test(` - try { - } finally { - } - `, nil) - - test(` - try { - } catch (abc) { - } finally { - } - `, nil) - - test(` - try { - } - catch (abc) { - } - finally { - } - `, nil) - - test(`try {} catch (abc) {} finally {}`, nil) - - test(` - do { + test(` do { - } while (0) - } while (0) - `, nil) + } while (true) + `, nil) - test(` - (function(){ + test(` try { - if ( - 1 - ) { - return 1 - } - return 0 } finally { } - })() - `, nil) + `, nil) - test("abc = ''\ndef", nil) - - test("abc = 1\ndef", nil) - - test("abc = Math\ndef", nil) - - test(`"\'"`, nil) - - test(` - abc = function(){ - } - abc = 0 - `, nil) - - test("abc.null = 0", nil) - - test("0x41", nil) - - test(`"\d"`, nil) - - test(`(function(){return this})`, nil) - - test(` - Object.defineProperty(Array.prototype, "0", { - value: 100, - writable: false, - configurable: true - }); - abc = [101]; - abc.hasOwnProperty("0") && abc[0] === 101; - `, nil) - - test(`new abc()`, nil) - test(`new {}`, nil) - - test(` - limit = 4 - result = 0 - while (limit) { - limit = limit - 1 - if (limit) { - } - else { - break - } - result = result + 1 - } - `, nil) - - test(` - while (0) { - if (0) { - continue + test(` + try { + } catch (abc) { + } finally { } - } - `, nil) + `, nil) - test("var \u0061\u0062\u0063 = 0", nil) - - // 7_3_1 - test("var test7_3_1\nabc = 66;", nil) - test("var test7_3_1\u2028abc = 66;", nil) - - // 7_3_3 - test("//\u2028 =;", "(anonymous): Line 2:2 Unexpected token =") - - // 7_3_10 - test("var abc = \u2029;", "(anonymous): Line 2:1 Unexpected token ;") - test("var abc = \\u2029;", "(anonymous): Line 1:11 Unexpected token ILLEGAL") - test("var \\u0061\\u0062\\u0063 = 0;", nil) - - test("'", "(anonymous): Line 1:1 Unexpected token ILLEGAL") - - test("'\nstr\ning\n'", "(anonymous): Line 1:1 Unexpected token ILLEGAL") - - // S7.6_A4.3_T1 - test(`var $\u0030 = 0;`, nil) - - // S7.6.1.1_A1.1 - test(`switch = 1`, "(anonymous): Line 1:8 Unexpected token =") - - // S7.8.3_A2.1_T1 - test(`.0 === 0.0`, nil) - - // 7.8.5-1 - test("var regExp = /\\\rn/;", "(anonymous): Line 1:14 Invalid regular expression: missing /") - - // S7.8.5_A1.1_T2 - test("var regExp = /=/;", nil) - - // S7.8.5_A1.2_T1 - test("/*/", "(anonymous): Line 1:4 Unexpected end of input") - - // Sbp_7.9_A9_T3 - test(` - do { - ; - } while (false) true - `, nil) - - // S7.9_A10_T10 - test(` - {a:1 - } 3 - `, nil) - - test(` - abc - ++def - `, nil) - - // S7.9_A5.2_T1 - test(` - for(false;false - ) { - break; - } - `, "(anonymous): Line 3:9 Unexpected token )") - - // S7.9_A9_T8 - test(` - do {}; - while (false) - `, "(anonymous): Line 2:14 Unexpected token ;") - - // S8.4_A5 - test(` - "x\0y" - `, nil) - - // S9.3.1_A6_T1 - test(` - 10e10000 - `, nil) - - // 10.4.2-1-5 - test(` - "abc\ - def" - `, nil) - - test("'\\\n'", nil) - - test("'\\\r\n'", nil) - - //// 11.13.1-1-1 - test("42 = 42;", "(anonymous): Line 1:1 Invalid left-hand side in assignment") - - // S11.13.2_A4.2_T1.3 - test(` - abc /= "1" - `, nil) - - // 12.1-1 - test(` - try{};catch(){} - `, "(anonymous): Line 2:9 Missing catch or finally after try") - - // 12.1-3 - test(` - try{};finally{} - `, "(anonymous): Line 2:9 Missing catch or finally after try") - - // S12.6.3_A11.1_T3 - test(` - while (true) { - break abc; - } - `, "(anonymous): Line 3:13 Undefined label 'abc'") - - // S15.3_A2_T1 - test(`var x / = 1;`, "(anonymous): Line 1:7 Unexpected token /") - - test(` - function abc() { - if (0) - return; - else { + test(` + try { } - } - `, nil) + catch (abc) { + } + finally { + } + `, nil) - test("//\u2028 var =;", "(anonymous): Line 2:6 Unexpected token =") + test(`try {} catch (abc) {} finally {}`, nil) - test(` - throw - {} - `, "(anonymous): Line 2:9 Illegal newline after throw") + test(` + do { + do { + } while (0) + } while (0) + `, nil) - // S7.6.1.1_A1.11 - test(` - function = 1 - `, "(anonymous): Line 2:18 Unexpected token =") + test(` + (function(){ + try { + if ( + 1 + ) { + return 1 + } + return 0 + } finally { + } + })() + `, nil) - // S7.8.3_A1.2_T1 - test(`0e1`, nil) + test("abc = ''\ndef", nil) - test("abc = 1; abc\n++", "(anonymous): Line 2:3 Unexpected end of input") + test("abc = 1\ndef", nil) - // --- + test("abc = Math\ndef", nil) - test("({ get abc() {} })", nil) + test(`"\'"`, nil) - test(`for (abc.def in {}) {}`, nil) + test(` + abc = function(){ + } + abc = 0 + `, nil) - test(`while (true) { break }`, nil) + test("abc.null = 0", nil) - test(`while (true) { continue }`, nil) + test("0x41", nil) - test(`abc=/^(?:(\w+:)\/{2}(\w+(?:\.\w+)*\/?)|(.{0,2}\/{1}))?([/.]*?(?:[^?]+)?\/)?((?:[^/?]+)\.(\w+))(?:\?(\S+)?)?$/,def=/^(?:(\w+:)\/{2})|(.{0,2}\/{1})?([/.]*?(?:[^?]+)?\/?)?$/`, nil) + test(`"\d"`, nil) - test(`(function() { try {} catch (err) {} finally {} return })`, nil) + test(`(function(){return this})`, nil) - test(`0xde0b6b3a7640080.toFixed(0)`, nil) + test(` + Object.defineProperty(Array.prototype, "0", { + value: 100, + writable: false, + configurable: true + }); + abc = [101]; + abc.hasOwnProperty("0") && abc[0] === 101; + `, nil) - test(`/[^-._0-9A-Za-z\xb7\xc0-\xd6\xd8-\xf6\xf8-\u037d\u37f-\u1fff\u200c-\u200d\u203f\u2040\u2070-\u218f]/`, nil) + test(`new abc()`, nil) + test(`new {}`, nil) - test(`/[\u0000-\u0008\u000B-\u000C\u000E-\u001F\uD800-\uDFFF\uFFFE-\uFFFF]/`, nil) + test(` + limit = 4 + result = 0 + while (limit) { + limit = limit - 1 + if (limit) { + } + else { + break + } + result = result + 1 + } + `, nil) - test("var abc = 1;\ufeff", nil) + test(` + while (0) { + if (0) { + continue + } + } + `, nil) - test("\ufeff/* var abc = 1; */", nil) + test("var \u0061\u0062\u0063 = 0", nil) - test(`if (-0x8000000000000000<=abc&&abc<=0x8000000000000000) {}`, nil) + // 7_3_1 + test("var test7_3_1\nabc = 66;", nil) + test("var test7_3_1\u2028abc = 66;", nil) - test(`(function(){debugger;return this;})`, nil) + // 7_3_3 + test("//\u2028 =;", "(anonymous): Line 2:2 Unexpected token =") - test(` + // 7_3_10 + test("var abc = \u2029;", "(anonymous): Line 2:1 Unexpected token ;") + test("var abc = \\u2029;", "(anonymous): Line 1:11 Unexpected token ILLEGAL") + test("var \\u0061\\u0062\\u0063 = 0;", nil) - `, nil) + test("'", "(anonymous): Line 1:1 Unexpected token ILLEGAL") - test(` - var abc = "" - debugger - `, nil) + test("'\nstr\ning\n'", "(anonymous): Line 1:1 Unexpected token ILLEGAL") - test(` - var abc = /\[\]$/ - debugger - `, nil) + // S7.6_A4.3_T1 + test(`var $\u0030 = 0;`, nil) - test(` - var abc = 1 / - 2 - debugger - `, nil) + // S7.6.1.1_A1.1 + test(`switch = 1`, "(anonymous): Line 1:8 Unexpected token =") + + // S7.8.3_A2.1_T1 + test(`.0 === 0.0`, nil) + + // 7.8.5-1 + test("var regExp = /\\\rn/;", "(anonymous): Line 1:14 Invalid regular expression: missing /") + + // S7.8.5_A1.1_T2 + test("var regExp = /=/;", nil) + + // S7.8.5_A1.2_T1 + test("/*/", "(anonymous): Line 1:4 Unexpected end of input") + + // Sbp_7.9_A9_T3 + test(` + do { + ; + } while (false) true + `, nil) + + // S7.9_A10_T10 + test(` + {a:1 + } 3 + `, nil) + + test(` + abc + ++def + `, nil) + + // S7.9_A5.2_T1 + test(` + for(false;false + ) { + break; + } + `, "(anonymous): Line 3:13 Unexpected token )") + + // S7.9_A9_T8 + test(` + do {}; + while (false) + `, "(anonymous): Line 2:18 Unexpected token ;") + + // S8.4_A5 + test(` + "x\0y" + `, nil) + + // S9.3.1_A6_T1 + test(` + 10e10000 + `, nil) + + // 10.4.2-1-5 + test(` + "abc\ + def" + `, nil) + + test("'\\\n'", nil) + + test("'\\\r\n'", nil) + + //// 11.13.1-1-1 + test("42 = 42;", "(anonymous): Line 1:1 Invalid left-hand side in assignment") + + // S11.13.2_A4.2_T1.3 + test(` + abc /= "1" + `, nil) + + // 12.1-1 + test(` + try{};catch(){} + `, "(anonymous): Line 2:13 Missing catch or finally after try") + + // 12.1-3 + test(` + try{};finally{} + `, "(anonymous): Line 2:13 Missing catch or finally after try") + + // S12.6.3_A11.1_T3 + test(` + while (true) { + break abc; + } + `, "(anonymous): Line 3:17 Undefined label 'abc'") + + // S15.3_A2_T1 + test(`var x / = 1;`, "(anonymous): Line 1:7 Unexpected token /") + + test(` + function abc() { + if (0) + return; + else { + } + } + `, nil) + + test("//\u2028 var =;", "(anonymous): Line 2:6 Unexpected token =") + + test(` + throw + {} + `, "(anonymous): Line 2:13 Illegal newline after throw") + + // S7.6.1.1_A1.11 + test(` + function = 1 + `, "(anonymous): Line 2:22 Unexpected token =") + + // S7.8.3_A1.2_T1 + test(`0e1`, nil) + + test("abc = 1; abc\n++", "(anonymous): Line 2:3 Unexpected end of input") + + // --- + + test("({ get abc() {} })", nil) + + test(`for (abc.def in {}) {}`, nil) + + test(`while (true) { break }`, nil) + + test(`while (true) { continue }`, nil) + + test(`abc=/^(?:(\w+:)\/{2}(\w+(?:\.\w+)*\/?)|(.{0,2}\/{1}))?([/.]*?(?:[^?]+)?\/)?((?:[^/?]+)\.(\w+))(?:\?(\S+)?)?$/,def=/^(?:(\w+:)\/{2})|(.{0,2}\/{1})?([/.]*?(?:[^?]+)?\/?)?$/`, nil) + + test(`(function() { try {} catch (err) {} finally {} return })`, nil) + + test(`0xde0b6b3a7640080.toFixed(0)`, nil) + + test(`/[^-._0-9A-Za-z\xb7\xc0-\xd6\xd8-\xf6\xf8-\u037d\u37f-\u1fff\u200c-\u200d\u203f\u2040\u2070-\u218f]/`, nil) + + test(`/[\u0000-\u0008\u000B-\u000C\u000E-\u001F\uD800-\uDFFF\uFFFE-\uFFFF]/`, nil) + + test("var abc = 1;\ufeff", nil) + + test("\ufeff/* var abc = 1; */", nil) + + test(`if (-0x8000000000000000<=abc&&abc<=0x8000000000000000) {}`, nil) + + test(`(function(){debugger;return this;})`, nil) + + test(` + + `, nil) + + test(` + var abc = "" + debugger + `, nil) + + test(` + var abc = /\[\]$/ + debugger + `, nil) + + test(` + var abc = 1 / + 2 + debugger + `, nil) + }) } func Test_parseStringLiteral(t *testing.T) { - Terst(t) + tt(t, func() { + test := func(have, want string) { + have, err := parseStringLiteral(have) + is(err, nil) + is(have, want) + } - test := func(have, want string) { - have, err := parseStringLiteral(have) - Is(err, nil) - Is(have, want) - } + test("", "") - test("", "") + test("1(\\\\d+)", "1(\\d+)") - test("1(\\\\d+)", "1(\\d+)") + test("\\u2029", "\u2029") - test("\\u2029", "\u2029") + test("abc\\uFFFFabc", "abc\uFFFFabc") - test("abc\\uFFFFabc", "abc\uFFFFabc") + test("[First line \\\nSecond line \\\n Third line\\\n. ]", + "[First line Second line Third line. ]") - test("[First line \\\nSecond line \\\n Third line\\\n. ]", - "[First line Second line Third line. ]") + test("\\u007a\\x79\\u000a\\x78", "zy\nx") - test("\\u007a\\x79\\u000a\\x78", "zy\nx") + // S7.8.4_A4.2_T3 + test("\\a", "a") + test("\u0410", "\u0410") - // S7.8.4_A4.2_T3 - test("\\a", "a") - test("\u0410", "\u0410") + // S7.8.4_A5.1_T1 + test("\\0", "\u0000") - // S7.8.4_A5.1_T1 - test("\\0", "\u0000") + // S8.4_A5 + test("\u0000", "\u0000") - // S8.4_A5 - test("\u0000", "\u0000") + // 15.5.4.20 + test("'abc'\\\n'def'", "'abc''def'") - // 15.5.4.20 - test("'abc'\\\n'def'", "'abc''def'") + // 15.5.4.20-4-1 + test("'abc'\\\r\n'def'", "'abc''def'") - // 15.5.4.20-4-1 - test("'abc'\\\r\n'def'", "'abc''def'") + // Octal + test("\\0", "\000") + test("\\00", "\000") + test("\\000", "\000") + test("\\09", "\0009") + test("\\009", "\0009") + test("\\0009", "\0009") + test("\\1", "\001") + test("\\01", "\001") + test("\\001", "\001") + test("\\0011", "\0011") + test("\\1abc", "\001abc") - // Octal - test("\\0", "\000") - test("\\00", "\000") - test("\\000", "\000") - test("\\09", "\0009") - test("\\009", "\0009") - test("\\0009", "\0009") - test("\\1", "\001") - test("\\01", "\001") - test("\\001", "\001") - test("\\0011", "\0011") - test("\\1abc", "\001abc") + test("\\\u4e16", "\u4e16") - test("\\\u4e16", "\u4e16") + // err + test = func(have, want string) { + have, err := parseStringLiteral(have) + is(err.Error(), want) + is(have, "") + } - // err - test = func(have, want string) { - have, err := parseStringLiteral(have) - Is(err.Error(), want) - Is(have, "") - } - - test(`\u`, `invalid escape: \u: len("") != 4`) - test(`\u0`, `invalid escape: \u: len("0") != 4`) - test(`\u00`, `invalid escape: \u: len("00") != 4`) - test(`\u000`, `invalid escape: \u: len("000") != 4`) - - test(`\x`, `invalid escape: \x: len("") != 2`) - test(`\x0`, `invalid escape: \x: len("0") != 2`) - test(`\x0`, `invalid escape: \x: len("0") != 2`) + test(`\u`, `invalid escape: \u: len("") != 4`) + test(`\u0`, `invalid escape: \u: len("0") != 4`) + test(`\u00`, `invalid escape: \u: len("00") != 4`) + test(`\u000`, `invalid escape: \u: len("000") != 4`) + test(`\x`, `invalid escape: \x: len("") != 2`) + test(`\x0`, `invalid escape: \x: len("0") != 2`) + test(`\x0`, `invalid escape: \x: len("0") != 2`) + }) } func Test_parseNumberLiteral(t *testing.T) { - Terst(t) + tt(t, func() { + test := func(input string, expect interface{}) { + result, err := parseNumberLiteral(input) + is(err, nil) + is(result, expect) + } - test := func(input string, expect interface{}) { - result, err := parseNumberLiteral(input) - Is(err, nil) - Is(result, expect) - } + test("0", 0) - test("0", 0) - - test("0x8000000000000000", float64(9.223372036854776e+18)) + test("0x8000000000000000", float64(9.223372036854776e+18)) + }) } func TestPosition(t *testing.T) { - Terst(t) + tt(t, func() { + parser := newParser("", "// Lorem ipsum") - parser := newParser("", "// Lorem ipsum") + // Out of range, idx0 (error condition) + is(parser.slice(0, 1), "") + is(parser.slice(0, 10), "") - // Out of range, idx0 (error condition) - Is(parser.slice(0, 1), "") - Is(parser.slice(0, 10), "") + // Out of range, idx1 (error condition) + is(parser.slice(1, 128), "") - // Out of range, idx1 (error condition) - Is(parser.slice(1, 128), "") + is(parser.str[0:0], "") + is(parser.slice(1, 1), "") - Is(parser.str[0:0], "") - Is(parser.slice(1, 1), "") + is(parser.str[0:1], "/") + is(parser.slice(1, 2), "/") - Is(parser.str[0:1], "/") - Is(parser.slice(1, 2), "/") + is(parser.str[0:14], "// Lorem ipsum") + is(parser.slice(1, 15), "// Lorem ipsum") - Is(parser.str[0:14], "// Lorem ipsum") - Is(parser.slice(1, 15), "// Lorem ipsum") + parser = newParser("", "(function(){ return 0; })") + program, err := parser.parse() + is(err, nil) - parser = newParser("", "(function(){ return 0; })") - program, err := parser.parse() - Is(err, nil) + var node ast.Node + node = program.Body[0].(*ast.ExpressionStatement).Expression.(*ast.FunctionLiteral) + is(node.Idx0(), file.Idx(2)) + is(node.Idx1(), file.Idx(25)) + is(parser.slice(node.Idx0(), node.Idx1()), "function(){ return 0; }") + is(parser.slice(node.Idx0(), node.Idx1()+1), "function(){ return 0; })") + is(parser.slice(node.Idx0(), node.Idx1()+2), "") + is(node.(*ast.FunctionLiteral).Source, "function(){ return 0; }") - var node ast.Node - node = program.Body[0].(*ast.ExpressionStatement).Expression.(*ast.FunctionLiteral) - Is(node.Idx0(), 2) - Is(node.Idx1(), 25) - Is(parser.slice(node.Idx0(), node.Idx1()), "function(){ return 0; }") - Is(parser.slice(node.Idx0(), node.Idx1()+1), "function(){ return 0; })") - Is(parser.slice(node.Idx0(), node.Idx1()+2), "") - Is(node.(*ast.FunctionLiteral).Source, "function(){ return 0; }") + node = program + is(node.Idx0(), file.Idx(2)) + is(node.Idx1(), file.Idx(25)) + is(parser.slice(node.Idx0(), node.Idx1()), "function(){ return 0; }") - node = program - Is(node.Idx0(), 2) - Is(node.Idx1(), 25) - Is(parser.slice(node.Idx0(), node.Idx1()), "function(){ return 0; }") - - parser = newParser("", "(function(){ return abc; })") - program, err = parser.parse() - Is(err, nil) - node = program.Body[0].(*ast.ExpressionStatement).Expression.(*ast.FunctionLiteral) - Is(node.(*ast.FunctionLiteral).Source, "function(){ return abc; }") + parser = newParser("", "(function(){ return abc; })") + program, err = parser.parse() + is(err, nil) + node = program.Body[0].(*ast.ExpressionStatement).Expression.(*ast.FunctionLiteral) + is(node.(*ast.FunctionLiteral).Source, "function(){ return abc; }") + }) } diff --git a/parser/regexp_test.go b/parser/regexp_test.go index aea78cb..3222db1 100644 --- a/parser/regexp_test.go +++ b/parser/regexp_test.go @@ -1,150 +1,149 @@ package parser import ( - . "../terst" "regexp" "testing" ) func TestRegExp(t *testing.T) { - Terst(t) + tt(t, func() { + { + // err + test := func(input string, expect interface{}) { + _, err := TransformRegExp(input) + is(err, expect) + } - { - // err - test := func(input string, expect interface{}) { - _, err := TransformRegExp(input) - Is(err, expect) + test("[", "Unterminated character class") + + test("(", "Unterminated group") + + test("(?=)", "re2: Invalid (?=) ") + + test("(?=)", "re2: Invalid (?=) ") + + test("(?!)", "re2: Invalid (?!) ") + + // An error anyway + test("(?=", "re2: Invalid (?=) ") + + test("\\1", "re2: Invalid \\1 ") + + test("\\90", "re2: Invalid \\90 ") + + test("\\9123456789", "re2: Invalid \\9123456789 ") + + test("\\(?=)", "Unmatched ')'") + + test(")", "Unmatched ')'") } - test("[", "Unterminated character class") + { + // err + test := func(input, expect string, expectErr interface{}) { + output, err := TransformRegExp(input) + is(output, expect) + is(err, expectErr) + } - test("(", "Unterminated group") + test("(?!)", "(?!)", "re2: Invalid (?!) ") - test("(?=)", "re2: Invalid (?=) ") + test(")", "", "Unmatched ')'") - test("(?=)", "re2: Invalid (?=) ") + test("(?!))", "", "re2: Invalid (?!) ") - test("(?!)", "re2: Invalid (?!) ") + test("\\0", "\\0", nil) - // An error anyway - test("(?=", "re2: Invalid (?=) ") + test("\\1", "\\1", "re2: Invalid \\1 ") - test("\\1", "re2: Invalid \\1 ") - - test("\\90", "re2: Invalid \\90 ") - - test("\\9123456789", "re2: Invalid \\9123456789 ") - - test("\\(?=)", "Unmatched ')'") - - test(")", "Unmatched ')'") - } - - { - // err - test := func(input, expect string, expectErr interface{}) { - output, err := TransformRegExp(input) - Is(output, expect) - Is(err, expectErr) + test("\\9123456789", "\\9123456789", "re2: Invalid \\9123456789 ") } - test("(?!)", "(?!)", "re2: Invalid (?!) ") - - test(")", "", "Unmatched ')'") - - test("(?!))", "", "re2: Invalid (?!) ") - - test("\\0", "\\0", nil) - - test("\\1", "\\1", "re2: Invalid \\1 ") - - test("\\9123456789", "\\9123456789", "re2: Invalid \\9123456789 ") - } - - { - // err - test := func(input string, expect string) { - result, err := TransformRegExp(input) - Is(err, nil) - if Is(result, expect) { - _, err := regexp.Compile(result) - if !Is(err, nil) { - t.Log(result) + { + // err + test := func(input string, expect string) { + result, err := TransformRegExp(input) + is(err, nil) + if is(result, expect) { + _, err := regexp.Compile(result) + if !is(err, nil) { + t.Log(result) + } } } + + test("", "") + + test("abc", "abc") + + test(`\abc`, `abc`) + + test(`\a\b\c`, `a\bc`) + + test(`\x`, `x`) + + test(`\c`, `c`) + + test(`\cA`, `\x01`) + + test(`\cz`, `\x1a`) + + test(`\ca`, `\x01`) + + test(`\cj`, `\x0a`) + + test(`\ck`, `\x0b`) + + test(`\+`, `\+`) + + test(`[\b]`, `[\x08]`) + + test(`\u0z01\x\undefined`, `u0z01xundefined`) + + test(`\\|'|\r|\n|\t|\u2028|\u2029`, `\\|'|\r|\n|\t|\x{2028}|\x{2029}`) + + test("]", "]") + + test("}", "}") + + test("%", "%") + + test("(%)", "(%)") + + test("(?:[%\\s])", "(?:[%\\s])") + + test("[[]", "[[]") + + test("\\101", "\\x41") + + test("\\51", "\\x29") + + test("\\051", "\\x29") + + test("\\175", "\\x7d") + + test("\\04", "\\x04") + + test(`<%([\s\S]+?)%>`, `<%([\s\S]+?)%>`) + + test(`(.)^`, "(.)^") + + test(`<%-([\s\S]+?)%>|<%=([\s\S]+?)%>|<%([\s\S]+?)%>|$`, `<%-([\s\S]+?)%>|<%=([\s\S]+?)%>|<%([\s\S]+?)%>|$`) + + test(`\$`, `\$`) + + test(`[G-b]`, `[G-b]`) + + test(`[G-b\0]`, `[G-b\0]`) } - - test("", "") - - test("abc", "abc") - - test(`\abc`, `abc`) - - test(`\a\b\c`, `a\bc`) - - test(`\x`, `x`) - - test(`\c`, `c`) - - test(`\cA`, `\x01`) - - test(`\cz`, `\x1a`) - - test(`\ca`, `\x01`) - - test(`\cj`, `\x0a`) - - test(`\ck`, `\x0b`) - - test(`\+`, `\+`) - - test(`[\b]`, `[\x08]`) - - test(`\u0z01\x\undefined`, `u0z01xundefined`) - - test(`\\|'|\r|\n|\t|\u2028|\u2029`, `\\|'|\r|\n|\t|\x{2028}|\x{2029}`) - - test("]", "]") - - test("}", "}") - - test("%", "%") - - test("(%)", "(%)") - - test("(?:[%\\s])", "(?:[%\\s])") - - test("[[]", "[[]") - - test("\\101", "\\x41") - - test("\\51", "\\x29") - - test("\\051", "\\x29") - - test("\\175", "\\x7d") - - test("\\04", "\\x04") - - test(`<%([\s\S]+?)%>`, `<%([\s\S]+?)%>`) - - test(`(.)^`, "(.)^") - - test(`<%-([\s\S]+?)%>|<%=([\s\S]+?)%>|<%([\s\S]+?)%>|$`, `<%-([\s\S]+?)%>|<%=([\s\S]+?)%>|<%([\s\S]+?)%>|$`) - - test(`\$`, `\$`) - - test(`[G-b]`, `[G-b]`) - - test(`[G-b\0]`, `[G-b\0]`) - } + }) } func TestTransformRegExp(t *testing.T) { - Terst(t) - - pattern, err := TransformRegExp(`\s+abc\s+`) - Is(err, nil) - Is(pattern, `\s+abc\s+`) - Is(regexp.MustCompile(pattern).MatchString("\t abc def"), true) + tt(t, func() { + pattern, err := TransformRegExp(`\s+abc\s+`) + is(err, nil) + is(pattern, `\s+abc\s+`) + is(regexp.MustCompile(pattern).MatchString("\t abc def"), true) + }) } diff --git a/parser_test.go b/parser_test.go index 7406f60..7db43d2 100644 --- a/parser_test.go +++ b/parser_test.go @@ -1,35 +1,33 @@ package otto import ( - . "./terst" "testing" ) func TestPersistence(t *testing.T) { - Terst(t) + tt(t, func() { + test, _ := test() - _, test := runTestWithOtto() - - test(` + test(` function abc() { return 1; } abc.toString(); `, "function abc() { return 1; }") - test(` + test(` function def() { return 3.14159; } [ abc.toString(), def.toString() ]; `, "function abc() { return 1; },function def() { return 3.14159; }") - test(` + test(` eval("function ghi() { return 'ghi' }"); [ abc.toString(), def.toString(), ghi.toString() ]; `, "function abc() { return 1; },function def() { return 3.14159; },function ghi() { return 'ghi' }") - test(` + test(` [ abc.toString(), def.toString(), ghi.toString() ]; `, "function abc() { return 1; },function def() { return 3.14159; },function ghi() { return 'ghi' }") - test(`/* + test(`/* @@ -40,4 +38,5 @@ func TestPersistence(t *testing.T) { */`, UndefinedValue()) + }) } diff --git a/reflect_test.go b/reflect_test.go index 44db44f..f91b38c 100644 --- a/reflect_test.go +++ b/reflect_test.go @@ -1,7 +1,6 @@ package otto import ( - . "./terst" "math" "reflect" "testing" @@ -43,370 +42,370 @@ func (t testStruct) FuncVarArgs(as ...string) int { } func TestReflect(t *testing.T) { - Terst(t) - - if false { + return + tt(t, func() { // Testing dbgf // These should panic toValue("Xyzzy").toReflectValue(reflect.Ptr) stringToReflectValue("Xyzzy", reflect.Ptr) - } + }) } func Test_reflectStruct(t *testing.T) { - Terst(t) + tt(t, func() { + test, vm := test() - _, test := runTestWithOtto() + // testStruct + { + abc := &testStruct{} + vm.Set("abc", abc) - // testStruct - { - abc := &testStruct{} - failSet("abc", abc) + test(` + abc.FuncPointerReciever(); + `, "abc") - test(` - abc.FuncPointerReciever(); - `, "abc") + test(` + [ abc.Abc, abc.Ghi ]; + `, "false,") - test(` - [ abc.Abc, abc.Ghi ]; - `, "false,") + abc.Abc = true + abc.Ghi = "Nothing happens." - abc.Abc = true - abc.Ghi = "Nothing happens." + test(` + [ abc.Abc, abc.Ghi ]; + `, "true,Nothing happens.") - test(` - [ abc.Abc, abc.Ghi ]; - `, "true,Nothing happens.") + *abc = testStruct{} - *abc = testStruct{} + test(` + [ abc.Abc, abc.Ghi ]; + `, "false,") - test(` - [ abc.Abc, abc.Ghi ]; - `, "false,") + abc.Abc = true + abc.Ghi = "Xyzzy" + vm.Set("abc", abc) - abc.Abc = true - abc.Ghi = "Xyzzy" - failSet("abc", abc) + test(` + [ abc.Abc, abc.Ghi ]; + `, "true,Xyzzy") - test(` - [ abc.Abc, abc.Ghi ]; - `, "true,Xyzzy") + is(abc.Abc, true) + test(` + abc.Abc = false; + abc.Def = 451; + abc.Ghi = "Nothing happens."; + abc.abc = "Something happens."; + [ abc.Def, abc.abc ]; + `, "451,Something happens.") + is(abc.Abc, false) + is(abc.Def, 451) + is(abc.Ghi, "Nothing happens.") - Is(abc.Abc, true) - test(` - abc.Abc = false; - abc.Def = 451; - abc.Ghi = "Nothing happens."; - abc.abc = "Something happens."; - [ abc.Def, abc.abc ]; - `, "451,Something happens.") - Is(abc.Abc, false) - Is(abc.Def, 451) - Is(abc.Ghi, "Nothing happens.") + test(` + delete abc.Def; + delete abc.abc; + [ abc.Def, abc.abc ]; + `, "451,") + is(abc.Def, 451) - test(` - delete abc.Def; - delete abc.abc; - [ abc.Def, abc.abc ]; - `, "451,") - Is(abc.Def, 451) + test(` + abc.FuncNoArgsNoRet(); + `, "undefined") + test(` + abc.FuncNoArgs(); + `, "abc") + test(` + abc.FuncOneArgs("abc"); + `, "abc") + test(` + abc.FuncMultArgs("abc", "def"); + `, "abcdef") + test(` + abc.FuncVarArgs("abc", "def", "ghi"); + `, 3) - test(` - abc.FuncNoArgsNoRet(); - `, "undefined") - test(` - abc.FuncNoArgs(); - `, "abc") - test(` - abc.FuncOneArgs("abc"); - `, "abc") - test(` - abc.FuncMultArgs("abc", "def"); - `, "abcdef") - test(` - abc.FuncVarArgs("abc", "def", "ghi"); - `, "3") - - test(`raise: - abc.FuncNoArgsMultRet(); - `, "TypeError") - } + test(`raise: + abc.FuncNoArgsMultRet(); + `, "TypeError") + } + }) } func Test_reflectMap(t *testing.T) { - Terst(t) + tt(t, func() { + test, vm := test() - _, test := runTestWithOtto() + // map[string]string + { + abc := map[string]string{ + "Xyzzy": "Nothing happens.", + "def": "1", + } + vm.Set("abc", abc) - // map[string]string - { - abc := map[string]string{ - "Xyzzy": "Nothing happens.", - "def": "1", + test(` + abc.xyz = "pqr"; + [ abc.Xyzzy, abc.def, abc.ghi ]; + `, "Nothing happens.,1,") + + is(abc["xyz"], "pqr") } - failSet("abc", abc) - test(` - abc.xyz = "pqr"; - [ abc.Xyzzy, abc.def, abc.ghi ]; - `, "Nothing happens.,1,") + // map[string]float64 + { + abc := map[string]float64{ + "Xyzzy": math.Pi, + "def": 1, + } + vm.Set("abc", abc) - Is(abc["xyz"], "pqr") - } + test(` + abc.xyz = "pqr"; + abc.jkl = 10; + [ abc.Xyzzy, abc.def, abc.ghi ]; + `, "3.141592653589793,1,") - // map[string]float64 - { - abc := map[string]float64{ - "Xyzzy": math.Pi, - "def": 1, + is(abc["xyz"], math.NaN()) + is(abc["jkl"], float64(10)) } - failSet("abc", abc) - test(` - abc.xyz = "pqr"; - abc.jkl = 10; - [ abc.Xyzzy, abc.def, abc.ghi ]; - `, "3.141592653589793,1,") + // map[string]int32 + { + abc := map[string]int32{ + "Xyzzy": 3, + "def": 1, + } + vm.Set("abc", abc) - Is(abc["xyz"], "NaN") - Is(abc["jkl"], float64(10)) - } + test(` + abc.xyz = "pqr"; + abc.jkl = 10; + [ abc.Xyzzy, abc.def, abc.ghi ]; + `, "3,1,") - // map[string]int32 - { - abc := map[string]int32{ - "Xyzzy": 3, - "def": 1, + is(abc["xyz"], 0) + is(abc["jkl"], int32(10)) + + test(` + delete abc["Xyzzy"]; + `) + + _, exists := abc["Xyzzy"] + is(exists, false) + is(abc["Xyzzy"], 0) } - failSet("abc", abc) - test(` - abc.xyz = "pqr"; - abc.jkl = 10; - [ abc.Xyzzy, abc.def, abc.ghi ]; - `, "3,1,") + // map[int32]string + { + abc := map[int32]string{ + 0: "abc", + 1: "def", + } + vm.Set("abc", abc) - Is(abc["xyz"], 0) - Is(abc["jkl"], int32(10)) + test(` + abc[2] = "pqr"; + //abc.jkl = 10; + abc[3] = 10; + [ abc[0], abc[1], abc[2], abc[3] ] + `, "abc,def,pqr,10") - test(` - delete abc["Xyzzy"]; - `) + is(abc[2], "pqr") + is(abc[3], "10") - _, exists := abc["Xyzzy"] - IsFalse(exists) - Is(abc["Xyzzy"], 0) - } + test(` + delete abc[2]; + `) - // map[int32]string - { - abc := map[int32]string{ - 0: "abc", - 1: "def", + _, exists := abc[2] + is(exists, false) } - failSet("abc", abc) - - test(` - abc[2] = "pqr"; - //abc.jkl = 10; - abc[3] = 10; - [ abc[0], abc[1], abc[2], abc[3] ] - `, "abc,def,pqr,10") - - Is(abc[2], "pqr") - Is(abc[3], "10") - - test(` - delete abc[2]; - `) - - _, exists := abc[2] - IsFalse(exists) - } + }) } func Test_reflectSlice(t *testing.T) { - Terst(t) + tt(t, func() { + test, vm := test() - _, test := runTestWithOtto() + // []bool + { + abc := []bool{ + false, + true, + true, + false, + } + vm.Set("abc", abc) - // []bool - { - abc := []bool{ - false, - true, - true, - false, + test(` + abc; + `, "false,true,true,false") + + test(` + abc[0] = true; + abc[abc.length-1] = true; + delete abc[2]; + abc; + `, "true,true,false,true") + + is(abc, []bool{true, true, false, true}) + is(abc[len(abc)-1], true) } - failSet("abc", abc) - test(` - abc; - `, "false,true,true,false") + // []int32 + { + abc := make([]int32, 4) + vm.Set("abc", abc) - test(` - abc[0] = true; - abc[abc.length-1] = true; - delete abc[2]; - abc; - `, "true,true,false,true") + test(` + abc; + `, "0,0,0,0") - Is(abc, []bool{true, true, false, true}) - Is(abc[len(abc)-1], true) - } + test(` + abc[0] = 4.2; + abc[1] = "42"; + abc[2] = 3.14; + abc; + `, "4,42,3,0") - // []int32 - { - abc := make([]int32, 4) - failSet("abc", abc) + is(abc, []int32{4, 42, 3, 0}) - test(` - abc; - `, "0,0,0,0") - - test(` - abc[0] = 4.2; - abc[1] = "42"; - abc[2] = 3.14; - abc; - `, "4,42,3,0") - - Is(abc, []int32{4, 42, 3, 0}) - - test(` - delete abc[1]; - delete abc[2]; - `) - Is(abc[1], 0) - Is(abc[2], 0) - } + test(` + delete abc[1]; + delete abc[2]; + `) + is(abc[1], 0) + is(abc[2], 0) + } + }) } func Test_reflectArray(t *testing.T) { - Terst(t) + tt(t, func() { + test, vm := test() - _, test := runTestWithOtto() + // []bool + { + abc := [4]bool{ + false, + true, + true, + false, + } + vm.Set("abc", abc) - // []bool - { - abc := [4]bool{ - false, - true, - true, - false, + test(` + abc; + `, "false,true,true,false") + // Unaddressable array + + test(` + abc[0] = true; + abc[abc.length-1] = true; + abc; + `, "false,true,true,false") + // Again, unaddressable array + + is(abc, [4]bool{false, true, true, false}) + is(abc[len(abc)-1], false) + // ... } - failSet("abc", abc) - test(` - abc; - `, "false,true,true,false") - // Unaddressable array + // []int32 + { + abc := make([]int32, 4) + vm.Set("abc", abc) - test(` - abc[0] = true; - abc[abc.length-1] = true; - abc; - `, "false,true,true,false") - // Again, unaddressable array + test(` + abc; + `, "0,0,0,0") - Is(abc, [4]bool{false, true, true, false}) - Is(abc[len(abc)-1], false) - // ... - } + test(` + abc[0] = 4.2; + abc[1] = "42"; + abc[2] = 3.14; + abc; + `, "4,42,3,0") - // []int32 - { - abc := make([]int32, 4) - failSet("abc", abc) - - test(` - abc; - `, "0,0,0,0") - - test(` - abc[0] = 4.2; - abc[1] = "42"; - abc[2] = 3.14; - abc; - `, "4,42,3,0") - - Is(abc, []int32{4, 42, 3, 0}) - } - - // []bool - { - abc := [4]bool{ - false, - true, - true, - false, + is(abc, []int32{4, 42, 3, 0}) } - failSet("abc", &abc) - test(` - abc; - `, "false,true,true,false") + // []bool + { + abc := [4]bool{ + false, + true, + true, + false, + } + vm.Set("abc", &abc) - test(` - abc[0] = true; - abc[abc.length-1] = true; - delete abc[2]; - abc; - `, "true,true,false,true") + test(` + abc; + `, "false,true,true,false") - Is(abc, [4]bool{true, true, false, true}) - Is(abc[len(abc)-1], true) - } + test(` + abc[0] = true; + abc[abc.length-1] = true; + delete abc[2]; + abc; + `, "true,true,false,true") + is(abc, [4]bool{true, true, false, true}) + is(abc[len(abc)-1], true) + } + + }) } func Test_reflectArray_concat(t *testing.T) { - Terst(t) + tt(t, func() { + test, vm := test() - _, test := runTestWithOtto() - failSet("ghi", []string{"jkl", "mno"}) - failSet("pqr", []interface{}{"jkl", 42, 3.14159, true}) - test(` - var def = { - "abc": ["abc"], - "xyz": ["xyz"] - }; - xyz = pqr.concat(ghi, def.abc, def, def.xyz); - [ xyz, xyz.length ]; - `, "jkl,42,3.14159,true,jkl,mno,abc,[object Object],xyz,9") + vm.Set("ghi", []string{"jkl", "mno"}) + vm.Set("pqr", []interface{}{"jkl", 42, 3.14159, true}) + test(` + var def = { + "abc": ["abc"], + "xyz": ["xyz"] + }; + xyz = pqr.concat(ghi, def.abc, def, def.xyz); + [ xyz, xyz.length ]; + `, "jkl,42,3.14159,true,jkl,mno,abc,[object Object],xyz,9") + }) } func Test_reflectMapInterface(t *testing.T) { - Terst(t) + tt(t, func() { + test, vm := test() - _, test := runTestWithOtto() + { + abc := map[string]interface{}{ + "Xyzzy": "Nothing happens.", + "def": "1", + "jkl": "jkl", + } + vm.Set("abc", abc) + vm.Set("mno", &testStruct{}) - { - abc := map[string]interface{}{ - "Xyzzy": "Nothing happens.", - "def": "1", - "jkl": "jkl", + test(` + abc.xyz = "pqr"; + abc.ghi = {}; + abc.jkl = 3.14159; + abc.mno = mno; + mno.Abc = true; + mno.Ghi = "Something happens."; + [ abc.Xyzzy, abc.def, abc.ghi, abc.mno ]; + `, "Nothing happens.,1,[object Object],[object Object]") + + is(abc["xyz"], "pqr") + is(abc["ghi"], "[object Object]") + is(abc["jkl"], float64(3.14159)) + mno, valid := abc["mno"].(*testStruct) + is(valid, true) + is(mno.Abc, true) + is(mno.Ghi, "Something happens.") } - failSet("abc", abc) - failSet("mno", &testStruct{}) - - test(` - abc.xyz = "pqr"; - abc.ghi = {}; - abc.jkl = 3.14159; - abc.mno = mno; - mno.Abc = true; - mno.Ghi = "Something happens."; - [ abc.Xyzzy, abc.def, abc.ghi, abc.mno ]; - `, "Nothing happens.,1,[object Object],[object Object]") - - Is(abc["xyz"], "pqr") - Is(abc["ghi"], "[object Object]") - Equal(abc["jkl"], float64(3.14159)) - mno, valid := abc["mno"].(*testStruct) - Is(valid, true) - Is(mno.Abc, true) - Is(mno.Ghi, "Something happens.") - } + }) } diff --git a/regexp_test.go b/regexp_test.go index 325d459..36183a0 100644 --- a/regexp_test.go +++ b/regexp_test.go @@ -1,275 +1,287 @@ package otto import ( - . "./terst" "fmt" "testing" ) func TestRegExp(t *testing.T) { - Terst(t) + tt(t, func() { + test, _ := test() - test := runTest() + test(` + [ + /abc/.toString(), + /abc/gim.toString(), + ""+/abc/gi.toString(), + new RegExp("1(\\d+)").toString(), + ]; + `, "/abc/,/abc/gim,/abc/gi,/1(\\d+)/") - test(` - [ - /abc/.toString(), - /abc/gim.toString(), - ""+/abc/gi.toString(), - new RegExp("1(\\d+)").toString(), - ]; - `, "/abc/,/abc/gim,/abc/gi,/1(\\d+)/") + test(` + [ + new RegExp("abc").exec("123abc456"), + null === new RegExp("xyzzy").exec("123abc456"), + new RegExp("1(\\d+)").exec("123abc456"), + new RegExp("xyzzy").test("123abc456"), + new RegExp("1(\\d+)").test("123abc456"), + new RegExp("abc").exec("123abc456"), + ]; + `, "abc,true,123,23,false,true,abc") - test(` - [ - new RegExp("abc").exec("123abc456"), - null === new RegExp("xyzzy").exec("123abc456"), - new RegExp("1(\\d+)").exec("123abc456"), - new RegExp("xyzzy").test("123abc456"), - new RegExp("1(\\d+)").test("123abc456"), - new RegExp("abc").exec("123abc456"), - ]; - `, "abc,true,123,23,false,true,abc") + test(`new RegExp("abc").toString()`, "/abc/") + test(`new RegExp("abc", "g").toString()`, "/abc/g") + test(`new RegExp("abc", "mig").toString()`, "/abc/gim") - test(`new RegExp("abc").toString()`, "/abc/") - test(`new RegExp("abc", "g").toString()`, "/abc/g") - test(`new RegExp("abc", "mig").toString()`, "/abc/gim") + result := test(`/(a)?/.exec('b')`, ",") + is(result._object().get("0"), "") + is(result._object().get("1"), "undefined") + is(result._object().get("length"), 2) - result := test(`/(a)?/.exec('b')`, ",") - Is(result._object().get("0"), "") - Is(result._object().get("1"), "undefined") - Is(result._object().get("length"), "2") + result = test(`/(a)?(b)?/.exec('b')`, "b,,b") + is(result._object().get("0"), "b") + is(result._object().get("1"), "undefined") + is(result._object().get("2"), "b") + is(result._object().get("length"), 3) - result = test(`/(a)?(b)?/.exec('b')`, "b,,b") - Is(result._object().get("0"), "b") - Is(result._object().get("1"), "undefined") - Is(result._object().get("2"), "b") - Is(result._object().get("length"), "3") + test(`/\u0041/.source`, "\\u0041") + test(`/\a/.source`, "\\a") + test(`/\;/.source`, "\\;") - test(`/\u0041/.source`, "\\u0041") - test(`/\a/.source`, "\\a") - test(`/\;/.source`, "\\;") + test(`/a\a/.source`, "a\\a") + test(`/,\;/.source`, ",\\;") + test(`/ \ /.source`, " \\ ") - test(`/a\a/.source`, "a\\a") - test(`/,\;/.source`, ",\\;") - test(`/ \ /.source`, " \\ ") + // Start sanity check... + test("eval(\"/abc/\").source", "abc") + test("eval(\"/\u0023/\").source", "#") + test("eval(\"/\u0058/\").source", "X") + test("eval(\"/\\\u0023/\").source == \"\\\u0023\"", true) + test("'0x' + '0058'", "0x0058") + test("'\\\\' + '0x' + '0058'", "\\0x0058") + // ...stop sanity check - // Start sanity check... - test("eval(\"/abc/\").source", "abc") - test("eval(\"/\u0023/\").source", "#") - test("eval(\"/\u0058/\").source", "X") - test("eval(\"/\\\u0023/\").source == \"\\\u0023\"", "true") - test("'0x' + '0058'", "0x0058") - test("'\\\\' + '0x' + '0058'", "\\0x0058") - // ...stop sanity check + test(`abc = '\\' + String.fromCharCode('0x' + '0058'); eval('/' + abc + '/').source`, "\\X") + test(`abc = '\\' + String.fromCharCode('0x0058'); eval('/' + abc + '/').source == "\\\u0058"`, true) + test(`abc = '\\' + String.fromCharCode('0x0023'); eval('/' + abc + '/').source == "\\\u0023"`, true) + test(`abc = '\\' + String.fromCharCode('0x0078'); eval('/' + abc + '/').source == "\\\u0078"`, true) - test(`abc = '\\' + String.fromCharCode('0x' + '0058'); eval('/' + abc + '/').source`, "\\X") - test(`abc = '\\' + String.fromCharCode('0x0058'); eval('/' + abc + '/').source == "\\\u0058"`, "true") - test(`abc = '\\' + String.fromCharCode('0x0023'); eval('/' + abc + '/').source == "\\\u0023"`, "true") - test(`abc = '\\' + String.fromCharCode('0x0078'); eval('/' + abc + '/').source == "\\\u0078"`, "true") - - test(` - var abc = Object.getOwnPropertyDescriptor(RegExp, "prototype"); - [ [ typeof RegExp.prototype ], - [ abc.writable, abc.enumerable, abc.configurable ] ]; - `, "object,false,false,false") + test(` + var abc = Object.getOwnPropertyDescriptor(RegExp, "prototype"); + [ [ typeof RegExp.prototype ], + [ abc.writable, abc.enumerable, abc.configurable ] ]; + `, "object,false,false,false") + }) } func TestRegExp_global(t *testing.T) { - Terst(t) + tt(t, func() { + test, _ := test() - test := runTest() - test(` - var abc = /(?:ab|cd)\d?/g; - var found = []; - do { - match = abc.exec("ab cd2 ab34 cd"); - if (match !== null) { - found.push(match[0]); - } else { - break; - } - } while (true); - found; - `, "ab,cd2,ab3,cd") + test(` + var abc = /(?:ab|cd)\d?/g; + var found = []; + do { + match = abc.exec("ab cd2 ab34 cd"); + if (match !== null) { + found.push(match[0]); + } else { + break; + } + } while (true); + found; + `, "ab,cd2,ab3,cd") + }) } func TestRegExp_exec(t *testing.T) { - Terst(t) + tt(t, func() { + test, _ := test() - test := runTest() - test(` - abc = /./g; - def = '123456'; - ghi = 0; - while (ghi < 100 && abc.exec(def) !== null) { - ghi += 1; - } - [ ghi, def.length, ghi == def.length ]; - `, "6,6,true") + test(` + abc = /./g; + def = '123456'; + ghi = 0; + while (ghi < 100 && abc.exec(def) !== null) { + ghi += 1; + } + [ ghi, def.length, ghi == def.length ]; + `, "6,6,true") - test(` - abc = /[abc](\d)?/g; - def = 'a0 b c1 d3'; - ghi = 0; - lastIndex = 0; - while (ghi < 100 && abc.exec(def) !== null) { - lastIndex = abc.lastIndex; - ghi += 1; + test(` + abc = /[abc](\d)?/g; + def = 'a0 b c1 d3'; + ghi = 0; + lastIndex = 0; + while (ghi < 100 && abc.exec(def) !== null) { + lastIndex = abc.lastIndex; + ghi += 1; - } - [ ghi, lastIndex ]; - `, "3,7") + } + [ ghi, lastIndex ]; + `, "3,7") - test(` - var abc = /[abc](\d)?/.exec("a0 b c1 d3"); - [ abc.length, abc.input, abc.index, abc ]; - `, "2,a0 b c1 d3,0,a0,0") + test(` + var abc = /[abc](\d)?/.exec("a0 b c1 d3"); + [ abc.length, abc.input, abc.index, abc ]; + `, "2,a0 b c1 d3,0,a0,0") - test(`raise: - var exec = RegExp.prototype.exec; - exec("Xyzzy"); - `, "TypeError: Calling RegExp.exec on a non-RegExp object") + test(`raise: + var exec = RegExp.prototype.exec; + exec("Xyzzy"); + `, "TypeError: Calling RegExp.exec on a non-RegExp object") - test(` - var abc = /\w{3}\d?/.exec("CE\uFFFFL\uFFDDbox127"); - [ abc.input.length, abc.length, abc.input, abc.index, abc ]; - `, "11,1,CE\uFFFFL\uFFDDbox127,5,box1") + test(` + var abc = /\w{3}\d?/.exec("CE\uFFFFL\uFFDDbox127"); + [ abc.input.length, abc.length, abc.input, abc.index, abc ]; + `, "11,1,CE\uFFFFL\uFFDDbox127,5,box1") - test(`RegExp.prototype.exec.length`, "1") - test(`RegExp.prototype.exec.prototype`, "undefined") + test(`RegExp.prototype.exec.length`, 1) + test(`RegExp.prototype.exec.prototype`, "undefined") + }) } func TestRegExp_test(t *testing.T) { - Terst(t) + tt(t, func() { + test, _ := test() - test := runTest() - test(`RegExp.prototype.test.length`, "1") - test(`RegExp.prototype.test.prototype`, "undefined") + test(`RegExp.prototype.test.length`, 1) + test(`RegExp.prototype.test.prototype`, "undefined") + }) } func TestRegExp_toString(t *testing.T) { - Terst(t) + tt(t, func() { + test, _ := test() - test := runTest() - test(`RegExp.prototype.toString.length`, "0") - test(`RegExp.prototype.toString.prototype`, "undefined") + test(`RegExp.prototype.toString.length`, 0) + test(`RegExp.prototype.toString.prototype`, "undefined") + }) } func TestRegExp_zaacbbbcac(t *testing.T) { - Terst(t) + return + tt(t, func() { + test, _ := test() - test := runTest() - if false { // FIXME? TODO /(z)((a+)?(b+)?(c))*/.exec("zaacbbbcac") test(` var abc = /(z)((a+)?(b+)?(c))*/.exec("zaacbbbcac"); [ abc.length, abc.index, abc ]; `, "6,0,zaacbbbcac,z,ac,a,,c") - } + }) } func TestRegExpCopying(t *testing.T) { - Terst(t) + tt(t, func() { + test, _ := test() - test := runTest() - test(` - abc = /xyzzy/i; - def = RegExp(abc); - abc.indicator = 1; - [ abc.indicator, def.indicator ]; - `, "1,1") + test(` + abc = /xyzzy/i; + def = RegExp(abc); + abc.indicator = 1; + [ abc.indicator, def.indicator ]; + `, "1,1") - test(`raise: - RegExp(new RegExp("\\d"), "1"); - `, "TypeError: Cannot supply flags when constructing one RegExp from another") + test(`raise: + RegExp(new RegExp("\\d"), "1"); + `, "TypeError: Cannot supply flags when constructing one RegExp from another") + }) } func TestRegExp_multiline(t *testing.T) { - Terst(t) + tt(t, func() { + test, _ := test() - test := runTest() - test(` - var abc = /s$/m.exec("pairs\nmakes\tdouble"); - [ abc.length, abc.index, abc ]; - `, "1,4,s") + test(` + var abc = /s$/m.exec("pairs\nmakes\tdouble"); + [ abc.length, abc.index, abc ]; + `, "1,4,s") + }) } func TestRegExp_source(t *testing.T) { - Terst(t) + tt(t, func() { + test, _ := test() - test := runTest() - test(` - [ /xyzzy/i.source, /./i.source ]; - `, "xyzzy,.") + test(` + [ /xyzzy/i.source, /./i.source ]; + `, "xyzzy,.") - test(` - var abc = /./i; - var def = new RegExp(abc); - [ abc.source, def.source, abc.source === def.source ]; - `, ".,.,true") + test(` + var abc = /./i; + var def = new RegExp(abc); + [ abc.source, def.source, abc.source === def.source ]; + `, ".,.,true") - test(` - var abc = /./i; - var def = abc.hasOwnProperty("source"); - var ghi = abc.source; - abc.source = "xyzzy"; - [ def, abc.source ]; - `, "true,.") + test(` + var abc = /./i; + var def = abc.hasOwnProperty("source"); + var ghi = abc.source; + abc.source = "xyzzy"; + [ def, abc.source ]; + `, "true,.") + }) } func TestRegExp_newRegExp(t *testing.T) { - Terst(t) + tt(t, func() { + test, _ := test() - test := runTest() - test(` - Math.toString(); - var abc = new RegExp(Math,eval("\"g\"")); - [ abc, abc.global ]; - `, "/[object Math]/g,true") + test(` + Math.toString(); + var abc = new RegExp(Math,eval("\"g\"")); + [ abc, abc.global ]; + `, "/[object Math]/g,true") + }) } func TestRegExp_flags(t *testing.T) { - Terst(t) + tt(t, func() { + test, _ := test() - test := runTest() - test(` - var abc = /./i; - var def = new RegExp(abc); - [ abc.multiline == def.multiline, abc.global == def.global, abc.ignoreCase == def.ignoreCase ]; - `, "true,true,true") + test(` + var abc = /./i; + var def = new RegExp(abc); + [ abc.multiline == def.multiline, abc.global == def.global, abc.ignoreCase == def.ignoreCase ]; + `, "true,true,true") + }) } func TestRegExp_controlCharacter(t *testing.T) { - Terst(t) + tt(t, func() { + test, _ := test() - test := runTest() - for code := 0x41; code < 0x5a; code++ { - string_ := string(code - 64) - test(fmt.Sprintf(` - var code = 0x%x; - var string = String.fromCharCode(code %% 32); - var result = (new RegExp("\\c" + String.fromCharCode(code))).exec(string); - [ code, string, result ]; - `, code), fmt.Sprintf("%d,%s,%s", code, string_, string_)) - } + for code := 0x41; code < 0x5a; code++ { + string_ := string(code - 64) + test(fmt.Sprintf(` + var code = 0x%x; + var string = String.fromCharCode(code %% 32); + var result = (new RegExp("\\c" + String.fromCharCode(code))).exec(string); + [ code, string, result ]; + `, code), fmt.Sprintf("%d,%s,%s", code, string_, string_)) + } + }) } func TestRegExp_notNotEmptyCharacterClass(t *testing.T) { - Terst(t) - test := runTest() - test(` - var abc = /[\s\S]a/m.exec("a\naba"); - [ abc.length, abc.input, abc ]; - `, "1,a\naba,\na") + tt(t, func() { + test, _ := test() + + test(` + var abc = /[\s\S]a/m.exec("a\naba"); + [ abc.length, abc.input, abc ]; + `, "1,a\naba,\na") + }) } func TestRegExp_compile(t *testing.T) { - Terst(t) + tt(t, func() { + test, _ := test() - test := runTest() - test(` - var abc = /[\s\S]a/; - abc.compile('^\w+'); - `, "undefined") + test(` + var abc = /[\s\S]a/; + abc.compile('^\w+'); + `, "undefined") + }) } diff --git a/runtime_test.go b/runtime_test.go index 9a7325d..8706d59 100644 --- a/runtime_test.go +++ b/runtime_test.go @@ -1,819 +1,778 @@ package otto import ( - . "./terst" "math" "testing" ) +// FIXME terst, Review tests + func TestOperator(t *testing.T) { - Terst(t) + tt(t, func() { + test, vm := test() - Otto, test := runTestWithOtto() + test("xyzzy = 1") + test("xyzzy", 1) - test("xyzzy = 1") - test("xyzzy", "1") + if true { + vm.Set("twoPlusTwo", func(FunctionCall) Value { + return toValue(5) + }) + test("twoPlusTwo( 1 )", 5) - if true { - Otto.Set("twoPlusTwo", func(FunctionCall) Value { - return toValue(5) - }) - test("twoPlusTwo( 1 )", "5") + test("1 + twoPlusTwo( 1 )", 6) - test("1 + twoPlusTwo( 1 )", "6") + test("-1 + twoPlusTwo( 1 )", 4) + } - test("-1 + twoPlusTwo( 1 )", "4") - } + test("result = 4") + test("result", 4) - test("result = 4") - test("result", "4") + test("result += 1") + test("result", 5) - test("result += 1") - test("result", "5") + test("result *= 2") + test("result", 10) - test("result *= 2") - test("result", "10") + test("result /= 2") + test("result", 5) - test("result /= 2") - test("result", "5") + test("result = 112.51 % 3.1") + test("result", 0.9100000000000019) - test("result = 112.51 % 3.1") - test("result", "0.9100000000000019") + test("result = 'Xyzzy'") + test("result", "Xyzzy") - test("result = 'Xyzzy'") - test("result", "Xyzzy") + test("result = 'Xyz' + 'zy'") + test("result", "Xyzzy") - test("result = 'Xyz' + 'zy'") - test("result", "Xyzzy") + test("result = \"Xyzzy\"") + test("result", "Xyzzy") - test("result = \"Xyzzy\"") - test("result", "Xyzzy") + test("result = 1; result = result") + test("result", 1) - test("result = 1; result = result") - test("result", "1") + test(` + var result64 + = + 64 + , result10 = + 10 + `) + test("result64", 64) + test("result10", 10) - test(` - var result64 - = - 64 - , result10 = - 10 - `) - test("result64", "64") - test("result10", "10") - - test(` - result = 1; - result += 1; - `) - test("result", "2") + test(` + result = 1; + result += 1; + `) + test("result", 2) + }) } func TestFunction_(t *testing.T) { - Terst(t) + tt(t, func() { + test, _ := test() - test := runTest() - test(` - result = 2 - xyzzy = function() { - result += 1 - } - xyzzy() - `) - test("result", "3") - - test(` - xyzzy = function() { - return 1 - } - result = xyzzy() - `) - test("result", "1") - - test(` - xyzzy = function() {} - result = xyzzy() - `) - test("result", "undefined") - - test(` - xyzzy = function() { - return 64 - return 1 - } - result = xyzzy() - `) - test("result", "64") - - test(` - result = 4 - xyzzy = function() { - result = 2 - } - xyzzy() - `) - test("result", "2") - - test(` - result = 4 - xyzzy = function() { - var result - result = 2 - } - xyzzy() - `) - test("result", "4") - - test(` - xyzzy = function() { - var result = 4 - return result - } - result = xyzzy() - `) - test("result", "4") - - test(` - xyzzy = function() { - function test() { - var result = 1 - return result - } - return test() + 1 - } - result = xyzzy() + 1 - `) - test("result", "3") - - test(` - xyzzy = function() { - function test() { - var result = 1 - return result - } - _xyzzy = 2 - var result = _xyzzy + test() + 1 - return result - } - result = xyzzy() + 1 - `) - test("result", "5") - test("_xyzzy", "2") - - test(` - xyzzy = function(apple) { - return 1 - } - result = xyzzy(1) - `) - test("result", "1") - - test(` - xyzzy = function(apple) { - return apple + 1 - } - result = xyzzy(2) - `) - test("result", "3") - - test(` - { - result = 1 - result += 1; - } - `) - test("result", "2") - - test(` - var global = 1 - outer = function() { - var global = 2 - var inner = function(){ - return global - } - return inner() - } - result = outer() - `) - test("result", "2") - - test(` - var apple = 1 - var banana = function() { - return apple - } - var cherry = function() { - var apple = 2 - return banana() - } - result = cherry() - `) - test("result", "1") - - test(` - function xyz() { - }; - delete xyz; - `, "false") - - test(` - var abc = function __factorial(def){ - if (def === 1) { - return def; - } else { - return __factorial(def-1)*def; + test(` + result = 2 + xyzzy = function() { + result += 1 } - }; - abc(3); - `, "6") + xyzzy() + result; + `, 3) + + test(` + xyzzy = function() { + return 1 + } + result = xyzzy() + `, 1) + + test(` + xyzzy = function() {} + result = xyzzy() + `, "undefined") + + test(` + xyzzy = function() { + return 64 + return 1 + } + result = xyzzy() + `, 64) + + test(` + result = 4 + xyzzy = function() { + result = 2 + } + xyzzy(); + result; + `, 2) + + test(` + result = 4 + xyzzy = function() { + var result + result = 2 + } + xyzzy(); + result; + `, 4) + + test(` + xyzzy = function() { + var result = 4 + return result + } + result = xyzzy() + `, 4) + + test(` + xyzzy = function() { + function test() { + var result = 1 + return result + } + return test() + 1 + } + result = xyzzy() + 1 + `, 3) + + test(` + xyzzy = function() { + function test() { + var result = 1 + return result + } + _xyzzy = 2 + var result = _xyzzy + test() + 1 + return result + } + result = xyzzy() + 1; + [ result, _xyzzy ]; + `, "5,2") + + test(` + xyzzy = function(apple) { + return 1 + } + result = xyzzy(1) + `, 1) + + test(` + xyzzy = function(apple) { + return apple + 1 + } + result = xyzzy(2) + `, 3) + + test(` + { + result = 1 + result += 1; + } + `, 2) + + test(` + var global = 1 + outer = function() { + var global = 2 + var inner = function(){ + return global + } + return inner() + } + result = outer() + `, 2) + + test(` + var apple = 1 + var banana = function() { + return apple + } + var cherry = function() { + var apple = 2 + return banana() + } + result = cherry() + `, 1) + + test(` + function xyz() { + }; + delete xyz; + `, false) + + test(` + var abc = function __factorial(def){ + if (def === 1) { + return def; + } else { + return __factorial(def-1)*def; + } + }; + abc(3); + `, 6) + }) } func TestDoWhile(t *testing.T) { - Terst(t) + tt(t, func() { + test, _ := test() - test := runTest() + test(` + limit = 4; + result = 0; + do { + result = result + 1; + limit = limit - 1; + } while (limit); + result; + `, 4) - test(` - limit = 4; - result = 0; - do { - result = result + 1; - limit = limit - 1; - } while (limit); - result; - `, "4") - - test(` - result = eval("do {abc=1; break; abc=2;} while (0);"); - [ result, abc ]; - `, "1,1") + test(` + result = eval("do {abc=1; break; abc=2;} while (0);"); + [ result, abc ]; + `, "1,1") + }) } func TestContinueBreak(t *testing.T) { - Terst(t) + tt(t, func() { + test, _ := test() - test := runTest() + test(` + limit = 4 + result = 0 + while (limit) { + limit = limit - 1 + if (limit) { + } + else { + break + } + result = result + 1 + } + [ result, limit ]; + `, "3,0") - test(` - limit = 4 - result = 0 - while (limit) { - limit = limit - 1 - if (limit) { - } - else { - break - } - result = result + 1 - } - `) - test("result", "3") - test("limit", "0") + test(` + limit = 4 + result = 0 + while (limit) { + limit = limit - 1 + if (limit) { + continue + } + else { + break + } + result = result + 1 + } + result; + `, 0) - test(` - limit = 4 - result = 0 - while (limit) { - limit = limit - 1 - if (limit) { - continue - } - else { - break - } - result = result + 1 - } - `) - test("result", "0") - - test(` - limit = 4 - result = 0 - do { - limit = limit - 1 - if (limit) { - continue - } - else { - break - } - result = result + 1 - } while (limit) - `) - test("result", "0") + test(` + limit = 4 + result = 0 + do { + limit = limit - 1 + if (limit) { + continue + } + else { + break + } + result = result + 1 + } while (limit) + result; + `, 0) + }) } func TestTryCatchError(t *testing.T) { - Terst(t) + tt(t, func() { + test, _ := test() - test := runTest() - - test(` - var abc - try { - 1() - } - catch (def) { - abc = def - } - abc - `, "TypeError: 1 is not a function") + test(` + var abc + try { + 1() + } + catch (def) { + abc = def + } + abc; + `, "TypeError: 1 is not a function") + }) } func TestPositiveNegativeZero(t *testing.T) { - Terst(t) + tt(t, func() { + test, _ := test() - test := runTest() - - test(`1/0`, "Infinity") - test(`1/-0`, "-Infinity") - test(` - abc = -0 - 1/abc - `, - "-Infinity", - ) + test(`1/0`, _Infinity) + test(`1/-0`, -_Infinity) + test(` + abc = -0 + 1/abc + `, -_Infinity) + }) } func TestComparison(t *testing.T) { - Terst(t) + tt(t, func() { + test, _ := test() - test := runTest() + test(` + undefined = 1; undefined; + `, "undefined") - test("undefined = 1") - test("undefined", "undefined") + test("undefined == undefined", true) - test("result = undefined == undefined") - test("result", "true") + test("undefined != undefined", false) - test("result = undefined != undefined") - test("result", "false") + test("null == null", true) - test("result = null == null") - test("result", "true") + test("null != null", false) - test("result = null != null") - test("result", "false") + test("0 == 1", false) - test("result = 0 == 1") - test("result", "false") + is(negativeZero(), -0) + is(positiveZero(), 0) + is(math.Signbit(negativeZero()), true) + is(positiveZero() == negativeZero(), true) - Is(negativeZero(), "-0") - Is(positiveZero(), "0") - IsTrue(math.Signbit(negativeZero())) - IsTrue(positiveZero() == negativeZero()) + test("1 == 1", true) - test("result = 1 == 1") - test("result", "true") + test("'Hello, World.' == 'Goodbye, World.'", false) - test("result = 'Hello, World.' == 'Goodbye, World.'") - test("result", "false") + test("'Hello, World.' == true", false) - test("result = 'Hello, World.' == true") - test("result", "false") + test("'Hello, World.' == false", false) - test("result = 'Hello, World.' == false") - test("result", "false") + test("'Hello, World.' == 1", false) - test("result = 'Hello, World.' == 1") - test("result", "false") + test("1 == 'Hello, World.'", false) - test("result = 1 == 'Hello, World.'") - test("result", "false") + is(stringToFloat("-1"), -1) - Is(stringToFloat("-1"), -1) - - test("result = 0+Object") - test("result", "0function Object() { [native code] }") + test("0+Object", "0function Object() { [native code] }") + }) } func TestComparisonRelational(t *testing.T) { - Terst(t) + tt(t, func() { + test, _ := test() - test := runTest() + test("0 < 0", false) - test("result = 0 < 0") - test("result", "false") + test("0 > 0", false) - test("result = 0 > 0") - test("result", "false") + test("0 <= 0", true) - test("result = 0 <= 0") - test("result", "true") + test("0 >= 0", true) - test("result = 0 >= 0") - test("result", "true") + test("' 0' >= 0", true) - test("result = ' 0' >= 0") - test("result", "true") - - test("result = '_ 0' >= 0") - test("result", "false") + test("'_ 0' >= 0", false) + }) } func TestArguments(t *testing.T) { - Terst(t) + tt(t, func() { + test, _ := test() - test := runTest() - test(` - xyzzy = function() { - return arguments[0] - } - result = xyzzy("xyzzy") - `) - test("result", "xyzzy") + test(` + xyzzy = function() { + return arguments[0] + } + result = xyzzy("xyzzy"); + `, "xyzzy") - test(` - xyzzy = function() { - arguments[0] = "abcdef" - return arguments[0] - } - result = xyzzy("xyzzy") - `) - test("result", "abcdef") + test(` + xyzzy = function() { + arguments[0] = "abcdef" + return arguments[0] + } + result = xyzzy("xyzzy"); + `, "abcdef") - test(` - xyzzy = function(apple) { - apple = "abcdef" - return arguments[0] - } - result = xyzzy("xyzzy") - `) - test("result", "abcdef") + test(` + xyzzy = function(apple) { + apple = "abcdef" + return arguments[0] + } + result = xyzzy("xyzzy"); + `, "abcdef") - test(` - (function(){ - return arguments - })() - `, "[object Arguments]") + test(` + (function(){ + return arguments + })() + `, "[object Arguments]") - test(` - (function(){ - return arguments.length - })() - `, "0") + test(` + (function(){ + return arguments.length + })() + `, 0) - test(` - (function(){ - return arguments.length - })(1, 2, 4, 8, 10) - `, "5") + test(` + (function(){ + return arguments.length + })(1, 2, 4, 8, 10) + `, 5) + }) } func TestObjectLiteral(t *testing.T) { - Terst(t) + tt(t, func() { + test, _ := test() - test := runTest() + test(` + ({}); + `, "[object Object]") - test(` - ({}); - `, "[object Object]") + test(` + var abc = { + xyzzy: "Nothing happens.", + get 1e2() { + return 3.14159; + }, + get null() { + return true; + }, + get "[\n]"() { + return "<>"; + } + }; + [ abc["1e2"], abc.null, abc["[\n]"] ]; + `, "3.14159,true,<>") - test(` - var abc = { - xyzzy: "Nothing happens.", - get 1e2() { - return 3.14159; - }, - get null() { - return true; - }, - get "[\n]"() { - return "<>"; - } - }; - [ abc["1e2"], abc.null, abc["[\n]"] ]; - `, "3.14159,true,<>") - - test(` - var abc = { - xyzzy: "Nothing happens.", - set 1e2() { - this[3.14159] = 100; - return Math.random(); - }, - set null(def) { - this.def = def; - return Math.random(); - }, - }; - [ abc["1e2"] = Infinity, abc[3.14159], abc.null = "xyz", abc.def ]; - `, "Infinity,100,xyz,xyz") + test(` + var abc = { + xyzzy: "Nothing happens.", + set 1e2() { + this[3.14159] = 100; + return Math.random(); + }, + set null(def) { + this.def = def; + return Math.random(); + }, + }; + [ abc["1e2"] = Infinity, abc[3.14159], abc.null = "xyz", abc.def ]; + `, "Infinity,100,xyz,xyz") + }) } func TestUnaryPrefix(t *testing.T) { - Terst(t) + tt(t, func() { + test, _ := test() - test := runTest() + test(` + var result = 0; + [++result, result]; + `, "1,1") - test(` - var result = 0; - [++result, result]; - `, "1,1") + test(` + result = 0; + [--result, result]; + `, "-1,-1") - test(` - result = 0; - [--result, result]; - `, "-1,-1") + test(` + var object = { valueOf: function() { return 1; } }; + result = ++object; + [ result, typeof result ]; + `, "2,number") - test(` - var object = { valueOf: function() { return 1; } }; - result = ++object; - [ result, typeof result ]; - `, "2,number") - - test(` - var object = { valueOf: function() { return 1; } }; - result = --object; - [ result, typeof result ]; - `, "0,number") + test(` + var object = { valueOf: function() { return 1; } }; + result = --object; + [ result, typeof result ]; + `, "0,number") + }) } func TestUnaryPostfix(t *testing.T) { - Terst(t) + tt(t, func() { + test, _ := test() - test := runTest() + test(` + var result = 0; + result++; + [ result++, result ]; + `, "1,2") - test(` - var result = 0; - result++; - [ result++, result ]; - `, "1,2") + test(` + result = 0; + result--; + [ result--, result ]; + `, "-1,-2") - test(` - result = 0; - result--; - [ result--, result ]; - `, "-1,-2") + test(` + var object = { valueOf: function() { return 1; } }; + result = object++; + [ result, typeof result ]; + `, "1,number") - test(` - var object = { valueOf: function() { return 1; } }; - result = object++; - [ result, typeof result ]; - `, "1,number") - - test(` - var object = { valueOf: function() { return 1; } }; - result = object-- - [ result, typeof result ]; - `, "1,number") + test(` + var object = { valueOf: function() { return 1; } }; + result = object-- + [ result, typeof result ]; + `, "1,number") + }) } func TestBinaryLogicalOperation(t *testing.T) { - Terst(t) + tt(t, func() { + test, _ := test() - test := runTest() + test(` + abc = true + def = false + ghi = false + jkl = false + result = abc && def || ghi && jkl + `, false) - test(` - abc = true - def = false - ghi = false - jkl = false - result = abc && def || ghi && jkl - `) - test("result", "false") - - test(` - abc = true - def = true - ghi = false - jkl = false - result = abc && def || ghi && jkl - `) - test("result", "true") + test(` + abc = true + def = true + ghi = false + jkl = false + result = abc && def || ghi && jkl + `, true) + }) } func TestBinaryBitwiseOperation(t *testing.T) { - Terst(t) + tt(t, func() { + test, _ := test() - test := runTest() - - test(` - abc = 1 & 2 - def = 1 & 3 - ghi = 1 | 3 - jkl = 1 ^ 2 - mno = 1 ^ 3 - - `) - test("abc", "0") - test("def", "1") - test("ghi", "3") - test("jkl", "3") - test("mno", "2") + test(` + abc = 1 & 2; + def = 1 & 3; + ghi = 1 | 3; + jkl = 1 ^ 2; + mno = 1 ^ 3; + [ abc, def, ghi, jkl, mno ]; + `, "0,1,3,3,2") + }) } func TestBinaryShiftOperation(t *testing.T) { - Terst(t) - - test := runTest() - - test(` - high = (1 << 30) - 1 + (1 << 30) - low = -high - 1 - abc = 23 << 1 - def = -105 >> 1 - ghi = 23 << 2 - jkl = 1 >>> 31 - mno = 1 << 64 - pqr = 1 >> 2 - stu = -2 >> 4 - vwx = low >> 1 - yz = low >>> 1 - `) - test("abc", "46") - test("def", "-53") - test("ghi", "92") - test("jkl", "0") - test("mno", "1") - test("pqr", "0") - test("stu", "-1") - test("vwx", "-1073741824") - test("yz", "1073741824") + tt(t, func() { + test, _ := test() + test(` + high = (1 << 30) - 1 + (1 << 30) + low = -high - 1 + abc = 23 << 1 + def = -105 >> 1 + ghi = 23 << 2 + jkl = 1 >>> 31 + mno = 1 << 64 + pqr = 1 >> 2 + stu = -2 >> 4 + vwx = low >> 1 + yz = low >>> 1 + `) + test("abc", 46) + test("def", -53) + test("ghi", 92) + test("jkl", 0) + test("mno", 1) + test("pqr", 0) + test("stu", -1) + test("vwx", -1073741824) + test("yz", 1073741824) + }) } func TestParenthesizing(t *testing.T) { - Terst(t) + tt(t, func() { + test, _ := test() - test := runTest() - - test(` - abc = 1 + 2 * 3 - def = (1 + 2) * 3 - ghi = !(false || true) - jkl = !false || true - `) - test("abc", "7") - test("def", "9") - test("ghi", "false") - test("jkl", "true") + test(` + abc = 1 + 2 * 3 + def = (1 + 2) * 3 + ghi = !(false || true) + jkl = !false || true + `) + test("abc", 7) + test("def", 9) + test("ghi", false) + test("jkl", true) + }) } func Test_instanceof(t *testing.T) { - Terst(t) + tt(t, func() { + test, _ := test() - test := runTest() + test(` + abc = {} instanceof Object; + `, true) - test(` - abc = {} instanceof Object; - `) - test("abc", "true") + test(` + abc = "abc" instanceof Object; + `, false) - test(` - abc = "abc" instanceof Object; - `) - test("abc", "false") + test(`raise: + abc = {} instanceof "abc"; + `, "TypeError: Expecting a function in instanceof check, but got: abc") - test(`raise: - abc = {} instanceof "abc"; - `, "TypeError: Expecting a function in instanceof check, but got: abc") - - test(`raise: - "xyzzy" instanceof Math; - `, "TypeError") + test(`raise: + "xyzzy" instanceof Math; + `, "TypeError") + }) } func TestIn(t *testing.T) { - Terst(t) + tt(t, func() { + test, _ := test() - test := runTest() - - test(` - abc = "prototype" in Object - def = "xyzzy" in Object - `) - test("abc", "true") - test("def", "false") + test(` + abc = "prototype" in Object; + def = "xyzzy" in Object; + [ abc, def ]; + `, "true,false") + }) } func Test_new(t *testing.T) { - Terst(t) + tt(t, func() { + test, _ := test() - test := runTest() - - test(` - abc = new Boolean - def = new Boolean(1) - `) - test("abc", "false") - test("def", "true") + test(` + abc = new Boolean; + def = new Boolean(1); + [ abc, def ]; + `, "false,true") + }) } func TestNewFunction(t *testing.T) { - Terst(t) + tt(t, func() { + test, _ := test() - test := runTest() + test(` + new Function("return 11")() + `, 11) - test(` - new Function("return 11")() - `, "11") + test(` + abc = 10 + new Function("abc += 1")() + abc + `, 11) - test(` - abc = 10 - new Function("abc += 1")() - abc - `, "11") + test(` + new Function("a", "b", "c", "return b + 2")(10, 11, 12) + `, 13) - test(` - new Function("a", "b", "c", "return b + 2")(10, 11, 12) - `, "13") + test(`raise: + new 1 + `, "TypeError: 1 is not a function") - test(`raise: - new 1 - `, "TypeError: 1 is not a function") + // TODO Better error reporting: new this + test(`raise: + new this + `, "TypeError: [object environment] is not a function") - // TODO Better error reporting: new this - test(`raise: - new this - `, "TypeError: [object environment] is not a function") - - test(`raise: - new {} - `, "TypeError: [object Object] is not a function") + test(`raise: + new {} + `, "TypeError: [object Object] is not a function") + }) } func TestNewPrototype(t *testing.T) { - Terst(t) + tt(t, func() { + test, _ := test() - test := runTest() - - test(` - abc = { 'xyzzy': 'Nothing happens.' } - function Xyzzy(){} - Xyzzy.prototype = abc; - (new Xyzzy()).xyzzy - `, "Nothing happens.") + test(` + abc = { 'xyzzy': 'Nothing happens.' } + function Xyzzy(){} + Xyzzy.prototype = abc; + (new Xyzzy()).xyzzy + `, "Nothing happens.") + }) } func TestBlock(t *testing.T) { - Terst(t) + tt(t, func() { + test, _ := test() - test := runTest() - - test(` - var abc=0; - var ghi; - def: { - do { - abc++; - if (!(abc < 10)) { - break def; - ghi = "ghi"; - } - } while (true); - } - [ abc,ghi ]; - `, "10,") + test(` + var abc=0; + var ghi; + def: { + do { + abc++; + if (!(abc < 10)) { + break def; + ghi = "ghi"; + } + } while (true); + } + [ abc,ghi ]; + `, "10,") + }) } func Test_toString(t *testing.T) { - Terst(t) + tt(t, func() { + test, _ := test() - test := runTest() - test(` - [undefined+""] - `, "undefined") + test(` + [undefined+""] + `, "undefined") + }) } func TestEvaluationOrder(t *testing.T) { - Terst(t) + tt(t, func() { + test, _ := test() - test := runTest() - test(` - var abc = 0; - abc < (abc = 1) === true; - `, "true") + test(` + var abc = 0; + abc < (abc = 1) === true; + `, true) + }) } func TestClone(t *testing.T) { - Terst(t) + tt(t, func() { + vm1 := New() + vm1.Run(` + var abc = 1; + `) - otto1 := New() - otto1.Run(` - var abc = 1; - `) + vm2 := vm1.clone() + vm1.Run(` + abc += 2; + `) + vm2.Run(` + abc += 4; + `) - otto2 := otto1.clone() - otto1.Run(` - abc += 2; - `) - otto2.Run(` - abc += 4; - `) - - Is(otto1.getValue("abc"), "3") - Is(otto2.getValue("abc"), "5") + is(vm1.getValue("abc"), 3) + is(vm2.getValue("abc"), 5) + }) } func Test_debugger(t *testing.T) { - Terst(t) + tt(t, func() { + test, _ := test() - test := runTest() - - test(` - debugger; - `, "undefined") + test(` + debugger; + `, "undefined") + }) } diff --git a/script_test.go b/script_test.go index 34dd190..1a25b8a 100644 --- a/script_test.go +++ b/script_test.go @@ -1,77 +1,76 @@ package otto import ( - . "./terst" "testing" ) func TestScript(t *testing.T) { - Terst(t) + tt(t, func() { + return - return + vm := New() - vm := New() + script, err := vm.Compile("xyzzy", `var abc; if (!abc) abc = 0; abc += 2; abc;`) + is(err, nil) - script, err := vm.Compile("xyzzy", `var abc; if (!abc) abc = 0; abc += 2; abc;`) - Is(err, nil) - - str := script.String() - Is(str, "// xyzzy\nvar abc; if (!abc) abc = 0; abc += 2; abc;") - - value, err := vm.Run(script) - Is(err, nil) - is(value, 2) - - tmp, err := script.marshalBinary() - Is(err, nil) - Is(len(tmp), 1228) - - { - script := &Script{} - err = script.unmarshalBinary(tmp) - Is(err, nil) - - Is(script.String(), str) - - value, err = vm.Run(script) - Is(err, nil) - is(value, 4) - - tmp, err = script.marshalBinary() - Is(err, nil) - Is(len(tmp), 1228) - } - - { - script := &Script{} - err = script.unmarshalBinary(tmp) - Is(err, nil) - - Is(script.String(), str) + str := script.String() + is(str, "// xyzzy\nvar abc; if (!abc) abc = 0; abc += 2; abc;") value, err := vm.Run(script) - Is(err, nil) - is(value, 6) + is(err, nil) + is(value, 2) - tmp, err = script.marshalBinary() - Is(err, nil) - Is(len(tmp), 1228) - } + tmp, err := script.marshalBinary() + is(err, nil) + is(len(tmp), 1228) - { - version := scriptVersion - scriptVersion = "bogus" + { + script := &Script{} + err = script.unmarshalBinary(tmp) + is(err, nil) - script := &Script{} - err = script.unmarshalBinary(tmp) - Is(err, "version mismatch") + is(script.String(), str) - Is(script.String(), "// \n") - Is(script.version, "") - Is(script.program == nil, true) - Is(script.filename, "") - Is(script.src, "") + value, err = vm.Run(script) + is(err, nil) + is(value, 4) - scriptVersion = version - } + tmp, err = script.marshalBinary() + is(err, nil) + is(len(tmp), 1228) + } + + { + script := &Script{} + err = script.unmarshalBinary(tmp) + is(err, nil) + + is(script.String(), str) + + value, err := vm.Run(script) + is(err, nil) + is(value, 6) + + tmp, err = script.marshalBinary() + is(err, nil) + is(len(tmp), 1228) + } + + { + version := scriptVersion + scriptVersion = "bogus" + + script := &Script{} + err = script.unmarshalBinary(tmp) + is(err, "version mismatch") + + is(script.String(), "// \n") + is(script.version, "") + is(script.program == nil, true) + is(script.filename, "") + is(script.src, "") + + scriptVersion = version + } + }) } diff --git a/string_test.go b/string_test.go index dabd825..b7b0632 100644 --- a/string_test.go +++ b/string_test.go @@ -1,349 +1,365 @@ package otto import ( - . "./terst" "testing" ) func TestString(t *testing.T) { - Terst(t) + tt(t, func() { + test, _ := test() - test := runTest() - - test(` - abc = (new String("xyzzy")).length; - def = new String().length; - ghi = new String("Nothing happens.").length; - `) - test("abc", "5") - test("def", "0") - test("ghi", "16") - test(`"".length`, "0") - test(`"a\uFFFFbc".length`, "4") - test(`String(+0)`, "0") - test(`String(-0)`, "0") - test(`""+-0`, "0") - test(` - var abc = Object.getOwnPropertyDescriptor(String, "prototype"); - [ [ typeof String.prototype ], - [ abc.writable, abc.enumerable, abc.configurable ] ]; - `, "object,false,false,false") + test(` + abc = (new String("xyzzy")).length; + def = new String().length; + ghi = new String("Nothing happens.").length; + `) + test("abc", 5) + test("def", 0) + test("ghi", 16) + test(`"".length`, 0) + test(`"a\uFFFFbc".length`, 4) + test(`String(+0)`, "0") + test(`String(-0)`, "0") + test(`""+-0`, "0") + test(` + var abc = Object.getOwnPropertyDescriptor(String, "prototype"); + [ [ typeof String.prototype ], + [ abc.writable, abc.enumerable, abc.configurable ] ]; + `, "object,false,false,false") + }) } func TestString_charAt(t *testing.T) { - Terst(t) + tt(t, func() { + test, _ := test() - test := runTest() - test(` - abc = "xyzzy".charAt(0) - def = "xyzzy".charAt(11) - `) - test("abc", "x") - test("def", "") + test(` + abc = "xyzzy".charAt(0) + def = "xyzzy".charAt(11) + `) + test("abc", "x") + test("def", "") + }) } func TestString_charCodeAt(t *testing.T) { - Terst(t) + tt(t, func() { + test, _ := test() - test := runTest() - test(` - abc = "xyzzy".charCodeAt(0) - def = "xyzzy".charCodeAt(11) - `) - test("abc", "120") - test("def", "NaN") + test(` + abc = "xyzzy".charCodeAt(0) + def = "xyzzy".charCodeAt(11) + `) + test("abc", 120) + test("def", _NaN) + }) } func TestString_fromCharCode(t *testing.T) { - Terst(t) + tt(t, func() { + test, _ := test() - test := runTest() - test(`String.fromCharCode()`, "") - test(`String.fromCharCode(88, 121, 122, 122, 121)`, "Xyzzy") - test(`String.fromCharCode("88", 121, 122, 122.05, 121)`, "Xyzzy") - test(`String.fromCharCode("88", 121, 122, NaN, 121)`, "Xyz\x00y") - test(`String.fromCharCode("0x21")`, "!") - test(`String.fromCharCode(-1).charCodeAt(0)`, "65535") - test(`String.fromCharCode(65535).charCodeAt(0)`, "65535") - test(`String.fromCharCode(65534).charCodeAt(0)`, "65534") - test(`String.fromCharCode(4294967295).charCodeAt(0)`, "65535") - test(`String.fromCharCode(4294967294).charCodeAt(0)`, "65534") - test(`String.fromCharCode(0x0024) === "$"`, "true") + test(`String.fromCharCode()`, []uint16{}) + test(`String.fromCharCode(88, 121, 122, 122, 121)`, []uint16{88, 121, 122, 122, 121}) // FIXME terst, Double-check these... + test(`String.fromCharCode("88", 121, 122, 122.05, 121)`, []uint16{88, 121, 122, 122, 121}) + test(`String.fromCharCode("88", 121, 122, NaN, 121)`, []uint16{88, 121, 122, 0, 121}) + test(`String.fromCharCode("0x21")`, []uint16{33}) + test(`String.fromCharCode(-1).charCodeAt(0)`, 65535) + test(`String.fromCharCode(65535).charCodeAt(0)`, 65535) + test(`String.fromCharCode(65534).charCodeAt(0)`, 65534) + test(`String.fromCharCode(4294967295).charCodeAt(0)`, 65535) + test(`String.fromCharCode(4294967294).charCodeAt(0)`, 65534) + test(`String.fromCharCode(0x0024) === "$"`, true) + }) } func TestString_concat(t *testing.T) { - Terst(t) + tt(t, func() { + test, _ := test() - test := runTest() - test(`"".concat()`, "") - test(`"".concat("abc", "def")`, "abcdef") - test(`"".concat("abc", undefined, "def")`, "abcundefineddef") + test(`"".concat()`, "") + test(`"".concat("abc", "def")`, "abcdef") + test(`"".concat("abc", undefined, "def")`, "abcundefineddef") + }) } func TestString_indexOf(t *testing.T) { - Terst(t) + tt(t, func() { + test, _ := test() - test := runTest() - test(`"".indexOf("")`, "0") - test(`"".indexOf("", 11)`, "0") - test(`"abc".indexOf("")`, "0") - test(`"abc".indexOf("", 11)`, "3") - test(`"abc".indexOf("a")`, "0") - test(`"abc".indexOf("bc")`, "1") - test(`"abc".indexOf("bc", 11)`, "-1") - test(`"$$abcdabcd".indexOf("ab", function(){return -Infinity;}())`, "2") - test(`"$$abcdabcd".indexOf("ab", function(){return NaN;}())`, "2") + test(`"".indexOf("")`, 0) + test(`"".indexOf("", 11)`, 0) + test(`"abc".indexOf("")`, 0) + test(`"abc".indexOf("", 11)`, 3) + test(`"abc".indexOf("a")`, 0) + test(`"abc".indexOf("bc")`, 1) + test(`"abc".indexOf("bc", 11)`, -1) + test(`"$$abcdabcd".indexOf("ab", function(){return -Infinity;}())`, 2) + test(`"$$abcdabcd".indexOf("ab", function(){return NaN;}())`, 2) - test(` - var abc = {toString:function(){return "\u0041B";}} - var def = {valueOf:function(){return true;}} - var ghi = "ABB\u0041BABAB"; - var jkl; - with(ghi) { - jkl = indexOf(abc, def); - } - [ jkl ]; - `, "3") + test(` + var abc = {toString:function(){return "\u0041B";}} + var def = {valueOf:function(){return true;}} + var ghi = "ABB\u0041BABAB"; + var jkl; + with(ghi) { + jkl = indexOf(abc, def); + } + jkl; + `, 3) + }) } func TestString_lastIndexOf(t *testing.T) { - Terst(t) + tt(t, func() { + test, _ := test() - test := runTest() - test(`"".lastIndexOf("")`, "0") - test(`"".lastIndexOf("", 11)`, "0") - test(`"abc".lastIndexOf("")`, "3") - test(`"abc".lastIndexOf("", 11)`, "3") - test(`"abc".lastIndexOf("a")`, "0") - test(`"abc".lastIndexOf("bc")`, "1") - test(`"abc".lastIndexOf("bc", 11)`, "1") - test(`"abc".lastIndexOf("bc", 0)`, "-1") - test(`"abc".lastIndexOf("abcabcabc", 2)`, "-1") - test(`"abc".lastIndexOf("abc", 0)`, "0") - test(`"abc".lastIndexOf("abc", 1)`, "0") - test(`"abc".lastIndexOf("abc", 2)`, "0") - test(`"abc".lastIndexOf("abc", 3)`, "0") + test(`"".lastIndexOf("")`, 0) + test(`"".lastIndexOf("", 11)`, 0) + test(`"abc".lastIndexOf("")`, 3) + test(`"abc".lastIndexOf("", 11)`, 3) + test(`"abc".lastIndexOf("a")`, 0) + test(`"abc".lastIndexOf("bc")`, 1) + test(`"abc".lastIndexOf("bc", 11)`, 1) + test(`"abc".lastIndexOf("bc", 0)`, -1) + test(`"abc".lastIndexOf("abcabcabc", 2)`, -1) + test(`"abc".lastIndexOf("abc", 0)`, 0) + test(`"abc".lastIndexOf("abc", 1)`, 0) + test(`"abc".lastIndexOf("abc", 2)`, 0) + test(`"abc".lastIndexOf("abc", 3)`, 0) - test(` - abc = new Object(true); - abc.lastIndexOf = String.prototype.lastIndexOf; - abc.lastIndexOf(true, false); - `, "0") + test(` + abc = new Object(true); + abc.lastIndexOf = String.prototype.lastIndexOf; + abc.lastIndexOf(true, false); + `, 0) + }) } func TestString_match(t *testing.T) { - Terst(t) + tt(t, func() { + test, _ := test() - test := runTest() - test(`"abc____abc_abc___".match(/__abc/)`, "__abc") - test(`"abc___abc_abc__abc__abc".match(/abc/g)`, "abc,abc,abc,abc,abc") - test(`"abc____abc_abc___".match(/__abc/g)`, "__abc") - test(` - abc = /abc/g - "abc___abc_abc__abc__abc".match(abc) - `, "abc,abc,abc,abc,abc") - test(`abc.lastIndex`, "23") + test(`"abc____abc_abc___".match(/__abc/)`, "__abc") + test(`"abc___abc_abc__abc__abc".match(/abc/g)`, "abc,abc,abc,abc,abc") + test(`"abc____abc_abc___".match(/__abc/g)`, "__abc") + test(` + abc = /abc/g + "abc___abc_abc__abc__abc".match(abc) + `, "abc,abc,abc,abc,abc") + test(`abc.lastIndex`, 23) + }) } func TestString_replace(t *testing.T) { - Terst(t) + tt(t, func() { + test, _ := test() - test := runTest() - test(`"abc_abc".replace(/abc/, "$&123")`, "abc123_abc") - test(`"abc_abc".replace(/abc/g, "$&123")`, "abc123_abc123") - test(`"abc_abc_".replace(/abc/g, "$&123")`, "abc123_abc123_") - test(`"_abc_abc_".replace(/abc/g, "$&123")`, "_abc123_abc123_") - test(`"abc".replace(/abc/, "$&123")`, "abc123") - test(`"abc_".replace(/abc/, "$&123")`, "abc123_") - test("\"^abc$\".replace(/abc/, \"$`def\")", "^^def$") - test("\"^abc$\".replace(/abc/, \"def$`\")", "^def^$") - test(`"_abc_abd_".replace(/ab(c|d)/g, "$1")`, "_c_d_") - test(` - "_abc_abd_".replace(/ab(c|d)/g, function(){ - }) - `, "_undefined_undefined_") + test(`"abc_abc".replace(/abc/, "$&123")`, "abc123_abc") + test(`"abc_abc".replace(/abc/g, "$&123")`, "abc123_abc123") + test(`"abc_abc_".replace(/abc/g, "$&123")`, "abc123_abc123_") + test(`"_abc_abc_".replace(/abc/g, "$&123")`, "_abc123_abc123_") + test(`"abc".replace(/abc/, "$&123")`, "abc123") + test(`"abc_".replace(/abc/, "$&123")`, "abc123_") + test("\"^abc$\".replace(/abc/, \"$`def\")", "^^def$") + test("\"^abc$\".replace(/abc/, \"def$`\")", "^def^$") + test(`"_abc_abd_".replace(/ab(c|d)/g, "$1")`, "_c_d_") + test(` + "_abc_abd_".replace(/ab(c|d)/g, function(){ + }) + `, "_undefined_undefined_") - test(`"b".replace(/(a)?(b)?/, "_$1_")`, "__") - test(` - "b".replace(/(a)?(b)?/, function(a, b, c, d, e, f){ - return [a, b, c, d, e, f] - }) - `, "b,,b,0,b,") + test(`"b".replace(/(a)?(b)?/, "_$1_")`, "__") + test(` + "b".replace(/(a)?(b)?/, function(a, b, c, d, e, f){ + return [a, b, c, d, e, f] + }) + `, "b,,b,0,b,") - test(` - var abc = 'She sells seashells by the seashore.'; - var def = /sh/; - [ abc.replace(def, "$'" + 'sch') ]; - `, "She sells seaells by the seashore.schells by the seashore.") + test(` + var abc = 'She sells seashells by the seashore.'; + var def = /sh/; + [ abc.replace(def, "$'" + 'sch') ]; + `, "She sells seaells by the seashore.schells by the seashore.") + }) } func TestString_search(t *testing.T) { - Terst(t) + tt(t, func() { + test, _ := test() - test := runTest() - test(`"abc".search(/abc/)`, "0") - test(`"abc".search(/def/)`, "-1") - test(`"abc".search(/c$/)`, "2") - test(`"abc".search(/$/)`, "3") + test(`"abc".search(/abc/)`, 0) + test(`"abc".search(/def/)`, -1) + test(`"abc".search(/c$/)`, 2) + test(`"abc".search(/$/)`, 3) + }) } func TestString_split(t *testing.T) { - Terst(t) + tt(t, func() { + test, _ := test() - test := runTest() - test(`"abc".split("", 1)`, "a") - test(`"abc".split("", 2)`, "a,b") - test(`"abc".split("", 3)`, "a,b,c") - test(`"abc".split("", 4)`, "a,b,c") - test(`"abc".split("", 11)`, "a,b,c") - test(`"abc".split("", 0)`, "") - test(`"abc".split("")`, "a,b,c") + test(`"abc".split("", 1)`, "a") + test(`"abc".split("", 2)`, "a,b") + test(`"abc".split("", 3)`, "a,b,c") + test(`"abc".split("", 4)`, "a,b,c") + test(`"abc".split("", 11)`, "a,b,c") + test(`"abc".split("", 0)`, "") + test(`"abc".split("")`, "a,b,c") - test(`"abc".split(undefined)`, "abc") + test(`"abc".split(undefined)`, "abc") - test(`"__1__3_1__2__".split("_")`, ",,1,,3,1,,2,,") + test(`"__1__3_1__2__".split("_")`, ",,1,,3,1,,2,,") - test(`"__1__3_1__2__".split(/_/)`, ",,1,,3,1,,2,,") + test(`"__1__3_1__2__".split(/_/)`, ",,1,,3,1,,2,,") - test(`"ab".split(/a*/)`, ",b") + test(`"ab".split(/a*/)`, ",b") - test(`_ = "Aboldandcoded".split(/<(\/)?([^<>]+)>/)`, "A,,B,bold,/,B,and,,CODE,coded,/,CODE,") - test(`_.length`, "13") - test(`_[1] === undefined`, "true") - test(`_[12] === ""`, "true") + test(`_ = "Aboldandcoded".split(/<(\/)?([^<>]+)>/)`, "A,,B,bold,/,B,and,,CODE,coded,/,CODE,") + test(`_.length`, 13) + test(`_[1] === undefined`, true) + test(`_[12] === ""`, true) - test(` - var abc = new String("one-1 two-2 three-3"); - var def = abc.split(new RegExp); + test(` + var abc = new String("one-1 two-2 three-3"); + var def = abc.split(new RegExp); - [ def.constructor === Array, abc.length, def.length, def.join('') ]; - `, "true,19,19,one-1 two-2 three-3") + [ def.constructor === Array, abc.length, def.length, def.join('') ]; + `, "true,19,19,one-1 two-2 three-3") + }) } func TestString_slice(t *testing.T) { - Terst(t) + tt(t, func() { + test, _ := test() - test := runTest() - test(`"abc".slice()`, "abc") - test(`"abc".slice(0)`, "abc") - test(`"abc".slice(0,11)`, "abc") - test(`"abc".slice(0,-1)`, "ab") - test(`"abc".slice(-1,11)`, "c") - test(`abc = "abc"; abc.slice(abc.length+1, 0)`, "") + test(`"abc".slice()`, "abc") + test(`"abc".slice(0)`, "abc") + test(`"abc".slice(0,11)`, "abc") + test(`"abc".slice(0,-1)`, "ab") + test(`"abc".slice(-1,11)`, "c") + test(`abc = "abc"; abc.slice(abc.length+1, 0)`, "") + }) } func TestString_substring(t *testing.T) { - Terst(t) + tt(t, func() { + test, _ := test() - test := runTest() - test(`"abc".substring()`, "abc") - test(`"abc".substring(0)`, "abc") - test(`"abc".substring(0,11)`, "abc") - test(`"abc".substring(11,0)`, "abc") - test(`"abc".substring(0,-1)`, "") - test(`"abc".substring(-1,11)`, "abc") - test(`"abc".substring(11,1)`, "bc") - test(`"abc".substring(1)`, "bc") - test(`"abc".substring(Infinity, Infinity)`, "") + test(`"abc".substring()`, "abc") + test(`"abc".substring(0)`, "abc") + test(`"abc".substring(0,11)`, "abc") + test(`"abc".substring(11,0)`, "abc") + test(`"abc".substring(0,-1)`, "") + test(`"abc".substring(-1,11)`, "abc") + test(`"abc".substring(11,1)`, "bc") + test(`"abc".substring(1)`, "bc") + test(`"abc".substring(Infinity, Infinity)`, "") + }) } func TestString_toCase(t *testing.T) { - Terst(t) + tt(t, func() { + test, _ := test() - test := runTest() - test(`"abc".toLowerCase()`, "abc") - test(`"ABC".toLowerCase()`, "abc") - test(`"abc".toLocaleLowerCase()`, "abc") - test(`"ABC".toLocaleLowerCase()`, "abc") - test(`"abc".toUpperCase()`, "ABC") - test(`"ABC".toUpperCase()`, "ABC") - test(`"abc".toLocaleUpperCase()`, "ABC") - test(`"ABC".toLocaleUpperCase()`, "ABC") + test(`"abc".toLowerCase()`, "abc") + test(`"ABC".toLowerCase()`, "abc") + test(`"abc".toLocaleLowerCase()`, "abc") + test(`"ABC".toLocaleLowerCase()`, "abc") + test(`"abc".toUpperCase()`, "ABC") + test(`"ABC".toUpperCase()`, "ABC") + test(`"abc".toLocaleUpperCase()`, "ABC") + test(`"ABC".toLocaleUpperCase()`, "ABC") + }) } func Test_floatToString(t *testing.T) { - Terst(t) + tt(t, func() { + test, _ := test() - test := runTest() - test(`String(-1234567890)`, "-1234567890") - test(`-+String(-(-1234567890))`, "-1234567890") - test(`String(-1e128)`, "-1e+128") - test(`String(0.12345)`, "0.12345") - test(`String(-0.00000012345)`, "-1.2345e-7") - test(`String(0.0000012345)`, "0.0000012345") - test(`String(1000000000000000000000)`, "1e+21") - test(`String(1e21)`, "1e+21") - test(`String(1E21)`, "1e+21") - test(`String(-1000000000000000000000)`, "-1e+21") - test(`String(-1e21)`, "-1e+21") - test(`String(-1E21)`, "-1e+21") - test(`String(0.0000001)`, "1e-7") - test(`String(1e-7)`, "1e-7") - test(`String(1E-7)`, "1e-7") - test(`String(-0.0000001)`, "-1e-7") - test(`String(-1e-7)`, "-1e-7") - test(`String(-1E-7)`, "-1e-7") + test(`String(-1234567890)`, "-1234567890") + test(`-+String(-(-1234567890))`, -1234567890) + test(`String(-1e128)`, "-1e+128") + test(`String(0.12345)`, "0.12345") + test(`String(-0.00000012345)`, "-1.2345e-7") + test(`String(0.0000012345)`, "0.0000012345") + test(`String(1000000000000000000000)`, "1e+21") + test(`String(1e21)`, "1e+21") + test(`String(1E21)`, "1e+21") + test(`String(-1000000000000000000000)`, "-1e+21") + test(`String(-1e21)`, "-1e+21") + test(`String(-1E21)`, "-1e+21") + test(`String(0.0000001)`, "1e-7") + test(`String(1e-7)`, "1e-7") + test(`String(1E-7)`, "1e-7") + test(`String(-0.0000001)`, "-1e-7") + test(`String(-1e-7)`, "-1e-7") + test(`String(-1E-7)`, "-1e-7") + }) } func TestString_indexing(t *testing.T) { - Terst(t) + tt(t, func() { + test, _ := test() - test := runTest() - - // Actually a test of stringToArrayIndex, under the hood. - test(` - abc = new String("abc"); - index = Math.pow(2, 32); - [ abc.length, abc[index], abc[index+1], abc[index+2], abc[index+3] ]; - `, "3,,,,") + // Actually a test of stringToArrayIndex, under the hood. + test(` + abc = new String("abc"); + index = Math.pow(2, 32); + [ abc.length, abc[index], abc[index+1], abc[index+2], abc[index+3] ]; + `, "3,,,,") + }) } func TestString_trim(t *testing.T) { - Terst(t) + tt(t, func() { + test, _ := test() - test := runTest() - test(`' \n abc \t \n'.trim();`, "abc") - test(`" abc\u000B".trim()`, "abc") - test(`"abc ".trim()`, "abc") - test(` - var a = "\u180Eabc \u000B " - var b = a.trim() - a.length + b.length - `, "10") + test(`' \n abc \t \n'.trim();`, "abc") + test(`" abc\u000B".trim()`, "abc") + test(`"abc ".trim()`, "abc") + test(` + var a = "\u180Eabc \u000B " + var b = a.trim() + a.length + b.length + `, 10) + }) } func TestString_trimLeft(t *testing.T) { - Terst(t) + tt(t, func() { + test, _ := test() - test := runTest() - test(`" abc\u000B".trimLeft()`, "abc\u000B") - test(`"abc ".trimLeft()`, "abc ") - test(` - var a = "\u180Eabc \u000B " - var b = a.trimLeft() - a.length + b.length - `, "13") + test(`" abc\u000B".trimLeft()`, "abc\u000B") + test(`"abc ".trimLeft()`, "abc ") + test(` + var a = "\u180Eabc \u000B " + var b = a.trimLeft() + a.length + b.length + `, 13) + }) } func TestString_trimRight(t *testing.T) { - Terst(t) + tt(t, func() { + test, _ := test() - test := runTest() - test(`" abc\u000B".trimRight()`, " abc") - test(`" abc ".trimRight()`, " abc") - test(` - var a = "\u180Eabc \u000B " - var b = a.trimRight() - a.length + b.length - `, "11") + test(`" abc\u000B".trimRight()`, " abc") + test(`" abc ".trimRight()`, " abc") + test(` + var a = "\u180Eabc \u000B " + var b = a.trimRight() + a.length + b.length + `, 11) + }) } func TestString_localeCompare(t *testing.T) { - Terst(t) + tt(t, func() { + test, _ := test() - test := runTest() - - test(`'a'.localeCompare('c');`, "-1") - test(`'c'.localeCompare('a');`, "1") - test(`'a'.localeCompare('a');`, "0") + test(`'a'.localeCompare('c');`, -1) + test(`'c'.localeCompare('a');`, 1) + test(`'a'.localeCompare('a');`, 0) + }) } diff --git a/terst/terst.go b/terst/terst.go index 375823f..042cc60 100644 --- a/terst/terst.go +++ b/terst/terst.go @@ -5,812 +5,355 @@ Package terst is a terse (terst = test + terse), easy-to-use testing library for terst is compatible with (and works via) the standard testing package: http://golang.org/pkg/testing - import ( - "testing" - . "github.com/robertkrimen/terst" - ) +Do not import terst directly, instead use `terst-import` to copy it into your testing environment. - func Test(t *testing.T) { - Terst(t) // Associate terst methods with t (the current testing.T) + var is = terst.Is - Is(getApple(), "apple") // Pass - Is(getOrange(), "orange") // Fail: emits nice-looking diagnostic + func Test(t *testing.T) { + terst.Terst(t, func() { + is("abc", "abc") - Compare(1, ">", 0) // Pass - Compare(1, "==", 1.0) // Pass - } + is(1, ">", 0) - func getApple() string { - return "apple" - } - - func getOrange() string { - return "apple" // Intentional mistake - } - -At the top of your testing function, call Terst(), passing the testing.T you receive as the first argument: - - func TestExample(t *testing.T) { - Terst(t) - ... - } - -After you initialize with the given *testing.T, you can use the following to test: - - Is - IsNot - Equal - Unequal - IsTrue - IsFalse - Like - Unlike - Compare - -Each of the methods above can take an additional (optional) argument, -which is a string describing the test. If the test fails, this -description will be included with the test output For example: - - Is(2 + 2, float32(5), "This result is Doubleplusgood") - - --- FAIL: Test (0.00 seconds) - test.go:17: This result is Doubleplusgood - Failed test (Is) - got: 4 (int) - expected: 5 (float32) - -Future - - - Add Catch() for testing panic() - - Add Same() for testing via .DeepEqual && == (without panicking?) - - Add StrictCompare to use {}= scoping - - Add BigCompare for easier math/big.Int testing? - - Support the complex type in Compare() - - Equality test for NaN? - - Better syntax for At* - - Need IsType/TypeIs + var abc []int + is(abc, nil) + } + } */ package terst import ( + "bytes" + "errors" "fmt" "math/big" - "os" "reflect" "regexp" "runtime" "strings" + "sync" "testing" - "unsafe" + "time" ) -func (self *Tester) hadResult(result bool, test *test, onFail func()) bool { - if self.selfTesting { - expect := true - if self.failIsPassing { - expect = false +// Is compares two values (got & expect) and returns true if the comparison is true, +// false otherwise. In addition, if the comparison is false, Is will report the error +// in a manner similar to testing.T.Error(...). Is also takes an optional argument, +// an operator, that changes how the comparison is made. The following +// operators are available: +// +// == # got == expect, This is the default +// != # got != expect +// +// > # got > expect (float32, uint, uint16, int, int64, ...) +// >= # got >= expect +// < # got < expect +// <= # got <= expect +// +// =~ # regexp.MustCompile(expect).Match{String}(got) +// !~ # !regexp.MustCompile(expect).Match{String}(got) +// +// A simple comparison: +// +// Is(2 + 2, 4) +// +// A bit trickier: +// +// Is(1, ">", 0) +// Is(2 + 2, "!=", 5) +// Is("Nothing happens.", "=~", `ing(\s+)happens\.$`) +// +// Is should only be called under a Terst(t, ...) call. For a standalone version, +// use IsErr(...). If no scope is found and the comparison is false, then Is will panic the error. +// +func Is(arguments ...interface{}) bool { + err := IsErr(arguments...) + if err != nil { + call := Caller() + if call == nil { + panic(err) } - if expect != result { - self.Log(fmt.Sprintf("Expect %v but got %v (%v) (%v) (%v)\n", expect, result, test.kind, test.have, test.want)) - onFail() - self._fail() - } - return result + call.Error(err) + return false } - if !result { - onFail() - self._fail() - } - return result -} - -// IsTrue is DEPRECATED by: -// -// Is(..., true) -// -func IsTrue(have bool, description ...interface{}) bool { - return terstTester().IsTrue(have, description...) -} - -// IsTrue is DEPRECATED by: -// -// Is(..., true) -// -func (self *Tester) IsTrue(have bool, description ...interface{}) bool { - return self.trueOrFalse(true, have, description...) -} - -// IsFalse is DEPRECATED by: -// -// Is(..., false) -// -func IsFalse(have bool, description ...interface{}) bool { - return terstTester().IsFalse(have, description...) -} - -// IsFalse is DEPRECATED by: -// -// Is(..., false) -// -func (self *Tester) IsFalse(have bool, description ...interface{}) bool { - return self.trueOrFalse(false, have, description...) -} - -func (self *Tester) trueOrFalse(want bool, have bool, description ...interface{}) bool { - kind := "IsTrue" - if want == false { - kind = "IsFalse" - } - test := newTest(kind, have, want, description) - didPass := have == want - return self.hadResult(didPass, test, func() { - self.Log(self.failMessageForIsTrue(test)) - }) -} - -// Fail will fail immediately, reporting a test failure with the (optional) description -func Fail(description ...interface{}) bool { - return terstTester().Fail(description...) -} - -// Fail will fail immediately, reporting a test failure with the (optional) description -func (self *Tester) Fail(description ...interface{}) bool { - return self.fail(description...) -} - -func (self *Tester) fail(description ...interface{}) bool { - kind := "Fail" - test := newTest(kind, false, false, description) - didPass := false - return self.hadResult(didPass, test, func() { - self.Log(self.failMessageForFail(test)) - }) -} - -// FailNow will fail immediately, triggering testing.FailNow() and optionally reporting a test failure with description -func FailNow(description ...interface{}) bool { - return terstTester().FailNow(description...) -} - -// FailNow will fail immediately, triggering testing.FailNow() and optionally reporting a test failure with description -func (self *Tester) FailNow(description ...interface{}) bool { - return self.failNow(description...) -} - -func (self *Tester) failNow(description ...interface{}) bool { - if len(description) > 0 { - kind := "FailNow" - test := newTest(kind, false, false, description) - didPass := false - self.hadResult(didPass, test, func() { - self.Log(self.failMessageForFail(test)) - }) - } - self.TestingT.FailNow() - return false -} - -// Equal tests have against want via ==: -// -// Equal(have, want) // Pass if have == want -// -// No special coercion or type inspection is done. -// -// If the type is incomparable (e.g. type mismatch) this will panic. -func Equal(have, want interface{}, description ...interface{}) bool { - return terstTester().Equal(have, want, description...) -} - -func (self *Tester) Equal(have, want interface{}, description ...interface{}) bool { - return self.equal(have, want, description...) -} - -func (self *Tester) equal(have, want interface{}, description ...interface{}) bool { - test := newTest("==", have, want, description) - didPass := have == want - return self.hadResult(didPass, test, func() { - self.Log(self.failMessageForEqual(test)) - }) -} - -// Unequal tests have against want via !=: -// -// Unequal(have, want) // Pass if have != want -// -// No special coercion or type inspection is done. -// -// If the type is incomparable (e.g. type mismatch) this will panic. -func Unequal(have, want interface{}, description ...interface{}) bool { - return terstTester().Unequal(have, want, description...) -} - -func (self *Tester) Unequal(have, want interface{}, description ...interface{}) bool { - return self.unequal(have, want, description...) -} - -func (self *Tester) unequal(have, want interface{}, description ...interface{}) bool { - test := newTest("!=", have, want, description) - didPass := have != want - return self.hadResult(didPass, test, func() { - self.Log(self.failMessageForIs(test)) - }) -} - -// Is tests against in different ways, depending on the -// type of . -// -// If is a string, then it will first convert -// to a string before doing the comparison: -// -// Is(fmt.Sprintf("%v", have), want) // Pass if have == want -// -// Otherwise, Is is a shortcut for: -// -// Compare(have, "==", want) -// -// If is a slice, struct, or similar, Is will perform a reflect.DeepEqual() comparison. -func Is(have, want interface{}, description ...interface{}) bool { - return terstTester().Is(have, want, description...) -} - -// TODO "slice, struct, or similar" What is similar? - -func (self *Tester) Is(have, want interface{}, description ...interface{}) bool { - return self.isOrIsNot(true, have, want, description...) -} - -// IsNot tests against in different ways, depending on the -// type of . -// -// If is a string, then it will first convert -// to a string before doing the comparison: -// -// IsNot(fmt.Sprintf("%v", have), want) // Pass if have != want -// -// Otherwise, Is is a shortcut for: -// -// Compare(have, "!=", want) -// -// If is a slice, struct, or similar, Is will perform a reflect.DeepEqual() comparison. -func IsNot(have, want interface{}, description ...interface{}) bool { - return terstTester().IsNot(have, want, description...) -} - -// TODO "slice, struct, or similar" What is similar? - -func (self *Tester) IsNot(have, want interface{}, description ...interface{}) bool { - return self.isOrIsNot(false, have, want, description...) -} - -func (self *Tester) isOrIsNot(wantIs bool, have, want interface{}, description ...interface{}) bool { - test := newTest("Is", have, want, description) - if !wantIs { - test.kind = "IsNot" - } - didPass := false - switch want.(type) { - case string: - didPass = stringValue(have) == want - default: - didPass, _ = compare(have, "{}* ==", want) - } - if !wantIs { - didPass = !didPass - } - return self.hadResult(didPass, test, func() { - self.Log(self.failMessageForIs(test)) - }) -} - -// Like tests against in different ways, depending on the -// type of . -// -// If is a string, then it will first convert -// to a string before doing a regular expression comparison: -// -// Like(fmt.Sprintf("%v", have), want) // Pass if regexp.Match(want, have) -// -// Otherwise, Like is a shortcut for: -// -// Compare(have, "{}~ ==", want) -// -// If is a slice, struct, or similar, Like will perform a reflect.DeepEqual() comparison. -func Like(have, want interface{}, description ...interface{}) bool { - return terstTester().Like(have, want, description...) -} - -func (self *Tester) Like(have, want interface{}, description ...interface{}) bool { - return self.likeOrUnlike(true, have, want, description...) -} - -// Unlike tests against in different ways, depending on the -// type of . -// -// If is a string, then it will first convert -// to a string before doing a regular expression comparison: -// -// Unlike(fmt.Sprintf("%v", have), want) // Pass if !regexp.Match(want, have) -// -// Otherwise, Unlike is a shortcut for: -// -// Compare(have, "{}~ !=", want) -// -// If is a slice, struct, or similar, Unlike will perform a reflect.DeepEqual() comparison. -func Unlike(have, want interface{}, description ...interface{}) bool { - return terstTester().Unlike(have, want, description...) -} - -func (self *Tester) Unlike(have, want interface{}, description ...interface{}) bool { - return self.likeOrUnlike(false, have, want, description...) -} - -func (self *Tester) likeOrUnlike(wantLike bool, have, want interface{}, description ...interface{}) bool { - test := newTest("Like", have, want, description) - if !wantLike { - test.kind = "Unlike" - } - didPass := false - switch want0 := want.(type) { - case string: - haveString := stringValue(have) - didPass, error := regexp.Match(want0, []byte(haveString)) - if !wantLike { - didPass = !didPass - } - if error != nil { - panic("regexp.Match(" + want0 + ", ...): " + error.Error()) - } - want = fmt.Sprintf("(?:%v)", want) // Make it look like a regular expression - return self.hadResult(didPass, test, func() { - self.Log(self.failMessageForMatch(test, stringValue(have), stringValue(want), wantLike)) - }) - } - didPass, operator := compare(have, "{}~ ==", want) - if !wantLike { - didPass = !didPass - } - test.operator = operator - return self.hadResult(didPass, test, func() { - self.Log(self.failMessageForLike(test, stringValue(have), stringValue(want), wantLike)) - }) -} - -// Compare will compare to with the given operator. The operator can be one of the following: -// -// == -// != -// < -// <= -// > -// >= -// -// Compare is not strict when comparing numeric types, -// and will make a best effort to promote and to the -// same type. -// -// Compare will promote int and uint to big.Int for testing -// against each other. -// -// Compare will promote int, uint, and float to float64 for -// float testing. -// -// For example: -// -// Compare(float32(1.0), "<", int8(2)) // A valid test -// -// result := float32(1.0) < int8(2) // Will not compile because of the type mismatch -// -func Compare(have interface{}, operator string, want interface{}, description ...interface{}) bool { - return terstTester().Compare(have, operator, want, description...) -} - -func (self *Tester) Compare(have interface{}, operator string, want interface{}, description ...interface{}) bool { - return self.compare(have, operator, want, description...) -} - -func (self *Tester) compare(left interface{}, operatorString string, right interface{}, description ...interface{}) bool { - operatorString = strings.TrimSpace(operatorString) - test := newTest("Compare "+operatorString, left, right, description) - didPass, operator := compare(left, operatorString, right) - test.operator = operator - return self.hadResult(didPass, test, func() { - self.Log(self.failMessageForCompare(test)) - }) + return true } type ( - compareScope int + // ErrFail indicates a comparison failure (e.g. 0 > 1) + ErrFail error + + // ErrInvalid indicates an invalid comparison (e.g. bool == string) + ErrInvalid error ) -const ( - compareScopeEqual compareScope = iota - compareScopeTilde - compareScopeAsterisk -) +var errInvalid = errors.New("invalid") -type compareOperator struct { - scope compareScope - comparison string +var registry = struct { + table map[uintptr]*_scope + lock sync.RWMutex +}{ + table: map[uintptr]*_scope{}, } -var newCompareOperatorRE *regexp.Regexp = regexp.MustCompile(`^\s*(?:((?:{}|#)[*~=])\s+)?(==|!=|<|<=|>|>=)\s*$`) - -func newCompareOperator(operatorString string) compareOperator { - - if operatorString == "" { - return compareOperator{compareScopeEqual, ""} - } - - result := newCompareOperatorRE.FindStringSubmatch(operatorString) - if result == nil { - panic(fmt.Errorf("Unable to parse %v into a compareOperator", operatorString)) - } - - scope := compareScopeAsterisk - switch result[1] { - case "#*", "{}*": - scope = compareScopeAsterisk - case "#~", "{}~": - scope = compareScopeTilde - case "#=", "{}=": - scope = compareScopeEqual - } - - comparison := result[2] - - return compareOperator{scope, comparison} +func registerScope(pc uintptr, scope *_scope) { + registry.lock.Lock() + defer registry.lock.Unlock() + registry.table[pc] = scope } -func compare(left interface{}, operatorString string, right interface{}) (bool, compareOperator) { - pass := true - operator := newCompareOperator(operatorString) - comparator := newComparator(left, operator, right) - // FIXME Confusing - switch operator.comparison { - case "==": - pass = comparator.IsEqual() - case "!=": - pass = !comparator.IsEqual() - default: - if comparator.HasOrder() { - switch operator.comparison { - case "<": - pass = comparator.Compare() == -1 - case "<=": - pass = comparator.Compare() <= 0 - case ">": - pass = comparator.Compare() == 1 - case ">=": - pass = comparator.Compare() >= 0 - default: - panic(fmt.Errorf("Compare operator (%v) is invalid", operator.comparison)) - } - } else { - pass = false - } - } - return pass, operator +func scope() *_scope { + scope, _ := findScope() + return scope } -// Compare / Comparator +func floatCompare(a float64, b float64) int { + if a > b { + return 1 + } else if a < b { + return -1 + } + // NaN == NaN for our purposes + return 0 +} -type compareKind int +func bigIntCompare(a *big.Int, b *big.Int) int { + return a.Cmp(b) +} -const ( - kindInterface compareKind = iota - kindInteger - kindUnsignedInteger - kindFloat - kindString - kindBoolean -) +func bigInt(value int64) *big.Int { + return big.NewInt(value) +} -func comparatorValue(value interface{}) (reflect.Value, compareKind) { - reflectValue := reflect.ValueOf(value) - kind := kindInterface - switch value.(type) { - case int, int8, int16, int32, int64: - kind = kindInteger - case uint, uint8, uint16, uint32, uint64: - kind = kindUnsignedInteger - case float32, float64: - kind = kindFloat +func bigUint(value uint64) *big.Int { + return big.NewInt(0).SetUint64(value) +} + +type _toString interface { + String() string +} + +func toString(value interface{}) (string, error) { + switch value := value.(type) { case string: - kind = kindString - case bool: - kind = kindBoolean + return value, nil + case _toString: + return value.String(), nil + case error: + return value.Error(), nil } - return reflectValue, kind + return "", errInvalid } -func toFloat(value reflect.Value) float64 { - switch value.Kind() { - case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: - return float64(value.Int()) - case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: - return float64(value.Uint()) - case reflect.Float32, reflect.Float64: - return float64(value.Float()) +func match(got string, expect *regexp.Regexp) (int, error) { + if expect.MatchString(got) { + return 0, nil } - panic(fmt.Errorf("toFloat( %v <%[1]T> )", value.Interface())) + return -1, nil } -func toInteger(value reflect.Value) *big.Int { - switch value.Kind() { - case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: - return big.NewInt(value.Int()) - case reflect.Uint, reflect.Uint8, reflect.Uint16: - return big.NewInt(int64(value.Uint())) - case reflect.Uint32, reflect.Uint64: - tmp := big.NewInt(0) - tmp.SetString(fmt.Sprintf("%v", value.Uint()), 10) - return tmp - } - panic(fmt.Errorf("toInteger( %v <%[1]T> )", value.Interface())) -} - -func toString(value reflect.Value) string { - switch value.Kind() { - case reflect.String: - return value.String() - } - panic(fmt.Errorf("toString( %v <%[1]T> )", value.Interface())) -} - -func toBoolean(value reflect.Value) bool { - switch value.Kind() { - case reflect.Bool: - return value.Bool() - } - panic(fmt.Errorf("toBoolean( %v <%[1]T> )", value.Interface())) -} - -type aComparator interface { - Compare() int - HasOrder() bool - IsEqual() bool - CompareScope() compareScope -} - -type baseComparator struct { - hasOrder bool - operator compareOperator -} - -func (self *baseComparator) Compare() int { - panic(fmt.Errorf("Invalid .Compare()")) -} -func (self *baseComparator) HasOrder() bool { - return self.hasOrder -} -func (self *baseComparator) CompareScope() compareScope { - return self.operator.scope -} -func comparatorWithOrder(operator compareOperator) *baseComparator { - return &baseComparator{true, operator} -} -func comparatorWithoutOrder(operator compareOperator) *baseComparator { - return &baseComparator{false, operator} -} - -type interfaceComparator struct { - *baseComparator - left interface{} - right interface{} -} - -func (self *interfaceComparator) IsEqual() bool { - if self.CompareScope() != compareScopeEqual { - return reflect.DeepEqual(self.left, self.right) - } - return self.left == self.right -} - -type floatComparator struct { - *baseComparator - left float64 - right float64 -} - -func (self *floatComparator) Compare() int { - if self.left == self.right { - return 0 - } else if self.left < self.right { - return -1 - } - return 1 -} -func (self *floatComparator) IsEqual() bool { - return self.left == self.right -} - -type integerComparator struct { - *baseComparator - left *big.Int - right *big.Int -} - -func (self *integerComparator) Compare() int { - return self.left.Cmp(self.right) -} -func (self *integerComparator) IsEqual() bool { - return 0 == self.left.Cmp(self.right) -} - -type stringComparator struct { - *baseComparator - left string - right string -} - -func (self *stringComparator) Compare() int { - if self.left == self.right { - return 0 - } else if self.left < self.right { - return -1 - } - return 1 -} -func (self *stringComparator) IsEqual() bool { - return self.left == self.right -} - -type booleanComparator struct { - *baseComparator - left bool - right bool -} - -func (self *booleanComparator) IsEqual() bool { - return self.left == self.right -} - -func newComparator(left interface{}, operator compareOperator, right interface{}) aComparator { - leftValue, _ := comparatorValue(left) - rightValue, rightKind := comparatorValue(right) - - // The simplest comparator is comparing interface{} =? interface{} - targetKind := kindInterface - // Are left and right of the same kind? - // (reflect.Value.Kind() is different from compareKind) - scopeEqual := leftValue.Kind() == rightValue.Kind() - scopeTilde := false - scopeAsterisk := false - if scopeEqual { - targetKind = rightKind // Since left and right are the same, the targetKind is Integer/Float/String/Boolean - } else { - // Examine the prefix of reflect.Value.Kind().String() to see if there is a similarity of - // the left value to right value - lk := leftValue.Kind().String() - hasPrefix := func(prefix string) bool { - return strings.HasPrefix(lk, prefix) - } - - switch right.(type) { - case float32, float64: - // Right is float* - if hasPrefix("float") { - // Left is also float* - targetKind = kindFloat - scopeTilde = true - } else if hasPrefix("int") || hasPrefix("uint") { - // Left is a kind of numeric (int* or uint*) - targetKind = kindFloat - scopeAsterisk = true - } else { - // Otherwise left is a non-numeric - } - case uint, uint8, uint16, uint32, uint64: - // Right is uint* - if hasPrefix("uint") { - // Left is also uint* - targetKind = kindInteger - scopeTilde = true - } else if hasPrefix("int") { - // Left is an int* (a numeric) - targetKind = kindInteger - scopeAsterisk = true - } else if hasPrefix("float") { - // Left is an float* (a numeric) - targetKind = kindFloat - scopeAsterisk = true - } else { - // Otherwise left is a non-numeric - } - case int, int8, int16, int32, int64: - // Right is int* - if hasPrefix("int") { - // Left is also int* - targetKind = kindInteger - scopeTilde = true - } else if hasPrefix("uint") { - // Left is a uint* (a numeric) - targetKind = kindInteger - scopeAsterisk = true - } else if hasPrefix("float") { - // Left is an float* (a numeric) - targetKind = kindFloat - scopeAsterisk = true - } else { - // Otherwise left is a non-numeric +func compareMatch(got, expect interface{}) (int, error) { + if got, err := toString(got); err != nil { + switch expect := expect.(type) { + case string: + { + expect := regexp.MustCompile(expect) + return match(got, expect) } + case *regexp.Regexp: + return match(got, expect) default: - // Right is a non-numeric - // Can only really compare string to string or boolean to boolean, so - // we will either have a string/boolean/interfaceComparator + goto invalid } + } else { + return 0, err } +invalid: + return 0, errInvalid +} - /*fmt.Println("%v %v %v %v %s %s", operator.scope, same, sibling, family, leftValue, rightValue)*/ +func floatPromote(value reflect.Value) (float64, error) { + kind := value.Kind() + if reflect.Int <= kind && kind <= reflect.Int64 { + return float64(value.Int()), nil + } + if reflect.Uint <= kind && kind <= reflect.Uint64 { + return float64(value.Uint()), nil + } + if reflect.Float32 <= kind && kind <= reflect.Float64 { + return value.Float(), nil + } + return 0, errInvalid +} + +func bigIntPromote(value reflect.Value) (*big.Int, error) { + kind := value.Kind() + if reflect.Int <= kind && kind <= reflect.Int64 { + return bigInt(value.Int()), nil + } + if reflect.Uint <= kind && kind <= reflect.Uint64 { + return bigUint(value.Uint()), nil + } + return nil, errInvalid +} + +func compareOther(got, expect interface{}) (int, error) { { - mismatch := false - switch operator.scope { - case compareScopeEqual: - mismatch = !scopeEqual - case compareScopeTilde: - mismatch = !scopeEqual && !scopeTilde - case compareScopeAsterisk: - mismatch = !scopeEqual && !scopeTilde && !scopeAsterisk - } - if mismatch { - targetKind = kindInterface + switch expect.(type) { + case float32, float64: + return compareNumber(got, expect) + case uint, uint8, uint16, uint32, uint64: + return compareNumber(got, expect) + case int, int8, int16, int32, int64: + return compareNumber(got, expect) + case string: + var err error + got, err = toString(got) + if err != nil { + return 0, err + } + case nil: + got := reflect.ValueOf(got) + switch got.Kind() { + case reflect.Chan, reflect.Func, reflect.Map, reflect.Ptr, reflect.Slice, reflect.Interface: + if got.IsNil() { + return 0, nil + } + return -1, nil + case reflect.Invalid: // reflect.Invalid: var abc interface{} = nil + return 0, nil + } + return 0, errInvalid } } - switch targetKind { - case kindFloat: - return &floatComparator{ - comparatorWithOrder(operator), - toFloat(leftValue), - toFloat(rightValue), - } - case kindInteger: - return &integerComparator{ - comparatorWithOrder(operator), - toInteger(leftValue), - toInteger(rightValue), - } - case kindString: - return &stringComparator{ - comparatorWithOrder(operator), - toString(leftValue), - toString(rightValue), - } - case kindBoolean: - return &booleanComparator{ - comparatorWithoutOrder(operator), - toBoolean(leftValue), - toBoolean(rightValue), - } + if reflect.ValueOf(got).Type() != reflect.ValueOf(expect).Type() { + return 0, errInvalid } - // As a last resort, we can always compare left (interface{}) to right (interface{}) - return &interfaceComparator{ - comparatorWithoutOrder(operator), - left, - right, + if reflect.DeepEqual(got, expect) { + return 0, nil } + return -1, nil } -// failMessage* +func compareNumber(got, expect interface{}) (int, error) { + { + got := reflect.ValueOf(got) + k0 := got.Kind() + expect := reflect.ValueOf(expect) + k1 := expect.Kind() + if reflect.Float32 <= k0 && k0 <= reflect.Float64 || + reflect.Float32 <= k1 && k1 <= reflect.Float64 { + got, err := floatPromote(got) + if err != nil { + return 0, err + } + expect, err := floatPromote(expect) + if err != nil { + return 0, err + } + return floatCompare(got, expect), nil + } else { + got, err := bigIntPromote(got) + if err != nil { + return 0, err + } + expect, err := bigIntPromote(expect) + if err != nil { + return 0, err + } + return got.Cmp(expect), nil + } + } -func (self *Tester) failMessageForIsTrue(test *test) string { - test.findFileLineFunction(self) - return formatMessage(` - %s:%d: %s - Failed test (%s) - got: %s - expected: %s - `, test.file, test.line, test.Description(), test.kind, stringValue(test.have), stringValue(test.want)) + return 0, errInvalid } -func (self *Tester) failMessageForFail(test *test) string { - test.findFileLineFunction(self) - return formatMessage(` - %s:%d: %s - Failed test (%s) - `, test.file, test.line, test.Description(), test.kind) +// IsErr compares two values (got & expect) and returns nil if the comparison is true, an ErrFail if +// the comparison is false, or an ErrInvalid if the comparison is invalid. IsErr also +// takes an optional argument, an operator, that changes how the comparison is made. +// +func IsErr(arguments ...interface{}) error { + var got, expect interface{} + operator := "==" + switch len(arguments) { + case 0, 1: + return fmt.Errorf("invalid number of arguments to IsErr: %d", len(arguments)) + case 2: + got, expect = arguments[0], arguments[1] + default: + if value, ok := arguments[1].(string); ok { + operator = value + } else { + return fmt.Errorf("invalid operator: %v", arguments[1]) + } + got, expect = arguments[0], arguments[2] + } + + var result int + var err error + + switch operator { + case "<", "<=", ">", ">=": + result, err = compareNumber(got, expect) + case "=~", "!~": + result, err = compareMatch(got, expect) + case "==", "!=": + result, err = compareOther(got, expect) + default: + return fmt.Errorf("invalid operator: %s", operator) + } + + if err == errInvalid { + return ErrInvalid(fmt.Errorf( + "\nINVALID (%s):\n got: %v (%T)\n expected: %v (%T)", + operator, + got, got, + expect, expect, + )) + } else if err != nil { + return err + } + + equality, pass := false, false + + switch operator { + case "==", "=~": + equality = true + pass = result == 0 + case "!=", "!~": + equality = true + pass = result != 0 + case "<": + pass = result < 0 + case "<=": + pass = result <= 0 + case ">": + pass = result > 0 + case ">=": + pass = result >= 0 + } + + if !pass { + if equality { + return ErrFail(fmt.Errorf( + "\nFAIL (%s)\n got: %v%s\nexpected: %v%s", + operator, + got, typeKindString(got), + expect, typeKindString(expect), + )) + } + return ErrFail(fmt.Errorf( + "\nFAIL (%s)\n got: %v%s\nexpected: %s %v%s", + operator, + got, typeKindString(got), + operator, expect, typeKindString(expect), + )) + } + + return nil } func typeKindString(value interface{}) string { @@ -826,341 +369,246 @@ func typeKindString(value interface{}) string { return fmt.Sprintf(" (%T=%s)", value, kind) } -func (self *Tester) failMessageForCompare(test *test) string { - test.findFileLineFunction(self) - return formatMessage(` - %s:%d: %s - Failed test (%s) - %v%s - %s - %v%s - `, test.file, test.line, test.Description(), test.kind, test.have, typeKindString(test.have), test.operator.comparison, test.want, typeKindString(test.want)) +func (scope *_scope) reset() { + scope.name = "" + scope.output = scope.output[:] + scope.start = time.Time{} + scope.duration = 0 } -func (self *Tester) failMessageForEqual(test *test) string { - return self.failMessageForIs(test) -} - -func (self *Tester) failMessageForIs(test *test) string { - test.findFileLineFunction(self) - return formatMessage(` - %s:%d: %v - Failed test (%s) - got: %v%s - expected: %v%s - `, test.file, test.line, test.Description(), test.kind, test.have, typeKindString(test.have), test.want, typeKindString(test.want)) -} - -func (self *Tester) failMessageForMatch(test *test, have, want string, wantMatch bool) string { - test.findFileLineFunction(self) - expect := " like" - if !wantMatch { - expect = "unlike" +// Terst creates a testing scope, where Is can be called and errors will be reported +// according to the top-level location of the comparison, and not where the Is call +// actually takes place. For example: +// +// func test() { +// Is(2 + 2, 5) // <--- This failure is reported below. +// } +// +// Terst(t, func(){ +// +// Is(2, ">", 3) // <--- An error is reported here. +// +// test() // <--- An error is reported here. +// +// }) +// +func Terst(t *testing.T, arguments ...func()) { + scope := &_scope{ + t: t, } - return formatMessage(` - %s:%d: %s - Failed test (%s) - got: %v%s - %s: %s - `, test.file, test.line, test.Description(), test.kind, have, typeKindString(have), expect, want) -} -func (self *Tester) failMessageForLike(test *test, have, want string, wantLike bool) string { - test.findFileLineFunction(self) - if !wantLike { - want = "Anything else" + pc, _, _, ok := runtime.Caller(1) // TODO Associate with the Test... func + if !ok { + panic("Here be dragons.") } - return formatMessage(` - %s:%d: %s - Failed test (%s) - got: %v%s - expected: %v%s - `, test.file, test.line, test.Description(), test.kind, have, typeKindString(have), want, typeKindString(want)) -} -// ... + _, scope.testFunc = findTestFunc() -type Tester struct { - TestingT *testing.T + registerScope(pc, scope) - sanityChecking bool - selfTesting bool - failIsPassing bool - - testEntry uintptr - focusEntry uintptr -} - -var _terstTester *Tester = nil - -func findTestEntry() uintptr { - height := 2 - for { - functionPC, _, _, ok := runtime.Caller(height) - function := runtime.FuncForPC(functionPC) - functionName := function.Name() - if !ok { - return 0 - } - if index := strings.LastIndex(functionName, ".Test"); index >= 0 { - // Assume we have an instance of TestXyzzy in a _test file - return function.Entry() - } - height += 1 - } - return 0 -} - -// Focus will focus the entry point of the test to the current method. -// -// This is important for test failures in getting feedback on which line was at fault. -// -// Consider the following scenario: -// -// func testingMethod( ... ) { -// Is( ..., ... ) -// } -// -// func TestExample(t *testing.T) { -// Terst(t) -// -// testingMethod( ... ) -// testingMethod( ... ) // If something in testingMethod fails, this line number will come up -// testingMethod( ... ) -// } -// -// By default, when a test fails, terst will report the outermost line that led to the failure. -// Usually this is what you want, but if you need to drill down, you can by inserting a special -// call at the top of your testing method: -// -// func testingMethod( ... ) { -// Terst().Focus() // Grab the global Tester and tell it to focus on this method -// Is( ..., ... ) // Now if this test fails, this line number will come up -// } -// -func (self *Tester) Focus() { - pc, _, _, ok := runtime.Caller(1) - if ok { - function := runtime.FuncForPC(pc) - self.focusEntry = function.Entry() - } -} - -// Terst(*testing.T) -// -// Create a new terst Tester and return it. Associate calls to Is, Compare, Like, etc. with the newly created terst. -// -// Terst() -// -// Return the current Tester (if any). -// -// Terst(nil) -// -// Clear out the current Tester (if any). -func Terst(terst ...interface{}) *Tester { - if len(terst) == 0 { - return terstTester() - } else { - if terst[0] == nil { - _terstTester = nil - return nil - } - _terstTester = newTester(terst[0].(*testing.T)) - _terstTester.enableSanityChecking() - _terstTester.testEntry = findTestEntry() - _terstTester.focusEntry = _terstTester.testEntry - } - return _terstTester -} - -func terstTester() *Tester { - if _terstTester == nil { - panic("_terstTester == nil") - } - return _terstTester.checkSanity() -} - -func newTester(t *testing.T) *Tester { - return &Tester{ - TestingT: t, - } -} - -func formatMessage(message string, argumentList ...interface{}) string { - message = fmt.Sprintf(message, argumentList...) - message = strings.TrimLeft(message, "\n") - message = strings.TrimRight(message, " \n") - return message + "\n\n" -} - -// Log is a utility method that will append the given output to the normal output stream. -func (self *Tester) Log(output string) { - outputValue := reflect.ValueOf(self.TestingT).Elem().FieldByName("output") - output_ := outputValue.Bytes() - output_ = append(output_, output...) - *(*[]byte)(unsafe.Pointer(outputValue.UnsafeAddr())) = output_ -} - -func (self *Tester) _fail() { - self.TestingT.Fail() -} - -func (self *Tester) enableSanityChecking() *Tester { - self.sanityChecking = true - return self -} - -func (self *Tester) disableSanityChecking() *Tester { - self.sanityChecking = false - return self -} - -func (self *Tester) enableSelfTesting() *Tester { - self.selfTesting = true - return self -} - -func (self *Tester) disableSelfTesting() *Tester { - self.selfTesting = false - return self -} - -func (self *Tester) failIsPass() *Tester { - self.failIsPassing = true - return self -} - -func (self *Tester) passIsPass() *Tester { - self.failIsPassing = false - return self -} - -func (self *Tester) checkSanity() *Tester { - if self.sanityChecking && self.testEntry != 0 { - foundEntryPoint := findTestEntry() - if self.testEntry != foundEntryPoint { - panic(fmt.Errorf("TestEntry(%v) does not match foundEntry(%v): Did you call Terst when entering a new Test* function?", self.testEntry, foundEntryPoint)) - } - } - return self -} - -func (self *Tester) findDepth() int { - height := 1 // Skip us - for { - pc, _, _, ok := runtime.Caller(height) - function := runtime.FuncForPC(pc) - if !ok { - // Got too close to the sun - if false { - for ; height > 0; height-- { - pc, _, _, ok := runtime.Caller(height) - fmt.Printf("[%d %v %v]", height, pc, ok) - if ok { - function := runtime.FuncForPC(pc) - fmt.Printf(" => [%s]", function.Name()) - } - fmt.Printf("\n") + for _, fn := range arguments { + func() { + scope.reset() + scope.name = "-" + scope.start = time.Now() + defer func() { + scope.duration = time.Now().Sub(scope.start) + if err := recover(); err != nil { + scope.t.Fail() + scope.report() + panic(err) } - } - return 1 - } - functionEntry := function.Entry() - if functionEntry == self.focusEntry || functionEntry == self.testEntry { - return height - 1 // Not the surrounding test function, but within it - } - height += 1 - } - return 1 -} - -// test - -type test struct { - kind string - have interface{} - want interface{} - description []interface{} - operator compareOperator - - file string - line int - functionPC uintptr - function string -} - -func newTest(kind string, have, want interface{}, description []interface{}) *test { - operator := newCompareOperator("") - return &test{ - kind: kind, - have: have, - want: want, - description: description, - operator: operator, + scope.report() + }() + fn() + }() } } -func (self *test) findFileLineFunction(tester *Tester) { - self.file, self.line, self.functionPC, self.function, _ = atFileLineFunction(tester.findDepth()) +// From "testing" +func (scope *_scope) report() { + tstr := fmt.Sprintf("(%.2f seconds)", scope.duration.Seconds()) + format := "--- %s: %s %s\n%s" + if scope.t.Failed() { + fmt.Printf(format, "FAIL", scope.name, tstr, scope.output) + } else if testing.Verbose() { + fmt.Printf(format, "PASS", scope.name, tstr, scope.output) + } } -func (self *test) Description() string { - description := "" - if len(self.description) > 0 { - description = fmt.Sprintf("%v", self.description[0]) - } - return description +func (scope *_scope) log(call _entry, str string) { + scope.mu.Lock() + defer scope.mu.Unlock() + scope.output = append(scope.output, decorate(call, str)...) } -func findPathForFile(file string) string { - terstBase := os.ExpandEnv("$TERST_BASE") - if len(terstBase) > 0 && strings.HasPrefix(file, terstBase) { - file = file[len(terstBase):] - if file[0] == '/' || file[0] == '\\' { - file = file[1:] - } - return file - } +// decorate prefixes the string with the file and line of the call site +// and inserts the final newline if needed and indentation tabs for formascing. +func decorate(call _entry, s string) string { - if index := strings.LastIndex(file, "/"); index >= 0 { - file = file[index+1:] - } else if index = strings.LastIndex(file, "\\"); index >= 0 { - file = file[index+1:] - } - - return file -} - -func atFileLineFunction(callDepth int) (string, int, uintptr, string, bool) { - pc, file, line, ok := runtime.Caller(callDepth + 1) - function := runtime.FuncForPC(pc).Name() - if ok { - file = findPathForFile(file) - if index := strings.LastIndex(function, ".Test"); index >= 0 { - function = function[index+1:] + file, line := call.File, call.Line + if call.PC > 0 { + // Truncate file name at last file name separator. + if index := strings.LastIndex(file, "/"); index >= 0 { + file = file[index+1:] + } else if index = strings.LastIndex(file, "\\"); index >= 0 { + file = file[index+1:] } } else { - pc = 0 - file = "?" + file = "???" line = 1 } - return file, line, pc, function, ok + buf := new(bytes.Buffer) + // Every line is indented at least one tab. + buf.WriteByte('\t') + fmt.Fprintf(buf, "%s:%d: ", file, line) + lines := strings.Split(s, "\n") + if l := len(lines); l > 1 && lines[l-1] == "" { + lines = lines[:l-1] + } + for i, line := range lines { + if i > 0 { + // Second and subsequent lines are indented an extra tab. + buf.WriteString("\n\t\t") + } + buf.WriteString(line) + } + buf.WriteByte('\n') + return buf.String() } -// Conversion - -func integerValue(value interface{}) int64 { - return reflect.ValueOf(value).Int() +func findScope() (*_scope, _entry) { + registry.lock.RLock() + defer registry.lock.RUnlock() + table := registry.table + depth := 2 // Starting depth + call := _entry{} + for { + pc, _, _, ok := runtime.Caller(depth) + if !ok { + break + } + if scope, exists := table[pc]; exists { + pc, file, line, _ := runtime.Caller(depth - 3) // Terst(...) + func(){}() + fn() => ???() + call.PC = pc + call.File = file + call.Line = line + return scope, call + } + depth++ + } + return nil, _entry{} } -func unsignedIntegerValue(value interface{}) uint64 { - return reflect.ValueOf(value).Uint() +// Call is a reference to a line immediately under a Terst testing scope. +type Call struct { + scope *_scope + entry _entry } -func floatValue(value interface{}) float64 { - return reflect.ValueOf(value).Float() +// Caller will search the stack, looking for a Terst testing scope. If a scope +// is found, then Caller returns a Call for logging errors, accessing testing.T, etc. +// If no scope is found, Caller returns nil. +func Caller() *Call { + scope, entry := findScope() + if scope == nil { + return nil + } + return &Call{ + scope: scope, + entry: entry, + } } -func stringValue(value interface{}) string { - return fmt.Sprintf("%v", value) +// TestFunc returns the *runtime.Func entry for the top-level Test...(t testing.T) +// function. +func (cl *Call) TestFunc() *runtime.Func { + return cl.scope.testFunc +} + +// T returns the original testing.T passed to Terst(...) +func (cl *Call) T() *testing.T { + return cl.scope.t +} + +// Log is the terst version of `testing.T.Log` +func (cl *Call) Log(arguments ...interface{}) { + cl.scope.log(cl.entry, fmt.Sprintln(arguments...)) +} + +// Logf is the terst version of `testing.T.Logf` +func (cl *Call) Logf(format string, arguments ...interface{}) { + cl.scope.log(cl.entry, fmt.Sprintf(format, arguments...)) +} + +// Error is the terst version of `testing.T.Error` +func (cl *Call) Error(arguments ...interface{}) { + cl.scope.log(cl.entry, fmt.Sprintln(arguments...)) + cl.scope.t.Fail() +} + +// Errorf is the terst version of `testing.T.Errorf` +func (cl *Call) Errorf(format string, arguments ...interface{}) { + cl.scope.log(cl.entry, fmt.Sprintf(format, arguments...)) + cl.scope.t.Fail() +} + +// Skip is the terst version of `testing.T.Skip` +func (cl *Call) Skip(arguments ...interface{}) { + cl.scope.log(cl.entry, fmt.Sprintln(arguments...)) + cl.scope.t.SkipNow() +} + +// Skipf is the terst version of `testing.T.Skipf` +func (cl *Call) Skipf(format string, arguments ...interface{}) { + cl.scope.log(cl.entry, fmt.Sprintf(format, arguments...)) + cl.scope.t.SkipNow() +} + +type _scope struct { + t *testing.T + testFunc *runtime.Func + name string + mu sync.RWMutex + output []byte + start time.Time + duration time.Duration +} + +type _entry struct { + PC uintptr + File string + Line int + Func *runtime.Func +} + +func _findFunc(match string) (_entry, *runtime.Func) { + depth := 2 // Starting depth + for { + pc, file, line, ok := runtime.Caller(depth) + if !ok { + break + } + fn := runtime.FuncForPC(pc) + name := fn.Name() + if index := strings.LastIndex(name, match); index >= 0 { + // Assume we have an instance of TestXyzzy in a _test file + return _entry{ + PC: pc, + File: file, + Line: line, + Func: fn, + }, fn + } + depth++ + } + return _entry{}, nil +} + +func findTestFunc() (_entry, *runtime.Func) { + return _findFunc(".Test") +} + +func findTerstFunc() (_entry, *runtime.Func) { + return _findFunc(".Terst") } diff --git a/testing_test.go b/testing_test.go new file mode 100644 index 0000000..90d1771 --- /dev/null +++ b/testing_test.go @@ -0,0 +1,128 @@ +package otto + +import ( + "./terst" + "errors" + "strings" + "testing" + "time" +) + +func tt(t *testing.T, arguments ...func()) { + halt := errors.New("A test was taking too long") + timer := time.AfterFunc(2*time.Second, func() { + panic(halt) + }) + defer func() { + timer.Stop() + }() + terst.Terst(t, arguments...) +} + +func is(arguments ...interface{}) bool { + var got, expect interface{} + + switch len(arguments) { + case 0, 1: + return terst.Is(arguments...) + case 2: + got, expect = arguments[0], arguments[1] + default: + got, expect = arguments[0], arguments[2] + } + + if value, ok := got.(Value); ok { + if _, ok := expect.(Value); !ok { + if value.value != nil { + got = value.value + } + } + } + + if len(arguments) == 2 { + arguments[0] = got + arguments[1] = expect + } else { + arguments[0] = got + arguments[2] = expect + } + + return terst.Is(arguments...) +} + +func test(arguments ...interface{}) (func(string, ...interface{}) Value, *_tester) { + tester := newTester() + if len(arguments) > 0 { + tester.test(arguments[0].(string)) + } + return tester.test, tester +} + +type _tester struct { + vm *Otto +} + +func newTester() *_tester { + return &_tester{ + vm: New(), + } +} + +func (self *_tester) Get(name string) (Value, error) { + return self.vm.Get(name) +} + +func (self *_tester) Set(name string, value interface{}) Value { + err := self.vm.Set(name, value) + is(err, nil) + if err != nil { + terst.Caller().T().FailNow() + } + return self.vm.getValue(name) +} + +func (self *_tester) Run(src interface{}) (Value, error) { + return self.vm.Run(src) +} + +func (self *_tester) test(name string, expect ...interface{}) Value { + vm := self.vm + raise := false + defer func() { + if caught := recover(); caught != nil { + if exception, ok := caught.(*_exception); ok { + caught = exception.eject() + } + if raise { + if len(expect) > 0 { + is(caught, expect[0]) + } + } else { + dbg("Panic, caught:", caught) + panic(caught) + } + } + }() + var value Value + var err error + if isIdentifier(name) { + value = vm.getValue(name) + } else { + source := name + index := strings.Index(source, "raise:") + if index == 0 { + raise = true + source = source[6:] + source = strings.TrimLeft(source, " ") + } + value, err = vm.runtime.cmpl_run(source) + if err != nil { + panic(err) + } + } + value = vm.runtime.GetValue(value) + if len(expect) > 0 { + is(value, expect[0]) + } + return value +} diff --git a/underscore/testify b/underscore/testify index 4ec27b3..7f6e0f7 100755 --- a/underscore/testify +++ b/underscore/testify @@ -52,7 +52,6 @@ for my $file (@js) { package otto import ( - . "./terst" "testing" ) @@ -65,13 +64,13 @@ _END_ $fh->print(<<_END_); // $name func Test_${underscore_name}_$count(t *testing.T) { - Terst(t) + tt(t, func(){ + test := underscoreTest() - test := underscoreTest() - - test(` + test(` $test - `) + `) + }) } _END_ diff --git a/underscore_arrays_test.go b/underscore_arrays_test.go index d105b73..9d62978 100644 --- a/underscore_arrays_test.go +++ b/underscore_arrays_test.go @@ -1,17 +1,15 @@ package otto import ( - . "./terst" "testing" ) // first func Test_underscore_arrays_0(t *testing.T) { - Terst(t) + tt(t, func() { + test, _ := test_() - test := underscoreTest() - - test(` + test(` test("first", function() { equal(_.first([1,2,3]), 1, 'can pull out the first element of an array'); equal(_([1, 2, 3]).first(), 1, 'can perform OO-style "first()"'); @@ -27,16 +25,16 @@ func Test_underscore_arrays_0(t *testing.T) { equal(_.first(null), undefined, 'handles nulls'); }); - `) + `) + }) } // rest func Test_underscore_arrays_1(t *testing.T) { - Terst(t) + tt(t, func() { + test, _ := test_() - test := underscoreTest() - - test(` + test(` test("rest", function() { var numbers = [1, 2, 3, 4]; equal(_.rest(numbers).join(", "), "2, 3, 4", 'working rest()'); @@ -49,16 +47,16 @@ func Test_underscore_arrays_1(t *testing.T) { result = (function(){ return _(arguments).drop(); })(1, 2, 3, 4); equal(result.join(', '), '2, 3, 4', 'aliased as drop and works on arguments object'); }); - `) + `) + }) } // initial func Test_underscore_arrays_2(t *testing.T) { - Terst(t) + tt(t, func() { + test, _ := test_() - test := underscoreTest() - - test(` + test(` test("initial", function() { equal(_.initial([1,2,3,4,5]).join(", "), "1, 2, 3, 4", 'working initial()'); equal(_.initial([1,2,3,4],2).join(", "), "1, 2", 'initial can take an index'); @@ -67,16 +65,16 @@ func Test_underscore_arrays_2(t *testing.T) { result = _.map([[1,2,3],[1,2,3]], _.initial); equal(_.flatten(result).join(','), '1,2,1,2', 'initial works with _.map'); }); - `) + `) + }) } // last func Test_underscore_arrays_3(t *testing.T) { - Terst(t) + tt(t, func() { + test, _ := test_() - test := underscoreTest() - - test(` + test(` test("last", function() { equal(_.last([1,2,3]), 3, 'can pull out the last element of an array'); equal(_.last([1,2,3], 0).join(', '), "", 'can pass an index to last'); @@ -89,31 +87,31 @@ func Test_underscore_arrays_3(t *testing.T) { equal(_.last(null), undefined, 'handles nulls'); }); - `) + `) + }) } // compact func Test_underscore_arrays_4(t *testing.T) { - Terst(t) + tt(t, func() { + test, _ := test_() - test := underscoreTest() - - test(` + test(` test("compact", function() { equal(_.compact([0, 1, false, 2, false, 3]).length, 3, 'can trim out all falsy values'); var result = (function(){ return _.compact(arguments).length; })(0, 1, false, 2, false, 3); equal(result, 3, 'works on an arguments object'); }); - `) + `) + }) } // flatten func Test_underscore_arrays_5(t *testing.T) { - Terst(t) + tt(t, func() { + test, _ := test_() - test := underscoreTest() - - test(` + test(` test("flatten", function() { var list = [1, [2], [3, [[[4]]]]]; deepEqual(_.flatten(list), [1,2,3,4], 'can flatten nested arrays'); @@ -121,16 +119,16 @@ func Test_underscore_arrays_5(t *testing.T) { var result = (function(){ return _.flatten(arguments); })(1, [2], [3, [[[4]]]]); deepEqual(result, [1,2,3,4], 'works on an arguments object'); }); - `) + `) + }) } // without func Test_underscore_arrays_6(t *testing.T) { - Terst(t) + tt(t, func() { + test, _ := test_() - test := underscoreTest() - - test(` + test(` test("without", function() { var list = [1, 2, 1, 0, 3, 1, 4]; equal(_.without(list, 0, 1).join(', '), '2, 3, 4', 'can remove all instances of an object'); @@ -141,16 +139,16 @@ func Test_underscore_arrays_6(t *testing.T) { ok(_.without(list, {one : 1}).length == 2, 'uses real object identity for comparisons.'); ok(_.without(list, list[0]).length == 1, 'ditto.'); }); - `) + `) + }) } // uniq func Test_underscore_arrays_7(t *testing.T) { - Terst(t) + tt(t, func() { + test, _ := test_() - test := underscoreTest() - - test(` + test(` test("uniq", function() { var list = [1, 2, 1, 3, 1, 4]; equal(_.uniq(list).join(', '), '1, 2, 3, 4', 'can find the unique values of an unsorted array'); @@ -171,16 +169,16 @@ func Test_underscore_arrays_7(t *testing.T) { var result = (function(){ return _.uniq(arguments); })(1, 2, 1, 3, 1, 4); equal(result.join(', '), '1, 2, 3, 4', 'works on an arguments object'); }); - `) + `) + }) } // intersection func Test_underscore_arrays_8(t *testing.T) { - Terst(t) + tt(t, func() { + test, _ := test_() - test := underscoreTest() - - test(` + test(` test("intersection", function() { var stooges = ['moe', 'curly', 'larry'], leaders = ['moe', 'groucho']; equal(_.intersection(stooges, leaders).join(''), 'moe', 'can take the set intersection of two arrays'); @@ -188,16 +186,16 @@ func Test_underscore_arrays_8(t *testing.T) { var result = (function(){ return _.intersection(arguments, leaders); })('moe', 'curly', 'larry'); equal(result.join(''), 'moe', 'works on an arguments object'); }); - `) + `) + }) } // union func Test_underscore_arrays_9(t *testing.T) { - Terst(t) + tt(t, func() { + test, _ := test_() - test := underscoreTest() - - test(` + test(` test("union", function() { var result = _.union([1, 2, 3], [2, 30, 1], [1, 40]); equal(result.join(' '), '1 2 3 30 40', 'takes the union of a list of arrays'); @@ -205,16 +203,16 @@ func Test_underscore_arrays_9(t *testing.T) { var result = _.union([1, 2, 3], [2, 30, 1], [1, 40, [1]]); equal(result.join(' '), '1 2 3 30 40 1', 'takes the union of a list of nested arrays'); }); - `) + `) + }) } // difference func Test_underscore_arrays_10(t *testing.T) { - Terst(t) + tt(t, func() { + test, _ := test_() - test := underscoreTest() - - test(` + test(` test("difference", function() { var result = _.difference([1, 2, 3], [2, 30, 40]); equal(result.join(' '), '1 3', 'takes the difference of two arrays'); @@ -222,31 +220,31 @@ func Test_underscore_arrays_10(t *testing.T) { var result = _.difference([1, 2, 3, 4], [2, 30, 40], [1, 11, 111]); equal(result.join(' '), '3 4', 'takes the difference of three arrays'); }); - `) + `) + }) } // zip func Test_underscore_arrays_11(t *testing.T) { - Terst(t) + tt(t, func() { + test, _ := test_() - test := underscoreTest() - - test(` + test(` test('zip', function() { var names = ['moe', 'larry', 'curly'], ages = [30, 40, 50], leaders = [true]; var stooges = _.zip(names, ages, leaders); equal(String(stooges), 'moe,30,true,larry,40,,curly,50,', 'zipped together arrays of different lengths'); }); - `) + `) + }) } // object func Test_underscore_arrays_12(t *testing.T) { - Terst(t) + tt(t, func() { + test, _ := test_() - test := underscoreTest() - - test(` + test(` test('object', function() { var result = _.object(['moe', 'larry', 'curly'], [30, 40, 50]); var shouldBe = {moe: 30, larry: 40, curly: 50}; @@ -261,16 +259,16 @@ func Test_underscore_arrays_12(t *testing.T) { ok(_.isEqual(_.object(null), {}), 'handles nulls'); }); - `) + `) + }) } // indexOf func Test_underscore_arrays_13(t *testing.T) { - Terst(t) + tt(t, func() { + test, _ := test_() - test := underscoreTest() - - test(` + test(` test("indexOf", function() { var numbers = [1, 2, 3]; numbers.indexOf = null; @@ -295,16 +293,16 @@ func Test_underscore_arrays_13(t *testing.T) { index = _.indexOf(numbers, 2, 5); equal(index, 7, 'supports the fromIndex argument'); }); - `) + `) + }) } // lastIndexOf func Test_underscore_arrays_14(t *testing.T) { - Terst(t) + tt(t, func() { + test, _ := test_() - test := underscoreTest() - - test(` + test(` test("lastIndexOf", function() { var numbers = [1, 0, 1]; equal(_.lastIndexOf(numbers, 1), 2); @@ -321,16 +319,16 @@ func Test_underscore_arrays_14(t *testing.T) { var index = _.lastIndexOf(numbers, 2, 2); equal(index, 1, 'supports the fromIndex argument'); }); - `) + `) + }) } // range func Test_underscore_arrays_15(t *testing.T) { - Terst(t) + tt(t, func() { + test, _ := test_() - test := underscoreTest() - - test(` + test(` test("range", function() { equal(_.range(0).join(''), '', 'range with 0 as a first argument generates an empty array'); equal(_.range(4).join(' '), '0 1 2 3', 'range with a single positive argument generates an array of elements 0,1,2,...,n-1'); @@ -341,5 +339,6 @@ func Test_underscore_arrays_15(t *testing.T) { equal(_.range(12, 7, -2).join(' '), '12 10 8', 'range with three arguments a & b & c, a > b, c < 0 generates an array of elements a,a-c,a-2c and ends with the number not less than b'); equal(_.range(0, -10, -1).join(' '), '0 -1 -2 -3 -4 -5 -6 -7 -8 -9', 'final example in the Python docs'); }); - `) + `) + }) } diff --git a/underscore_chaining_test.go b/underscore_chaining_test.go index ee241c5..accf04f 100644 --- a/underscore_chaining_test.go +++ b/underscore_chaining_test.go @@ -1,17 +1,15 @@ package otto import ( - . "./terst" "testing" ) // map/flatten/reduce func Test_underscore_chaining_0(t *testing.T) { - Terst(t) + tt(t, func() { + test, _ := test_() - test := underscoreTest() - - test(` + test(` test("map/flatten/reduce", function() { var lyrics = [ "I'm a lumberjack and I'm okay", @@ -29,16 +27,16 @@ func Test_underscore_chaining_0(t *testing.T) { }, {}).value(); ok(counts['a'] == 16 && counts['e'] == 10, 'counted all the letters in the song'); }); - `) + `) + }) } // select/reject/sortBy func Test_underscore_chaining_1(t *testing.T) { - Terst(t) + tt(t, func() { + test, _ := test_() - test := underscoreTest() - - test(` + test(` test("select/reject/sortBy", function() { var numbers = [1,2,3,4,5,6,7,8,9,10]; numbers = _(numbers).chain().select(function(n) { @@ -50,16 +48,16 @@ func Test_underscore_chaining_1(t *testing.T) { }).value(); equal(numbers.join(', '), "10, 6, 2", "filtered and reversed the numbers"); }); - `) + `) + }) } // select/reject/sortBy in functional style func Test_underscore_chaining_2(t *testing.T) { - Terst(t) + tt(t, func() { + test, _ := test_() - test := underscoreTest() - - test(` + test(` test("select/reject/sortBy in functional style", function() { var numbers = [1,2,3,4,5,6,7,8,9,10]; numbers = _.chain(numbers).select(function(n) { @@ -71,16 +69,16 @@ func Test_underscore_chaining_2(t *testing.T) { }).value(); equal(numbers.join(', '), "10, 6, 2", "filtered and reversed the numbers"); }); - `) + `) + }) } // reverse/concat/unshift/pop/map func Test_underscore_chaining_3(t *testing.T) { - Terst(t) + tt(t, func() { + test, _ := test_() - test := underscoreTest() - - test(` + test(` test("reverse/concat/unshift/pop/map", function() { var numbers = [1,2,3,4,5]; numbers = _(numbers).chain() @@ -92,5 +90,6 @@ func Test_underscore_chaining_3(t *testing.T) { .value(); equal(numbers.join(', '), "34, 10, 8, 6, 4, 2, 10, 10", 'can chain together array functions.'); }); - `) + `) + }) } diff --git a/underscore_collections_test.go b/underscore_collections_test.go index b1d4fbb..9afc2a2 100644 --- a/underscore_collections_test.go +++ b/underscore_collections_test.go @@ -1,17 +1,15 @@ package otto import ( - . "./terst" "testing" ) // each func Test_underscore_collections_0(t *testing.T) { - Terst(t) + tt(t, func() { + test, _ := test_() - test := underscoreTest() - - test(` + test(` test("each", function() { _.each([1, 2, 3], function(num, i) { equal(num, i + 1, 'each iterators provide value and iteration count'); @@ -29,8 +27,7 @@ func Test_underscore_collections_0(t *testing.T) { var obj = {one : 1, two : 2, three : 3}; obj.constructor.prototype.four = 4; _.each(obj, function(value, key){ answers.push(key); }); - // TODO: Property ordering unreliable - //equal(answers.join(", "), 'one, two, three', 'iterating over objects works, and ignores the object prototype.'); + equal(answers.join(", "), 'one, two, three', 'iterating over objects works, and ignores the object prototype.'); delete obj.constructor.prototype.four; var answer = null; @@ -41,16 +38,16 @@ func Test_underscore_collections_0(t *testing.T) { _.each(null, function(){ ++answers; }); equal(answers, 0, 'handles a null properly'); }); - `) + `) + }) } // map func Test_underscore_collections_1(t *testing.T) { - Terst(t) + tt(t, func() { + test, _ := test_() - test := underscoreTest() - - test(` + test(` test('map', function() { var doubled = _.map([1, 2, 3], function(num){ return num * 2; }); equal(doubled.join(', '), '2, 4, 6', 'doubled numbers'); @@ -64,30 +61,33 @@ func Test_underscore_collections_1(t *testing.T) { var doubled = _([1, 2, 3]).map(function(num){ return num * 2; }); equal(doubled.join(', '), '2, 4, 6', 'OO-style doubled numbers'); - //if (document.querySelectorAll) { - // var ids = _.map(document.querySelectorAll('#map-test *'), function(n){ return n.id; }); - // deepEqual(ids, ['id1', 'id2'], 'Can use collection methods on NodeLists.'); - //} + // TEST: ReferenceError: document is not defined + return; - //var ids = _.map($('#map-test').children(), function(n){ return n.id; }); - //deepEqual(ids, ['id1', 'id2'], 'Can use collection methods on jQuery Array-likes.'); + if (document.querySelectorAll) { + var ids = _.map(document.querySelectorAll('#map-test *'), function(n){ return n.id; }); + deepEqual(ids, ['id1', 'id2'], 'Can use collection methods on NodeLists.'); + } - //var ids = _.map(document.images, function(n){ return n.id; }); - //ok(ids[0] == 'chart_image', 'can use collection methods on HTMLCollections'); + var ids = _.map($('#map-test').children(), function(n){ return n.id; }); + deepEqual(ids, ['id1', 'id2'], 'Can use collection methods on jQuery Array-likes.'); + + var ids = _.map(document.images, function(n){ return n.id; }); + ok(ids[0] == 'chart_image', 'can use collection methods on HTMLCollections'); var ifnull = _.map(null, function(){}); ok(_.isArray(ifnull) && ifnull.length === 0, 'handles a null properly'); }); - `) + `) + }) } // reduce func Test_underscore_collections_2(t *testing.T) { - Terst(t) + tt(t, func() { + test, _ := test_() - test := underscoreTest() - - test(` + test(` test('reduce', function() { var sum = _.reduce([1, 2, 3], function(sum, num){ return sum + num; }, 0); equal(sum, 6, 'can sum up an array'); @@ -115,19 +115,18 @@ func Test_underscore_collections_2(t *testing.T) { ok(_.reduce(null, function(){}, 138) === 138, 'handles a null (with initial value) properly'); equal(_.reduce([], function(){}, undefined), undefined, 'undefined can be passed as a special case'); - return raises(function() { _.reduce([], function(){}); }, TypeError, 'throws an error for empty arrays with no initial value'); }); - `) + `) + }) } // reduceRight func Test_underscore_collections_3(t *testing.T) { - Terst(t) + tt(t, func() { + test, _ := test_() - test := underscoreTest() - - test(` + test(` test('reduceRight', function() { var list = _.reduceRight(["foo", "bar", "baz"], function(memo, str){ return memo + str; }, ''); equal(list, 'bazbarfoo', 'can perform right folds'); @@ -156,9 +155,6 @@ func Test_underscore_collections_3(t *testing.T) { // Assert that the correct arguments are being passed. - // TODO: Property ordering unreliable - return; - var args, memo = {}, object = {a: 1, b: 2}, @@ -190,45 +186,45 @@ func Test_underscore_collections_3(t *testing.T) { deepEqual(args, expected); }); - `) + `) + }) } // find func Test_underscore_collections_4(t *testing.T) { - Terst(t) + tt(t, func() { + test, _ := test_() - test := underscoreTest() - - test(` + test(` test('find', function() { var array = [1, 2, 3, 4]; strictEqual(_.find(array, function(n) { return n > 2; }), 3, 'should return first found '); strictEqual(_.find(array, function() { return false; }), void 0, 'should return if is not found'); }); - `) + `) + }) } // detect func Test_underscore_collections_5(t *testing.T) { - Terst(t) + tt(t, func() { + test, _ := test_() - test := underscoreTest() - - test(` + test(` test('detect', function() { var result = _.detect([1, 2, 3], function(num){ return num * 2 == 4; }); equal(result, 2, 'found the first "2" and broke the loop'); }); - `) + `) + }) } // select func Test_underscore_collections_6(t *testing.T) { - Terst(t) + tt(t, func() { + test, _ := test_() - test := underscoreTest() - - test(` + test(` test('select', function() { var evens = _.select([1, 2, 3, 4, 5, 6], function(num){ return num % 2 == 0; }); equal(evens.join(', '), '2, 4, 6', 'selected each even number'); @@ -236,16 +232,16 @@ func Test_underscore_collections_6(t *testing.T) { evens = _.filter([1, 2, 3, 4, 5, 6], function(num){ return num % 2 == 0; }); equal(evens.join(', '), '2, 4, 6', 'aliased as "filter"'); }); - `) + `) + }) } // reject func Test_underscore_collections_7(t *testing.T) { - Terst(t) + tt(t, func() { + test, _ := test_() - test := underscoreTest() - - test(` + test(` test('reject', function() { var odds = _.reject([1, 2, 3, 4, 5, 6], function(num){ return num % 2 == 0; }); equal(odds.join(', '), '1, 3, 5', 'rejected each even number'); @@ -258,16 +254,16 @@ func Test_underscore_collections_7(t *testing.T) { }, context); equal(evens.join(', '), '2, 4, 6', 'rejected each odd number'); }); - `) + `) + }) } // all func Test_underscore_collections_8(t *testing.T) { - Terst(t) + tt(t, func() { + test, _ := test_() - test := underscoreTest() - - test(` + test(` test('all', function() { ok(_.all([], _.identity), 'the empty set'); ok(_.all([true, true, true], _.identity), 'all true values'); @@ -279,16 +275,16 @@ func Test_underscore_collections_8(t *testing.T) { ok(_.every([true, true, true], _.identity), 'aliased as "every"'); ok(!_.all([undefined, undefined, undefined], _.identity), 'works with arrays of undefined'); }); - `) + `) + }) } // any func Test_underscore_collections_9(t *testing.T) { - Terst(t) + tt(t, func() { + test, _ := test_() - test := underscoreTest() - - test(` + test(` test('any', function() { var nativeSome = Array.prototype.some; Array.prototype.some = null; @@ -304,64 +300,64 @@ func Test_underscore_collections_9(t *testing.T) { ok(_.some([false, false, true]), 'aliased as "some"'); Array.prototype.some = nativeSome; }); - `) + `) + }) } // include func Test_underscore_collections_10(t *testing.T) { - Terst(t) + tt(t, func() { + test, _ := test_() - test := underscoreTest() - - test(` + test(` test('include', function() { ok(_.include([1,2,3], 2), 'two is in the array'); ok(!_.include([1,3,9], 2), 'two is not in the array'); ok(_.contains({moe:1, larry:3, curly:9}, 3) === true, '_.include on objects checks their values'); ok(_([1,2,3]).include(2), 'OO-style include'); }); - `) + `) + }) } // invoke func Test_underscore_collections_11(t *testing.T) { - Terst(t) + tt(t, func() { + test, _ := test_() - test := underscoreTest() - - test(` + test(` test('invoke', function() { var list = [[5, 1, 7], [3, 2, 1]]; var result = _.invoke(list, 'sort'); equal(result[0].join(', '), '1, 5, 7', 'first array sorted'); equal(result[1].join(', '), '1, 2, 3', 'second array sorted'); }); - `) + `) + }) } // invoke w/ function reference func Test_underscore_collections_12(t *testing.T) { - Terst(t) + tt(t, func() { + test, _ := test_() - test := underscoreTest() - - test(` + test(` test('invoke w/ function reference', function() { var list = [[5, 1, 7], [3, 2, 1]]; var result = _.invoke(list, Array.prototype.sort); equal(result[0].join(', '), '1, 5, 7', 'first array sorted'); equal(result[1].join(', '), '1, 2, 3', 'second array sorted'); }); - `) + `) + }) } // invoke when strings have a call method func Test_underscore_collections_13(t *testing.T) { - Terst(t) + tt(t, func() { + test, _ := test_() - test := underscoreTest() - - test(` + test(` test('invoke when strings have a call method', function() { String.prototype.call = function() { return 42; @@ -375,30 +371,30 @@ func Test_underscore_collections_13(t *testing.T) { delete String.prototype.call; equal(s.call, undefined, "call function removed"); }); - `) + `) + }) } // pluck func Test_underscore_collections_14(t *testing.T) { - Terst(t) + tt(t, func() { + test, _ := test_() - test := underscoreTest() - - test(` + test(` test('pluck', function() { var people = [{name : 'moe', age : 30}, {name : 'curly', age : 50}]; equal(_.pluck(people, 'name').join(', '), 'moe, curly', 'pulls names out of objects'); }); - `) + `) + }) } // where func Test_underscore_collections_15(t *testing.T) { - Terst(t) + tt(t, func() { + test, _ := test_() - test := underscoreTest() - - test(` + test(` test('where', function() { var list = [{a: 1, b: 2}, {a: 2, b: 2}, {a: 1, b: 3}, {a: 1, b: 4}]; var result = _.where(list, {a: 1}); @@ -408,16 +404,16 @@ func Test_underscore_collections_15(t *testing.T) { equal(result.length, 2); equal(result[0].a, 1); }); - `) + `) + }) } // findWhere func Test_underscore_collections_16(t *testing.T) { - Terst(t) + tt(t, func() { + test, _ := test_() - test := underscoreTest() - - test(` + test(` test('findWhere', function() { var list = [{a: 1, b: 2}, {a: 2, b: 2}, {a: 1, b: 3}, {a: 1, b: 4}, {a: 2, b: 4}]; var result = _.findWhere(list, {a: 1}); @@ -425,16 +421,16 @@ func Test_underscore_collections_16(t *testing.T) { result = _.findWhere(list, {b: 4}); deepEqual(result, {a: 1, b: 4}); }); - `) + `) + }) } // max func Test_underscore_collections_17(t *testing.T) { - Terst(t) + tt(t, func() { + test, _ := test_() - test := underscoreTest() - - test(` + test(` test('max', function() { equal(3, _.max([1, 2, 3]), 'can perform a regular Math.max'); @@ -445,18 +441,21 @@ func Test_underscore_collections_17(t *testing.T) { equal(-Infinity, _.max([]), 'Maximum value of an empty array'); equal(_.max({'a': 'a'}), -Infinity, 'Maximum value of a non-numeric collection'); - //equal(299999, _.max(_.range(1,300000)), "Maximum value of a too-big array"); + // TEST: Takes too long + return; + + equal(299999, _.max(_.range(1,300000)), "Maximum value of a too-big array"); }); - `) + `) + }) } // min func Test_underscore_collections_18(t *testing.T) { - Terst(t) + tt(t, func() { + test, _ := test_() - test := underscoreTest() - - test(` + test(` test('min', function() { equal(1, _.min([1, 2, 3]), 'can perform a regular Math.min'); @@ -471,18 +470,21 @@ func Test_underscore_collections_18(t *testing.T) { var then = new Date(0); equal(_.min([now, then]), then); - //equal(1, _.min(_.range(1,300000)), "Minimum value of a too-big array"); + // TEST: Takes too long + return; + + equal(1, _.min(_.range(1,300000)), "Minimum value of a too-big array"); }); - `) + `) + }) } // sortBy func Test_underscore_collections_19(t *testing.T) { - Terst(t) + tt(t, func() { + test, _ := test_() - test := underscoreTest() - - test(` + test(` test('sortBy', function() { var people = [{name : 'curly', age : 50}, {name : 'moe', age : 30}]; people = _.sortBy(people, function(person){ return person.age; }); @@ -518,16 +520,16 @@ func Test_underscore_collections_19(t *testing.T) { deepEqual(actual, collection, 'sortBy should be stable'); }); - `) + `) + }) } // groupBy func Test_underscore_collections_20(t *testing.T) { - Terst(t) + tt(t, func() { + test, _ := test_() - test := underscoreTest() - - test(` + test(` test('groupBy', function() { var parity = _.groupBy([1, 2, 3, 4, 5, 6], function(num){ return num % 2; }); ok('0' in parity && '1' in parity, 'created a group for each value'); @@ -556,16 +558,16 @@ func Test_underscore_collections_20(t *testing.T) { equal(grouped['1'].length, 2); equal(grouped['3'].length, 1); }); - `) + `) + }) } // countBy func Test_underscore_collections_21(t *testing.T) { - Terst(t) + tt(t, func() { + test, _ := test_() - test := underscoreTest() - - test(` + test(` test('countBy', function() { var parity = _.countBy([1, 2, 3, 4, 5], function(num){ return num % 2 == 0; }); equal(parity['true'], 2); @@ -594,16 +596,16 @@ func Test_underscore_collections_21(t *testing.T) { equal(grouped['1'], 2); equal(grouped['3'], 1); }); - `) + `) + }) } // sortedIndex func Test_underscore_collections_22(t *testing.T) { - Terst(t) + tt(t, func() { + test, _ := test_() - test := underscoreTest() - - test(` + test(` test('sortedIndex', function() { var numbers = [10, 20, 30, 40, 50], num = 35; var indexForNum = _.sortedIndex(numbers, num); @@ -621,32 +623,32 @@ func Test_underscore_collections_22(t *testing.T) { iterator = function(obj){ return this[obj]; }; strictEqual(_.sortedIndex([1, 3], 2, iterator, context), 1); }); - `) + `) + }) } // shuffle func Test_underscore_collections_23(t *testing.T) { - Terst(t) + tt(t, func() { + test, _ := test_() - test := underscoreTest() - - test(` + test(` test('shuffle', function() { var numbers = _.range(10); var shuffled = _.shuffle(numbers).sort(); notStrictEqual(numbers, shuffled, 'original object is unmodified'); equal(shuffled.join(','), numbers.join(','), 'contains the same members before and after shuffle'); }); - `) + `) + }) } // toArray func Test_underscore_collections_24(t *testing.T) { - Terst(t) + tt(t, func() { + test, _ := test_() - test := underscoreTest() - - test(` + test(` test('toArray', function() { ok(!_.isArray(arguments), 'arguments object is not an array'); ok(_.isArray(_.toArray(arguments)), 'arguments object converted into array'); @@ -654,12 +656,12 @@ func Test_underscore_collections_24(t *testing.T) { ok(_.toArray(a) !== a, 'array is cloned'); equal(_.toArray(a).join(', '), '1, 2, 3', 'cloned array contains same elements'); - // TODO: Property ordering unreliable - return; - var numbers = _.toArray({one : 1, two : 2, three : 3}); equal(numbers.join(', '), '1, 2, 3', 'object flattened into array'); + // TEST: ReferenceError: document is not defined + return; + // test in IE < 9 try { var actual = _.toArray(document.childNodes); @@ -667,16 +669,16 @@ func Test_underscore_collections_24(t *testing.T) { ok(_.isArray(actual), 'should not throw converting a node list'); }); - `) + `) + }) } // size func Test_underscore_collections_25(t *testing.T) { - Terst(t) + tt(t, func() { + test, _ := test_() - test := underscoreTest() - - test(` + test(` test('size', function() { equal(_.size({one : 1, two : 2, three : 3}), 3, 'can compute the size of an object'); equal(_.size([1, 2, 3]), 3, 'can compute the size of an array'); @@ -691,5 +693,6 @@ func Test_underscore_collections_25(t *testing.T) { equal(_.size(null), 0, 'handles nulls'); }); - `) + `) + }) } diff --git a/underscore_functions_test.go b/underscore_functions_test.go index 4833807..be59e16 100644 --- a/underscore_functions_test.go +++ b/underscore_functions_test.go @@ -1,17 +1,15 @@ package otto import ( - . "./terst" "testing" ) // bind func Test_underscore_functions_0(t *testing.T) { - Terst(t) + tt(t, func() { + test, _ := test_() - test := underscoreTest() - - test(` + test(` test("bind", function() { var context = {name : 'moe'}; var func = function(arg) { return "name: " + (this.name || arg); }; @@ -46,16 +44,16 @@ func Test_underscore_functions_0(t *testing.T) { var Boundf = _.bind(F, {hello: "moe curly"}); equal(Boundf().hello, "moe curly", "When called without the new operator, it's OK to be bound to the context"); }); - `) + `) + }) } // partial func Test_underscore_functions_1(t *testing.T) { - Terst(t) + tt(t, func() { + test, _ := test_() - test := underscoreTest() - - test(` + test(` test("partial", function() { var obj = {name: 'moe'}; var func = function() { return this.name + ' ' + _.toArray(arguments).join(' '); }; @@ -63,16 +61,16 @@ func Test_underscore_functions_1(t *testing.T) { obj.func = _.partial(func, 'a', 'b'); equal(obj.func('c', 'd'), 'moe a b c d', 'can partially apply'); }); - `) + `) + }) } // bindAll func Test_underscore_functions_2(t *testing.T) { - Terst(t) + tt(t, func() { + test, _ := test_() - test := underscoreTest() - - test(` + test(` test("bindAll", function() { var curly = {name : 'curly'}, moe = { name : 'moe', @@ -91,24 +89,20 @@ func Test_underscore_functions_2(t *testing.T) { getName : function() { return 'name: ' + this.name; }, sayHi : function() { return 'hi: ' + this.name; } }; - - // FIXME: This functionality is being changed in the underscore master right now - //raises(function() { _.bindAll(moe); }, Error, 'throws an error for bindAll with no functions named'); - - _.bindAll(moe, 'sayHi'); + _.bindAll(moe); curly.sayHi = moe.sayHi; - equal(curly.sayHi(), 'hi: moe'); + equal(curly.sayHi(), 'hi: moe', 'calling bindAll with no arguments binds all functions to the object'); }); - `) + `) + }) } // memoize func Test_underscore_functions_3(t *testing.T) { - Terst(t) + tt(t, func() { + test, _ := test_() - test := underscoreTest() - - test(` + test(` test("memoize", function() { var fib = function(n) { return n < 2 ? n : fib(n - 1) + fib(n - 2); @@ -124,16 +118,16 @@ func Test_underscore_functions_3(t *testing.T) { equal(o('toString'), 'toString', 'checks hasOwnProperty'); equal(fastO('toString'), 'toString', 'checks hasOwnProperty'); }); - `) + `) + }) } // once func Test_underscore_functions_4(t *testing.T) { - Terst(t) + tt(t, func() { + test, _ := test_() - test := underscoreTest() - - test(` + test(` test("once", function() { var num = 0; var increment = _.once(function(){ num++; }); @@ -141,16 +135,16 @@ func Test_underscore_functions_4(t *testing.T) { increment(); equal(num, 1); }); - `) + `) + }) } // wrap func Test_underscore_functions_5(t *testing.T) { - Terst(t) + tt(t, func() { + test, _ := test_() - test := underscoreTest() - - test(` + test(` test("wrap", function() { var greet = function(name){ return "hi: " + name; }; var backwards = _.wrap(greet, function(func, name){ return func(name) + ' ' + name.split('').reverse().join(''); }); @@ -166,16 +160,16 @@ func Test_underscore_functions_5(t *testing.T) { var ret = wrapped(['whats', 'your'], 'vector', 'victor'); deepEqual(ret, [noop, ['whats', 'your'], 'vector', 'victor']); }); - `) + `) + }) } // compose func Test_underscore_functions_6(t *testing.T) { - Terst(t) + tt(t, func() { + test, _ := test_() - test := underscoreTest() - - test(` + test(` test("compose", function() { var greet = function(name){ return "hi: " + name; }; var exclaim = function(sentence){ return sentence + '!'; }; @@ -185,16 +179,16 @@ func Test_underscore_functions_6(t *testing.T) { composed = _.compose(greet, exclaim); equal(composed('moe'), 'hi: moe!', 'in this case, the functions are also commutative'); }); - `) + `) + }) } // after func Test_underscore_functions_7(t *testing.T) { - Terst(t) + tt(t, func() { + test, _ := test_() - test := underscoreTest() - - test(` + test(` test("after", function() { var testAfter = function(afterAmount, timesCalled) { var afterCalled = 0; @@ -209,5 +203,6 @@ func Test_underscore_functions_7(t *testing.T) { equal(testAfter(5, 4), 0, "after(N) should not fire unless called N times"); equal(testAfter(0, 0), 1, "after(0) should fire immediately"); }); - `) + `) + }) } diff --git a/underscore_objects_test.go b/underscore_objects_test.go index 740882d..ae9c5d5 100644 --- a/underscore_objects_test.go +++ b/underscore_objects_test.go @@ -1,19 +1,17 @@ package otto import ( - . "./terst" "testing" ) // keys func Test_underscore_objects_0(t *testing.T) { - Terst(t) + tt(t, func() { + test, _ := test_() - test := underscoreTest() - - test(` + test(` test("keys", function() { - equal(_.keys({one : 1, two : 2}).sort().join(', '), 'one, two', 'can extract the keys from an object'); + equal(_.keys({one : 1, two : 2}).join(', '), 'one, two', 'can extract the keys from an object'); // the test above is not safe because it relies on for-in enumeration order var a = []; a[1] = 0; equal(_.keys(a).join(', '), '1', 'is not fooled by sparse arrays; see issue #95'); @@ -23,65 +21,62 @@ func Test_underscore_objects_0(t *testing.T) { raises(function() { _.keys('a'); }, TypeError, 'throws an error for string primitives'); raises(function() { _.keys(true); }, TypeError, 'throws an error for boolean primitives'); }); - `) + `) + }) } // values func Test_underscore_objects_1(t *testing.T) { - Terst(t) + tt(t, func() { + test, _ := test_() - test := underscoreTest() - - test(` + test(` test("values", function() { - equal(_.values({one: 1, two: 2}).sort().join(', '), '1, 2', 'can extract the values from an object'); - equal(_.values({one: 1, two: 2, length: 3}).sort().join(', '), '1, 2, 3', '... even when one of them is "length"'); + equal(_.values({one: 1, two: 2}).join(', '), '1, 2', 'can extract the values from an object'); + equal(_.values({one: 1, two: 2, length: 3}).join(', '), '1, 2, 3', '... even when one of them is "length"'); }); - `) + `) + }) } // pairs func Test_underscore_objects_2(t *testing.T) { - Terst(t) + tt(t, func() { + test, _ := test_() - test := underscoreTest() - - test(` + test(` test("pairs", function() { - // TODO: Property ordering unreliable - return; deepEqual(_.pairs({one: 1, two: 2}), [['one', 1], ['two', 2]], 'can convert an object into pairs'); deepEqual(_.pairs({one: 1, two: 2, length: 3}), [['one', 1], ['two', 2], ['length', 3]], '... even when one of them is "length"'); }); - `) + `) + }) } // invert func Test_underscore_objects_3(t *testing.T) { - Terst(t) + tt(t, func() { + test, _ := test_() - test := underscoreTest() - - test(` + test(` test("invert", function() { var obj = {first: 'Moe', second: 'Larry', third: 'Curly'}; - // TODO: Property ordering unreliable - //equal(_.keys(_.invert(obj)).join(' '), 'Moe Larry Curly', 'can invert an object'); + equal(_.keys(_.invert(obj)).join(' '), 'Moe Larry Curly', 'can invert an object'); ok(_.isEqual(_.invert(_.invert(obj)), obj), 'two inverts gets you back where you started'); var obj = {length: 3}; ok(_.invert(obj)['3'] == 'length', 'can invert an object with "length"') }); - `) + `) + }) } // functions func Test_underscore_objects_4(t *testing.T) { - Terst(t) + tt(t, func() { + test, _ := test_() - test := underscoreTest() - - test(` + test(` test("functions", function() { var obj = {a : 'dash', b : _.map, c : (/yo/), d : _.reduce}; ok(_.isEqual(['b', 'd'], _.functions(obj)), 'can grab the function names of any passed-in object'); @@ -90,16 +85,16 @@ func Test_underscore_objects_4(t *testing.T) { Animal.prototype.run = function(){}; equal(_.functions(new Animal).join(''), 'run', 'also looks up functions on the prototype'); }); - `) + `) + }) } // extend func Test_underscore_objects_5(t *testing.T) { - Terst(t) + tt(t, func() { + test, _ := test_() - test := underscoreTest() - - test(` + test(` test("extend", function() { var result; equal(_.extend({}, {a:'b'}).a, 'b', 'can extend an object with the attributes of another'); @@ -110,8 +105,7 @@ func Test_underscore_objects_5(t *testing.T) { result = _.extend({x:'x'}, {a:'a', x:2}, {a:'b'}); ok(_.isEqual(result, {x:2, a:'b'}), 'extending from multiple source objects last property trumps'); result = _.extend({}, {a: void 0, b: null}); - // TODO: Property ordering unreliable - //equal(_.keys(result).join(''), 'ab', 'extend does not copy undefined values'); + equal(_.keys(result).join(''), 'ab', 'extend does not copy undefined values'); try { result = {}; @@ -120,16 +114,16 @@ func Test_underscore_objects_5(t *testing.T) { equal(result.a, 1, 'should not error on or sources'); }); - `) + `) + }) } // pick func Test_underscore_objects_6(t *testing.T) { - Terst(t) + tt(t, func() { + test, _ := test_() - test := underscoreTest() - - test(` + test(` test("pick", function() { var result; result = _.pick({a:1, b:2, c:3}, 'a', 'c'); @@ -143,16 +137,16 @@ func Test_underscore_objects_6(t *testing.T) { Obj.prototype = {a: 1, b: 2, c: 3}; ok(_.isEqual(_.pick(new Obj, 'a', 'c'), {a:1, c: 3}), 'include prototype props'); }); - `) + `) + }) } // omit func Test_underscore_objects_7(t *testing.T) { - Terst(t) + tt(t, func() { + test, _ := test_() - test := underscoreTest() - - test(` + test(` test("omit", function() { var result; result = _.omit({a:1, b:2, c:3}, 'b'); @@ -166,16 +160,16 @@ func Test_underscore_objects_7(t *testing.T) { Obj.prototype = {a: 1, b: 2, c: 3}; ok(_.isEqual(_.omit(new Obj, 'b'), {a:1, c: 3}), 'include prototype props'); }); - `) + `) + }) } // defaults func Test_underscore_objects_8(t *testing.T) { - Terst(t) + tt(t, func() { + test, _ := test_() - test := underscoreTest() - - test(` + test(` test("defaults", function() { var result; var options = {zero: 0, one: 1, empty: "", nan: NaN, string: "string"}; @@ -197,16 +191,16 @@ func Test_underscore_objects_8(t *testing.T) { equal(options.a, 1, 'should not error on or sources'); }); - `) + `) + }) } // clone func Test_underscore_objects_9(t *testing.T) { - Terst(t) + tt(t, func() { + test, _ := test_() - test := underscoreTest() - - test(` + test(` test("clone", function() { var moe = {name : 'moe', lucky : [13, 27, 34]}; var clone = _.clone(moe); @@ -222,16 +216,16 @@ func Test_underscore_objects_9(t *testing.T) { equal(_.clone(1), 1, 'non objects should not be changed by clone'); equal(_.clone(null), null, 'non objects should not be changed by clone'); }); - `) + `) + }) } // isEqual func Test_underscore_objects_10(t *testing.T) { - Terst(t) + tt(t, func() { + test, _ := test_() - test := underscoreTest() - - test(` + test(` test("isEqual", function() { function First() { this.value = 1; @@ -460,19 +454,22 @@ func Test_underscore_objects_10(t *testing.T) { b = _({x: 1, y: 2}).chain(); equal(_.isEqual(a.isEqual(b), _(true)), true, ' can be chained'); - //// Objects from another frame. - //ok(_.isEqual({}, iObject)); + // TEST: ??? + return; + + // Objects from another frame. + ok(_.isEqual({}, iObject)); }); - `) + `) + }) } // isEmpty func Test_underscore_objects_11(t *testing.T) { - Terst(t) + tt(t, func() { + test, _ := test_() - test := underscoreTest() - - test(` + test(` test("isEmpty", function() { ok(!_([1]).isEmpty(), '[1] is not empty'); ok(_.isEmpty([]), '[] is empty'); @@ -488,16 +485,34 @@ func Test_underscore_objects_11(t *testing.T) { delete obj.one; ok(_.isEmpty(obj), 'deleting all the keys from an object empties it'); }); - `) + `) + }) +} + +// isElement +func Test_underscore_objects_12(t *testing.T) { + // TEST: ReferenceError: $ is not defined + return + + tt(t, func() { + test, _ := test_() + + test(` + test("isElement", function() { + ok(!_.isElement('div'), 'strings are not dom elements'); + ok(_.isElement($('html')[0]), 'the html tag is a DOM element'); + ok(_.isElement(iElement), 'even from another frame'); + }); + `) + }) } // isArguments func Test_underscore_objects_13(t *testing.T) { - Terst(t) + tt(t, func() { + test, _ := test_() - test := underscoreTest() - - test(` + test(` test("isArguments", function() { var args = (function(){ return arguments; })(1, 2, 3); ok(!_.isArguments('string'), 'a string is not an arguments object'); @@ -505,25 +520,30 @@ func Test_underscore_objects_13(t *testing.T) { ok(_.isArguments(args), 'but the arguments object is an arguments object'); ok(!_.isArguments(_.toArray(args)), 'but not when it\'s converted into an array'); ok(!_.isArguments([1,2,3]), 'and not vanilla arrays.'); - //ok(_.isArguments(iArguments), 'even from another frame'); + + // TEST: ReferenceError: iArguments is not defined + return; + ok(_.isArguments(iArguments), 'even from another frame'); }); - `) + `) + }) } // isObject func Test_underscore_objects_14(t *testing.T) { - Terst(t) + tt(t, func() { + test, _ := test_() - test := underscoreTest() - - test(` + test(` test("isObject", function() { ok(_.isObject(arguments), 'the arguments object is object'); ok(_.isObject([1, 2, 3]), 'and arrays'); - //ok(_.isObject($('html')[0]), 'and DOM element'); - //ok(_.isObject(iElement), 'even from another frame'); + // TEST: ReferenceError: $ is not defined + return; + ok(_.isObject($('html')[0]), 'and DOM element'); + ok(_.isObject(iElement), 'even from another frame'); ok(_.isObject(function () {}), 'and functions'); - //ok(_.isObject(iFunction), 'even from another frame'); + ok(_.isObject(iFunction), 'even from another frame'); ok(!_.isObject(null), 'but not null'); ok(!_.isObject(undefined), 'and not undefined'); ok(!_.isObject('string'), 'and not string'); @@ -531,46 +551,53 @@ func Test_underscore_objects_14(t *testing.T) { ok(!_.isObject(true), 'and not boolean'); ok(_.isObject(new String('string')), 'but new String()'); }); - `) + `) + }) } // isArray func Test_underscore_objects_15(t *testing.T) { - Terst(t) + tt(t, func() { + test, _ := test_() - test := underscoreTest() - - test(` + test(` test("isArray", function() { ok(!_.isArray(arguments), 'the arguments object is not an array'); ok(_.isArray([1, 2, 3]), 'but arrays are'); - //ok(_.isArray(iArray), 'even from another frame'); + // TEST: ??? + return; + ok(_.isArray(iArray), 'even from another frame'); }); - `) + `) + }) } // isString func Test_underscore_objects_16(t *testing.T) { - Terst(t) + // TEST: ReferenceError: document is not defined + return - test := underscoreTest() + tt(t, func() { + test, _ := test_() - test(` + test(` test("isString", function() { - //ok(!_.isString(document.body), 'the document body is not a string'); + ok(!_.isString(document.body), 'the document body is not a string'); ok(_.isString([1, 2, 3].join(', ')), 'but strings are'); - //ok(_.isString(iString), 'even from another frame'); + // TEST: ??? + return; + ok(_.isString(iString), 'even from another frame'); }); - `) + `) + }) } // isNumber func Test_underscore_objects_17(t *testing.T) { - Terst(t) + tt(t, func() { + test, _ := test_() - test := underscoreTest() - - test(` + test(` test("isNumber", function() { ok(!_.isNumber('string'), 'a string is not a number'); ok(!_.isNumber(arguments), 'the arguments object is not a number'); @@ -578,19 +605,21 @@ func Test_underscore_objects_17(t *testing.T) { ok(_.isNumber(3 * 4 - 7 / 10), 'but numbers are'); ok(_.isNumber(NaN), 'NaN *is* a number'); ok(_.isNumber(Infinity), 'Infinity is a number'); - //ok(_.isNumber(iNumber), 'even from another frame'); + // TEST: ??? + return; + ok(_.isNumber(iNumber), 'even from another frame'); ok(!_.isNumber('1'), 'numeric strings are not numbers'); }); - `) + `) + }) } // isBoolean func Test_underscore_objects_18(t *testing.T) { - Terst(t) + tt(t, func() { + test, _ := test_() - test := underscoreTest() - - test(` + test(` test("isBoolean", function() { ok(!_.isBoolean(2), 'a number is not a boolean'); ok(!_.isBoolean("string"), 'a string is not a boolean'); @@ -602,65 +631,73 @@ func Test_underscore_objects_18(t *testing.T) { ok(!_.isBoolean(null), 'null is not a boolean'); ok(_.isBoolean(true), 'but true is'); ok(_.isBoolean(false), 'and so is false'); - //ok(_.isBoolean(iBoolean), 'even from another frame'); + // TEST: ??? + return; + ok(_.isBoolean(iBoolean), 'even from another frame'); }); - `) + `) + }) } // isFunction func Test_underscore_objects_19(t *testing.T) { - Terst(t) + tt(t, func() { + test, _ := test_() - test := underscoreTest() - - test(` + test(` test("isFunction", function() { ok(!_.isFunction([1, 2, 3]), 'arrays are not functions'); ok(!_.isFunction('moe'), 'strings are not functions'); ok(_.isFunction(_.isFunction), 'but functions are'); - //ok(_.isFunction(iFunction), 'even from another frame'); + // TEST: ??? + return; + ok(_.isFunction(iFunction), 'even from another frame'); }); - `) + `) + }) } // isDate func Test_underscore_objects_20(t *testing.T) { - Terst(t) + tt(t, func() { + test, _ := test_() - test := underscoreTest() - - test(` + test(` test("isDate", function() { ok(!_.isDate(100), 'numbers are not dates'); ok(!_.isDate({}), 'objects are not dates'); ok(_.isDate(new Date()), 'but dates are'); - //ok(_.isDate(iDate), 'even from another frame'); + // TEST: ??? + return; + ok(_.isDate(iDate), 'even from another frame'); }); - `) + `) + }) } // isRegExp func Test_underscore_objects_21(t *testing.T) { - Terst(t) + tt(t, func() { + test, _ := test_() - test := underscoreTest() - - test(` + test(` test("isRegExp", function() { ok(!_.isRegExp(_.identity), 'functions are not RegExps'); ok(_.isRegExp(/identity/), 'but RegExps are'); - //ok(_.isRegExp(iRegExp), 'even from another frame'); + // TEST: ??? + return; + ok(_.isRegExp(iRegExp), 'even from another frame'); }); - `) + `) + }) } // isFinite func Test_underscore_objects_22(t *testing.T) { - Terst(t) + tt(t, func() { + test, _ := test_() - test := underscoreTest() - - test(` + test(` test("isFinite", function() { ok(!_.isFinite(undefined), 'undefined is not Finite'); ok(!_.isFinite(null), 'null is not Finite'); @@ -676,50 +713,54 @@ func Test_underscore_objects_22(t *testing.T) { ok(_.isFinite(123), 'Ints are Finite'); ok(_.isFinite(-12.44), 'Floats are Finite'); }); - `) + `) + }) } // isNaN func Test_underscore_objects_23(t *testing.T) { - Terst(t) + tt(t, func() { + test, _ := test_() - test := underscoreTest() - - test(` + test(` test("isNaN", function() { ok(!_.isNaN(undefined), 'undefined is not NaN'); ok(!_.isNaN(null), 'null is not NaN'); ok(!_.isNaN(0), '0 is not NaN'); ok(_.isNaN(NaN), 'but NaN is'); - //ok(_.isNaN(iNaN), 'even from another frame'); + // TEST: ??? + return; + ok(_.isNaN(iNaN), 'even from another frame'); ok(_.isNaN(new Number(NaN)), 'wrapped NaN is still NaN'); }); - `) + `) + }) } // isNull func Test_underscore_objects_24(t *testing.T) { - Terst(t) + tt(t, func() { + test, _ := test_() - test := underscoreTest() - - test(` + test(` test("isNull", function() { ok(!_.isNull(undefined), 'undefined is not null'); ok(!_.isNull(NaN), 'NaN is not null'); ok(_.isNull(null), 'but null is'); - //ok(_.isNull(iNull), 'even from another frame'); + // TEST: ??? + return; + ok(_.isNull(iNull), 'even from another frame'); }); - `) + `) + }) } // isUndefined func Test_underscore_objects_25(t *testing.T) { - Terst(t) + tt(t, func() { + test, _ := test_() - test := underscoreTest() - - test(` + test(` test("isUndefined", function() { ok(!_.isUndefined(1), 'numbers are defined'); ok(!_.isUndefined(null), 'null is defined'); @@ -727,18 +768,20 @@ func Test_underscore_objects_25(t *testing.T) { ok(!_.isUndefined(NaN), 'NaN is defined'); ok(_.isUndefined(), 'nothing is undefined'); ok(_.isUndefined(undefined), 'undefined is undefined'); - //ok(_.isUndefined(iUndefined), 'even from another frame'); + // TEST: ??? + return; + ok(_.isUndefined(iUndefined), 'even from another frame'); }); - `) + `) + }) } // tap func Test_underscore_objects_26(t *testing.T) { - Terst(t) + tt(t, func() { + test, _ := test_() - test := underscoreTest() - - test(` + test(` test("tap", function() { var intercepted = null; var interceptor = function(obj) { intercepted = obj; }; @@ -753,16 +796,16 @@ func Test_underscore_objects_26(t *testing.T) { value(); ok(returned == 6 && intercepted == 6, 'can use tapped objects in a chain'); }); - `) + `) + }) } // has func Test_underscore_objects_27(t *testing.T) { - Terst(t) + tt(t, func() { + test, _ := test_() - test := underscoreTest() - - test(` + test(` test("has", function () { var obj = {foo: "bar", func: function () {} }; ok (_.has(obj, "foo"), "has() checks that the object has a property."); @@ -774,5 +817,6 @@ func Test_underscore_objects_27(t *testing.T) { child.prototype = obj; ok (_.has(child, "foo") == false, "has() does not check the prototype chain for a property.") }); - `) + `) + }) } diff --git a/underscore_test.go b/underscore_test.go index 3b211ee..96c8f2e 100644 --- a/underscore_test.go +++ b/underscore_test.go @@ -1,156 +1,164 @@ package otto import ( - . "./terst" - "github.com/robertkrimen/otto/underscore" + "./terst" "testing" + + "github.com/robertkrimen/otto/underscore" ) func init() { underscore.Disable() } -var ( - _underscoreTest = struct { - Otto *Otto - test func(string, ...interface{}) Value - }{} -) +// A persistent handle for the underscore tester +// We do not run underscore tests in parallel, so it is okay to stash globally +// (Maybe use sync.Pool in the future...) +var tester_ *_tester -func underscoreTest() func(string, ...interface{}) Value { - cache := &_underscoreTest - if cache.Otto == nil { - Otto, test := runTestWithOtto() - cache.Otto, cache.test = Otto, test - _, err := Otto.Run(underscore.Source()) - if err != nil { - panic(err) - } - Otto.Set("assert", func(call FunctionCall) Value { - if !toBoolean(call.Argument(0)) { - message := "Assertion failed" - if len(call.ArgumentList) > 1 { - message = toString(call.ArgumentList[1]) - } - Fail(message) - return FalseValue() - } - return TrueValue() - }) - - Otto.Run(` - - var templateSettings; - - function _setup() { - templateSettings = _.clone(_.templateSettings); - } - - function _teardown() { - _.templateSettings = templateSettings; - } - - function module() { - /* Nothing happens. */ - } - - function equals(a, b, emit) { - assert(a == b, emit + ", <" + a + "> != <" + b + ">"); - } - var equal = equals; - - function notStrictEqual(a, b, emit) { - assert(a !== b, emit); - } - - function strictEqual(a, b, emit) { - assert(a === b, emit); - } - - function ok(a, emit) { - assert(a, emit); - } - - function raises(fn, want, emit) { - var have, _ok = false; - if (typeof want === "string") { - emit = want; - want = null; - } - - try { - fn(); - } catch(tmp) { - have = tmp; - } - - if (have) { - if (!want) { - _ok = true; - } - else if (want instanceof RegExp) { - _ok = want.test(have); - } - else if (have instanceof want) { - _ok = true - } - else if (want.call({}, have) === true) { - _ok = true; - } - } - - ok(_ok, emit); - } - - function test(name){ - _setup() - try { - templateSettings = _.clone(_.templateSettings); - if (arguments.length == 3) { - count = 0 - for (count = 0; count < arguments[1]; count++) { - arguments[2]() - } - } else { - // For now. - arguments[1]() - } - } - finally { - _teardown() - } - } - - function deepEqual(a, b, emit) { - // Also, for now. - assert(_.isEqual(a, b), emit) - } - `) +// A tester for underscore: test_ => test(underscore) :) +func test_(arguments ...interface{}) (func(string, ...interface{}) Value, *_tester) { + tester := tester_ + if tester == nil { + tester = newTester() + tester.underscore() // Load underscore and testing shim, etc. + tester_ = tester } - return cache.test + + return tester.test, tester +} + +func (self *_tester) underscore() { + vm := self.vm + _, err := vm.Run(underscore.Source()) + if err != nil { + panic(err) + } + + vm.Set("assert", func(call FunctionCall) Value { + if !toBoolean(call.Argument(0)) { + message := "Assertion failed" + if len(call.ArgumentList) > 1 { + message = toString(call.ArgumentList[1]) + } + t := terst.Caller().T() + is(message, nil) + t.Fail() + return FalseValue() + } + return TrueValue() + }) + + vm.Run(` + var templateSettings; + + function _setup() { + templateSettings = _.clone(_.templateSettings); + } + + function _teardown() { + _.templateSettings = templateSettings; + } + + function module() { + /* Nothing happens. */ + } + + function equals(a, b, emit) { + assert(a == b, emit + ", <" + a + "> != <" + b + ">"); + } + var equal = equals; + + function notStrictEqual(a, b, emit) { + assert(a !== b, emit); + } + + function strictEqual(a, b, emit) { + assert(a === b, emit); + } + + function ok(a, emit) { + assert(a, emit); + } + + function raises(fn, want, emit) { + var have, _ok = false; + if (typeof want === "string") { + emit = want; + want = null; + } + + try { + fn(); + } catch(tmp) { + have = tmp; + } + + if (have) { + if (!want) { + _ok = true; + } + else if (want instanceof RegExp) { + _ok = want.test(have); + } + else if (have instanceof want) { + _ok = true + } + else if (want.call({}, have) === true) { + _ok = true; + } + } + + ok(_ok, emit); + } + + function test(name){ + _setup() + try { + templateSettings = _.clone(_.templateSettings); + if (arguments.length == 3) { + count = 0 + for (count = 0; count < arguments[1]; count++) { + arguments[2]() + } + } else { + // For now. + arguments[1]() + } + } + finally { + _teardown() + } + } + + function deepEqual(a, b, emit) { + // Also, for now. + assert(_.isEqual(a, b), emit) + } + `) } func Test_underscore(t *testing.T) { - Terst(t) + tt(t, func() { + test, _ := test_() - test := underscoreTest() + test(` + _.map([1, 2, 3], function(value){ + return value + 1 + }) + `, "2,3,4") - test(` - _.map([1, 2, 3], function(value){ - return value + 1 - }) - `, "2,3,4") + test(` + abc = _.find([1, 2, 3, -1], function(value) { return value == -1 }) + `, -1) - test(` - abc = _.find([1, 2, 3, -1], function(value) { return value == -1 }) - `, "-1") - - test(`_.isEqual(1, 1)`, "true") - test(`_.isEqual([], [])`, "true") - test(`_.isEqual(['b', 'd'], ['b', 'd'])`, "true") - test(`_.isEqual(['b', 'd', 'c'], ['b', 'd', 'e'])`, "false") - test(`_.isFunction(function(){})`, "true") - test(`_.template('

\u2028<%= "\\u2028\\u2029" %>\u2029

')()`, "

\u2028\u2028\u2029\u2029

") + test(`_.isEqual(1, 1)`, true) + test(`_.isEqual([], [])`, true) + test(`_.isEqual(['b', 'd'], ['b', 'd'])`, true) + test(`_.isEqual(['b', 'd', 'c'], ['b', 'd', 'e'])`, false) + test(`_.isFunction(function(){})`, true) + test(`_.template('

\u2028<%= "\\u2028\\u2029" %>\u2029

')()`, "

\u2028\u2028\u2029\u2029

") + }) } // TODO Test: typeof An argument reference diff --git a/underscore_utility_test.go b/underscore_utility_test.go index 185c55b..ebabb08 100644 --- a/underscore_utility_test.go +++ b/underscore_utility_test.go @@ -1,46 +1,44 @@ package otto import ( - . "./terst" "testing" ) // #750 - Return _ instance. func Test_underscore_utility_0(t *testing.T) { - Terst(t) + tt(t, func() { + test, _ := test_() - test := underscoreTest() - - test(` + test(` test("#750 - Return _ instance.", 2, function() { var instance = _([]); ok(_(instance) === instance); ok(new _(instance) === instance); }); - `) + `) + }) } // identity func Test_underscore_utility_1(t *testing.T) { - Terst(t) + tt(t, func() { + test, _ := test_() - test := underscoreTest() - - test(` + test(` test("identity", function() { var moe = {name : 'moe'}; equal(_.identity(moe), moe, 'moe is the same as his identity'); }); - `) + `) + }) } // random func Test_underscore_utility_2(t *testing.T) { - Terst(t) + tt(t, func() { + test, _ := test_() - test := underscoreTest() - - test(` + test(` test("random", function() { var array = _.range(1000); var min = Math.pow(2, 31); @@ -54,31 +52,31 @@ func Test_underscore_utility_2(t *testing.T) { return _.random(Number.MAX_VALUE) > 0; }), "should produce a random number when passed "); }); - `) + `) + }) } // uniqueId func Test_underscore_utility_3(t *testing.T) { - Terst(t) + tt(t, func() { + test, _ := test_() - test := underscoreTest() - - test(` + test(` test("uniqueId", function() { var ids = [], i = 0; while(i++ < 100) ids.push(_.uniqueId()); equal(_.uniq(ids).length, ids.length, 'can generate a globally-unique stream of ids'); }); - `) + `) + }) } // times func Test_underscore_utility_4(t *testing.T) { - Terst(t) + tt(t, func() { + test, _ := test_() - test := underscoreTest() - - test(` + test(` test("times", function() { var vals = []; _.times(3, function (i) { vals.push(i); }); @@ -90,16 +88,16 @@ func Test_underscore_utility_4(t *testing.T) { // collects return values ok(_.isEqual([0, 1, 2], _.times(3, function(i) { return i; })), "collects return values"); }); - `) + `) + }) } // mixin func Test_underscore_utility_5(t *testing.T) { - Terst(t) + tt(t, func() { + test, _ := test_() - test := underscoreTest() - - test(` + test(` test("mixin", function() { _.mixin({ myReverse: function(string) { @@ -109,31 +107,31 @@ func Test_underscore_utility_5(t *testing.T) { equal(_.myReverse('panacea'), 'aecanap', 'mixed in a function to _'); equal(_('champ').myReverse(), 'pmahc', 'mixed in a function to the OOP wrapper'); }); - `) + `) + }) } // _.escape func Test_underscore_utility_6(t *testing.T) { - Terst(t) + tt(t, func() { + test, _ := test_() - test := underscoreTest() - - test(` + test(` test("_.escape", function() { equal(_.escape("Curly & Moe"), "Curly & Moe"); equal(_.escape("Curly & Moe"), "Curly &amp; Moe"); equal(_.escape(null), ''); }); - `) + `) + }) } // _.unescape func Test_underscore_utility_7(t *testing.T) { - Terst(t) + tt(t, func() { + test, _ := test_() - test := underscoreTest() - - test(` + test(` test("_.unescape", function() { var string = "Curly & Moe"; equal(_.unescape("Curly & Moe"), string); @@ -141,16 +139,16 @@ func Test_underscore_utility_7(t *testing.T) { equal(_.unescape(null), ''); equal(_.unescape(_.escape(string)), string); }); - `) + `) + }) } // template func Test_underscore_utility_8(t *testing.T) { - Terst(t) + tt(t, func() { + test, _ := test_() - test := underscoreTest() - - test(` + test(` test("template", function() { var basicTemplate = _.template("<%= thing %> is gettin' on my noives!"); var result = basicTemplate({thing : 'This'}); @@ -169,8 +167,7 @@ func Test_underscore_utility_8(t *testing.T) { for (var key in people) { \ %>
  • <%= people[key] %>
  • <% } %>"); result = fancyTemplate({people : {moe : "Moe", larry : "Larry", curly : "Curly"}}); - // TODO: Property ordering unreliable - //equal(result, "
    • Moe
    • Larry
    • Curly
    ", 'can run arbitrary javascript in templates'); + equal(result, "
    • Moe
    • Larry
    • Curly
    ", 'can run arbitrary javascript in templates'); var escapedCharsInJavascriptTemplate = _.template("
      <% _.each(numbers.split('\\n'), function(item) { %>
    • <%= item %>
    • <% }) %>
    "); result = escapedCharsInJavascriptTemplate({numbers: "one\ntwo\nthree\nfour"}); @@ -185,8 +182,7 @@ func Test_underscore_utility_8(t *testing.T) { 3: "p3-thumbnail.gif" } }); - // TODO: Property ordering unreliable - //equal(result, "3 p3-thumbnail.gif
    "); + equal(result, "3 p3-thumbnail.gif
    "); var noInterpolateTemplate = _.template("

    Just some text. Hey, I know this is silly but it aids consistency.

    "); result = noInterpolateTemplate(); @@ -213,20 +209,22 @@ func Test_underscore_utility_8(t *testing.T) { }; equal(stooge.template(), "I'm Moe"); - //if (!$.browser.msie) { - // var fromHTML = _.template($('#template').html()); - // equal(fromHTML({data : 12345}).replace(/\s/g, ''), '
  • 24690
  • '); - //} + // TEST: ReferenceError: $ is not defined + if (false) { + if (!$.browser.msie) { + var fromHTML = _.template($('#template').html()); + equal(fromHTML({data : 12345}).replace(/\s/g, ''), '
  • 24690
  • '); + } + } _.templateSettings = { evaluate : /\{\{([\s\S]+?)\}\}/g, interpolate : /\{\{=([\s\S]+?)\}\}/g }; - // TODO: Property ordering unreliable - //var custom = _.template("
      {{ for (var key in people) { }}
    • {{= people[key] }}
    • {{ } }}
    "); - //result = custom({people : {moe : "Moe", larry : "Larry", curly : "Curly"}}); - //equal(result, "
    • Moe
    • Larry
    • Curly
    ", 'can run arbitrary javascript in templates'); + var custom = _.template("
      {{ for (var key in people) { }}
    • {{= people[key] }}
    • {{ } }}
    "); + result = custom({people : {moe : "Moe", larry : "Larry", curly : "Curly"}}); + equal(result, "
    • Moe
    • Larry
    • Curly
    ", 'can run arbitrary javascript in templates'); var customQuote = _.template("It's its, not it's"); equal(customQuote({}), "It's its, not it's"); @@ -239,10 +237,9 @@ func Test_underscore_utility_8(t *testing.T) { interpolate : /<\?=([\s\S]+?)\?>/g }; - // TODO: Property ordering unreliable - //var customWithSpecialChars = _.template("
    "); - //result = customWithSpecialChars({people : {moe : "Moe", larry : "Larry", curly : "Curly"}}); - //equal(result, "
    • Moe
    • Larry
    • Curly
    ", 'can run arbitrary javascript in templates'); + var customWithSpecialChars = _.template("
    "); + result = customWithSpecialChars({people : {moe : "Moe", larry : "Larry", curly : "Curly"}}); + equal(result, "
    • Moe
    • Larry
    • Curly
    ", 'can run arbitrary javascript in templates'); var customWithSpecialCharsQuote = _.template("It's its, not it's"); equal(customWithSpecialCharsQuote({}), "It's its, not it's"); @@ -260,16 +257,16 @@ func Test_underscore_utility_8(t *testing.T) { var templateWithNull = _.template("a null undefined {{planet}}"); equal(templateWithNull({planet : "world"}), "a null undefined world", "can handle missing escape and evaluate settings"); }); - `) + `) + }) } // _.template provides the generated function source, when a SyntaxError occurs func Test_underscore_utility_9(t *testing.T) { - Terst(t) + tt(t, func() { + test, _ := test_() - test := underscoreTest() - - test(` + test(` test('_.template provides the generated function source, when a SyntaxError occurs', function() { try { _.template('<%= if x %>'); @@ -278,49 +275,48 @@ func Test_underscore_utility_9(t *testing.T) { } ok(/__p/.test(source)); }); - `) + `) + }) } // _.template handles \\u2028 & \\u2029 func Test_underscore_utility_10(t *testing.T) { - Terst(t) + tt(t, func() { + test, _ := test_() - test := underscoreTest() - - test(` + test(` test('_.template handles \\u2028 & \\u2029', function() { var tmpl = _.template('

    \u2028<%= "\\u2028\\u2029" %>\u2029

    '); strictEqual(tmpl(), '

    \u2028\u2028\u2029\u2029

    '); }); - `) + `) + }) } // result calls functions and returns primitives func Test_underscore_utility_11(t *testing.T) { - Terst(t) + tt(t, func() { + test, _ := test_() - test := underscoreTest() - - test(` + test(` test('result calls functions and returns primitives', function() { var obj = {w: '', x: 'x', y: function(){ return this.x; }}; strictEqual(_.result(obj, 'w'), ''); strictEqual(_.result(obj, 'x'), 'x'); strictEqual(_.result(obj, 'y'), 'x'); strictEqual(_.result(obj, 'z'), undefined); - // FIXME: This functionality is being changed in the underscore master right now - //strictEqual(_.result(null, 'x'), undefined); + strictEqual(_.result(null, 'x'), null); }); - `) + `) + }) } // _.templateSettings.variable func Test_underscore_utility_12(t *testing.T) { - Terst(t) + tt(t, func() { + test, _ := test_() - test := underscoreTest() - - test(` + test(` test('_.templateSettings.variable', function() { var s = '<%=data.x%>'; var data = {x: 'x'}; @@ -328,31 +324,31 @@ func Test_underscore_utility_12(t *testing.T) { _.templateSettings.variable = 'data'; strictEqual(_.template(s)(data), 'x'); }); - `) + `) + }) } // #547 - _.templateSettings is unchanged by custom settings. func Test_underscore_utility_13(t *testing.T) { - Terst(t) + tt(t, func() { + test, _ := test_() - test := underscoreTest() - - test(` + test(` test('#547 - _.templateSettings is unchanged by custom settings.', function() { ok(!_.templateSettings.variable); _.template('', {}, {variable: 'x'}); ok(!_.templateSettings.variable); }); - `) + `) + }) } // #556 - undefined template variables. func Test_underscore_utility_14(t *testing.T) { - Terst(t) + tt(t, func() { + test, _ := test_() - test := underscoreTest() - - test(` + test(` test('#556 - undefined template variables.', function() { var template = _.template('<%=x%>'); strictEqual(template({x: null}), ''); @@ -370,16 +366,16 @@ func Test_underscore_utility_14(t *testing.T) { strictEqual(templateWithPropertyEscaped({x: {} }), ''); strictEqual(templateWithPropertyEscaped({x: {} }), ''); }); - `) + `) + }) } // interpolate evaluates code only once. func Test_underscore_utility_15(t *testing.T) { - Terst(t) + tt(t, func() { + test, _ := test_() - test := underscoreTest() - - test(` + test(` test('interpolate evaluates code only once.', 2, function() { var count = 0; var template = _.template('<%= f() %>'); @@ -389,34 +385,35 @@ func Test_underscore_utility_15(t *testing.T) { var templateEscaped = _.template('<%- f() %>'); templateEscaped({f: function(){ ok(!(countEscaped++)); }}); }); - `) + `) + }) } // #746 - _.template settings are not modified. func Test_underscore_utility_16(t *testing.T) { - Terst(t) + tt(t, func() { + test, _ := test_() - test := underscoreTest() - - test(` + test(` test('#746 - _.template settings are not modified.', 1, function() { var settings = {}; _.template('', null, settings); deepEqual(settings, {}); }); - `) + `) + }) } // #779 - delimeters are applied to unescaped text. func Test_underscore_utility_17(t *testing.T) { - Terst(t) + tt(t, func() { + test, _ := test_() - test := underscoreTest() - - test(` + test(` test('#779 - delimeters are applied to unescaped text.', 1, function() { var template = _.template('<<\nx\n>>', null, {evaluate: /<<(.*?)>>/g}); strictEqual(template(), '<<\nx\n>>'); }); - `) + `) + }) } diff --git a/value_test.go b/value_test.go index 777596c..23d9fd4 100644 --- a/value_test.go +++ b/value_test.go @@ -1,280 +1,281 @@ package otto import ( - . "./terst" "encoding/json" "math" "testing" ) func TestValue(t *testing.T) { - Terst(t) + tt(t, func() { + value := UndefinedValue() + is(value.IsUndefined(), true) + is(value, UndefinedValue()) + is(value, "undefined") - value := UndefinedValue() - Is(value.IsUndefined(), true) - Is(value, UndefinedValue()) - Is(value, "undefined") - - Is(toValue(false), "false") - Is(toValue(1), "1") - Equal(toValue(1).toFloat(), float64(1)) + is(toValue(false), false) + is(toValue(1), 1) + is(toValue(1).toFloat(), float64(1)) + }) } func TestObject(t *testing.T) { - Terst(t) - - Is(Value{}.isEmpty(), true) - //Is(newObject().Value(), "[object]") - //Is(newBooleanObject(false).Value(), "false") - //Is(newFunctionObject(nil).Value(), "[function]") - //Is(newNumberObject(1).Value(), "1") - //Is(newStringObject("Hello, World.").Value(), "Hello, World.") + tt(t, func() { + is(Value{}.isEmpty(), true) + //is(newObject().Value(), "[object]") + //is(newBooleanObject(false).Value(), "false") + //is(newFunctionObject(nil).Value(), "[function]") + //is(newNumberObject(1).Value(), "1") + //is(newStringObject("Hello, World.").Value(), "Hello, World.") + }) } type intAlias int func TestToValue(t *testing.T) { - Terst(t) + tt(t, func() { + _, tester := test() + vm := tester.vm - otto, _ := runTestWithOtto() + value, _ := vm.ToValue(nil) + is(value, "undefined") - value, _ := otto.ToValue(nil) - Is(value, "undefined") + value, _ = vm.ToValue((*byte)(nil)) + is(value, "undefined") - value, _ = otto.ToValue((*byte)(nil)) - Is(value, "undefined") + value, _ = vm.ToValue(intAlias(5)) + is(value, 5) - value, _ = otto.ToValue(intAlias(5)) - Is(value, "5") + { + tmp := new(int) - { - tmp := new(int) + value, _ = vm.ToValue(&tmp) + is(value, 0) - value, _ = otto.ToValue(&tmp) - Is(value, "0") + *tmp = 1 - *tmp = 1 + value, _ = vm.ToValue(&tmp) + is(value, 1) - value, _ = otto.ToValue(&tmp) - Is(value, "1") + tmp = nil - tmp = nil + value, _ = vm.ToValue(&tmp) + is(value, "undefined") + } - value, _ = otto.ToValue(&tmp) - Is(value, "undefined") - } + { + tmp0 := new(int) + tmp1 := &tmp0 + tmp2 := &tmp1 - { - tmp0 := new(int) - tmp1 := &tmp0 - tmp2 := &tmp1 + value, _ = vm.ToValue(&tmp2) + is(value, 0) - value, _ = otto.ToValue(&tmp2) - Is(value, "0") + *tmp0 = 1 - *tmp0 = 1 + value, _ = vm.ToValue(&tmp2) + is(value, 1) - value, _ = otto.ToValue(&tmp2) - Is(value, "1") + tmp0 = nil - tmp0 = nil - - value, _ = otto.ToValue(&tmp2) - Is(value, "undefined") - } + value, _ = vm.ToValue(&tmp2) + is(value, "undefined") + } + }) } func TestToBoolean(t *testing.T) { - Terst(t) - is := func(left interface{}, right bool) { - Is(toValue(left).toBoolean(), right) - } - is("", false) - is("xyzzy", true) - is(1, true) - is(0, false) - //is(toValue(newObject()), true) - is(UndefinedValue(), false) - is(NullValue(), false) + tt(t, func() { + is := func(left interface{}, right bool) { + is(toValue(left).toBoolean(), right) + } + + is("", false) + is("xyzzy", true) + is(1, true) + is(0, false) + //is(toValue(newObject()), true) + is(UndefinedValue(), false) + is(NullValue(), false) + }) } func TestToFloat(t *testing.T) { - Terst(t) - is := func(left interface{}, right float64) { - if math.IsNaN(right) { - Is(toValue(left).toFloat(), "NaN") - } else { - Is(toValue(left).toFloat(), right) + tt(t, func() { + { + is := func(left interface{}, right float64) { + is(toValue(left).toFloat(), right) + } + is("", 0) + is("xyzzy", math.NaN()) + is("2", 2) + is(1, 1) + is(0, 0) + is(NullValue(), 0) + //is(newObjectValue(), math.NaN()) } - } - is("", 0) - is("xyzzy", math.NaN()) - is("2", 2) - is(1, 1) - is(0, 0) - //is(newObjectValue(), math.NaN()) - IsTrue(math.IsNaN(UndefinedValue().toFloat())) - is(NullValue(), 0) -} - -func TestToObject(t *testing.T) { - Terst(t) + is(math.IsNaN(UndefinedValue().toFloat()), true) + }) } func TestToString(t *testing.T) { - Terst(t) - Is("undefined", UndefinedValue().toString()) - Is("null", NullValue().toString()) - Is("true", toValue(true).toString()) - Is("false", toValue(false).toString()) + tt(t, func() { + is("undefined", UndefinedValue().toString()) + is("null", NullValue().toString()) + is("true", toValue(true).toString()) + is("false", toValue(false).toString()) - Is(UndefinedValue(), "undefined") - Is(NullValue(), "null") - Is(toValue(true), "true") - Is(toValue(false), "false") + is(UndefinedValue(), "undefined") + is(NullValue(), "null") + is(toValue(true), true) + is(toValue(false), false) + }) } func Test_toInt32(t *testing.T) { - Terst(t) - - test := []interface{}{ - 0, int32(0), - 1, int32(1), - -2147483649.0, int32(2147483647), - -4294967297.0, int32(-1), - -4294967296.0, int32(0), - -4294967295.0, int32(1), - math.Inf(+1), int32(0), - math.Inf(-1), int32(0), - } - for index := 0; index < len(test)/2; index++ { - Like( - toInt32(toValue(test[index*2])), - test[index*2+1].(int32), - ) - } + tt(t, func() { + test := []interface{}{ + 0, int32(0), + 1, int32(1), + -2147483649.0, int32(2147483647), + -4294967297.0, int32(-1), + -4294967296.0, int32(0), + -4294967295.0, int32(1), + math.Inf(+1), int32(0), + math.Inf(-1), int32(0), + } + for index := 0; index < len(test)/2; index++ { + // FIXME terst, Make strict again? + is( + toInt32(toValue(test[index*2])), + test[index*2+1].(int32), + ) + } + }) } func Test_toUint32(t *testing.T) { - Terst(t) - - test := []interface{}{ - 0, uint32(0), - 1, uint32(1), - -2147483649.0, uint32(2147483647), - -4294967297.0, uint32(4294967295), - -4294967296.0, uint32(0), - -4294967295.0, uint32(1), - math.Inf(+1), uint32(0), - math.Inf(-1), uint32(0), - } - for index := 0; index < len(test)/2; index++ { - Like( - toUint32(toValue(test[index*2])), - test[index*2+1].(uint32), - ) - } + tt(t, func() { + test := []interface{}{ + 0, uint32(0), + 1, uint32(1), + -2147483649.0, uint32(2147483647), + -4294967297.0, uint32(4294967295), + -4294967296.0, uint32(0), + -4294967295.0, uint32(1), + math.Inf(+1), uint32(0), + math.Inf(-1), uint32(0), + } + for index := 0; index < len(test)/2; index++ { + // FIXME terst, Make strict again? + is( + toUint32(toValue(test[index*2])), + test[index*2+1].(uint32), + ) + } + }) } func Test_toUint16(t *testing.T) { - Terst(t) - - test := []interface{}{ - 0, uint16(0), - 1, uint16(1), - -2147483649.0, uint16(65535), - -4294967297.0, uint16(65535), - -4294967296.0, uint16(0), - -4294967295.0, uint16(1), - math.Inf(+1), uint16(0), - math.Inf(-1), uint16(0), - } - for index := 0; index < len(test)/2; index++ { - Like( - toUint16(toValue(test[index*2])), - test[index*2+1].(uint16), - ) - } + tt(t, func() { + test := []interface{}{ + 0, uint16(0), + 1, uint16(1), + -2147483649.0, uint16(65535), + -4294967297.0, uint16(65535), + -4294967296.0, uint16(0), + -4294967295.0, uint16(1), + math.Inf(+1), uint16(0), + math.Inf(-1), uint16(0), + } + for index := 0; index < len(test)/2; index++ { + // FIXME terst, Make strict again? + is( + toUint16(toValue(test[index*2])), + test[index*2+1].(uint16), + ) + } + }) } func Test_sameValue(t *testing.T) { - Terst(t) - - IsFalse(sameValue(positiveZeroValue(), negativeZeroValue())) - IsTrue(sameValue(positiveZeroValue(), toValue(0))) - IsTrue(sameValue(NaNValue(), NaNValue())) - IsFalse(sameValue(NaNValue(), toValue("Nothing happens."))) + tt(t, func() { + is(sameValue(positiveZeroValue(), negativeZeroValue()), false) + is(sameValue(positiveZeroValue(), toValue(0)), true) + is(sameValue(NaNValue(), NaNValue()), true) + is(sameValue(NaNValue(), toValue("Nothing happens.")), false) + }) } func TestExport(t *testing.T) { - Terst(t) + tt(t, func() { + test, vm := test() - test := runTest() + is(test(`null;`).export(), nil) + is(test(`undefined;`).export(), nil) + is(test(`true;`).export(), true) + is(test(`false;`).export(), false) + is(test(`0;`).export(), 0) + is(test(`3.1459`).export(), 3.1459) + is(test(`"Nothing happens";`).export(), "Nothing happens") + is(test(`String.fromCharCode(97,98,99,100,101,102)`).export(), "abcdef") + { + value := test(`({ abc: 1, def: true, ghi: undefined });`).export().(map[string]interface{}) + is(value["abc"], 1) + is(value["def"], true) + _, exists := value["ghi"] + is(exists, false) + } + { + value := test(`[ "abc", 1, "def", true, undefined, null ];`).export().([]interface{}) + is(value[0], "abc") + is(value[1], 1) + is(value[2], "def") + is(value[3], true) + is(value[4], nil) + is(value[5], nil) + is(value[5], interface{}(nil)) + } - Is(test(`null;`).export(), nil) - Is(test(`undefined;`).export(), nil) - Is(test(`true;`).export(), true) - Is(test(`false;`).export(), false) - Is(test(`0;`).export(), 0) - Is(test(`3.1459`).export(), 3.1459) - Is(test(`"Nothing happens";`).export(), "Nothing happens") - Is(test(`String.fromCharCode(97,98,99,100,101,102)`).export(), "abcdef") - { - value := test(`({ abc: 1, def: true, ghi: undefined });`).export().(map[string]interface{}) - Is(value["abc"], 1) - Is(value["def"], true) - _, exists := value["ghi"] - Is(exists, false) - } - { - value := test(`[ "abc", 1, "def", true, undefined, null ];`).export().([]interface{}) - Is(value[0], "abc") - Is(value[1], 1) - Is(value[2], "def") - Is(value[3], true) - Is(value[4], nil) - Is(value[5], nil) - Is(value[5], interface{}(nil)) - } - - roundtrip := []interface{}{ - true, - false, - 0, - 3.1459, - []interface{}{true, false, 0, 3.1459, "abc"}, - map[string]interface{}{ - "Boolean": true, - "Number": 3.1459, - "String": "abc", - "Array": []interface{}{false, 0, "", nil}, - "Object": map[string]interface{}{ - "Boolean": false, - "Number": 0, - "String": "def", + roundtrip := []interface{}{ + true, + false, + 0, + 3.1459, + []interface{}{true, false, 0, 3.1459, "abc"}, + map[string]interface{}{ + "Boolean": true, + "Number": 3.1459, + "String": "abc", + "Array": []interface{}{false, 0, "", nil}, + "Object": map[string]interface{}{ + "Boolean": false, + "Number": 0, + "String": "def", + }, }, - }, - } + } - for _, value := range roundtrip { - input, err := json.Marshal(value) - Is(err, nil) + for _, value := range roundtrip { + input, err := json.Marshal(value) + is(err, nil) - output, err := json.Marshal(test("(" + string(input) + ");").export()) - Is(err, nil) + output, err := json.Marshal(test("(" + string(input) + ");").export()) + is(err, nil) - Is(string(input), string(output)) - } + is(string(input), string(output)) + } - { - abc := struct { - def int - ghi interface{} - xyz float32 - }{} - abc.def = 3 - abc.xyz = 3.1459 - failSet("abc", abc) - Is(test(`abc;`).export(), abc) - } + { + abc := struct { + def int + ghi interface{} + xyz float32 + }{} + abc.def = 3 + abc.xyz = 3.1459 + vm.Set("abc", abc) + is(test(`abc;`).export(), abc) + } + }) }