#!/usr/bin/env kjscmd var failures = 0; var total = 0; /* Literalise a string for printing purposes */ function literal(v) { switch (typeof v) { case "string": return '"' + v.replace(/[\\'"]/, "\\$1") + '"'; default: return String(v); } } /* Run a test, and check that the result is that expected */ function test(expr, expected) { var result, msg, ok, result_str, expected_str; try { result = eval(expr); ok = (result === expected); } catch (e) { ok = (expected == "exception"); result = e.name; // result = String(e); } try { result_str = literal(result); } catch (e) { result_str = ""; } msg = expr + ' = ' + result_str; if (ok) { msg += " PASS"; } else { try { expected_str = literal(expected); } catch (e) { expected_str = ""; } msg += " FAIL, expected " + expected_str; failures++; } println(msg); total++; } /* Tests begin here */ /* FutureReservedWord */ test("abstract", "exception"); test("boolean", "exception"); test("byte", "exception"); test("char", "exception"); test("class", "exception"); test("const", "exception"); test("debugger", "exception"); test("enum", "exception"); test("export", "exception"); test("extends", "exception"); test("final", "exception"); test("float", "exception"); test("goto", "exception"); test("implements", "exception"); test("int", "exception"); test("interface", "exception"); test("long", "exception"); test("native", "exception"); test("package", "exception"); test("private", "exception"); test("protected", "exception"); test("short", "exception"); test("static", "exception"); test("super", "exception"); test("synchronized", "exception"); test("throws", "exception"); test("transient", "exception"); test("volatile", "exception"); test("double", "exception"); test("import", "exception"); test("public", "exception"); test("1 + +1", 2); test("1 - +1", 0); test("1 + -1", 0); test("1 + +1", 2); test("this", this); test("null", null); test("undefined", undefined); test("'\\u0041'", "A"); test('"\\x1b\\x5bm"', ""); test('"\\33\\133m"', ""); ident = "ident"; test("ident", "ident"); test("[1,2,3].length", 3); test("({'foo':5}.foo)", 5); test("((((3))))", 3); function constr() { return constr; } constr.prototype = Object.prototype test("new new new constr()", constr); test("(1,2,3)", 3); test("i = 3; i++", 3); test("i", 4); test("i = 3; ++i", 4); test("i", 4); test("i = 3; i--", 3); test("i", 2); test("i = 3; --i", 2); test("i", 2); test("i = 3; i ++ ++", "exception"); test("i = 3; --i++", "exception"); /* only inc/decrement lvalues */ test("i = 3; ++i--", "exception"); /* only inc/decrement lvalues */ test("!true", false); test("~0", -1); test("void 'hi'", undefined); test("i = 3; delete i", true); test("i", "exception"); test("3 * 6 + 1", 19); test("1 + 3 * 6", 19); test("17 % 11 * 5", 30); test("30 / 3 / 5", 2); test("30 / 3 * 5", 50); test("1 - 1 - 1", -1); test("i=3;j=5; i*=j+=i", 24); /* instanceof only supports objects */ test("1 instanceof 1", "exception"); test("1 instanceof Number.prototype", "exception"); /* Only function objects should support HasInstance: */ test("new Number(1) instanceof Number.prototype", "exception"); /* Test the instanceof keyword and the new operator applied to functions. */ function Employee(age, name) { this.age = age; this.name = name; } Employee.prototype = new Object() Employee.prototype.constructor = Employee Employee.prototype.toString = function() { return "Name: " + this.name + ", age: " + this.age; } Employee.prototype.retireable = function() { return this.age > 55; } function Manager(age, name, group) { this.age = age; this.name = name; this.group = group; } Manager.prototype = new Employee(); Manager.prototype.toString = function() { return "Name: " + this.name + ", age: " + this.age + ", group: " + this.group; } e = new Employee(24, "Tony"); m = new Manager(62, "Paul", "Finance"); test("m.retireable()", true); test("m instanceof Employee", true); test("e instanceof Manager", false); test("{true;}", true); test(";", undefined); test("{}", undefined); test("i=0; do { i++; } while(i<10); i", 10); test("i=0; while (i<10) { i++; }; i", 10); test("for (i = 0; i < 10; i++); i", 10); test("i=0; for (; i < 10; i++); i", 10); test("i=0; for (; i < 10; ) i++; i", 10); test("i=0; for (; ;i++) if (i==10) break; i", 10); test("a=[1,2,3,4]; c=0; for (var v in a) c+=a[v]; c", 10); test("delete t; t", "exception"); test("{var t;} t", undefined); test("continue", "exception"); test("return", "exception"); test("break", "exception"); test("x = 0; outer: for (;;) { for (;;) break outer; x++; }; x", 0); test("x = 0; for (i = 0; i < 3; i++) { continue; x++; } x", 0); test("x = 0; it:for (i = 0; i < 3; i++) { for (;;) continue it; x++; } x", 0); test("c = 9; o = { a:'a', b: { c: 'c' }, c:7 }; with (o.b) x = c; x", 'c'); test("x = ''; for (i = 0; i < 8; i++) switch (i) {" + "case 0: x+='a'; case 1: x+='b'; break;" + "case 2: x+='c'; break; case 3: x+='d'; default: x+='e';" + "case 4: x+='f'; break; case 5: x+='g'; case 6: x+='h';}; x", "abbcdeffghhef"); test("foo:bar:baz:;", undefined); test("throw {}", "exception"); test("x=0;try{throw {a:1}} catch(e){x=e.a};x", 1); test("x=y=0;try{" + " try { throw {a:1} } finally {x=2}; " + "} catch(e) {y=e.a}; x+y", 3); test("x=y=0; try{throw {a:2};y=1;} catch(e){x=e.a;y=-7;} finally{y=3}; x+y", 5); test("String(/a|ab/.exec('abc'))", "a"); test("String(/((a)|(ab))((c)|(bc))/.exec('abc'))", "abc,a,a,,bc,,bc"); test("String(/a[a-z]{2,4}/.exec('abcdefghi'))", "abcde"); test("String(/a[a-z]{2,4}?/.exec('abcdefghi'))", "abc"); test("String(/(aa|aabaac|ba|b|c)*/.exec('aabaac'))", "aaba,ba"); test("'aaaaaaaaaa,aaaaaaaaaaaaaaa'.replace(/^(a+)\\1*,\\1+$/,'$1')", "aaaaa"); test("String(/(z)((a+)?(b+)?(c))*/.exec('zaacbbbcac'))", "zaacbbbcac,z,ac,a,,c") test("String(/(a*)*/.exec('b'))",","); test("String(/(a*)b\\1+/.exec('baaaac'))","b,"); test("String(/(?=(a+))/.exec('baaabac'))",",aaa"); test("String(/(?=(a+))a*b\\1/.exec('baaabac'))", "aba,a"); test("String(/(.*?)a(?!(a+)b\\2c)\\2(.*)/.exec('baaabaac'))", "baaabaac,ba,,abaac"); test("'$1,$2'.replace(/(\\$(\\d))/g, '$$1-$1$2')", "$1-$11,$1-$22"); test("String('ab'.split(/a*?/))", "a,b"); test("String('ab'.split(/a*/))", ",b"); /* Print a summary of what went right, and what went wrong */ println(); println((total - failures) + " out of " + total + " passed."); /* Throw an error on failure */ if (failures > 0) throw new Error("tests failure");