114 lines
4.5 KiB
Python
114 lines
4.5 KiB
Python
#!/usr/bin/env python3
|
|
"""Unabhängige Soll-Gegenproben; Produktcode und bestehende Tests bleiben unverändert."""
|
|
from pathlib import Path
|
|
import os
|
|
import subprocess
|
|
import tempfile
|
|
|
|
ROOT = next(p for p in Path(__file__).resolve().parents
|
|
if (p / "Cargo.toml").is_file() and (p / "openspec").is_dir())
|
|
TBC = ROOT / "target/debug/tbc"
|
|
|
|
|
|
def run(*args, **kwargs):
|
|
return subprocess.run(args, capture_output=True, text=True, timeout=60, **kwargs)
|
|
|
|
|
|
def main():
|
|
subprocess.run(["cargo", "build", "-p", "tb-cli"], cwd=ROOT, check=True)
|
|
failed = []
|
|
|
|
def check(name, ok, evidence):
|
|
print(f"{'PASS' if ok else 'FAIL'} {name}: {evidence}")
|
|
if not ok:
|
|
failed.append(name)
|
|
|
|
with tempfile.TemporaryDirectory(prefix="tb-review-") as tmp:
|
|
tmp = Path(tmp)
|
|
for name, source in [("PSET", "PSET (1,1),2"),
|
|
("PALETTE", "DIM a%(15)\nPALETTE USING a%(0)")]:
|
|
path = tmp / "graphics.bas"
|
|
path.write_text(source + "\n")
|
|
out = run(str(TBC), "check", str(path))
|
|
check(name + " Non-Feature", out.returncode != 0 and
|
|
"Feature unavailable" in out.stderr and name in out.stderr,
|
|
out.stderr.strip())
|
|
|
|
path = tmp / "parent.frm"
|
|
path.write_text('''VERSION 1.00
|
|
Begin Form Form1
|
|
Begin Frame Group
|
|
Index = 0
|
|
End
|
|
Begin Frame Group
|
|
Index = 1
|
|
Begin TextBox Probe
|
|
End
|
|
End
|
|
End
|
|
DIM p AS CONTROL
|
|
p=Probe.Parent
|
|
Form1.Hide
|
|
PRINT p.Index
|
|
END
|
|
''')
|
|
out = run(str(TBC), "run", str(path))
|
|
check("Indizierter Parent aus FRM", out.returncode == 0 and out.stdout.strip() == "1",
|
|
f"Soll=1, Ist={out.stdout!r}, {out.stderr}")
|
|
build = run(str(TBC), "build", str(path))
|
|
assert build.returncode == 0, build.stderr
|
|
path.unlink()
|
|
out = run(str(TBC), "run", str(path.with_suffix(".tbc")))
|
|
check("Indizierter Parent aus TBC ohne Quelle", out.returncode == 0 and out.stdout.strip() == "1",
|
|
f"Soll=1, Ist={out.stdout!r}, {out.stderr}")
|
|
|
|
# Kopie im Temp-Verzeichnis erlaubt Zugriff auf den privaten Prüfer.
|
|
# Einzige Mutation: TIMEZONEKNOWN zeigt auf die gültige TIMER-Bindung.
|
|
source = (ROOT / "crates/tb-cli/tests/inventar.rs").read_text()
|
|
source = source.replace('include_str!("../../../tests/support/inventar-quellen.tsv")',
|
|
f'include_str!("{ROOT}/tests/support/inventar-quellen.tsv")')
|
|
source += r'''
|
|
#[test]
|
|
fn review_falsches_laufzeitziel_muss_abgewiesen_werden() {
|
|
let e=inventar().into_iter().find(|e|e.name=="TIMEZONEKNOWN").unwrap();
|
|
let (src,catalog)=probe_source(&e);
|
|
let mut module=tb_vm::compile_source_with_forms("FORM1",&src,&catalog).unwrap();
|
|
let mut changed=false;
|
|
for i in module.procs.iter_mut().flat_map(|p|&mut p.code) {
|
|
if let tb_vm::bytecode::Instr::CallBuiltin(id,_) = i {
|
|
if *id==tb_runtime::builtins::ids::TIMEZONEKNOWN {
|
|
*id=tb_runtime::builtins::ids::TIMER;
|
|
changed=true;
|
|
}
|
|
}
|
|
}
|
|
assert!(changed);
|
|
let result=pruefe_kompilat(&e,Ok(module),|id|tb_runtime::builtins::builtin_table().get(id as usize).is_some());
|
|
assert!(result.is_err(),"TIMEZONEKNOWN mit TIMER-Ziel wird akzeptiert: {result:?}");
|
|
}
|
|
'''
|
|
probe = tmp / "inventar.rs"
|
|
probe.write_text(source)
|
|
# Cargo resolves a coherent dependency graph; selecting rlibs by mtime
|
|
# can mix feature variants after a workspace test run.
|
|
source = source.replace('env!("CARGO_MANIFEST_DIR")', f'"{ROOT}/crates/tb-cli"')
|
|
probe.write_text(source)
|
|
manifest = '[package]\nname = "tb-review-probes"\nversion = "0.0.0"\nedition = "2021"\n[workspace]\n'
|
|
manifest += '[[test]]\nname = "inventar"\npath = "inventar.rs"\n[dependencies]\n'
|
|
for name in ["tb-vm", "tb-frontend", "tb-runtime"]:
|
|
manifest += f'{name} = {{ path = "{ROOT}/crates/{name}" }}\n'
|
|
(tmp / "Cargo.toml").write_text(manifest)
|
|
env = os.environ.copy()
|
|
env["CARGO_BIN_EXE_tbc"] = str(TBC)
|
|
out = run("cargo", "test", "--manifest-path", str(tmp / "Cargo.toml"),
|
|
"--offline", "--target-dir", str(ROOT / "target/review-probes"),
|
|
"--test", "inventar", "review_falsches", "--", "--nocapture", env=env)
|
|
check("Inventar erkennt falsches Laufzeitziel", out.returncode == 0,
|
|
out.stdout + out.stderr)
|
|
print(f"{len(failed)} fehlgeschlagene Soll-Gegenproben")
|
|
return bool(failed)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
raise SystemExit(main())
|