if (Sk.inBrowser) { goog.require('goog.dom'); goog.require('goog.ui.ComboBox'); } var tokenizefail = 0; var tokenizepass = 0; function dump_tokens(fn, input) { var uneval = function(t) { return new Sk.builtins['repr'](new Sk.builtins['str'](t)).v; }; var ret = '', lines = input.split("\n"), curIndex = 0, printer = function (type, token, st, en, line) { var srow = st[0], scol = st[1], erow = en[0], ecol = en[1]; var data = sprintf("%-12.12s %-13.13s (%d, %d) (%d, %d)", Sk.Tokenizer.tokenNames[type], uneval(token), srow, scol, erow, ecol); //print("DUMP:"+data); ret += data; ret += "\n"; }; var tokenizer = new Sk.Tokenizer(fn, false, printer); var done = false; for (var i = 0; i < lines.length && !done; ++i) { done = tokenizer.generateTokens(lines[i] + ((i === lines.length - 1) ? "" : "\n")); } if (!done) tokenizer.generateTokens(); return ret; } function testTokenize(name) { try { var input = read(name + ".py"); } catch (e) { return; } if (input.charAt(input.length - 1) !== "\n") { throw "input wasn't nl term"; } input = input.substring(0, input.length - 1); if (input.charAt(input.length - 1) === "\r") { input = input.substring(0, input.length - 1); } var expect = read(name + ".expect"); var got = ''; try { got = dump_tokens(name + ".py", input); } catch (e) { got += Sk.builtins['str'](e).v + "\n"; } if (expect !== got) { print("FAILED: (" + name + ".py)\n-----"); print(input); print("-----\nGOT:\n-----"); print(got); print("-----\nWANTED:\n-----"); print(expect); tokenizefail += 1; } else { tokenizepass += 1; } } var parsefail = 0; var parsepass = 0; function testParse(name) { try { var input = read(name + ".py"); } catch (e) { return; } var expect = read(name + ".expect"); var got; try { got = Sk.parseTreeDump(Sk.parse(name + ".py", input)); } catch (e) { got = "EXCEPTION\n"; got += e.constructor.name + "\n"; got += JSON.stringify(e) + "\n"; } if (expect !== got) { print("FAILED: (" + name + ".py)\n-----"); print(input); print("-----\nGOT:\n-----"); print(got); print("-----\nWANTED:\n-----"); print(expect); parsefail += 1; } else { parsepass += 1; } } var transformpass = 0; var transformfail = 0; var transformdisabled = 0; function testTransform(name) { try { var input = read(name + ".py"); } catch (e) { return; } var expect = 'NO_.TRANS_FILE'; try { expect = read(name + ".trans"); } catch (e) { transformdisabled += 1; return; } var cst = Sk.parse(name + ".py", input); var got = Sk.astDump(Sk.astFromParse(cst)) + "\n"; //print(got); //print(Sk.parseTreeDump(cst)); if (expect !== got) { print("FAILED: (" + name + ".py)\n-----"); print(input); print("-----\nGOT:\n-----"); print(got); print("-----\nWANTED:\n-----"); print(expect); //print("-----\nCST:\n-----"); //print(Sk.parseTestDump(cst)); transformfail += 1; } else { transformpass += 1; } } var symtabpass = 0; var symtabfail = 0; var symtabdisabled = 0; function testSymtab(name) { try { var input = read(name + ".py"); } catch (e) { return; } //print(name); var expect = 'NO_.SYMTAB_FILE'; try { expect = read(name + ".py.symtab"); } catch (e) { symtabdisabled += 1; return; } var cst = Sk.parse(name + ".py", input); var ast = Sk.astFromParse(cst); var st = Sk.symboltable(ast, name + ".py"); var got = Sk.dumpSymtab(st); if (expect !== got) { print("FAILED: (" + name + ".py)\n-----"); print(input); print("-----\nGOT:\n-----"); print(got); print("-----\nWANTED:\n-----"); print(expect); symtabfail += 1; } else { symtabpass += 1; } } var AllRunTests = []; var runpass = 0; var runfail = 0; var rundisabled = 0; function testRun(name, nocatch, debugMode) { try { var input = read(name + ".py"); } catch (e) { try { read(name + ".py.disabled"); rundisabled += 1;} catch (e) {} return; } AllRunTests.unshift(name); var got = ''; var justpath = name.substr(0, name.lastIndexOf('/')); Sk.configure({ output: function(str) { got += str; }, sysargv: [ name + '.py' ], read: read, debugging: debugMode, syspath: [ justpath ] }); var expect = read(name + ".py.real"); var expectalt; try { expectalt = read(name + ".py.real.alt"); } catch (e) {} var justname = name.substr(name.lastIndexOf('/') + 1); var promise = Sk.misceval.asyncToPromise(function() { return Sk.importMain(justname, false, true); }); if (!nocatch) { promise = promise.then(null, function(e) { if (e instanceof Sk.builtin.SystemExit) { // SystemExit isn't a failing exception, so treat it specially got += e.toString() + "\n"; } else if (e.name !== undefined) { // js exception, currently happens for del'd objects. shouldn't // really though. got = "EXCEPTION: " + e.name + "\n"; } else { got = "EXCEPTION: " + Sk.builtins['str'](e).v + "\n"; } }); var origPromise = promise; promise = new Promise(function(resolve) { var compareResult = function(module) { if (expect !== got && (expectalt === undefined || expectalt !== got)) { print("FAILED: (" + name + ".py)\n-----"); print(input); print("-----\nGOT:\n-----"); print(got); print("-----\nWANTED:\n-----"); print(expect); print("-----\nDIFF:\n-----") print("len got: " + got.length + "\n") print("len wanted: " + expect.length + "\n") var longest = got.length > expect.length ? got : expect; for (var i in longest) { if (got[i] !== expect[i]){ try{ print("firstdiff at: " + i + " got: " + got[i].charCodeAt(0) + " (" + got.substr(i) + ") expect: " + expect[i].charCodeAt(0) + " (" + expect.substr(i) + ")"); } catch (err){ break; } break; } } if (module && module.$js) { print("-----\nJS:\n-----"); var beaut = js_beautify(module.$js); print(beaut); } runfail += 1; //throw "dying on first run fail"; } else { runpass += 1; } resolve(); }; // Whatever happens, we resolve our promise successfully origPromise.then(compareResult, compareResult); }); } return promise; } var interactivepass = 0; var interactivefail = 0; var interactivedisabled = 0; function testInteractive(name) { try { var input = read(name + ".py"); } catch (e) { try { read(name + ".py.disabled"); interactivedisabled += 1;} catch (e) {} return; } var expect = read(name + ".py.real"); var got = ''; sk$output = function(str) { got += str; } var lines = input.split("\n"); var ic = new Skulpt.InteractiveContext(); for (var i = 0; i < lines.length; ++i) { //print("LINE:"+lines[i]); js = ic.evalLine(lines[i] + "\n"); //print("JS now:'"+js+"'"); if (js !== false) { try { var ret = eval(js); if (ret && ret.tp$repr !== undefined) got += ret.tp$repr().v + "\n"; } catch (e) { got += "EXCEPTION: " + e.name + "\n" } //print("made new context"); ic = new Skulpt.InteractiveContext(); } } if (expect !== got) { print("FAILED: (" + name + ".py)\n-----"); print(input); print("-----\nGOT:\n-----"); print(got); print("-----\nWANTED:\n-----"); print(expect); interactivefail += 1; } else { interactivepass += 1; } } var doTestToken = false var doTestParse = false var doTestTrans = false var doTestSymtab = false var doTestRun = true var testInDebugMode = arguments.indexOf("--debug-mode") != -1; function testsMain() { var i, promise = Promise.resolve(); if (doTestToken) { for (i = 0; i <= 100; i += 1) { testTokenize(sprintf("test/tokenize/t%02d", i)); } print(sprintf("tokenize: %d/%d", tokenizepass, tokenizepass + tokenizefail)); } if (doTestParse) { for (i = 0; i <= 10; i += 1) { testParse(sprintf("test/parse/t%02d", i)); } print(sprintf("parse: %d/%d", parsepass, parsepass + parsefail)); } if (doTestTrans) { for (i = 0; i <= 1000; ++i) { testTransform(sprintf("test/run/t%02d", i)); } print(sprintf("transform: %d/%d (+%d disabled)", transformpass, transformpass + transformfail, transformdisabled)); } if (doTestSymtab) { for (i = 0; i <= 1000; ++i) { testSymtab(sprintf("test/run/t%02d", i)); } print(sprintf("symtab: %d/%d (+%d disabled)", symtabpass, symtabpass + symtabfail, symtabdisabled)); } if (doTestRun) { for (i = 0; i <= 1000; ++i) { (function(i) { promise = promise.then(function(p) { return testRun(sprintf("test/run/t%02d", i), undefined, testInDebugMode); }); })(i); } for (i = 0; i < namedtfiles.length; i++ ) { (function(i) { promise = promise.then(function(p) { return testRun(namedtfiles[i],undefined,testInDebugMode); }); })(i); } promise = promise.then(function() { print(sprintf("run: %d/%d (+%d disabled)", runpass, runpass + runfail, rundisabled)); }, function(e) { print("Internal error: "+e); }); } if (Sk.inBrowser) { var origrunfail = runfail; runpass = runfail = rundisabled = 0; for (i = 0; i <= 20; ++i) { (function(i) { promise = promise.then(function() { testRun(sprintf("test/closure/t%02d", i)); }); })(i); } promise = promise.then(function() { print(sprintf("closure: %d/%d", runpass, runpass + runfail)); runfail += origrunfail; // for exit code // make a combobox of all tests so we can run just one var el = goog.dom.getElement('one-test'); var cb = new goog.ui.ComboBox(); cb.setUseDropdownArrow(true); cb.setDefaultText('Run one test...'); for (var i = 0; i < AllRunTests.length; ++i) { cb.addItem(new goog.ui.ComboBoxItem(AllRunTests[i])); } cb.render(el); goog.events.listen(cb, 'change', function(e) { goog.dom.setTextContent(goog.dom.getElement('output'), ""); print("running", e.target.getValue()); testRun(e.target.getValue(), true); }); }); } else { print("closure: skipped"); } //return; // for (i = 0; i <= 100; ++i) // { // testInteractive(sprintf("test/interactive/t%02d", i)); // } // print(sprintf("interactive: %d/%d (+%d disabled)", interactivepass, interactivepass + interactivefail, interactivedisabled)); //print('exiting with: ' + tokenizefail + parsefail + transformfail + symtabfail + runfail + interactivefail); if (!Sk.inBrowser) { promise.then(function(x) { print("Quitting"); var exitCode = tokenizefail + parsefail + transformfail + symtabfail + runfail + interactivefail; if (exitCode > 0) { quit(exitCode); } // Do not quit if success; may prevent other scripts from running after this one }); } } if (!Sk.inBrowser) { testsMain(); }