Skip to content

Commit 00eb20a

Browse files
committed
Generalize the test command
1 parent 8da39c7 commit 00eb20a

6 files changed

Lines changed: 210 additions & 200 deletions

File tree

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
1-
Add ``test`` and ``buildbottest`` commands to :file:`Platforms/WASI` for CI
2-
and Buildbot use, respectively.
1+
Add a ``test`` command to :file:`Platforms/WASI` with ``--speed`` to select
2+
fast CI or slow Buildbot tests and ``--target`` to test the build, gathered
3+
distribution, or release archive.

‎Platforms/WASI/README.md‎

Lines changed: 8 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -205,26 +205,23 @@ After building, you can run the CI tests with:
205205
python3 Platforms/WASI test
206206
```
207207

208-
This runs `make test` in the WASI build directory.
208+
The `--speed` flag selects `fast` (the default) for `make test` or `slow` for
209+
`make buildbottest`. The `--target` flag selects the files to test:
209210

210-
After running `gather` or `package`, you can run the buildbot tests against the
211-
distribution with:
211+
- `build` (the default): the WASI build in `cross-build/`.
212+
- `dist`: the distribution files gathered in `dist/`.
213+
- `archive`: the contents of the release archive, unpacked into `dist/`.
212214

213-
```shell
214-
python3 Platforms/WASI buildbottest
215-
```
216-
217-
This uses `make buildbottest` appropriately with the binary for releasing.
218215

219-
To test the contents of the release archive instead of the gathered files, use:
216+
To thoroughly test the contents of the release archive, use:
220217

221218
```shell
222-
python3 Platforms/WASI buildbottest --unpack
219+
python3 Platforms/WASI test --speed slow --target archive
223220
```
224221

225222
This requires an archive created by `package` or `release`. It deletes the
226223
selected versioned distribution directory inside `dist/`, then restores it
227-
from the matching `.tar.xz` archive before running `make buildbottest`.
224+
from the matching `.tar.xz` archive before running the tests.
228225
The archive and other distributions in `dist/` are left untouched.
229226

230227
You can also tests more directly. To find out where the WASI build directory

‎Platforms/WASI/__main__.py‎

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -78,14 +78,19 @@ def main():
7878
release = subcommands.add_parser(
7979
"release", help="Build and package for a release"
8080
)
81-
test = subcommands.add_parser("test", help="Run the CI tests")
82-
buildbottest = subcommands.add_parser(
83-
"buildbottest", help="Run the buildbot tests against the distribution"
81+
test = subcommands.add_parser("test", help="Run the tests")
82+
test.add_argument(
83+
"--speed",
84+
choices={"fast", "slow"},
85+
default="fast",
86+
help="Run `make test` (fast, the default) or `make buildbottest` (slow)",
8487
)
85-
buildbottest.add_argument(
86-
"--unpack",
87-
action="store_true",
88-
help="Replace the distribution directory with the release archive's contents",
88+
test.add_argument(
89+
"--target",
90+
choices={"build", "dist", "archive"},
91+
default="build",
92+
help="Test the build (the default), gathered distribution, or release archive; "
93+
"'archive' replaces the distribution directory with the archive's contents",
8994
)
9095
path = subcommands.add_parser(
9196
"path", help="Print the path to a build or distribution directory"
@@ -112,7 +117,6 @@ def main():
112117
build_host,
113118
release,
114119
test,
115-
buildbottest,
116120
):
117121
subcommand.add_argument(
118122
"--quiet",
@@ -188,7 +192,6 @@ def main():
188192
path,
189193
release,
190194
test,
191-
buildbottest,
192195
):
193196
subcommand.add_argument(
194197
"--host-triple",
@@ -251,8 +254,6 @@ def main():
251254
_package.archive(context)
252255
case "test":
253256
_test.test(context)
254-
case "buildbottest":
255-
_test.buildbottest(context)
256257
case "path":
257258
paths = {
258259
"build-python": "build_python_path",

‎Platforms/WASI/_build.py‎

Lines changed: 17 additions & 134 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,16 @@
11
__lazy_modules__ = [
2-
"contextlib",
3-
"functools",
42
"os",
53
"pathlib",
64
"shutil",
75
"subprocess",
86
"sys",
9-
"tempfile",
107
]
118

12-
import contextlib
13-
import functools
149
import os
1510
import pathlib
1611
import shutil
1712
import subprocess
1813
import sys
19-
import tempfile
2014

2115
try:
2216
from os import process_cpu_count as cpu_count
@@ -29,130 +23,19 @@
2923
WASMTIME_HOST_RUNNER_VAR = f"{{{WASMTIME_VAR_NAME}}}"
3024

3125

32-
def separator():
33-
"""Print a separator line across the terminal width."""
34-
try:
35-
tput_output = subprocess.check_output(
36-
["tput", "cols"], encoding="utf-8"
37-
)
38-
except subprocess.CalledProcessError:
39-
terminal_width = 80
40-
else:
41-
terminal_width = int(tput_output.strip())
42-
print("⎯" * terminal_width)
43-
44-
45-
def updated_env(updates={}):
46-
"""Create a new dict representing the environment to use.
47-
48-
The changes made to the execution environment are printed out.
49-
"""
50-
env_defaults = {}
51-
# https://reproducible-builds.org/docs/source-date-epoch/
52-
git_epoch_cmd = ["git", "log", "-1", "--pretty=%ct"]
53-
try:
54-
epoch = subprocess.check_output(
55-
git_epoch_cmd, encoding="utf-8"
56-
).strip()
57-
env_defaults["SOURCE_DATE_EPOCH"] = epoch
58-
except subprocess.CalledProcessError:
59-
pass # Might be building from a tarball.
60-
# This layering lets SOURCE_DATE_EPOCH from os.environ takes precedence.
61-
environment = env_defaults | os.environ | updates
62-
63-
env_diff = {}
64-
for key, value in environment.items():
65-
if os.environ.get(key) != value:
66-
env_diff[key] = value
67-
68-
env_vars = [
69-
f"\n {key}={item}" for key, item in sorted(env_diff.items())
70-
]
71-
_shared.log("🌎", f"Environment changes:{''.join(env_vars)}")
72-
73-
return environment
74-
75-
76-
def subdir(context_attr, *, clean_ok=False):
77-
"""Decorator to change to a working directory."""
78-
79-
def decorator(func):
80-
@functools.wraps(func)
81-
def wrapper(context):
82-
nonlocal context_attr
83-
84-
working_dir = getattr(context, context_attr)
85-
separator()
86-
_shared.log("📁", os.fsdecode(working_dir))
87-
if clean_ok and context.clean and working_dir.exists():
88-
_shared.log("🚮", "Deleting directory (--clean)...")
89-
shutil.rmtree(working_dir)
90-
91-
working_dir.mkdir(parents=True, exist_ok=True)
92-
93-
with contextlib.chdir(working_dir):
94-
return func(context, working_dir)
95-
96-
return wrapper
97-
98-
return decorator
99-
100-
101-
def call(command, *, context=None, quiet=False, **kwargs):
102-
"""Execute a command.
103-
104-
If 'quiet' is true, then redirect stdout and stderr to a temporary file.
105-
"""
106-
if context is not None:
107-
quiet = context.quiet
108-
109-
_shared.log("❯", " ".join(map(str, command)), spacing=" ")
110-
if not quiet:
111-
stdout = None
112-
stderr = None
113-
else:
114-
if (log_path := getattr(context, "log_path", None)) is None:
115-
log_path = pathlib.Path(tempfile.gettempdir())
116-
log_path.mkdir(parents=True, exist_ok=True)
117-
stdout = tempfile.NamedTemporaryFile(
118-
"w",
119-
encoding="utf-8",
120-
delete=False,
121-
dir=log_path,
122-
prefix="cpython-wasi-",
123-
suffix=".log",
124-
)
125-
stderr = subprocess.STDOUT
126-
_shared.log("📝", f"Logging output to {stdout.name} (--quiet)...")
127-
128-
try:
129-
subprocess.check_call(command, **kwargs, stdout=stdout, stderr=stderr)
130-
except subprocess.CalledProcessError as error:
131-
if quiet:
132-
_shared.log("❌", f"Exit code {error.returncode}")
133-
separator()
134-
with open(stdout.name, encoding="utf-8") as file:
135-
lines = file.readlines()
136-
# Inefficient, but the log shouldn't be dramatically large.
137-
print("".join(lines[-10:]), end="")
138-
if not lines[-1].endswith("\n"):
139-
print()
140-
sys.exit(error.returncode)
141-
142-
143-
@subdir("build_python_path", clean_ok=True)
26+
@_shared.subdir("build_python_path", clean_ok=True)
14427
def configure_build_python(context, working_dir):
14528
"""Configure the build/host Python."""
14629
configure = [os.path.relpath(context.checkout / "configure", working_dir)]
14730
configure.extend(context.configure_args)
14831

149-
call(configure, context=context)
32+
context.call(configure)
15033

15134

152-
@subdir("build_python_path")
35+
@_shared.subdir("build_python_path")
15336
def make_build_python(context, _working_dir):
15437
"""Make/build the build Python."""
155-
call(["make", "--jobs", str(cpu_count()), "all"], context=context)
38+
context.call(["make", "--jobs", str(cpu_count()), "all"])
15639

15740
binary = context.build_python_interpreter
15841
cmd = [
@@ -205,7 +88,7 @@ def wasi_sdk_env(context):
20588
return env
20689

20790

208-
@subdir("wasi_build_path", clean_ok=True)
91+
@_shared.subdir("wasi_build_path", clean_ok=True)
20992
def configure_wasi_python(context, working_dir):
21093
"""Configure the WASI/host build."""
21194
config_site = os.fsdecode(context.here / "config.site-wasm32-wasi")
@@ -247,10 +130,9 @@ def configure_wasi_python(context, working_dir):
247130
if context.is_debug:
248131
configure.append("--with-pydebug")
249132
configure.extend(context.configure_args)
250-
call(
133+
context.call(
251134
configure,
252-
env=updated_env(env_additions | wasi_sdk_env(context)),
253-
context=context,
135+
env=_shared.updated_env(env_additions | wasi_sdk_env(context)),
254136
)
255137

256138
python_wasm = working_dir / "python.wasm"
@@ -262,17 +144,18 @@ def configure_wasi_python(context, working_dir):
262144
sys.stdout.flush()
263145

264146

265-
@subdir("wasi_build_path")
147+
@_shared.subdir("wasi_build_path")
266148
def make_wasi_python(context, working_dir):
267149
"""Run `make` for the WASI/host build."""
268-
call(
150+
context.call(
269151
["make", "--jobs", str(cpu_count()), "all"],
270-
env=updated_env(),
271-
context=context,
152+
env=_shared.updated_env(),
272153
)
273154

274155
exec_script = working_dir / "python.sh"
275-
call([exec_script, "-c", "import sys; print(sys.version)"], quiet=False)
156+
context.call(
157+
[exec_script, "-c", "import sys; print(sys.version)"], quiet=False
158+
)
276159
_shared.log(
277160
"🎉",
278161
f"Use `{exec_script.relative_to(pathlib.Path().absolute())}` "
@@ -289,13 +172,13 @@ def clean_contents(context):
289172
shutil.rmtree(path)
290173

291174

292-
@subdir("build_python_path")
175+
@_shared.subdir("build_python_path")
293176
def pythoninfo_build_python(context, working_dir):
294177
"""Display build info of the build Python."""
295-
call(["make", "pythoninfo"], context=context)
178+
context.call(["make", "pythoninfo"])
296179

297180

298-
@subdir("wasi_build_path")
181+
@_shared.subdir("wasi_build_path")
299182
def pythoninfo_wasi_python(context, working_dir):
300183
"""Display build info of the host/WASI Python."""
301-
call(["make", "pythoninfo"], context=context)
184+
context.call(["make", "pythoninfo"])

0 commit comments

Comments
 (0)