forked from josch/mmdebstrap
Compare commits
168 commits
57e0ecb20f
...
5fd96553f5
Author | SHA1 | Date | |
---|---|---|---|
5fd96553f5 | |||
b67d30cb86 | |||
d4eb268795 | |||
60186650cd | |||
59ac33cebe | |||
847d8fe95b | |||
4595d3df44 | |||
577f690540 | |||
2b832e0128 | |||
a7b7e16033 | |||
eb98dfbaee | |||
6c5210a94f | |||
a6a31e60eb | |||
0dfd9adf2b | |||
2fd3d768e8 | |||
ccd8919e67 | |||
b39713def5 | |||
348c582866 | |||
67fbe118f3 | |||
5a263b5532 | |||
830270840b | |||
|
374ae3dc99 | ||
1f15194a6e | |||
117e4251a1 | |||
adf8f9399d | |||
543093eddc | |||
4dc1375840 | |||
c3aa679fec | |||
7a057e37dd | |||
5bd3da0aef | |||
d442f436de | |||
889c02419e | |||
a156d93314 | |||
4ccd799b50 | |||
24c5a45202 | |||
2e8eaeb18b | |||
420080648e | |||
be156e7a14 | |||
ea146ad108 | |||
449fb248e2 | |||
eb54f6a23a | |||
d2238c891b | |||
bf33a614c3 | |||
d15be6abbf | |||
67902e06e9 | |||
d9ca7c21ff | |||
d29f9195d7 | |||
b454892ddd | |||
c2cd4a2a77 | |||
5ec6256461 | |||
46f5889b54 | |||
822f8eafec | |||
b5f6c7f08f | |||
43ba07e790 | |||
eb7cf54155 | |||
80ade97458 | |||
e887a329ab | |||
fce852770b | |||
07e3673161 | |||
10c3d3e5f4 | |||
4048293be5 | |||
0903b3f6a7 | |||
aac7157820 | |||
bcb3fcdaf1 | |||
f0f211f383 | |||
3a17a91b3c | |||
fc5b60e038 | |||
a207ac020b | |||
a16937e3e4 | |||
8cb5b6e0ef | |||
91ca37706f | |||
d84a65b07f | |||
fbc3e5549d | |||
d4cb065639 | |||
|
adf62afcea | ||
3999212c48 | |||
c6c2baee6a | |||
6c68ab2e5e | |||
2f27eccad4 | |||
045b56bb4e | |||
7123808b6c | |||
6416ce96c9 | |||
410c5fcb24 | |||
9682e74385 | |||
b0caeeef54 | |||
d209fb0c11 | |||
f4a3865c00 | |||
892e568496 | |||
b85df6b8f2 | |||
7e8931578b | |||
e1f0b0fa40 | |||
0ff2bef84c | |||
e875bca7fb | |||
0af22912f7 | |||
add9412a47 | |||
e61e352f67 | |||
18c1e9bbc5 | |||
7ce6db0ca7 | |||
7d7d757f00 | |||
902bc55c4d | |||
226f86fea9 | |||
df2226fb25 | |||
3fb97753ea | |||
89a7e4c6ee | |||
f1d847e4ae | |||
c95632f963 | |||
5533b25255 | |||
34a9de929d | |||
b385eb548a | |||
d82afec5de | |||
117a1591c5 | |||
3fcb125e3c | |||
35dc676394 | |||
0ae0adde26 | |||
5e22e0bfc8 | |||
2021f6f7cd | |||
432170c68e | |||
15c7de4a3b | |||
bf379f7e50 | |||
d91a18a350 | |||
7cec147b9e | |||
009089ee8a | |||
679f6cb2fc | |||
e9e9cec884 | |||
b707676432 | |||
b51b5b9e2a | |||
793d8bb561 | |||
9ca613da0a | |||
51ad1426c3 | |||
153d1fa969 | |||
c4962f9ab0 | |||
c37e5e6059 | |||
28122a8b5c | |||
bf31355c62 | |||
b46149b851 | |||
7198ad50f6 | |||
5ea760920d | |||
86f616996d | |||
1b5d87c7cf | |||
d96e85fddd | |||
c1c6297db7 | |||
e4ef326b59 | |||
158956e213 | |||
4c3fddcd54 | |||
e71676e15c | |||
a238d90774 | |||
790294ddca | |||
cffd47e087 | |||
c6c9c27969 | |||
27926c75f9 | |||
0f9c6543c4 | |||
b99f1d53d5 | |||
cc3150ef04 | |||
c8835a6149 | |||
dc8b09ed50 | |||
21b23ebb9f | |||
0664792cd5 | |||
26af846d0a | |||
df6900ec4a | |||
5c5f7de898 | |||
29b23bbcbc | |||
d10f320f5d | |||
ce23e702e2 | |||
2c155f7cc9 | |||
d7b39b6c97 | |||
6ec09c27ca | |||
454121acb1 | |||
09f1dd2ee6 |
130 changed files with 5306 additions and 4664 deletions
2
.mailmap
2
.mailmap
|
@ -1,2 +1,4 @@
|
|||
Johannes Schauer Marin Rodrigues <josch@mister-muffin.de>
|
||||
Johannes Schauer Marin Rodrigues <josch@mister-muffin.de> <j.schauer@email.de>
|
||||
Helmut Grohne <helmut@subdivi.de> <helmut.grohne@intenta.de>
|
||||
Benjamin Drung <benjamin.drung@ionos.com> <benjamin.drung@cloud.ionos.com>
|
||||
|
|
68
CHANGELOG.md
68
CHANGELOG.md
|
@ -1,3 +1,71 @@
|
|||
1.2.5 (2023-01-04)
|
||||
------------------
|
||||
|
||||
- bugfix release
|
||||
|
||||
1.2.4 (2022-12-23)
|
||||
------------------
|
||||
|
||||
- bugfix release
|
||||
- add jessie-or-older extract hook
|
||||
|
||||
1.2.3 (2022-11-16)
|
||||
------------------
|
||||
|
||||
- use Text::ParseWords::shellwords instead of spawning a new shell
|
||||
- mount and unmount once, instead for each run_chroot() call
|
||||
|
||||
1.2.2 (2022-10-27)
|
||||
------------------
|
||||
|
||||
- allow /etc/apt/trusted.gpg.d/ not to exist
|
||||
- always create /var/lib/dpkg/arch to make foreign architecture chrootless
|
||||
tarballs bit-by-bit identical
|
||||
- write an empty /etc/machine-id instead of writing 'uninitialized'
|
||||
- only print progress bars on interactive terminals that are wide enough
|
||||
|
||||
1.2.1 (2022-09-08)
|
||||
------------------
|
||||
|
||||
- bugfix release
|
||||
|
||||
1.2.0 (2022-09-05)
|
||||
------------------
|
||||
|
||||
- remove proot mode
|
||||
- error out if stdout is an interactive terminal
|
||||
- replace taridshift by tarfilter --idshift
|
||||
- tarfilter: add --transform option
|
||||
- multiple --skip options can be separated by comma or whitespace
|
||||
- also cleanup the contents of /run
|
||||
- support apt patterns and paths with commas and whitespace in --include
|
||||
- hooks: store the values of the --include option in MMDEBSTRAP_INCLUDE
|
||||
- add new --skip options: chroot/start-stop-daemon, chroot/policy-rc.d
|
||||
chroot/mount, chroot/mount/dev, chroot/mount/proc, chroot/mount/sys,
|
||||
cleanup/run
|
||||
|
||||
1.1.0 (2022-07-26)
|
||||
----------------
|
||||
|
||||
- mount a new /dev/pts instance into the chroot to make posix_openpt work
|
||||
- adjust merged-/usr hook to work the same way as debootstrap
|
||||
- add no-merged-usr hook
|
||||
|
||||
1.0.1 (2022-05-29)
|
||||
------------------
|
||||
|
||||
- bugfix release
|
||||
|
||||
1.0.0 (2022-05-28)
|
||||
------------------
|
||||
|
||||
- all documented interfaces are now considered stable
|
||||
- allow file:// mirrors
|
||||
- /var/cache/apt/archives/ is now allowed to contain *.deb packages
|
||||
- add file-mirror-automount hook-dir
|
||||
- set $MMDEBSTRAP_VERBOSITY in hooks
|
||||
- rewrite coverage with multiple individual and skippable shell scripts
|
||||
|
||||
0.8.6 (2022-03-25)
|
||||
------------------
|
||||
|
||||
|
|
20
README.md
20
README.md
|
@ -34,7 +34,7 @@ Summary:
|
|||
- chroot with apt in 11 seconds
|
||||
- gzipped tarball with apt is 27M small
|
||||
- bit-by-bit reproducible output
|
||||
- unprivileged operation using Linux user namespaces, fakechroot or proot
|
||||
- unprivileged operation using Linux user namespaces or fakechroot
|
||||
- can operate on filesystems mounted with nodev
|
||||
- foreign architecture chroots with qemu-user
|
||||
- variant installing only Essential:yes packages and dependencies
|
||||
|
@ -78,9 +78,9 @@ privileges to create a file (the chroot tarball) in one's home directory.
|
|||
Thus, mmdebstrap provides multiple options to create a chroot tarball with the
|
||||
right permissions **without superuser privileges**. This avoids a whole class
|
||||
of bugs like #921815. Depending on what is available, it uses either Linux user
|
||||
namespaces, fakechroot or proot. Debootstrap supports fakechroot but will not
|
||||
namespaces or fakechroot. Debootstrap supports fakechroot but will not
|
||||
create a tarball with the right permissions by itself. Support for Linux user
|
||||
namespaces and proot is missing (see bugs #829134 and #698347, respectively).
|
||||
namespaces is missing (see #829134).
|
||||
|
||||
When creating a chroot tarball with debootstrap, the temporary chroot directory
|
||||
cannot be on a filesystem that has been mounted with nodev. In unprivileged
|
||||
|
@ -137,6 +137,11 @@ By default, `coverage.sh` will skip running a single test which tries creating
|
|||
a Ubuntu Focal chroot. To not skip that test, run `coverage.sh` with the
|
||||
environment variable `ONLINE=yes`.
|
||||
|
||||
If a test fails you can run individual tests by executing `coverage.py` with
|
||||
the test name and optionally limit it to a specific distribution like so:
|
||||
|
||||
CMD=./mmdebstrap ./coverage.py --dist unstable check-against-debootstrap-dist
|
||||
|
||||
Bugs
|
||||
====
|
||||
|
||||
|
@ -147,11 +152,16 @@ Contributors
|
|||
============
|
||||
|
||||
- Johannes Schauer Marin Rodrigues (main author)
|
||||
- Gioele Barabucci
|
||||
- Helmut Grohne
|
||||
- Benjamin Drung
|
||||
- Steve Dodd
|
||||
- Jochen Sprickerhof
|
||||
- Josh Triplett
|
||||
- Konstantin Demin
|
||||
- David Kalnischkies
|
||||
- Joe Groocock
|
||||
- Nicolas Vigier
|
||||
- Raul Tambre
|
||||
- Steve Dodd
|
||||
- Trent W. Buck
|
||||
- Vagrant Cascadian
|
||||
- Gioele Barabucci
|
||||
|
|
408
coverage.py
Executable file
408
coverage.py
Executable file
|
@ -0,0 +1,408 @@
|
|||
#!/usr/bin/env python3
|
||||
|
||||
from debian.deb822 import Deb822, Release
|
||||
import email.utils
|
||||
import os
|
||||
import sys
|
||||
import shutil
|
||||
import subprocess
|
||||
import argparse
|
||||
import time
|
||||
from datetime import timedelta
|
||||
from collections import defaultdict
|
||||
from itertools import product
|
||||
|
||||
have_qemu = os.getenv("HAVE_QEMU", "yes") == "yes"
|
||||
have_unshare = os.getenv("HAVE_UNSHARE", "yes") == "yes"
|
||||
have_binfmt = os.getenv("HAVE_BINFMT", "yes") == "yes"
|
||||
run_ma_same_tests = os.getenv("RUN_MA_SAME_TESTS", "yes") == "yes"
|
||||
cmd = os.getenv("CMD", "./mmdebstrap")
|
||||
|
||||
default_dist = os.getenv("DEFAULT_DIST", "unstable")
|
||||
all_dists = ["oldstable", "stable", "testing", "unstable"]
|
||||
default_mode = "auto" if have_unshare else "root"
|
||||
all_modes = ["auto", "root", "unshare", "fakechroot", "chrootless"]
|
||||
default_variant = "apt"
|
||||
all_variants = [
|
||||
"extract",
|
||||
"custom",
|
||||
"essential",
|
||||
"apt",
|
||||
"minbase",
|
||||
"buildd",
|
||||
"-",
|
||||
"standard",
|
||||
]
|
||||
default_format = "auto"
|
||||
all_formats = ["auto", "directory", "tar", "squashfs", "ext2", "null"]
|
||||
|
||||
mirror = os.getenv("mirror", "http://127.0.0.1/debian")
|
||||
hostarch = subprocess.check_output(["dpkg", "--print-architecture"]).decode().strip()
|
||||
|
||||
release_path = f"./shared/cache/debian/dists/{default_dist}/Release"
|
||||
if not os.path.exists(release_path):
|
||||
print("path doesn't exist:", release_path, file=sys.stderr)
|
||||
print("run ./make_mirror.sh first", file=sys.stderr)
|
||||
exit(1)
|
||||
if os.getenv("SOURCE_DATE_EPOCH") is not None:
|
||||
s_d_e = os.getenv("SOURCE_DATE_EPOCH")
|
||||
else:
|
||||
with open(release_path) as f:
|
||||
rel = Release(f)
|
||||
s_d_e = str(email.utils.mktime_tz(email.utils.parsedate_tz(rel["Date"])))
|
||||
|
||||
separator = (
|
||||
"------------------------------------------------------------------------------"
|
||||
)
|
||||
|
||||
|
||||
def skip(condition, dist, mode, variant, fmt):
|
||||
if not condition:
|
||||
return ""
|
||||
for line in condition.splitlines():
|
||||
if not line:
|
||||
continue
|
||||
if eval(line):
|
||||
return line.strip()
|
||||
return ""
|
||||
|
||||
|
||||
def parse_config(confname):
|
||||
config_dict = defaultdict(dict)
|
||||
config_order = list()
|
||||
all_vals = {
|
||||
"Dists": all_dists,
|
||||
"Modes": all_modes,
|
||||
"Variants": all_variants,
|
||||
"Formats": all_formats,
|
||||
}
|
||||
with open(confname) as f:
|
||||
for test in Deb822.iter_paragraphs(f):
|
||||
if "Test" not in test.keys():
|
||||
print("Test without name", file=sys.stderr)
|
||||
exit(1)
|
||||
name = test["Test"]
|
||||
config_order.append(name)
|
||||
for k in test.keys():
|
||||
v = test[k]
|
||||
if k not in [
|
||||
"Test",
|
||||
"Dists",
|
||||
"Modes",
|
||||
"Variants",
|
||||
"Formats",
|
||||
"Skip-If",
|
||||
"Needs-QEMU",
|
||||
"Needs-Root",
|
||||
]:
|
||||
print(f"Unknown field name {k} in test {name}")
|
||||
exit(1)
|
||||
if k in all_vals.keys():
|
||||
if v == "default":
|
||||
print(
|
||||
f"Setting {k} to default in Test {name} is redundant",
|
||||
file=sys.stderr,
|
||||
)
|
||||
exit(1)
|
||||
if v == "any":
|
||||
v = all_vals[k]
|
||||
else:
|
||||
# else, split the value by whitespace
|
||||
v = v.split()
|
||||
for i in v:
|
||||
if i not in all_vals[k]:
|
||||
print(
|
||||
f"{i} is not a valid value for {k}", file=sys.stderr
|
||||
)
|
||||
exit(1)
|
||||
config_dict[name][k] = v
|
||||
return config_order, config_dict
|
||||
|
||||
|
||||
def format_failed(num, total, name, dist, mode, variant, fmt, config_dict):
|
||||
ret = f"({num}/{total}) {name}"
|
||||
if len(config_dict[name].get("Dists", [])) > 1:
|
||||
ret += f" --dist={dist}"
|
||||
if len(config_dict[name].get("Modes", [])) > 1:
|
||||
ret += f" --mode={mode}"
|
||||
if len(config_dict[name].get("Variants", [])) > 1:
|
||||
ret += f" --variant={variant}"
|
||||
if len(config_dict[name].get("Formats", [])) > 1:
|
||||
ret += f" --format={fmt}"
|
||||
return ret
|
||||
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument("test", nargs="*", help="only run these tests")
|
||||
parser.add_argument(
|
||||
"-x",
|
||||
"--exitfirst",
|
||||
action="store_const",
|
||||
dest="maxfail",
|
||||
const=1,
|
||||
help="exit instantly on first error or failed test.",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--maxfail",
|
||||
metavar="num",
|
||||
action="store",
|
||||
type=int,
|
||||
dest="maxfail",
|
||||
default=0,
|
||||
help="exit after first num failures or errors.",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--mode",
|
||||
metavar="mode",
|
||||
help=f"only run tests with this mode (Default = {default_mode})",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--dist",
|
||||
metavar="dist",
|
||||
help=f"only run tests with this dist (Default = {default_dist})",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--variant",
|
||||
metavar="variant",
|
||||
help=f"only run tests with this variant (Default = {default_variant})",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--format",
|
||||
metavar="format",
|
||||
help=f"only run tests with this format (Default = {default_format})",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--skip", metavar="test", action="append", help="skip this test"
|
||||
)
|
||||
args = parser.parse_args()
|
||||
|
||||
# copy over files from git or as distributed
|
||||
for (git, dist, target) in [
|
||||
("./mmdebstrap", "/usr/bin/mmdebstrap", "mmdebstrap"),
|
||||
("./tarfilter", "/usr/bin/mmtarfilter", "tarfilter"),
|
||||
(
|
||||
"./proxysolver",
|
||||
"/usr/lib/apt/solvers/mmdebstrap-dump-solution",
|
||||
"proxysolver",
|
||||
),
|
||||
(
|
||||
"./ldconfig.fakechroot",
|
||||
"/usr/libexec/mmdebstrap/ldconfig.fakechroot",
|
||||
"ldconfig.fakechroot",
|
||||
),
|
||||
]:
|
||||
if os.path.exists(git):
|
||||
shutil.copy(git, f"shared/{target}")
|
||||
else:
|
||||
shutil.copy(dist, f"shared/{target}")
|
||||
# copy over hooks from git or as distributed
|
||||
if os.path.exists("hooks"):
|
||||
shutil.copytree("hooks", "shared/hooks", dirs_exist_ok=True)
|
||||
else:
|
||||
shutil.copytree(
|
||||
"/usr/share/mmdebstrap/hooks", "shared/hooks", dirs_exist_ok=True
|
||||
)
|
||||
|
||||
# parse coverage.txt
|
||||
config_order, config_dict = parse_config("coverage.txt")
|
||||
|
||||
indirbutnotcovered = set(
|
||||
[d for d in os.listdir("tests") if not d.startswith(".")]
|
||||
) - set(config_order)
|
||||
if indirbutnotcovered:
|
||||
print(
|
||||
"test(s) missing from coverage.txt: %s"
|
||||
% (", ".join(sorted(indirbutnotcovered))),
|
||||
file=sys.stderr,
|
||||
)
|
||||
exit(1)
|
||||
coveredbutnotindir = set(config_order) - set(
|
||||
[d for d in os.listdir("tests") if not d.startswith(".")]
|
||||
)
|
||||
if coveredbutnotindir:
|
||||
print(
|
||||
"test(s) missing from ./tests: %s"
|
||||
% (", ".join(sorted(coveredbutnotindir))),
|
||||
file=sys.stderr,
|
||||
)
|
||||
|
||||
exit(1)
|
||||
|
||||
# produce the list of tests using the cartesian product of all allowed
|
||||
# dists, modes, variants and formats of a given test
|
||||
tests = []
|
||||
for name in config_order:
|
||||
test = config_dict[name]
|
||||
for dist, mode, variant, fmt in product(
|
||||
test.get("Dists", [default_dist]),
|
||||
test.get("Modes", [default_mode]),
|
||||
test.get("Variants", [default_variant]),
|
||||
test.get("Formats", [default_format]),
|
||||
):
|
||||
skipreason = skip(test.get("Skip-If"), dist, mode, variant, fmt)
|
||||
if skipreason:
|
||||
tt = ("skip", skipreason)
|
||||
elif have_qemu:
|
||||
tt = "qemu"
|
||||
elif test.get("Needs-QEMU", "false") == "true":
|
||||
tt = ("skip", "test needs QEMU")
|
||||
elif test.get("Needs-Root", "false") == "true":
|
||||
tt = "sudo"
|
||||
elif mode == "auto" and not have_unshare:
|
||||
tt = "sudo"
|
||||
elif mode == "root":
|
||||
tt = "sudo"
|
||||
elif mode == "unshare" and not have_unshare:
|
||||
tt = ("skip", "test needs unshare")
|
||||
else:
|
||||
tt = "null"
|
||||
tests.append((tt, name, dist, mode, variant, fmt))
|
||||
|
||||
torun = []
|
||||
num_tests = len(tests)
|
||||
if args.test:
|
||||
# check if all given tests are either a valid name or a valid number
|
||||
for test in args.test:
|
||||
if test in [name for (_, name, _, _, _, _) in tests]:
|
||||
continue
|
||||
if not test.isdigit():
|
||||
print(f"cannot find test named {test}", file=sys.stderr)
|
||||
exit(1)
|
||||
if int(test) >= len(tests) or int(test) <= 0 or str(int(test)) != test:
|
||||
print(f"test number {test} doesn't exist", file=sys.stderr)
|
||||
exit(1)
|
||||
|
||||
for i, (_, name, _, _, _, _) in enumerate(tests):
|
||||
# if either the number or test name matches, then we use this test,
|
||||
# otherwise we skip it
|
||||
if name in args.test:
|
||||
torun.append(i)
|
||||
if str(i + 1) in args.test:
|
||||
torun.append(i)
|
||||
num_tests = len(torun)
|
||||
|
||||
starttime = time.time()
|
||||
skipped = defaultdict(list)
|
||||
failed = []
|
||||
num_success = 0
|
||||
num_finished = 0
|
||||
for i, (test, name, dist, mode, variant, fmt) in enumerate(tests):
|
||||
if torun and i not in torun:
|
||||
continue
|
||||
print(separator, file=sys.stderr)
|
||||
print("(%d/%d) %s" % (i + 1, len(tests), name), file=sys.stderr)
|
||||
print("dist: %s" % dist, file=sys.stderr)
|
||||
print("mode: %s" % mode, file=sys.stderr)
|
||||
print("variant: %s" % variant, file=sys.stderr)
|
||||
print("format: %s" % fmt, file=sys.stderr)
|
||||
if num_finished > 0:
|
||||
currenttime = time.time()
|
||||
timeleft = timedelta(
|
||||
seconds=int(
|
||||
(num_tests - num_finished)
|
||||
* (currenttime - starttime)
|
||||
/ num_finished
|
||||
)
|
||||
)
|
||||
print("time left: %s" % timeleft, file=sys.stderr)
|
||||
if failed:
|
||||
print("failed: %d" % len(failed), file=sys.stderr)
|
||||
num_finished += 1
|
||||
with open("tests/" + name) as fin, open("shared/test.sh", "w") as fout:
|
||||
for line in fin:
|
||||
line = line.replace("{{ CMD }}", cmd)
|
||||
line = line.replace("{{ SOURCE_DATE_EPOCH }}", s_d_e)
|
||||
line = line.replace("{{ DIST }}", dist)
|
||||
line = line.replace("{{ MIRROR }}", mirror)
|
||||
line = line.replace("{{ MODE }}", mode)
|
||||
line = line.replace("{{ VARIANT }}", variant)
|
||||
line = line.replace("{{ FORMAT }}", fmt)
|
||||
line = line.replace("{{ HOSTARCH }}", hostarch)
|
||||
fout.write(line)
|
||||
# ignore:
|
||||
# SC2016 Expressions don't expand in single quotes, use double quotes for that.
|
||||
# SC2050 This expression is constant. Did you forget the $ on a variable?
|
||||
# SC2194 This word is constant. Did you forget the $ on a variable?
|
||||
shellcheck = subprocess.run(
|
||||
[
|
||||
"shellcheck",
|
||||
"--exclude=SC2050,SC2194,SC2016",
|
||||
"-f",
|
||||
"gcc",
|
||||
"shared/test.sh",
|
||||
],
|
||||
check=False,
|
||||
stdout=subprocess.PIPE,
|
||||
).stdout.decode()
|
||||
argv = None
|
||||
match test:
|
||||
case "qemu":
|
||||
argv = ["./run_qemu.sh"]
|
||||
case "sudo":
|
||||
argv = ["./run_null.sh", "SUDO"]
|
||||
case "null":
|
||||
argv = ["./run_null.sh"]
|
||||
case ("skip", reason):
|
||||
skipped[reason].append(
|
||||
("(%d/%d) %s" % (i + 1, len(tests), name), dist, mode, variant, fmt)
|
||||
)
|
||||
print(f"skipped because of {reason}", file=sys.stderr)
|
||||
continue
|
||||
print(separator, file=sys.stderr)
|
||||
if args.skip and name in args.skip:
|
||||