sku-pg
Version:
Skulpt is a Javascript implementation of Python 2.x. Python that runs in your browser!
468 lines (433 loc) • 13.2 kB
JavaScript
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();
}