From 7f418172870cd3dcd6117008fc717ea4844ae23e Mon Sep 17 00:00:00 2001 From: Volodymyr Shymanskyy Date: Mon, 30 Dec 2019 13:58:25 +0200 Subject: [PATCH] Allow running tests for proposals --- .gitignore | 4 ++- extra/testutils.py | 51 ++++++++++++++++++++++++++ source/m3_parse.c | 14 +++++--- test/run-spec-test.py | 83 ++++++++++++------------------------------- test/run-wasi-test.py | 35 ++---------------- 5 files changed, 89 insertions(+), 98 deletions(-) create mode 100755 extra/testutils.py diff --git a/.gitignore b/.gitignore index bbcebfe..ecb154b 100644 --- a/.gitignore +++ b/.gitignore @@ -1,9 +1,11 @@ /build* /source-* -node_modules test/core +test/proposals test/*.log test/tailcall/*.S +node_modules/ +__pycache__/ .project .cproject .settings diff --git a/extra/testutils.py b/extra/testutils.py new file mode 100755 index 0000000..9b659e4 --- /dev/null +++ b/extra/testutils.py @@ -0,0 +1,51 @@ +#!/usr/bin/env python3 + +# Author: Volodymyr Shymanskyy + +import os +import re, fnmatch +import pathlib + +class ansi: + ENDC = '\033[0m' + HEADER = '\033[94m' + OKGREEN = '\033[92m' + WARNING = '\033[93m' + FAIL = '\033[91m' + BOLD = '\033[1m' + UNDERLINE = '\033[4m' + +class dotdict(dict): + def __init__(self, *args, **kwargs): + super(dotdict, self).__init__(*args, **kwargs) + for arg in args: + if isinstance(arg, dict): + for k, v in arg.items(): + self[k] = v + if kwargs: + for k, v in kwargs.items(): + self[k] = v + + __getattr__ = dict.get + __setattr__ = dict.__setitem__ + __delattr__ = dict.__delitem__ + +class Blacklist(): + def __init__(self, patterns): + patterns = map(fnmatch.translate, patterns) + final = '|'.join(patterns) + self._regex = re.compile(final) + + def __contains__(self, item): + return self._regex.match(item) != None + +def filename(p): + _, fn = os.path.split(p) + return fn + +def pathname(p): + pn, _ = os.path.split(p) + return pn + +def ensure_path(p): + pathlib.Path(p).mkdir(parents=True, exist_ok=True) diff --git a/source/m3_parse.c b/source/m3_parse.c index 16b08ac..d1b3469 100644 --- a/source/m3_parse.c +++ b/source/m3_parse.c @@ -498,19 +498,20 @@ M3Result ParseModuleSection (M3Module * o_module, u8 i_sectionType, bytes_t i_ ParseSection_Type, // 1 ParseSection_Import, // 2 ParseSection_Function, // 3 - NULL, // 4: table + NULL, // 4: Table ParseSection_Memory, // 5 ParseSection_Global, // 6 ParseSection_Export, // 7 ParseSection_Start, // 8 ParseSection_Element, // 9 ParseSection_Code, // 10 - ParseSection_Data // 11 + ParseSection_Data, // 11 + NULL, // 12: DataCount from bulk memory operations proposal }; M3Parser parser = NULL; - if (i_sectionType <= 11) + if (i_sectionType <= 12) parser = s_parsers [i_sectionType]; if (parser) @@ -559,8 +560,11 @@ _ (Read_u32 (&version, & pos, end)); u8 sectionCode; _ (ReadLEB_u7 (& sectionCode, & pos, end)); - if (sectionCode > previousSection or sectionCode == 0) // from the spec: sections must appear in order - { + if (sectionCode > previousSection or // from the spec: sections must appear in order + sectionCode == 0 or + (sectionCode == 12 and previousSection == 9) or // if present, DataCount goes after Element + (sectionCode == 10 and previousSection == 12) // and before Code + ) { u32 sectionLength; _ (ReadLEB_u32 (& sectionLength, & pos, end)); _ (ParseModuleSection (module, sectionCode, pos, sectionLength)); diff --git a/test/run-spec-test.py b/test/run-spec-test.py index 38dd416..cca5b12 100755 --- a/test/run-spec-test.py +++ b/test/run-spec-test.py @@ -5,6 +5,7 @@ # ./run-spec-test.py # ./run-spec-test.py ./core/i32.json # ./run-spec-test.py ./core/float_exprs.json --line 2070 +# ./run-spec-test.py ./proposals/tail-call/*.json # ./run-spec-test.py --exec ../build-custom/wasm3 # ./run-spec-test.py --engine "wasmer run" --exec ../build-wasi/wasm3.wasm # ./run-spec-test.py --engine "wasmer run --backend=llvm" --exec ../build-wasi/wasm3.wasm @@ -23,9 +24,15 @@ import json import re import struct import math +import pathlib +scriptDir = os.path.dirname(os.path.abspath(sys.argv[0])) +sys.path.append(os.path.join(scriptDir, '..', 'extra')) + +from testutils import * from pprint import pprint + # # Args handling # @@ -54,30 +61,6 @@ if args.line: log = open("spec-test.log","w+") log.write("======================\n") -class ansi: - ENDC = '\033[0m' - HEADER = '\033[94m' - OKGREEN = '\033[92m' - WARNING = '\033[93m' - FAIL = '\033[91m' - BOLD = '\033[1m' - UNDERLINE = '\033[4m' - -class dotdict(dict): - def __init__(self, *args, **kwargs): - super(dotdict, self).__init__(*args, **kwargs) - for arg in args: - if isinstance(arg, dict): - for k, v in arg.items(): - self[k] = v - if kwargs: - for k, v in kwargs.items(): - self[k] = v - - __getattr__ = dict.get - __setattr__ = dict.__setitem__ - __delattr__ = dict.__delitem__ - def warning(msg): log.write("Warning: " + msg + "\n") log.flush() @@ -90,10 +73,6 @@ def fatal(msg): print(f"{ansi.FAIL}Fatal:{ansi.ENDC} {msg}") sys.exit(1) -def filename(p): - _, fn = os.path.split(p) - return fn - def binaryToFloat(num, t): if t == "f32": return struct.unpack('!f', struct.pack('!L', int(num)))[0] @@ -163,7 +142,7 @@ if args.format == "fp": # Spec tests preparation # -def specTestsFetch(): +if not (os.path.isdir("./core") and os.path.isdir("./proposals")): from io import BytesIO from zipfile import ZipFile from urllib.request import urlopen @@ -174,8 +153,13 @@ def specTestsFetch(): resp = urlopen(officialSpec) with ZipFile(BytesIO(resp.read())) as zipFile: for zipInfo in zipFile.infolist(): - if re.match(r".*-master/core/.*", zipInfo.filename): - zipInfo.filename = "core/" + filename(zipInfo.filename) + if re.match(r".*-master/.*/.*(\.wasm|\.json)", zipInfo.filename): + parts = pathlib.Path(zipInfo.filename).parts + newpath = str(pathlib.Path(*parts[1:-1])) + newfn = str(pathlib.Path(*parts[-1:])) + ensure_path(newpath) + newpath = newpath + "/" + newfn + zipInfo.filename = newpath zipFile.extract(zipInfo) # @@ -323,29 +307,10 @@ class Wasm3(): self.p.wait(timeout=1.0) self.p = None -# -# Blacklist -# - -import fnmatch - -class Blacklist(): - def __init__(self, patterns): - patterns = map(fnmatch.translate, patterns) - final = '|'.join(patterns) - self._regex = re.compile(final) - - def __contains__(self, item): - return self._regex.match(item) != None - # # Actual test # -curDir = os.path.dirname(os.path.abspath(sys.argv[0])) -coreDir = os.path.join(curDir, "core") - - wasm3 = Wasm3(args.exec, args.engine) print("Version: " + wasm3.version()) @@ -480,15 +445,13 @@ def runInvoke(test): showTestResult() #sys.exit(1) -if not os.path.isdir(coreDir): - specTestsFetch() - if args.file: jsonFiles = args.file else: - jsonFiles = glob.glob(os.path.join(coreDir, "*.json")) - jsonFiles = list(map(lambda x: os.path.relpath(x, curDir), jsonFiles)) - jsonFiles.sort() + jsonFiles = glob.glob(os.path.join(".", "core", "*.json")) + #jsonFiles = list(map(lambda x: os.path.relpath(x, curDir), jsonFiles)) + +jsonFiles.sort() for fn in jsonFiles: with open(fn) as f: @@ -515,8 +478,8 @@ for fn in jsonFiles: print(f"Loading {wasm_module}") try: - fn = os.path.relpath(os.path.join(coreDir, wasm_module), curDir) - wasm3.load(fn) + wasm_fn = os.path.join(pathname(fn), wasm_module) + wasm3.load(wasm_fn) except Exception as e: pass #fatal(str(e)) @@ -568,8 +531,8 @@ for fn in jsonFiles: # These are irrelevant elif (test.type == "assert_invalid" or - test.type == "assert_malformed" or - test.type == "assert_uninstantiable"): + test.type == "assert_malformed" or + test.type == "assert_uninstantiable"): pass # Others - report as skipped diff --git a/test/run-wasi-test.py b/test/run-wasi-test.py index e7f4a30..d2de349 100755 --- a/test/run-wasi-test.py +++ b/test/run-wasi-test.py @@ -13,6 +13,9 @@ import subprocess import hashlib import fnmatch +sys.path.append('../extra') + +from testutils import * from pprint import pprint # @@ -25,38 +28,6 @@ parser.add_argument("--timeout", type=int, default=120) args = parser.parse_args() -# -# Helpers -# - -class ansi: - ENDC = '\033[0m' - HEADER = '\033[94m' - OKGREEN = '\033[92m' - WARNING = '\033[93m' - FAIL = '\033[91m' - BOLD = '\033[1m' - UNDERLINE = '\033[4m' - -class dotdict(dict): - def __init__(self, *args, **kwargs): - super(dotdict, self).__init__(*args, **kwargs) - for arg in args: - if isinstance(arg, dict): - for k, v in arg.items(): - self[k] = v - if kwargs: - for k, v in kwargs.items(): - self[k] = v - - __getattr__ = dict.get - __setattr__ = dict.__setitem__ - __delattr__ = dict.__delitem__ - -# -# Actual test -# - stats = dotdict(total_run=0, failed=0, crashed=0, timeout=0) commands = [