aboutsummaryrefslogtreecommitdiff
path: root/tests/drivers/learn.py
blob: 42f729fb881994a196fba8f35a97baee255287b1 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
#!/usr/bin/env python3
# checks docs/LEARN.md against the examples it shows. every examples/learn/*.zc runs
# from the repo root with its stdout compared to the matching .out file, and
# every ```zc block in docs/LEARN.md must be exactly one of those files, so the
# guide can't drift from the code it teaches. usage: learn.py path/to/zy
import glob, os, platform, re, subprocess, sys

root = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
os.chdir(root)
zy = os.path.abspath(sys.argv[1])
x86_only = {"22-raw-x86"}
bad = 0

def ok(name):
    print(f"ok   {name}")

def fail(name, why):
    global bad
    bad += 1
    print(f"FAIL {name}: {why}")

files = sorted(glob.glob("examples/learn/*.zc"))
for path in files:
    name = os.path.splitext(os.path.basename(path))[0]
    if name in x86_only and platform.machine() not in ("x86_64", "AMD64"):
        print(f"skip {name} (x86-64 only)")
        continue
    with open(path, "rb") as f:
        src = f.read()
    try:
        r = subprocess.run([zy], stdin=open(path, "rb"), capture_output=True, timeout=30)
    except subprocess.TimeoutExpired:
        fail(f"learn {name}", "timed out")
        continue
    got = r.stdout.decode("utf-8", "replace")
    want_path = os.path.splitext(path)[0] + ".out"
    if not os.path.exists(want_path):
        fail(f"learn {name}", f"no {want_path}")
    elif got == open(want_path, encoding="utf-8").read():
        ok(f"learn {name} prints what it says")
    else:
        fail(f"learn {name}", f"got [{got}]")

# every zc block in docs/LEARN.md is one of the example files
with open("docs/LEARN.md", encoding="utf-8") as f:
    doc = f.read()
blocks = re.findall(r"^```zc\n(.*?)^```", doc, re.S | re.M)
srcs = {}
for path in files:
    with open(path, encoding="utf-8") as f:
        srcs[os.path.basename(path)] = f.read()
used = set()
for b in blocks:
    hit = [n for n, s in srcs.items() if s == b]
    if hit:
        used.add(hit[0])
    else:
        fail("learn block", "a ```zc block in docs/LEARN.md is not an examples/learn file: " + b.splitlines()[0])
for n in srcs:
    if n not in used:
        fail(f"learn {n}", "not shown in docs/LEARN.md")
if not bad:
    ok(f"docs/LEARN.md: {len(blocks)} blocks, all match examples/learn")
sys.exit(1 if bad else 0)