diff --git a/ci/coding_guidelines_check.py b/ci/coding_guidelines_check.py index a0b4535f9..919a1f56c 100644 --- a/ci/coding_guidelines_check.py +++ b/ci/coding_guidelines_check.py @@ -145,7 +145,7 @@ def run_clang_format_diff(root: Path, commits: str) -> bool: found = False for summary in [x for x in diff_content if x.startswith("diff --git")]: # b/path/to/file -> path/to/file - with_invalid_format = re.split("\s+", summary)[-1][2:] + with_invalid_format = re.split(r"\s+", summary)[-1][2:] if not is_excluded(with_invalid_format): print(f"--- {with_invalid_format} failed on code style checking.") found = True diff --git a/test-tools/addr2line/addr2line.py b/test-tools/addr2line/addr2line.py index 421b0bdb2..800ba3750 100644 --- a/test-tools/addr2line/addr2line.py +++ b/test-tools/addr2line/addr2line.py @@ -206,7 +206,7 @@ def get_line_info_from_function_addr_sourcemapping( if not line: continue - m = re.match("(.*):(\d+):(\d+)", line) + m = re.match(r"(.*):(\d+):(\d+)", line) if m: function_file, function_line, function_column = m.groups() continue diff --git a/tests/wamr-test-suites/spec-test-script/all.py b/tests/wamr-test-suites/spec-test-script/all.py index fe694124a..91f9e5649 100644 --- a/tests/wamr-test-suites/spec-test-script/all.py +++ b/tests/wamr-test-suites/spec-test-script/all.py @@ -247,7 +247,7 @@ def test_case( CMD, bufsize=1, stdout=subprocess.PIPE, - stderr=subprocess.PIPE, + stderr=subprocess.STDOUT, universal_newlines=True, ) as p: try: @@ -285,7 +285,9 @@ def test_case( except subprocess.TimeoutExpired: print("failed with TimeoutExpired") raise Exception(case_name) - + except Exception as e: + print(f"An unexpected error occurred: {e}") + raise e def test_suite( target, diff --git a/tests/wamr-test-suites/spec-test-script/runtest.py b/tests/wamr-test-suites/spec-test-script/runtest.py index 6e963bdc7..427da3996 100755 --- a/tests/wamr-test-suites/spec-test-script/runtest.py +++ b/tests/wamr-test-suites/spec-test-script/runtest.py @@ -7,6 +7,7 @@ import array import atexit import math import os +import pathlib import re import shutil import struct @@ -81,9 +82,8 @@ def log(data, end='\n'): print(data, end=end) sys.stdout.flush() -def create_tmp_file(suffix: str) -> str: - with tempfile.NamedTemporaryFile(suffix=suffix, delete=False) as tmp_file: - return tmp_file.name +def create_tmp_file(prefix: str, suffix: str) -> str: + return tempfile.NamedTemporaryFile(prefix=prefix, suffix=suffix, delete=False).name # TODO: do we need to support '\n' too import platform @@ -181,7 +181,16 @@ class Runner(): # queue, so we keep it for non-windows platforms. [outs,_,_] = select([self.stdout], [], [], 1) if self.stdout in outs: - return True, self.stdout.read(1) + try: + stdout_byte = self.stdout.read(1) + except ValueError: + return True, None + except OSError: + return True, None + except Exception as e: + print("Exception: ", e) + return False, None + return True, stdout_byte else: return False, None @@ -212,6 +221,8 @@ class Runner(): buf = self.buf[0:end-len(prompt)] self.buf = self.buf[end:] return buf + + log("left read_to_prompt() because of timeout") return None def writeline(self, str): @@ -249,14 +260,14 @@ def assert_prompt(runner, prompts, timeout, is_need_execute_result): header = runner.read_to_prompt(prompts, timeout=timeout) if not header and is_need_execute_result: log(" ---------- will terminate cause the case needs result while there is none inside of buf. ----------") - sys.exit(1) + raise Exception("get nothing from Runner") if not header == None: if header: log("Started with:\n%s" % header) else: log("Did not one of following prompt(s): %s" % repr(prompts)) log(" Got : %s" % repr(r.buf)) - sys.exit(1) + raise Exception("Did not one of following prompt(s)") ### WebAssembly specific @@ -551,7 +562,7 @@ def parse_assertion_value(val): if not val: return None, "" - splitted = re.split('\s+', val) + splitted = re.split(r'\s+', val) splitted = [s for s in splitted if s] type = splitted[0].split(".")[0] lane_type = splitted[1] if len(splitted) > 2 else "" @@ -790,8 +801,8 @@ def test_assert(r, opts, mode, cmd, expected): return True ## 0x9:i32,-0x1:i32 -> ['0x9:i32', '-0x1:i32'] - expected_list = re.split(',', expected) - out_list = re.split(',', out) + expected_list = re.split(r',', expected) + out_list = re.split(r',', out) if len(expected_list) != len(out_list): raise Exception("Failed:\n Results count incorrect:\n expected: '%s'\n got: '%s'" % (expected, out)) for i in range(len(expected_list)): @@ -806,34 +817,34 @@ def test_assert_return(r, opts, form): n. to search a pattern like (assert_return (invoke $module_name function_name ... ) ...) """ # params, return - m = re.search('^\(assert_return\s+\(invoke\s+"((?:[^"]|\\\")*)"\s+(\(.*\))\s*\)\s*(\(.*\))\s*\)\s*$', form, re.S) + m = re.search(r'^\(assert_return\s+\(invoke\s+"((?:[^"]|\\\")*)"\s+(\(.*\))\s*\)\s*(\(.*\))\s*\)\s*$', form, re.S) # judge if assert_return cmd includes the module name - n = re.search('^\(assert_return\s+\(invoke\s+\$((?:[^\s])*)\s+"((?:[^"]|\\\")*)"\s+(\(.*\))\s*\)\s*(\(.*\))\s*\)\s*$', form, re.S) + n = re.search(r'^\(assert_return\s+\(invoke\s+\$((?:[^\s])*)\s+"((?:[^"]|\\\")*)"\s+(\(.*\))\s*\)\s*(\(.*\))\s*\)\s*$', form, re.S) # print("assert_return with {}".format(form)) if not m: # no params, return - m = re.search('^\(assert_return\s+\(invoke\s+"((?:[^"]|\\\")*)"\s*\)\s+()(\(.*\))\s*\)\s*$', form, re.S) + m = re.search(r'^\(assert_return\s+\(invoke\s+"((?:[^"]|\\\")*)"\s*\)\s+()(\(.*\))\s*\)\s*$', form, re.S) if not m: # params, no return - m = re.search('^\(assert_return\s+\(invoke\s+"([^"]*)"\s+(\(.*\))()\s*\)\s*\)\s*$', form, re.S) + m = re.search(r'^\(assert_return\s+\(invoke\s+"([^"]*)"\s+(\(.*\))()\s*\)\s*\)\s*$', form, re.S) if not m: # no params, no return - m = re.search('^\(assert_return\s+\(invoke\s+"([^"]*)"\s*()()\)\s*\)\s*$', form, re.S) + m = re.search(r'^\(assert_return\s+\(invoke\s+"([^"]*)"\s*()()\)\s*\)\s*$', form, re.S) if not m: # params, return if not n: # no params, return - n = re.search('^\(assert_return\s+\(invoke\s+\$((?:[^\s])*)\s+"((?:[^"]|\\\")*)"\s*\)\s+()(\(.*\))\s*\)\s*$', form, re.S) + n = re.search(r'^\(assert_return\s+\(invoke\s+\$((?:[^\s])*)\s+"((?:[^"]|\\\")*)"\s*\)\s+()(\(.*\))\s*\)\s*$', form, re.S) if not n: # params, no return - n = re.search('^\(assert_return\s+\(invoke\s+\$((?:[^\s])*)\s+"([^"]*)"\s+(\(.*\))()\s*\)\s*\)\s*$', form, re.S) + n = re.search(r'^\(assert_return\s+\(invoke\s+\$((?:[^\s])*)\s+"([^"]*)"\s+(\(.*\))()\s*\)\s*\)\s*$', form, re.S) if not n: # no params, no return - n = re.search('^\(assert_return\s+\(invoke\s+\$((?:[^\s])*)\s+"([^"]*)"*()()\)\s*\)\s*$', form, re.S) + n = re.search(r'^\(assert_return\s+\(invoke\s+\$((?:[^\s])*)\s+"([^"]*)"*()()\)\s*\)\s*$', form, re.S) if not m and not n: - if re.search('^\(assert_return\s+\(get.*\).*\)$', form, re.S): + if re.search(r'^\(assert_return\s+\(get.*\).*\)$', form, re.S): log("ignoring assert_return get") return else: @@ -852,7 +863,7 @@ def test_assert_return(r, opts, form): if m.group(2) == '': args = [] else: - #args = [re.split(' +', v)[1].replace('_', "") for v in re.split("\)\s*\(", m.group(2)[1:-1])] + #args = [re.split(r' +', v)[1].replace('_', "") for v in re.split(r"\)\s*\(", m.group(2)[1:-1])] # split arguments with ')spaces(', remove leading and tailing ) and ( args_type_and_value = re.split(r'\)\s+\(', m.group(2)[1:-1]) args_type_and_value = [s.replace('_', '') for s in args_type_and_value] @@ -863,7 +874,7 @@ def test_assert_return(r, opts, form): for arg in args_type_and_value: # remove leading and tailing spaces, it might confuse following assertions arg = arg.strip() - splitted = re.split('\s+', arg) + splitted = re.split(r'\s+', arg) splitted = [s for s in splitted if s] if splitted[0] in ["i32.const", "i64.const"]: @@ -881,7 +892,7 @@ def test_assert_return(r, opts, form): numbers, _ = cast_v128_to_i64x2(splitted[2:], 'v128', splitted[1]) assert(len(numbers) == 2), "has to reform arguments into i64x2" - args.append(f"{numbers[0]:#x}\{numbers[1]:#x}") + args.append(f"{numbers[0]:#x}\\{numbers[1]:#x}") elif "ref.null" == splitted[0]: args.append("null") elif "ref.extern" == splitted[0]: @@ -896,7 +907,7 @@ def test_assert_return(r, opts, form): if m.group(3) == '': returns= [] else: - returns = re.split("\)\s*\(", m.group(3)[1:-1]) + returns = re.split(r"\)\s*\(", m.group(3)[1:-1]) # processed numbers in strings if len(returns) == 1 and returns[0] in ["ref.array", "ref.struct", "ref.i31", "ref.eq", "ref.any", "ref.extern", @@ -921,8 +932,7 @@ def test_assert_return(r, opts, form): except: _, exc, _ = sys.exc_info() log("Run wamrc failed:\n got: '%s'" % r.buf) - ret_code = 1 - sys.exit(1) + raise Exception("Run wamrc failed 1") r = run_wasm_with_repl(module+".wasm", module+".aot" if test_aot else module, opts, r) # Wait for the initial prompt try: @@ -941,23 +951,23 @@ def test_assert_return(r, opts, form): # convert (ref.null extern/func) into (ref.null null) n1 = n.group(3).replace("(ref.null extern)", "(ref.null null)") n1 = n1.replace("ref.null func)", "(ref.null null)") - args = [re.split(' +', v)[1] for v in re.split("\)\s*\(", n1[1:-1])] + args = [re.split(r' +', v)[1] for v in re.split(r"\)\s*\(", n1[1:-1])] _, expected = parse_assertion_value(n.group(4)[1:-1]) test_assert(r, opts, "return", "%s %s" % (func, " ".join(args)), expected) def test_assert_trap(r, opts, form): # params - m = re.search('^\(assert_trap\s+\(invoke\s+"([^"]*)"\s+(\(.*\))\s*\)\s*"([^"]+)"\s*\)\s*$', form) + m = re.search(r'^\(assert_trap\s+\(invoke\s+"([^"]*)"\s+(\(.*\))\s*\)\s*"([^"]+)"\s*\)\s*$', form) # judge if assert_return cmd includes the module name - n = re.search('^\(assert_trap\s+\(invoke\s+\$((?:[^\s])*)\s+"([^"]*)"\s+(\(.*\))\s*\)\s*"([^"]+)"\s*\)\s*$', form, re.S) + n = re.search(r'^\(assert_trap\s+\(invoke\s+\$((?:[^\s])*)\s+"([^"]*)"\s+(\(.*\))\s*\)\s*"([^"]+)"\s*\)\s*$', form, re.S) if not m: # no params - m = re.search('^\(assert_trap\s+\(invoke\s+"([^"]*)"\s*()\)\s*"([^"]+)"\s*\)\s*$', form) + m = re.search(r'^\(assert_trap\s+\(invoke\s+"([^"]*)"\s*()\)\s*"([^"]+)"\s*\)\s*$', form) if not m: if not n: # no params - n = re.search('^\(assert_trap\s+\(invoke\s+\$((?:[^\s])*)\s+"([^"]*)"\s*()\)\s*"([^"]+)"\s*\)\s*$', form, re.S) + n = re.search(r'^\(assert_trap\s+\(invoke\s+\$((?:[^\s])*)\s+"([^"]*)"\s*()\)\s*"([^"]+)"\s*\)\s*$', form, re.S) if not m and not n: raise Exception("unparsed assert_trap: '%s'" % form) @@ -969,7 +979,7 @@ def test_assert_trap(r, opts, form): # convert (ref.null extern/func) into (ref.null null) m1 = m.group(2).replace("(ref.null extern)", "(ref.null null)") m1 = m1.replace("ref.null func)", "(ref.null null)") - args = [re.split(' +', v)[1] for v in re.split("\)\s*\(", m1[1:-1])] + args = [re.split(r' +', v)[1] for v in re.split(r"\)\s*\(", m1[1:-1])] expected = "Exception: %s" % m.group(3) test_assert(r, opts, "trap", "%s %s" % (func, " ".join(args)), expected) @@ -987,8 +997,7 @@ def test_assert_trap(r, opts, form): except: _, exc, _ = sys.exc_info() log("Run wamrc failed:\n got: '%s'" % r.buf) - ret_code = 1 - sys.exit(1) + raise Exception("Run wamrc failed 2") r = run_wasm_with_repl(module+".wasm", module+".aot" if test_aot else module, opts, r) # Wait for the initial prompt try: @@ -1002,23 +1011,23 @@ def test_assert_trap(r, opts, form): if n.group(3) == '': args = [] else: - args = [re.split(' +', v)[1] for v in re.split("\)\s*\(", n.group(3)[1:-1])] + args = [re.split(r' +', v)[1] for v in re.split(r"\)\s*\(", n.group(3)[1:-1])] expected = "Exception: %s" % n.group(4) test_assert(r, opts, "trap", "%s %s" % (func, " ".join(args)), expected) def test_assert_exhaustion(r,opts,form): # params - m = re.search('^\(assert_exhaustion\s+\(invoke\s+"([^"]*)"\s+(\(.*\))\s*\)\s*"([^"]+)"\s*\)\s*$', form) + m = re.search(r'^\(assert_exhaustion\s+\(invoke\s+"([^"]*)"\s+(\(.*\))\s*\)\s*"([^"]+)"\s*\)\s*$', form) if not m: # no params - m = re.search('^\(assert_exhaustion\s+\(invoke\s+"([^"]*)"\s*()\)\s*"([^"]+)"\s*\)\s*$', form) + m = re.search(r'^\(assert_exhaustion\s+\(invoke\s+"([^"]*)"\s*()\)\s*"([^"]+)"\s*\)\s*$', form) if not m: raise Exception("unparsed assert_exhaustion: '%s'" % form) func = m.group(1) if m.group(2) == '': args = [] else: - args = [re.split(' +', v)[1] for v in re.split("\)\s*\(", m.group(2)[1:-1])] + args = [re.split(r' +', v)[1] for v in re.split(r"\)\s*\(", m.group(2)[1:-1])] expected = "Exception: %s\n" % m.group(3) test_assert(r, opts, "exhaustion", "%s %s" % (func, " ".join(args)), expected) @@ -1035,7 +1044,7 @@ def test_assert_wasmexception(r,opts,form): # \)\s* # \)\s* # $ - m = re.search('^\(assert_exception\s+\(invoke\s+"([^"]+)"\s+(\(.*\))\s*\)\s*\)\s*$', form) + m = re.search(r'^\(assert_exception\s+\(invoke\s+"([^"]+)"\s+(\(.*\))\s*\)\s*\)\s*$', form) if not m: # no params @@ -1046,24 +1055,24 @@ def test_assert_wasmexception(r,opts,form): # \)\s* # \)\s* # $ - m = re.search('^\(assert_exception\s+\(invoke\s+"([^"]+)"\s*()\)\s*\)\s*$', form) + m = re.search(r'^\(assert_exception\s+\(invoke\s+"([^"]+)"\s*()\)\s*\)\s*$', form) if not m: raise Exception("unparsed assert_exception: '%s'" % form) func = m.group(1) # function name if m.group(2) == '': # arguments args = [] else: - args = [re.split(' +', v)[1] for v in re.split("\)\s*\(", m.group(2)[1:-1])] + args = [re.split(r' +', v)[1] for v in re.split(r"\)\s*\(", m.group(2)[1:-1])] expected = "Exception: uncaught wasm exception\n" test_assert(r, opts, "wasmexception", "%s %s" % (func, " ".join(args)), expected) def do_invoke(r, opts, form): # params - m = re.search('^\(invoke\s+"([^"]+)"\s+(\(.*\))\s*\)\s*$', form) + m = re.search(r'^\(invoke\s+"([^"]+)"\s+(\(.*\))\s*\)\s*$', form) if not m: # no params - m = re.search('^\(invoke\s+"([^"]+)"\s*()\)\s*$', form) + m = re.search(r'^\(invoke\s+"([^"]+)"\s*()\)\s*$', form) if not m: raise Exception("unparsed invoke: '%s'" % form) func = m.group(1) @@ -1074,7 +1083,7 @@ def do_invoke(r, opts, form): if m.group(2) == '': args = [] else: - args = [re.split(' +', v)[1] for v in re.split("\)\s*\(", m.group(2)[1:-1])] + args = [re.split(r' +', v)[1] for v in re.split(r"\)\s*\(", m.group(2)[1:-1])] log("Invoking %s(%s)" % ( func, ", ".join([str(a) for a in args]))) @@ -1114,8 +1123,8 @@ def compile_wast_to_wasm(form, wast_tempfile, wasm_tempfile, opts): log("Running: %s" % " ".join(cmd)) try: subprocess.check_call(cmd) - except subprocess.CalledProcessError as e: - print(str(e)) + except Exception as e: + print(e) return False return True @@ -1238,13 +1247,17 @@ def run_wasm_with_repl(wasm_tempfile, aot_tempfile, opts, r): return r -def create_tmpfiles(wast_name): +def create_tmpfiles(file_name, test_aot, temp_file_repo): tempfiles = [] - tempfiles.append(create_tmp_file(".wast")) - tempfiles.append(create_tmp_file(".wasm")) + tempfiles.append(create_tmp_file(file_name, ".wast")) + tempfiles.append(create_tmp_file(file_name, ".wasm")) if test_aot: - tempfiles.append(create_tmp_file(".aot")) + tempfiles.append(create_tmp_file(file_name, ".aot")) + else: + tempfiles.append(None) + + assert len(tempfiles) == 3, "tempfiles should have 3 elements" # add these temp file to temporal repo, will be deleted when finishing the test temp_file_repo.extend(tempfiles) @@ -1263,6 +1276,9 @@ def test_assert_with_exception(form, wast_tempfile, wasm_tempfile, aot_tempfile, if test_aot: r = compile_wasm_to_aot(wasm_tempfile, aot_tempfile, True, opts, r) + if not loadable: + return + try: assert_prompt(r, ['Compile success'], opts.start_fail_timeout, True) except: @@ -1275,8 +1291,7 @@ def test_assert_with_exception(form, wast_tempfile, wasm_tempfile, aot_tempfile, else: log("Run wamrc failed:\n expected: '%s'\n got: '%s'" % \ (expected, r.buf)) - ret_code = 1 - sys.exit(1) + raise Exception("Run wamrc failed 3") r = run_wasm_with_repl(wasm_tempfile, aot_tempfile if test_aot else None, opts, r) @@ -1296,6 +1311,20 @@ def test_assert_with_exception(form, wast_tempfile, wasm_tempfile, aot_tempfile, raise Exception("Failed:\n expected: '%s'\n got: '%s'" % \ (expected, r.buf)) +def recently_added_wasm(temp_file_repo): + for f in reversed(temp_file_repo): + if not f: + continue + + assert os.path.exists(f), f"temp file {f} should exist" + + if os.path.getsize(f) == 0: + continue + + if f.endswith(".wasm"): + return f + + if __name__ == "__main__": opts = parser.parse_args(sys.argv[1:]) # print('Input param :',opts) @@ -1314,16 +1343,10 @@ if __name__ == "__main__": else: SKIP_TESTS = C_SKIP_TESTS - wast_tempfile = create_tmp_file(".wast") - wasm_tempfile = create_tmp_file(".wasm") - if test_aot: - aot_tempfile = create_tmp_file(".aot") - # could be potientially compiled to aot - # with the future following call test_assert_xxx, - # add them to temp_file_repo now even if no actual following file, - # it will be simple ignore during final deletion if not exist - prefix = wasm_tempfile.split(".wasm")[0] - temp_file_repo.append(prefix + ".aot") + case_file = pathlib.Path(opts.test_file.name) + assert(case_file.exists()), f"Test file {case_file} doesn't exist" + + tmpfile_stem = case_file.stem + "_" ret_code = 0 try: @@ -1335,22 +1358,26 @@ if __name__ == "__main__": for form in forms: # log("\n### Current Case is " + form + "\n") + + wast_tempfile, wasm_tempfile, aot_tempfile = create_tmpfiles( + tmpfile_stem, test_aot, temp_file_repo) + if ";;" == form[0:2]: log(form) elif skip_test(form, SKIP_TESTS): log("Skipping test: %s" % form[0:60]) - elif re.match("^\(assert_trap\s+\(module", form): + elif re.match(r"^\(assert_trap\s+\(module", form): test_assert_with_exception(form, wast_tempfile, wasm_tempfile, aot_tempfile if test_aot else None, opts, r) - elif re.match("^\(assert_exhaustion\\b.*", form): + elif re.match(r"^\(assert_exhaustion\b.*", form): test_assert_exhaustion(r, opts, form) - elif re.match("^\(assert_exception\\b.*", form): + elif re.match(r"^\(assert_exception\b.*", form): test_assert_wasmexception(r, opts, form) - elif re.match("^\(assert_unlinkable\\b.*", form): + elif re.match(r"^\(assert_unlinkable\b.*", form): test_assert_with_exception(form, wast_tempfile, wasm_tempfile, aot_tempfile if test_aot else None, opts, r, False) - elif re.match("^\(assert_malformed\\b.*", form): + elif re.match(r"^\(assert_malformed\b.*", form): # remove comments in wast form,n = re.subn(";;.*\n", "", form) - m = re.match("^\(assert_malformed\s*\(module binary\s*(\".*\").*\)\s*\"(.*)\"\s*\)$", form, re.DOTALL) + m = re.match(r"^\(assert_malformed\s*\(module binary\s*(\".*\").*\)\s*\"(.*)\"\s*\)$", form, re.DOTALL) if m: # workaround: spec test changes error message to "malformed" while iwasm still use "invalid" @@ -1359,7 +1386,7 @@ if __name__ == "__main__": with open(wasm_tempfile, 'wb') as f: s = m.group(1) while s: - res = re.match("[^\"]*\"([^\"]*)\"(.*)", s, re.DOTALL) + res = re.match(r"[^\"]*\"([^\"]*)\"(.*)", s, re.DOTALL) if IS_PY_3: context = res.group(1).replace("\\", "\\x").encode("latin1").decode("unicode-escape").encode("latin1") f.write(context) @@ -1414,51 +1441,43 @@ if __name__ == "__main__": else: log("Run wamrc failed:\n expected: '%s'\n got: '%s'" % \ (error_msg, r.buf)) - ret_code = 1 - sys.exit(1) + raise Exception("Run wamrc failed 4") r = run_wasm_with_repl(wasm_tempfile, aot_tempfile if test_aot else None, opts, r) - elif re.match("^\(assert_malformed\s*\(module quote", form): + elif re.match(r"^\(assert_malformed\s*\(module quote", form): log("ignoring assert_malformed module quote") else: log("unrecognized assert_malformed") - elif re.match("^\(assert_return[_a-z]*_nan\\b.*", form): + elif re.match(r"^\(assert_return[_a-z]*_nan\b.*", form): log("ignoring assert_return_.*_nan") pass - elif re.match(".*\(invoke\s+\$\\b.*", form): + elif re.match(r".*\(invoke\s+\$\b.*", form): # invoke a particular named module's function if form.startswith("(assert_return"): test_assert_return(r,opts,form) elif form.startswith("(assert_trap"): test_assert_trap(r,opts,form) - elif re.match("^\(module\\b.*", form): + elif re.match(r"^\(module\b.*", form): # if the module includes the particular name startswith $ - m = re.search("^\(module\s+\$.\S+", form) + m = re.search(r"^\(module\s+\$.\S+", form) if m: # get module name - module_name = re.split('\$', m.group(0).strip())[1] + module_name = re.split(r'\$', m.group(0).strip())[1] if module_name: # create temporal files - temp_files = create_tmpfiles(module_name) + temp_files = create_tmpfiles(module_name, test_aot, temp_file_repo) if not compile_wast_to_wasm(form, temp_files[0], temp_files[1], opts): raise Exception("compile wast to wasm failed") if test_aot: r = compile_wasm_to_aot(temp_files[1], temp_files[2], True, opts, r) - # could be potientially compiled to aot - # with the future following call test_assert_xxx, - # add them to temp_file_repo now even if no actual following file, - # it will be simple ignore during final deletion if not exist - prefix = temp_files[1].split(".wasm")[0] - temp_file_repo.append(prefix + ".aot") try: assert_prompt(r, ['Compile success'], opts.start_timeout, False) except: _, exc, _ = sys.exc_info() log("Run wamrc failed:\n got: '%s'" % r.buf) - ret_code = 1 - sys.exit(1) + raise Exception("Run wamrc failed 5") temp_module_table[module_name] = temp_files[1] r = run_wasm_with_repl(temp_files[1], temp_files[2] if test_aot else None, opts, r) else: @@ -1472,8 +1491,7 @@ if __name__ == "__main__": except: _, exc, _ = sys.exc_info() log("Run wamrc failed:\n got: '%s'" % r.buf) - ret_code = 1 - sys.exit(1) + raise Exception("Run wamrc failed 6") r = run_wasm_with_repl(wasm_tempfile, aot_tempfile if test_aot else None, opts, r) @@ -1485,38 +1503,51 @@ if __name__ == "__main__": raise Exception("Failed:\n expected: '%s'\n got: '%s'" % \ (repr(exc), r.buf)) - elif re.match("^\(assert_return\\b.*", form): + elif re.match(r"^\(assert_return\b.*", form): assert(r), "iwasm repl runtime should be not null" test_assert_return(r, opts, form) - elif re.match("^\(assert_trap\\b.*", form): + elif re.match(r"^\(assert_trap\b.*", form): test_assert_trap(r, opts, form) - elif re.match("^\(invoke\\b.*", form): + elif re.match(r"^\(invoke\b.*", form): assert(r), "iwasm repl runtime should be not null" do_invoke(r, opts, form) - elif re.match("^\(assert_invalid\\b.*", form): - test_assert_with_exception(form, wast_tempfile, wasm_tempfile, aot_tempfile if test_aot else None, opts, r) - elif re.match("^\(register\\b.*", form): + elif re.match(r"^\(assert_invalid\b.*", form): + # loading invalid module will raise an error directly, so shell prompt won't show here + test_assert_with_exception(form, wast_tempfile, wasm_tempfile, aot_tempfile if test_aot else None, opts, r, False) + elif re.match(r"^\(register\b.*", form): # get module's new name from the register cmd - name_new =re.split('\"',re.search('\".*\"',form).group(0))[1] - if name_new: - new_module = os.path.join(tempfile.gettempdir(), name_new + ".wasm") - shutil.copyfile(temp_module_table.get(name_new, wasm_tempfile), new_module) - - # add new_module copied from the old into temp_file_repo[] - temp_file_repo.append(new_module) - - if test_aot: - new_module_aot = os.path.join(tempfile.gettempdir(), name_new + ".aot") - r = compile_wasm_to_aot(new_module, new_module_aot, True, opts, r) - try: - assert_prompt(r, ['Compile success'], opts.start_timeout, True) - except: - raise Exception("compile wasm to aot failed") - # add aot module into temp_file_repo[] - temp_file_repo.append(new_module_aot) - else: + name_new =re.split(r'\"',re.search(r'\".*\"',form).group(0))[1] + if not name_new: # there is no name defined in register cmd - raise Exception("can not find module name from the register") + raise Exception(f"Not following register cmd pattern {form}") + + # assumption + # - There exists a module in the form of (module $name). + # - The nearest module in the form of (module), without $name, is the candidate for registration. + recently_wasm = recently_added_wasm(temp_file_repo) + if not name_new in temp_module_table: + print(temp_file_repo) + print(f"Module {name_new} is not found in temp_module_table. use the nearest module {recently_wasm}") + + for_registration = temp_module_table.get(name_new, recently_wasm) + assert os.path.exists(for_registration), f"module {for_registration} is not found" + + new_module = os.path.join(tempfile.gettempdir(), name_new + ".wasm") + # for_registration(tmpfile) --copy-> name_new.wasm + shutil.copyfile(for_registration, new_module) + + # add new_module copied from the old into temp_file_repo[] + temp_file_repo.append(new_module) + + if test_aot: + new_module_aot = os.path.join(tempfile.gettempdir(), name_new + ".aot") + r = compile_wasm_to_aot(new_module, new_module_aot, True, opts, r) + try: + assert_prompt(r, ['Compile success'], opts.start_timeout, True) + except: + raise Exception("compile wasm to aot failed") + # add aot module into temp_file_repo[] + temp_file_repo.append(new_module_aot) else: raise Exception("unrecognized form '%s...'" % form[0:40]) except Exception as e: @@ -1524,35 +1555,42 @@ if __name__ == "__main__": print("THE FINAL EXCEPTION IS {}".format(e)) ret_code = 101 - shutil.copyfile(wasm_tempfile, os.path.join(opts.log_dir, os.path.basename(wasm_tempfile))) - - if opts.aot or opts.xip: - shutil.copyfile(aot_tempfile, os.path.join(opts.log_dir,os.path.basename(aot_tempfile))) - if "indirect-mode" in str(e): - compile_wasm_to_aot(wasm_tempfile, aot_tempfile, None, opts, None, "object") - shutil.copyfile(aot_tempfile, os.path.join(opts.log_dir,os.path.basename(aot_tempfile)+'.o')) - subprocess.check_call(["llvm-objdump", "-r", aot_tempfile]) - compile_wasm_to_aot(wasm_tempfile, aot_tempfile, None, opts, None, "ir") - shutil.copyfile(aot_tempfile, os.path.join(opts.log_dir,os.path.basename(aot_tempfile)+".ir")) + try: + shutil.copyfile(wasm_tempfile, os.path.join(opts.log_dir, os.path.basename(wasm_tempfile))) + if opts.aot or opts.xip: + shutil.copyfile(aot_tempfile, os.path.join(opts.log_dir,os.path.basename(aot_tempfile))) + if "indirect-mode" in str(e): + compile_wasm_to_aot(wasm_tempfile, aot_tempfile, None, opts, None, "object") + shutil.copyfile(aot_tempfile, os.path.join(opts.log_dir,os.path.basename(aot_tempfile)+'.o')) + subprocess.check_call(["llvm-objdump", "-r", aot_tempfile]) + compile_wasm_to_aot(wasm_tempfile, aot_tempfile, None, opts, None, "ir") + shutil.copyfile(aot_tempfile, os.path.join(opts.log_dir,os.path.basename(aot_tempfile)+".ir")) + except Exception as e: + print("Failed to copy files to log directory: %s" % e) + ret_code = 102 else: ret_code = 0 finally: - if not opts.no_cleanup: - log("Removing tempfiles") - os.remove(wast_tempfile) - os.remove(wasm_tempfile) - if test_aot: - os.remove(aot_tempfile) + try: + if not opts.no_cleanup: + # remove the files under /tempfiles/ and copy of .wasm files + log(f"Removing {temp_file_repo}") - # remove the files under /tempfiles/ and copy of .wasm files - if temp_file_repo: for t in temp_file_repo: - if(len(str(t))!=0 and os.path.exists(t)): + # None and empty + if not t: + continue + + if os.path.exists(t): os.remove(t) + else: + log(f"Leaving {temp_file_repo}") + + except Exception as e: + print("Failed to remove tempfiles: %s" % e) + # ignore the exception + ret_code = 0 - log("### End testing %s" % opts.test_file.name) - else: - log("Leaving tempfiles: %s" % ([wast_tempfile, wasm_tempfile])) - + log(f"### End testing {opts.test_file.name} with {ret_code}") sys.exit(ret_code) diff --git a/tests/wamr-test-suites/test_wamr.sh b/tests/wamr-test-suites/test_wamr.sh index 183033751..7a4ca08b5 100755 --- a/tests/wamr-test-suites/test_wamr.sh +++ b/tests/wamr-test-suites/test_wamr.sh @@ -448,9 +448,9 @@ function spec_test() # May 31, 2012 [interpreter] implement atomic.wait and atomic.notify (#194) git reset --hard 09f2831349bf409187abb6f7868482a8079f2264 - git apply ../../spec-test-script/thread_proposal_ignore_cases.patch || exit 1 - git apply ../../spec-test-script/thread_proposal_fix_atomic_case.patch || exit 1 - git apply ../../spec-test-script/thread_proposal_remove_memory64_flag_case.patch + git apply --ignore-whitespace ../../spec-test-script/thread_proposal_ignore_cases.patch || exit 1 + git apply --ignore-whitespace ../../spec-test-script/thread_proposal_fix_atomic_case.patch || exit 1 + git apply --ignore-whitespace ../../spec-test-script/thread_proposal_remove_memory64_flag_case.patch elif [ ${ENABLE_EH} == 1 ]; then echo "checkout exception-handling test cases" @@ -459,7 +459,7 @@ function spec_test() # Jun 6, 2023 Merge branch 'upstream' into merge-upstream git reset --hard 51c721661b671bb7dc4b3a3acb9e079b49778d36 - git apply ../../spec-test-script/exception_handling.patch || exit 1 + git apply --ignore-whitespace ../../spec-test-script/exception_handling.patch || exit 1 elif [[ ${ENABLE_GC} == 1 ]]; then echo "checkout spec for GC proposal" @@ -469,12 +469,12 @@ function spec_test() # Dec 9, 2024. Merge branch 'funcref' git reset --hard 756060f5816c7e2159f4817fbdee76cf52f9c923 - git apply ../../spec-test-script/gc_ignore_cases.patch || exit 1 + git apply --ignore-whitespace ../../spec-test-script/gc_ignore_cases.patch || exit 1 if [[ ${ENABLE_QEMU} == 1 ]]; then # Decrease the recursive count for tail call cases as nuttx qemu's # native stack size is much smaller - git apply ../../spec-test-script/gc_nuttx_tail_call.patch || exit 1 + git apply --ignore-whitespace ../../spec-test-script/gc_nuttx_tail_call.patch || exit 1 fi # As of version 1.0.36, wabt is still unable to correctly handle the GC proposal. @@ -497,7 +497,7 @@ function spec_test() git checkout 044d0d2e77bdcbe891f7e0b9dd2ac01d56435f0b -- test/core/elem.wast test/core/data.wast # Patch table64 extension git checkout 940398cd4823522a9b36bec4984be4b153dedb81 -- test/core/call_indirect.wast test/core/table.wast test/core/table_copy.wast test/core/table_copy_mixed.wast test/core/table_fill.wast test/core/table_get.wast test/core/table_grow.wast test/core/table_init.wast test/core/table_set.wast test/core/table_size.wast - git apply ../../spec-test-script/memory64_ignore_cases.patch || exit 1 + git apply --ignore-whitespace ../../spec-test-script/memory64_ignore_cases.patch || exit 1 elif [[ ${ENABLE_MULTI_MEMORY} == 1 ]]; then echo "checkout spec for multi memory proposal" @@ -508,9 +508,9 @@ function spec_test() # Reset to commit: "Merge pull request #48 from backes/specify-memcpy-immediate-order" git reset --hard fbc99efd7a788db300aec3dd62a14577ec404f1b git checkout 044d0d2e77bdcbe891f7e0b9dd2ac01d56435f0b -- test/core/elem.wast - git apply ../../spec-test-script/multi_memory_ignore_cases.patch || exit 1 + git apply --ignore-whitespace ../../spec-test-script/multi_memory_ignore_cases.patch || exit 1 if [[ ${RUNNING_MODE} == "aot" ]]; then - git apply ../../spec-test-script/multi_module_aot_ignore_cases.patch || exit 1 + git apply --ignore-whitespace ../../spec-test-script/multi_module_aot_ignore_cases.patch || exit 1 fi else echo "checkout spec for default proposal" @@ -520,15 +520,15 @@ function spec_test() # Dec 20, 2024. Use WPT version of test harness for HTML core test conversion (#1859) git reset --hard f3a0e06235d2d84bb0f3b5014da4370613886965 - git apply ../../spec-test-script/ignore_cases.patch || exit 1 + git apply --ignore-whitespace ../../spec-test-script/ignore_cases.patch || exit 1 if [[ ${ENABLE_SIMD} == 1 ]]; then - git apply ../../spec-test-script/simd_ignore_cases.patch || exit 1 + git apply --ignore-whitespace ../../spec-test-script/simd_ignore_cases.patch || exit 1 fi if [[ ${ENABLE_MULTI_MODULE} == 1 ]]; then - git apply ../../spec-test-script/multi_module_ignore_cases.patch || exit 1 + git apply --ignore-whitespace ../../spec-test-script/multi_module_ignore_cases.patch || exit 1 if [[ ${RUNNING_MODE} == "aot" ]]; then - git apply ../../spec-test-script/multi_module_aot_ignore_cases.patch || exit 1 + git apply --ignore-whitespace ../../spec-test-script/multi_module_aot_ignore_cases.patch || exit 1 fi fi fi