Files
mujs/tools/test262-harness.js
Avi Halachmi (:avih) 857ffd39b0 tools: add test262 and harness
tools: add test262-harness.js to run a single test

Usage: mujs <this-file> -- [-f] [-l file1.js -l ...] suit-root test-file
-f: print full paths/stacktraces if possible
-l: load a js file after the harness and before the test (to override things)

tools: add test-262 launcher

It can run the entire suite or just a sub-folder or one file, and by
default it skips tests which are known to crash/hang.

test262-harness: @negative: match regex if exists

Some @negative tests add a regex which needs to match the error.
This wasn't tested, and now it is. This results in few more failures.

The actual string to compare is not documented, but it appears to be
err.message for plain Error(..) where the message is always compared
to "NotEarlyError" (equals/different), and err.name for anything else.

test262 launcher: minor improvements and custom mujs path

- Use getopts instead of custom arguments parsing
- Support -m path/to/mujs
- Change -s (skip bad tests) to -b, and add -B to run only bad tests
  (useful when trying to update the known bad tests list).
- Combine stderr to stdout on a per-test basis (mujs function warnings)
- Exit with error if failures > 0

test262: remove 5 tests which no longer crash/hang

test262 and harness: support -s to print failed source

test262 and harness: convert spaces to tabs
2021-04-19 12:57:43 +02:00

153 lines
4.2 KiB
JavaScript

/*
* Runs one test file from the ES5 test suite test-262
* Usage: mujs <this-file> [-s ] [-f] [-l file1.js -l ...] suit-root test-file
* -s: print test source on failure
* -f: print full paths/stacktraces if possible
* -l: load a js file after the harness and before the test (to override things)
*
* If there are errors, print them and exits with code 1, else exit code is 0.
*
* The test suite is at: https://github.com/tc39/test262.git
* The ES5 suite is at branch "es5-tests"
*
* - The test suite throws on any error, possibly with info at ex.message .
* - Some tests make irreversible changes to global attrubutes, therefore it's
* required to run each test file in a new mujs instance.
*/
(function(global) {
"use strict";
// clean the global environment
var mujs = {};
["gc", "load", "compile", "print", "write", "read", "readline", "quit", "scriptArgs"]
.forEach(function(a) {
mujs[a] = global[a];
delete global[a];
});
// restore the original Error.toString behavior - it's being tested too
Error.prototype.toString = function() {
return this.name + ': ' + this.message;
}
function die_usage(str) {
if (str)
mujs.print(str);
mujs.print("Usage: mujs <this-file> [-f] [-l file1.js -l ...] suit-root test-file");
mujs.quit(1);
}
// our file loader
function load(str, as_filename) {
try {
var runtime_err = false;
var compiled = mujs.compile(str, as_filename);
runtime_err = true;
compiled();
return false;
} catch (e) {
return {err: e, runtime: runtime_err};
}
}
var args = mujs.scriptArgs;
var full_mode = false;
var print_src = false;
var overrides = [];
while ((""+args[0])[0] == "-") {
switch (args[0]) {
case "-f": full_mode = true;
break;
case "-s": print_src = true;
break;
case "-l": args.shift();
overrides.push(args[0]);
break;
default: die_usage("Unknown option " + args[0]);
}
args.shift();
}
if (args.length != 2)
die_usage("Exactly 2 paths are expected");
var root_path = args[0];
var test_path = args[1];
// load suite utils
["sta.js", "testBuiltInObject.js", "testIntl.js"]
.forEach(function(u) {
var path = root_path + "/test/harness/" + u;
var as_file = full_mode ? path : "test/harness/" + u;
var err = load(mujs.read(path), as_file);
if (err) throw (err.err);
});
// load user overrides (e.g. reduced getPrecision), with a global mujs
if (overrides.length) {
global.mujs = mujs
overrides.forEach(function(f) {
var err = load(mujs.read(f), f);
if (err) throw (err.err);
});
delete global.mujs;
}
// the actual test
var source = mujs.read(test_path);
var negative = !!source.match(/@negative/);
if (negative)
var neg_str = (source.match(/@negative (.*)/) || [])[1];
var as_file = test_path;
if (!full_mode) {
as_file = test_path.replace(/\\/g, "/");
var sub = as_file.indexOf("/suite/");
if (sub >= 0)
as_file = "test" + as_file.substring(sub);
}
var result = load(mujs.read(test_path), as_file);
if (!!result == negative) {
// The docs don't really help about matching str, but this covers all cases
if (neg_str)
var err_for_match = /NotEarlyError/.test(neg_str) ? result.err.message : result.err.name;
if (!negative || !neg_str || RegExp(neg_str).exec(err_for_match))
mujs.quit(0);
}
// failed
// FIXME: @description can span lines. E.g. test/suite/bestPractice/Sbp_A3_T2.js
var desc = source.match(/@description (.*)/);
var info = "[File] " + as_file +
(desc ? "\n[Desc] " + desc[1] : "") +
"\n";
if (result) {
var err = result.err;
var msg = !neg_str ? err : "[Mismatch @negative " + neg_str + "]" + "\n " + err;
info += (result.runtime ? "[run] " : "[load] ") + msg;
if (err && err.stackTrace && (result.runtime || full_mode)) {
if (full_mode) {
info += err.stackTrace;
} else {
// trim the internal loader from the trace
var internal = err.stackTrace.indexOf("\n" + load("mujs_blahblah()").err.stackTrace.trim().split("\n")[1]);
if (internal >= 0)
info += err.stackTrace.substring(0, internal);
else
info += err.stackTrace;
}
}
} else {
info += "[run] [Error expected but none thrown]";
}
if (print_src)
info += "\n[Source]\n" + source;
mujs.print(info);
mujs.quit(1);
})(this)