mmdebstrap/coverage.py

191 lines
5.9 KiB
Python
Executable file

#!/usr/bin/env python3
from debian.deb822 import Deb822
import os
import sys
import shutil
import subprocess
import argparse
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"
default_dist = os.getenv("DEFAULT_DIST", "unstable")
all_dists = ["oldstable", "stable", "testing", "unstable"]
default_mode = "unshare" 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"]
only_dists = []
mirror = os.getenv("mirror", "http://127.0.0.1/debian")
hostarch = subprocess.check_output(["dpkg", "--print-architecture"]).decode().strip()
def skip(condition, dist, mode, variant, fmt):
if not condition:
return False
toskip = False
for line in condition.splitlines():
if not line:
continue
if eval(line):
toskip = True
break
return toskip
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.",
)
args = parser.parse_args()
onlyrun = None
if len(sys.argv) > 1:
onlyrun = sys.argv[1]
tests = []
with open("coverage.txt") as f:
for test in Deb822.iter_paragraphs(f):
name = test["Test"]
if args.test and name not in args.text:
continue
tt = None
if have_qemu:
tt = "qemu"
elif test.get("Needs-QEMU", "false") == "true":
tt = "skip"
elif test.get("Needs-Root", "false") == "true":
tt = "sudo"
elif have_unshare:
tt = "null"
else:
tt = "sudo"
dists = test.get("Dists", default_dist)
if dists == "any":
dists = all_dists
elif dists == "default":
dists = [default_dist]
else:
dists = dists.split()
modes = test.get("Modes", default_mode)
if modes == "any":
modes = all_modes
elif modes == "default":
modes = [default_mode]
else:
modes = modes.split()
variants = test.get("Variants", default_variant)
if variants == "any":
variants = all_variants
elif variants == "default":
variants = [default_variant]
else:
variants = variants.split()
formats = test.get("Formats", default_format)
if formats == "any":
formats = all_formats
elif formats == "default":
formats = [default_format]
else:
formats = formats.split()
for dist in dists:
if only_dists and dist not in only_dists:
continue
for mode in modes:
for variant in variants:
for fmt in formats:
if skip(test.get("Skip-If"), dist, mode, variant, fmt):
tt = "skip"
tests.append((tt, name, dist, mode, variant, fmt))
skipped = []
failed = []
for i, (test, name, dist, mode, variant, fmt) in enumerate(tests):
print(
"------------------------------------------------------------------------------"
)
print("(%d/%d) %s" % (i + 1, len(tests), name))
print("dist: %s" % dist)
print("mode: %s" % mode)
print("variant: %s" % variant)
print("format: %s" % fmt)
print(
"------------------------------------------------------------------------------"
)
with open("tests/" + name) as fin, open("shared/test.sh", "w") as fout:
for line in fin:
for e in ["CMD", "SOURCE_DATE_EPOCH"]:
line = line.replace("{{ " + e + " }}", os.getenv(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)
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":
skipped.append((name, dist, mode, variant, fmt))
continue
proc = subprocess.Popen(argv)
try:
proc.wait()
except KeyboardInterrupt:
proc.kill()
break
if proc.returncode != 0:
failed.append((name, dist, mode, variant, fmt))
if args.maxfail and len(failed) >= args.maxfail:
break
if skipped:
print("skipped:")
for t in skipped:
print(t)
if failed:
print("failed:")
for t in failed:
print(t)
exit(1)
if __name__ == "__main__":
main()