Skip to content

Commit cd6cc98

Browse files
committed
Keep adapters independent
This commit removes test runner imports from the adapters, allowing them to be developed independently. Additionally this commit introduces the concept of `proposals` in the configuration, which are passed to the configuration in the form of `List[str]`, through the `proposals` the adapters can derive the specific flags needed to run the test to completion. As a last change, this commit also migrates the http-response test to use the new test configuration using the `http` proposal. Without this change it is not straight forward to derive "base proposals" for tests with the legacy configuration that wish to use specific proposals. We could certainly introduce other heuristics, at the cost of more complexity and seemingly not many advantages.
1 parent 695beec commit cd6cc98

File tree

14 files changed

+249
-149
lines changed

14 files changed

+249
-149
lines changed

adapters/pywasm.py

Lines changed: 15 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,6 @@
77
import importlib
88

99

10-
_test_runner_path = Path(__file__).parent.parent / "test-runner"
11-
if str(_test_runner_path) not in sys.path:
12-
sys.path.insert(0, str(_test_runner_path))
13-
14-
_test_case_module = importlib.import_module('wasi_test_runner.test_case')
15-
1610
# shlex.split() splits according to shell quoting rules
1711
RUN_PYWASM = Path(__file__).parent.parent / "tools" / "run-pywasm"
1812

@@ -34,17 +28,21 @@ def get_wasi_versions() -> List[str]:
3428
return ["wasm32-wasip1"]
3529

3630
def compute_argv(test_path: str,
37-
config: _test_case_module.Config,
31+
args_env_dirs: Tuple[List[str], Dict[str, str], List[Tuple[Path, str]]],
32+
proposals: List[str],
3833
wasi_version: str) -> List[str]:
34+
3935
argv = []
40-
for op in config.operations:
41-
match op:
42-
case _test_case_module.Run(args, env, dirs):
43-
argv += [str(RUN_PYWASM)]
44-
for k, v in env.items():
45-
argv += ["--env", f"{k}={v}"]
46-
for host, guest in dirs:
47-
argv += ["--dir", f"{host}::{guest}"] # noqa: E231
48-
argv += [test_path]
49-
argv += args
36+
argv += [str(RUN_PYWASM)]
37+
args, env, dirs = args_env_dirs
38+
39+
for k, v in env.items():
40+
argv += ["--env", f"{k}={v}"]
41+
42+
for host, guest in dirs:
43+
argv += ["--dir", f"{host}::{guest}"] # noqa: E231
44+
45+
argv += [test_path]
46+
47+
argv += args
5048
return argv

adapters/wasm-micro-runtime.py

Lines changed: 15 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,6 @@
77
import importlib
88

99

10-
_test_runner_path = Path(__file__).parent.parent / "test-runner"
11-
if str(_test_runner_path) not in sys.path:
12-
sys.path.insert(0, str(_test_runner_path))
13-
14-
_test_case_module = importlib.import_module('wasi_test_runner.test_case')
15-
1610
# shlex.split() splits according to shell quoting rules
1711
IWASM = shlex.split(os.getenv("IWASM", "iwasm"))
1812

@@ -35,17 +29,21 @@ def get_wasi_versions() -> List[str]:
3529

3630

3731
def compute_argv(test_path: str,
38-
config: _test_case_module.Config,
32+
args_env_dirs: Tuple[List[str], Dict[str, str], List[Tuple[Path, str]]],
33+
proposals: List[str],
3934
wasi_version: str) -> List[str]:
35+
4036
argv = []
41-
for op in config.operations:
42-
match op:
43-
case _test_case_module.Run(args, env, dirs):
44-
argv += [IWASM]
45-
for k, v in env.items():
46-
argv += ["--env", f"{k}={v}"]
47-
for host, guest in dirs:
48-
argv += ["--map-dir", f"{host}::{guest}"] # noqa: E231
49-
argv += [test_path]
50-
argv += args
37+
argv += IWASM
38+
args, env, dirs = args_env_dirs
39+
40+
for k, v in env.items():
41+
argv += ["--env", f"{k}={v}"]
42+
43+
for host, guest in dirs:
44+
argv += ["--map-dir", f"{host}::{guest}"] # noqa: E231
45+
46+
argv += [test_path]
47+
48+
argv += args
5149
return argv

adapters/wasmedge.py

Lines changed: 15 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,6 @@
77
import importlib
88

99

10-
_test_runner_path = Path(__file__).parent.parent / "test-runner"
11-
if str(_test_runner_path) not in sys.path:
12-
sys.path.insert(0, str(_test_runner_path))
13-
14-
_test_case_module = importlib.import_module('wasi_test_runner.test_case')
15-
1610
# shlex.split() splits according to shell quoting rules
1711
WASMEDGE = shlex.split(os.getenv("WASMEDGE", "wasmedge"))
1812

@@ -35,17 +29,21 @@ def get_wasi_versions() -> List[str]:
3529

3630

3731
def compute_argv(test_path: str,
38-
config: _test_case_module.Config,
32+
args_env_dirs: Tuple[List[str], Dict[str, str], List[Tuple[Path, str]]],
33+
proposals: List[str],
3934
wasi_version: str) -> List[str]:
35+
4036
argv = []
41-
for op in config.operations:
42-
match op:
43-
case _test_case_module.Run(args, env, dirs):
44-
argv += [WASMEDGE]
45-
for k, v in env.items():
46-
argv += ["--env", f"{k}={v}"]
47-
for host, guest in dirs:
48-
argv += ["--dir", f"{guest}:{host}"]
49-
argv += [test_path]
50-
argv += args
37+
argv += WASMEDGE
38+
args, env, dirs = args_env_dirs
39+
40+
for k, v in env.items():
41+
argv += ["--env", f"{k}={v}"]
42+
43+
for host, guest in dirs:
44+
argv += ["--dir", f"{guest}:{host}"]
45+
46+
argv += [test_path]
47+
48+
argv += args
5149
return argv

adapters/wasmtime.py

Lines changed: 24 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,6 @@
77
import importlib
88

99

10-
_test_runner_path = Path(__file__).parent.parent / "test-runner"
11-
if str(_test_runner_path) not in sys.path:
12-
sys.path.insert(0, str(_test_runner_path))
13-
14-
_test_case_module = importlib.import_module('wasi_test_runner.test_case')
15-
1610
# shlex.split() splits according to shell quoting rules
1711
WASMTIME = shlex.split(os.getenv("WASMTIME", "wasmtime"))
1812

@@ -35,38 +29,46 @@ def get_wasi_versions() -> List[str]:
3529

3630

3731
def compute_argv(test_path: str,
38-
config: _test_case_module.Config,
32+
args_env_dirs: Tuple[List[str], Dict[str, str], List[Tuple[Path, str]]],
33+
proposals: List[str],
3934
wasi_version: str) -> List[str]:
4035

4136
argv = []
42-
for op in config.operations:
43-
match op:
44-
case _test_case_module.Run(args, env, dirs):
45-
argv += WASMTIME
46-
for k, v in env.items():
47-
argv += ["--env", f"{k}={v}"]
48-
for host, guest in dirs:
49-
argv += ["--dir", f"{host}::{guest}"] # noqa: E231
50-
argv += [test_path]
51-
argv += args
52-
_add_wasi_version_options(argv, wasi_version)
53-
case _:
54-
pass
37+
argv += WASMTIME
38+
args, env, dirs = args_env_dirs
39+
40+
for k, v in env.items():
41+
argv += ["--env", f"{k}={v}"]
42+
43+
for host, guest in dirs:
44+
argv += ["--dir", f"{host}::{guest}"] # noqa: E231
45+
46+
argv += [test_path]
47+
48+
argv += args
49+
_add_wasi_version_options(argv, wasi_version, proposals)
5550
return argv
5651

5752

5853
# The user might provide WASMTIME="wasmtime --option -Sfoo". Let's
5954
# insert the options to choose the WASI version before the user's
6055
# options, so that the user can override our choices.
61-
def _add_wasi_version_options(argv: List[str], wasi_version: str) -> None:
56+
def _add_wasi_version_options(argv: List[str], wasi_version: str, proposals: List[str]) -> None:
6257
splice_pos = len(WASMTIME)
6358
while splice_pos > 1 and args[splice_pos-1].startswith("-"):
6459
splice_pos -= 1
6560
match wasi_version:
6661
case "wasm32-wasip1":
6762
pass
6863
case "wasm32-wasip3":
64+
flags_from_proposals = ""
65+
if "http" in proposals:
66+
flags_from_proposals += ",http"
67+
if "sockets" in proposals:
68+
flags_from_proposals += ",inherit-network"
69+
6970
argv[splice_pos:splice_pos] = ["-Wcomponent-model-async",
70-
"-Sp3,http,inherit-network"]
71+
f"-Sp3{flags_from_proposals}"]
72+
7173
case _:
7274
pass

adapters/wazero.py

Lines changed: 16 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,6 @@
77
import importlib
88

99

10-
_test_runner_path = Path(__file__).parent.parent / "test-runner"
11-
if str(_test_runner_path) not in sys.path:
12-
sys.path.insert(0, str(_test_runner_path))
13-
14-
_test_case_module = importlib.import_module('wasi_test_runner.test_case')
15-
1610
# shlex.split() splits according to shell quoting rules
1711
WAZERO = shlex.split(os.getenv("WAZERO", "wazero"))
1812

@@ -37,17 +31,22 @@ def get_wasi_versions() -> List[str]:
3731

3832

3933
def compute_argv(test_path: str,
40-
config: _test_case_module.Config,
34+
args_env_dirs: Tuple[List[str], Dict[str, str], List[Tuple[Path, str]]],
35+
proposals: List[str],
4136
wasi_version: str) -> List[str]:
37+
4238
argv = []
43-
for op in config.operations:
44-
match op:
45-
case _test_case_module.Run(args, env, dirs):
46-
argv += [WAZERO, "run", "-hostlogging=filesystem"]
47-
for k, v in env.items():
48-
argv += [f"-env={k}={v}"]
49-
for host, guest in dirs:
50-
argv += [f"-mount={host}:{guest}"]
51-
argv += [test_path]
52-
argv += args
39+
argv += WAZERO
40+
argv += ["run", "-hostlogging=filesystem"]
41+
args, env, dirs = args_env_dirs
42+
43+
for k, v in env.items():
44+
argv += [f"-env={k}={v}"]
45+
46+
for host, guest in dirs:
47+
argv += [f"-mount={host}:{guest}"]
48+
49+
argv += [test_path]
50+
51+
argv += args
5352
return argv

adapters/wizard.py

Lines changed: 16 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,6 @@
77
import importlib
88

99

10-
_test_runner_path = Path(__file__).parent.parent / "test-runner"
11-
if str(_test_runner_path) not in sys.path:
12-
sys.path.insert(0, str(_test_runner_path))
13-
14-
_test_case_module = importlib.import_module('wasi_test_runner.test_case')
15-
1610
# shlex.split() splits according to shell quoting rules
1711
WIZARD = shlex.split(os.getenv("WIZARD", "wizeng.x86-64-linux"))
1812

@@ -43,18 +37,22 @@ def get_wasi_versions() -> List[str]:
4337

4438

4539
def compute_argv(test_path: str,
46-
config: _test_case_module.Config,
40+
args_env_dirs: Tuple[List[str], Dict[str, str], List[Tuple[Path, str]]],
41+
proposals: List[str],
4742
wasi_version: str) -> List[str]:
43+
4844
argv = []
49-
for op in config.operations:
50-
match op:
51-
case _test_case_module.Run(args, env, dirs):
52-
argv += [WIZARD]
53-
for k, v in env.items():
54-
argv += [f"--env={k}={v}"]
55-
for host, guest in dirs:
56-
# FIXME: https://github.com/titzer/wizard-engine/issues/482
57-
argv += [f"--dir={host}"]
58-
argv += [test_path]
59-
argv += args
45+
argv += WIZARD
46+
args, env, dirs = args_env_dirs
47+
48+
for k, v in env.items():
49+
argv += [f"--env={k}={v}"]
50+
51+
for host, guest in dirs:
52+
# FIXME: https://github.com/titzer/wizard-engine/issues/482
53+
argv += [f"--dir={host}"]
54+
55+
argv += [test_path]
56+
57+
argv += args
6058
return argv

test-runner/tests/test_test_case.py

Lines changed: 45 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
import pytest
66

77
from wasi_test_runner.test_case import (
8-
Config, Failure, Result, Run, Wait, Read, Connect, Send, Recv, ProtocolType
8+
Config, Failure, Result, Run, Wait, Read, Connect, Send, Recv, ProtocolType, WasiProposal
99
)
1010

1111

@@ -69,13 +69,13 @@ def test_test_config_should_fail_when_mixing_config_styles(_mock_file: Mock) ->
6969

7070

7171
def test_test_results_should_mark_failed_if_multiple_failures() -> None:
72-
results = Result([], True, [Failure("type", "message")])
72+
results = Result(True, [Failure("type", "message")])
7373

7474
assert results.failed is True
7575

7676

7777
def test_test_results_should_not_mark_failed_if_no_failure() -> None:
78-
results = Result([], True, [])
78+
results = Result(True, [])
7979

8080
assert results.failed is False
8181

@@ -179,3 +179,45 @@ def test_recv_from_config_with_default_payload() -> None:
179179

180180
assert recv.id == "conn1"
181181
assert recv.payload == ""
182+
183+
184+
@patch("builtins.open", new_callable=mock_open, read_data="{}")
185+
def test_legacy_config_should_have_http_proposal_by_default(_mock_file: Mock) -> None:
186+
config = Config.from_file("file")
187+
188+
assert len(config.proposals) == 1
189+
assert config.proposals[0] == WasiProposal.HTTP
190+
191+
192+
@patch(
193+
"builtins.open",
194+
new_callable=mock_open,
195+
read_data='{"operations": [{"type": "run"}, {"type": "wait"}], "proposals": []}',
196+
)
197+
def test_new_config_with_empty_proposals(_mock_file: Mock) -> None:
198+
config = Config.from_file("file")
199+
200+
assert len(config.proposals) == 0
201+
202+
203+
@patch(
204+
"builtins.open",
205+
new_callable=mock_open,
206+
read_data='{"operations": [{"type": "run"}], "proposals": ["http", "sockets"]}',
207+
)
208+
def test_new_config_with_multiple_proposals(_mock_file: Mock) -> None:
209+
config = Config.from_file("file")
210+
211+
assert len(config.proposals) == 2
212+
assert config.proposals[0] == WasiProposal.HTTP
213+
assert config.proposals[1] == WasiProposal.SOCKETS
214+
215+
216+
@patch(
217+
"builtins.open",
218+
new_callable=mock_open,
219+
read_data='{"operations": [{"type": "run"}], "proposals": ["invalid"]}',
220+
)
221+
def test_new_config_should_fail_with_invalid_proposal(_mock_file: Mock) -> None:
222+
with pytest.raises(ValueError):
223+
Config.from_file("file")

test-runner/tests/test_test_suite.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ def create_test_case(name: str, is_executed: bool, is_failed: bool) -> tc.TestCa
1111
name,
1212
["test-runtime-exe", name],
1313
tc.Config(),
14-
tc.Result(["foo", "bar"], is_executed, failures),
14+
tc.Result(is_executed, failures),
1515
1.0,
1616
)
1717

0 commit comments

Comments
 (0)