extensions
Steven Massey 5 years ago
commit f83eefac72

@ -1,4 +1,4 @@
name: spec tests
name: tests
on: [push, pull_request]
@ -53,7 +53,6 @@ jobs:
run: |
cmake --build build
- name: Run spec tests
continue-on-error: true
run: |
cd test
./run-spec-test.py
@ -115,4 +114,5 @@ jobs:
run: |
source $HOME/.wasmer/wasmer.sh
cd test
./run-spec-test.py --exec "wasmer ../build-wasi/wasm3.wasm"
./run-spec-test.py --engine "wasmer run" --exec "../build-wasi/wasm3.wasm"

@ -35,7 +35,6 @@ if(WASIENV)
set(CMAKE_C_COMPILER "wasicc")
set(CMAKE_CXX_COMPILER "wasic++")
set(OUT_FILE "wasm3.wasm")
set(APP_DIR "platforms/emscripten")
#set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Dd_m3LogOutput=0")
#set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -flto -Wl,--lto-O3 -Wl,-z,stack-size=8388608")
@ -96,6 +95,7 @@ elseif(WIN32)
# for example: dumpbin /DISASM wasm3.exe /out:wasm3.S
#set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /DEBUG:FULL")
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /STACK:8388608") # stack size
else()
set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} /Oxs /Oy /GS- /Qvec -Clang -O3")
endif()

@ -185,7 +185,7 @@ int main (int i_argc, const char* i_argv[])
while (argRepl)
{
char cmd_buff[128] = { 0, };
char cmd_buff[256] = { 0, };
const char* argv[32] = { 0, };
fprintf(stdout, "wasm3> ");
fflush(stdout);

@ -5,14 +5,16 @@
# ./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 --exec ../custom_build/wasm3
# ./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
#
# TODO
# - Get more tests from: https://github.com/microsoft/ChakraCore/tree/master/test/WasmSpec
# - Fix "Empty Stack" check
# - Check Canonical NaN and Arithmetic NaN separately
# - Fix names.wast
# - Fix names.wast, imports.wast
import argparse
import os, sys, glob, time
@ -30,12 +32,11 @@ from pprint import pprint
parser = argparse.ArgumentParser()
parser.add_argument("--exec", metavar="<interpreter>", default="../build/wasm3")
parser.add_argument("--engine", metavar="<engine>")
parser.add_argument("--line", metavar="<source line>", type=int)
parser.add_argument("--all", action="store_true")
parser.add_argument("--show-logs", action="store_true")
parser.add_argument("--skip-crashes", action="store_true")
parser.add_argument("--format", choices=["raw", "hex", "fp"], default="fp")
#parser.add_argument("--wasm-opt", metavar="<opt flags>")
parser.add_argument("-v", "--verbose", action="store_true")
parser.add_argument("-s", "--silent", action="store_true")
parser.add_argument("file", nargs='*')
@ -87,9 +88,6 @@ def fatal(msg):
print(f"{ansi.FAIL}Fatal:{ansi.ENDC} {msg}")
sys.exit(1)
def run(cmd):
return subprocess.check_output(cmd, stderr=subprocess.STDOUT, shell=True)
def filename(p):
_, fn = os.path.split(p)
return fn
@ -168,36 +166,45 @@ from subprocess import Popen, STDOUT, PIPE
from threading import Thread
from queue import Queue, Empty
class Wasm3():
def __init__(self, executable):
if executable.endswith(".wasm"):
(engine, wasm) = executable.split(maxsplit=1)
if engine == "wasirun":
self.exe = [engine, wasm]
elif engine == "wasmer":
self.exe = [engine, "run", "--dir=.", wasm, "--"]
#elif engine == "wasmer-js":
# self.exe = [engine, "run", wasm]
elif engine == "wasmtime":
self.exe = [engine, "--dir=.", wasm, "--"]
elif engine == "iwasm":
self.exe = [engine, "--dir=.", wasm]
else:
fatal(f"Don't know how to run engine {engine}")
import shlex
def get_engine_cmd(engine, exe):
if engine:
cmd = shlex.split(engine)
if "wasirun" in engine or "wasm3" in engine:
return cmd + [exe, "--repl"]
elif "wasmer" in engine:
return cmd + ["--dir=.", exe, "--", "--repl"]
elif "wasmtime" in engine:
return cmd + ["--dir=.", exe, "--", "--repl"]
elif "iwasm" in engine:
return cmd + ["--dir=.", exe, "--repl"]
elif "wavm" in engine:
return cmd + ["--mount-root", ".", exe, "--repl"] # TODO, fix path
else:
self.exe = [executable]
fatal(f"Don't know how to run engine {engine}")
else:
if exe.endswith(".wasm"):
fatal(f"Need engine to execute wasm")
return shlex.split(exe) + ["--repl"]
class Wasm3():
def __init__(self, exe, engine=None):
self.exe = exe
self.engine = engine
self.p = None
self.timeout = 3.0
self.timeout = 15.0
self.init()
def load(self, fn):
def init(self):
if self.p:
self.terminate()
self.loaded = fn
#print("== Running", self.exe)
self.q = Queue()
self.p = Popen(
self.exe + ["--repl", fn],
shell = False,
get_engine_cmd(self.engine, self.exe),
bufsize=0, stdin=PIPE, stdout=PIPE, stderr=STDOUT
)
@ -206,18 +213,28 @@ class Wasm3():
queue.put(data)
queue.put(None)
self.q = Queue()
self.t = Thread(target=_read_output, args=(self.p.stdout, self.q))
self.t.daemon = True
self.t.start()
output = self._read_until("wasm3> ", False)
time.sleep(0.05)
def load(self, fn):
self.loaded = fn
#self._flush_input()
#self._write(f":init\n")
#self._read_until("wasm3> ", False)
self._flush_input()
self._write(f":load {fn}\n")
return self._read_until("wasm3> ", False)
def invoke(self, cmd):
cmd = " ".join(map(str, cmd)) + "\n"
self._flush_input()
self._write(cmd)
return self._read_until("\nwasm3> ")
return self._read_until("wasm3> ")
def _read_until(self, token, autorestart=True):
buff = ""
@ -241,13 +258,17 @@ class Wasm3():
# Crash => restart
if autorestart:
self.init()
self.load(self.loaded)
raise Exception(error)
def _write(self, data):
if not self._is_running():
self.init()
self.load(self.loaded)
#raise Exception("Not running")
raise Exception("Not running")
self.p.stdin.write(data.encode("utf-8"))
self.p.stdin.flush()
@ -287,12 +308,13 @@ curDir = os.path.dirname(os.path.abspath(sys.argv[0]))
coreDir = os.path.join(curDir, "core")
wasm3 = Wasm3(args.exec)
wasm3 = Wasm3(args.exec, args.engine)
blacklist = Blacklist([
"float_exprs.wast:* f32.nonarithmetic_nan_bitpattern*",
"*.wast:* *.wasm print32*",
"*.wast:* *.wasm print64*",
"imports.wast:*",
"names.wast:*",
])
@ -312,8 +334,9 @@ def runInvoke(test):
displayArgs.append(formatValue(arg['value'], arg['type']))
test_id = f"{test.source} {test.wasm} {test.cmd[0]}({', '.join(test.cmd[1:])})"
if test_id in blacklist:
warning(f"Skipping {test_id} (blacklisted)")
if test_id in blacklist and not args.all:
if args.verbose:
warning(f"Skipping {test_id} (blacklisted)")
stats.skipped += 1
return
@ -416,7 +439,6 @@ def runInvoke(test):
stats.failed += 1
log.write(f"FAIL: {actual}, should be: {expect}\n")
if args.silent: return
if args.skip_crashes and actual == "<Crashed>": return
showTestResult()
#sys.exit(1)
@ -424,49 +446,12 @@ def runInvoke(test):
if not os.path.isdir(coreDir):
specTestsFetch()
# Currently default to running the predefined list of tests
# TODO: Switch to running all tests when wasm spec is implemented
if args.file:
jsonFiles = args.file
elif args.all:
else:
jsonFiles = glob.glob(os.path.join(coreDir, "*.json"))
jsonFiles = list(map(lambda x: os.path.relpath(x, curDir), jsonFiles))
jsonFiles.sort()
else:
jsonFiles = list(map(lambda x: f"core/{x}.json", [
"get_local", "set_local", "tee_local",
"globals",
"int_literals",
"i32", "i64",
"int_exprs",
"float_literals",
"f32", "f32_cmp", "f32_bitwise",
"f64", "f64_cmp", "f64_bitwise",
"float_misc",
"select",
"conversions",
"stack", "fac",
"call", "call_indirect",
"left-to-right",
"break-drop",
"forward",
"func_ptrs",
"address", "align", "endianness",
"memory_redundancy", "float_memory",
"memory", "memory_trap", "memory_grow",
"unreachable",
"switch", "if", "br", "br_if", "br_table", "loop", "block",
"return", "nop", "start", "unwind", "labels"
#--- TODO ---
#"float_exprs",
]))
for fn in jsonFiles:
with open(fn) as f:
@ -493,8 +478,8 @@ for fn in jsonFiles:
try:
fn = os.path.relpath(os.path.join(coreDir, wast_module), curDir)
wasm3.load(fn)
except Exception:
pass
except Exception as e:
pass #fatal(str(e))
elif ( test.type == "action" or
test.type == "assert_return" or

Loading…
Cancel
Save