Created
April 18, 2021 03:23
-
-
Save avih/d4765c2d39d487737134682dbb08cf70 to your computer and use it in GitHub Desktop.
mujs test-262 patchset - on top of mujs dcb3f03 (after 1.0.4 and before 1.0.5)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
From 7297871b882483e748946cb7156244be2da9e752 Mon Sep 17 00:00:00 2001 | |
From: "Avi Halachmi (:avih)" <[email protected]> | |
Date: Thu, 30 Aug 2018 16:24:24 +0300 | |
Subject: [PATCH 1/4] mujs shell: Add compile function. | |
The new compile function compiles a source code string as a script and | |
returns a callable object. The optional 'filename' argument is used to | |
format error messages and stack traces. | |
--- | |
main.c | 10 ++++++++++ | |
1 file changed, 10 insertions(+) | |
diff --git a/main.c b/main.c | |
index cbc7edc..ef343a7 100644 | |
--- a/main.c | |
+++ b/main.c | |
@@ -98,6 +98,13 @@ static void jsB_load(js_State *J) | |
js_pushboolean(J, !rv); | |
} | |
+static void jsB_compile(js_State *J) | |
+{ | |
+ const char *source = js_tostring(J, 1); | |
+ const char *filename = js_isdefined(J, 2) ? js_tostring(J, 2) : "[string]"; | |
+ js_loadstring(J, filename, source); | |
+} | |
+ | |
static void jsB_print(js_State *J) | |
{ | |
int i, top = js_gettop(J); | |
@@ -288,6 +295,9 @@ main(int argc, char **argv) | |
js_newcfunction(J, jsB_load, "load", 1); | |
js_setglobal(J, "load"); | |
+ js_newcfunction(J, jsB_compile, "compile", 2); | |
+ js_setglobal(J, "compile"); | |
+ | |
js_newcfunction(J, jsB_print, "print", 0); | |
js_setglobal(J, "print"); | |
-- | |
2.25.1 | |
From ac4b326b45c4fa36dbad4ebbc5d2da485b908006 Mon Sep 17 00:00:00 2001 | |
From: "Avi Halachmi (:avih)" <[email protected]> | |
Date: Sun, 2 Sep 2018 23:41:06 +0300 | |
Subject: [PATCH 2/4] 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/test262-harness.js | 135 +++++++++++++++++++++++++++++++++++++++ | |
1 file changed, 135 insertions(+) | |
create mode 100644 tools/test262-harness.js | |
diff --git a/tools/test262-harness.js b/tools/test262-harness.js | |
new file mode 100644 | |
index 0000000..3722634 | |
--- /dev/null | |
+++ b/tools/test262-harness.js | |
@@ -0,0 +1,135 @@ | |
+/* | |
+ * Runs one test file from the ES5 test suite test-262 | |
+ * 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) | |
+ * | |
+ * 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 overrides = []; | |
+ while ((""+args[0])[0] == "-") { | |
+ switch (args[0]) { | |
+ case "-f": full_mode = 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/); | |
+ 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) | |
+ mujs.quit(0); | |
+ | |
+ // failed | |
+ var desc = source.match(/@description (.*)/); | |
+ var info = "[File] " + as_file + | |
+ (desc ? "\n[Desc] " + desc[1] : "") + | |
+ "\n"; | |
+ | |
+ if (result) { | |
+ var err = result.err; | |
+ info += (result.runtime ? "[run] " : "[load] ") + err; | |
+ 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]"; | |
+ } | |
+ | |
+ mujs.print(info); | |
+ mujs.quit(1); | |
+ | |
+})(this) | |
-- | |
2.25.1 | |
From f57fe789d7b89916fc5c6d5935ec391b6feba026 Mon Sep 17 00:00:00 2001 | |
From: "Avi Halachmi (:avih)" <[email protected]> | |
Date: Sun, 2 Sep 2018 23:42:06 +0300 | |
Subject: [PATCH 3/4] 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. | |
--- | |
tools/test262 | 130 ++++++++++++++++++++++++++++++++++++++++++++++++++ | |
1 file changed, 130 insertions(+) | |
create mode 100755 tools/test262 | |
diff --git a/tools/test262 b/tools/test262 | |
new file mode 100755 | |
index 0000000..6f5d6dc | |
--- /dev/null | |
+++ b/tools/test262 | |
@@ -0,0 +1,130 @@ | |
+#!/bin/sh | |
+ | |
+usage() { | |
+ [ "${1-}" ] && { to=2; >&$to printf "Error: %s\n" "$1"; } || to=1 | |
+ >&$to echo "Usage: $(basename "$0") [+s] [-p] [-f] [-l f1.js -l ..] test-file | test-dir" | |
+ >&$to echo "Run test-262 ES5 test file[s]." | |
+ >&$to echo " +s : Don't skip known crashing/hanging tests" | |
+ >&$to echo " -p : Print every test name before running it" | |
+ >&$to echo " -f : Display full paths and full stack trace when possible" | |
+ >&$to echo " -l file.js : load file.js after the harness and before the test" | |
+ exit $((to-1)) | |
+} | |
+ | |
+KNOWN_BAD=" | |
+ --hang-with-sta.js: | |
+ S15.1.3.2_A2.5_T1.js | |
+ S15.1.3.1_A2.5_T1.js | |
+ | |
+ --Hang-(or-taking-more-than-few-seconds): | |
+ 15.4.4.18-3-14.js | |
+ 15.4.4.20-3-14.js | |
+ S15.4.4.10_A3_T2.js | |
+ S15.4.4.10_A3_T1.js | |
+ 15.4.4.19-3-29.js | |
+ 15.4.4.19-3-28.js | |
+ 15.4.4.19-3-8.js | |
+ 15.4.4.19-3-14.js | |
+ S15.4.4.8_A3_T3.js | |
+ 15.4.4.22-3-9.js | |
+ 15.4.4.22-3-12.js | |
+ 15.4.4.22-3-7.js | |
+ 15.4.4.22-3-25.js | |
+ 15.4.4.22-3-14.js | |
+ 15.4.4.21-3-14.js | |
+ 15.4.4.15-3-28.js | |
+ 15.4.4.15-3-12.js | |
+ 15.4.4.15-3-14.js | |
+ 15.4.4.15-3-7.js | |
+ 15.4.4.15-3-25.js | |
+ 15.4.4.15-3-9.js | |
+ | |
+ --Buffer-overflow/abort: | |
+ S15.7.4.5_A1.4_T01.js | |
+ | |
+ --Segfault: | |
+ S15.4.4.5_A2_T2.js | |
+ S15.4.4.5_A4_T3.js | |
+" | |
+ | |
+SKIP_KNOWN=yes | |
+PRINT_ALL= | |
+EXTRA_ARGS= | |
+while [ "${1-}" ] && [ -z "${1##-*}" ]; do | |
+ case $1 in | |
+ -h|--help) usage ;; | |
+ +s) SKIP_KNOWN= ;; | |
+ -p) PRINT_ALL=yes ;; | |
+ -f) EXTRA_ARGS="$EXTRA_ARGS -f" ;; | |
+ -l) EXTRA_ARGS="$EXTRA_ARGS -l $2"; shift ;; | |
+ *) usage "unknown option $1" ;; | |
+ esac | |
+ shift | |
+done | |
+[ $# = 1 ] || usage "expecting one file/dir" | |
+ | |
+BAD= | |
+if [ "$SKIP_KNOWN" ]; then | |
+ for b in $KNOWN_BAD; do | |
+ BAD="$BAD $b " | |
+ done | |
+fi | |
+ | |
+find_root() { | |
+ ROOT=$1 | |
+ n=0 | |
+ while ! [ -e "$ROOT"/test/harness/sta.js ]; do | |
+ ROOT=$ROOT/.. | |
+ n=$((n+1)) | |
+ [ $n -lt 10 ] || usage "can't find test-suite root" | |
+ done | |
+} | |
+ | |
+if [ -d "$1" ]; then | |
+ find_root "$1" | |
+ | |
+ if [ "$ROOT" = "$1" ]; then | |
+ FILES_CMD='find "$1/test/suite" -name "*.js" | sort -V' | |
+ else | |
+ FILES_CMD='find "$1" -name "*.js" | sort -V' | |
+ fi | |
+else | |
+ find_root "$(dirname "$1")" | |
+ FILES_CMD='printf "%s\n" "$1"' | |
+fi | |
+ | |
+# try to use a recently built mujs rather than a global one | |
+mujs=$(dirname "$0")/../build/release/mujs | |
+[ -e "$mujs" ] || mujs=mujs | |
+jsharness=$(dirname "$0")/test262-harness.js | |
+ | |
+total=0 | |
+skipped=0 | |
+failed=0 | |
+ | |
+eval "$FILES_CMD" | ( | |
+ while read f && [ "$f" ]; do | |
+ total=$((total+1)) | |
+ base=${f##*/} | |
+ [ "$PRINT_ALL" ] && echo "Testing: $f" | |
+ | |
+ case $BAD in | |
+ *" $base "*) | |
+ skipped=$((skipped+1)) | |
+ printf "[Skipping: $base]\n\n" | |
+ ;; | |
+ *) | |
+ if ! $mujs $jsharness $EXTRA_ARGS "$ROOT" $f; then | |
+ failed=$((failed+1)) | |
+ echo | |
+ fi | |
+ esac | |
+ done | |
+ | |
+ if [ $total -gt 1 ]; then | |
+ printf "Total: $total\n" | |
+ printf "Pass: %${#total}s\n" $((total - skipped - failed)) | |
+ printf "Skip: %${#total}s\n" $skipped | |
+ printf "Fail: %${#total}s\n" $failed | |
+ fi | |
+) 2>&1 | |
-- | |
2.25.1 | |
From 263dafed5787d50bb1ba7cc1918c65070fa5584b Mon Sep 17 00:00:00 2001 | |
From: "Avi Halachmi (:avih)" <[email protected]> | |
Date: Tue, 4 Sep 2018 15:36:05 +0300 | |
Subject: [PATCH 4/4] 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. | |
--- | |
tools/test262-harness.js | 15 ++++++++++++--- | |
1 file changed, 12 insertions(+), 3 deletions(-) | |
diff --git a/tools/test262-harness.js b/tools/test262-harness.js | |
index 3722634..0a0f765 100644 | |
--- a/tools/test262-harness.js | |
+++ b/tools/test262-harness.js | |
@@ -92,6 +92,8 @@ | |
// 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, "/"); | |
@@ -101,8 +103,13 @@ | |
} | |
var result = load(mujs.read(test_path), as_file); | |
- if (!!result == negative) | |
- mujs.quit(0); | |
+ 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 | |
var desc = source.match(/@description (.*)/); | |
@@ -112,7 +119,9 @@ | |
if (result) { | |
var err = result.err; | |
- info += (result.runtime ? "[run] " : "[load] ") + 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; | |
-- | |
2.25.1 | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment