72 lines
2.9 KiB
Python
72 lines
2.9 KiB
Python
#!/usr/bin/env python3
|
|
"""Decoys for host_swap_rule_gate (R-421). Run: python3 scripts/test_host_swap_rule_gate.py
|
|
|
|
Each case builds a fake workspace (felhom.eu + a felhom-controller clone) and runs the real gate against it:
|
|
1. one row's verdict flipped on the controller side only — drift (the files share every NAME; the fact is a value);
|
|
2. identical tables, but no controller test reads the table any more — the label without the fact;
|
|
3. no controller clone — INCONCLUSIVE (2), never a pass;
|
|
4. the genuine article — must pass.
|
|
"""
|
|
from __future__ import annotations
|
|
|
|
import os
|
|
import shutil
|
|
import subprocess
|
|
import sys
|
|
import tempfile
|
|
|
|
HERE = os.path.dirname(os.path.abspath(__file__))
|
|
REPO = os.path.dirname(HERE)
|
|
GATE = os.path.join(HERE, "host_swap_rule_gate.py")
|
|
REAL = os.path.join(REPO, "hub", "internal", "api", "testdata", "host_swap_rule_cases.json")
|
|
NAME = "host_swap_rule_cases.json"
|
|
|
|
|
|
def build(tmp, ctrl_table=None, ctrl_test=True, with_ctrl=True):
|
|
repo = os.path.join(tmp, "felhom.eu")
|
|
hub = os.path.join(repo, "hub", "internal", "api")
|
|
os.makedirs(os.path.join(hub, "testdata"))
|
|
shutil.copy(REAL, os.path.join(hub, "testdata", NAME))
|
|
open(os.path.join(hub, "x_test.go"), "w").write('package api\n// os.ReadFile("testdata/%s")\n' % NAME)
|
|
if with_ctrl:
|
|
web = os.path.join(tmp, "felhom-controller", "controller", "internal", "web")
|
|
os.makedirs(os.path.join(web, "testdata"))
|
|
data = open(REAL, encoding="utf-8").read() if ctrl_table is None else ctrl_table
|
|
open(os.path.join(web, "testdata", NAME), "w", encoding="utf-8").write(data)
|
|
body = 'package web\n// os.ReadFile("testdata/%s")\n' % NAME if ctrl_test else "package web\n"
|
|
open(os.path.join(web, "y_test.go"), "w").write(body)
|
|
return repo
|
|
|
|
|
|
def run(repo):
|
|
env = dict(os.environ, HOST_SWAP_RULE_REPO=repo)
|
|
return subprocess.run([sys.executable, GATE], env=env, capture_output=True, text=True).returncode
|
|
|
|
|
|
def main():
|
|
real = open(REAL, encoding="utf-8").read()
|
|
flipped = real.replace('"guest_swap_mb": 12288, "short": false', '"guest_swap_mb": 12288, "short": true', 1)
|
|
assert flipped != real, "the decoy's row is gone from the real table"
|
|
cases = [
|
|
("one verdict flipped on the controller side", dict(ctrl_table=flipped), 1),
|
|
("no controller test reads the table", dict(ctrl_test=False), 1),
|
|
("no controller clone", dict(with_ctrl=False), 2),
|
|
("the genuine article", dict(), 0),
|
|
]
|
|
fails = 0
|
|
for label, kw, want in cases:
|
|
tmp = tempfile.mkdtemp()
|
|
try:
|
|
got = run(build(tmp, **kw))
|
|
finally:
|
|
shutil.rmtree(tmp)
|
|
ok = got == want
|
|
fails += 0 if ok else 1
|
|
print(" %s %-45s rc=%d want %d" % ("ok" if ok else "FAIL", label, got, want))
|
|
print("host-swap-rule decoys: %d/%d" % (len(cases) - fails, len(cases)))
|
|
return 1 if fails else 0
|
|
|
|
|
|
if __name__ == "__main__":
|
|
sys.exit(main())
|