112 lines
6.4 KiB
Python
112 lines
6.4 KiB
Python
#!/usr/bin/env python3
|
|
"""oracle_emit.py HARNESS_DIR CPP_FIXTURE.jsonl
|
|
|
|
Rebuilds the records test_emitter.cpp::write_oracle_fixture() writes, using the
|
|
reference emitter in HARNESS_DIR/mkfixture.py (emit_meta / emit_record), and compares
|
|
the two files byte for byte. Exit 0 = identical, 1 = differ, 2 = usage.
|
|
Stdlib only.
|
|
"""
|
|
import sys
|
|
|
|
|
|
def build(mk) -> str:
|
|
inf, nan = float("inf"), float("nan")
|
|
meta = {"format": 1, "build": "shim-trace test", "exe_sha256": "0" * 64,
|
|
"started": "2026-09-07T00:00:00Z", "inline_max": 256,
|
|
"hooks": {"Hook::A": {"ftol": 0.0, "ftol_kind": "abs", "ptr": "ignore",
|
|
"coverage": {"state": "complete",
|
|
"why": "nothing outside the declared regions",
|
|
"unmodelled": []}},
|
|
"Mars::ParseBlock": {"ftol": 1e-6, "ftol_kind": "rel", "ptr": "exact",
|
|
"unordered": ["ret.v.items"],
|
|
"coverage": {"state": "partial", "why": "",
|
|
"unmodelled": [
|
|
{"what": "appends to the owner's event list",
|
|
"risk": "high",
|
|
"why": "no region reaches it",
|
|
"mitigation": "guard:player"}]}}}}
|
|
fwd = bytes(range(16))
|
|
recs = [
|
|
{"ts": 1000, "hook": "CfgVar_RegisterKey", "mode": "trace", "call_id": 0, "thread": 4120, "depth": 0,
|
|
"args": [mk.s("Résumé", "key"), mk.i32(-3, "value"), mk.ptr(0x00A36FD0, "table")],
|
|
"ret": mk.boolean(True),
|
|
"side": {"cfg_table": {"before": mk.by(fwd), "after": mk.by(fwd[::-1])}}},
|
|
{"ts": 1037, "hook": "Manifest_Load", "mode": "trace", "call_id": 1, "thread": 4120,
|
|
"args": [mk.s("Weapons/_weapons.txt", "path")],
|
|
"ret": mk.i32(2, "count"),
|
|
"side": {"registry": {"after": mk.struct_({
|
|
"entries": mk.lst(mk.struct_({"id": mk.u32(i), "name": mk.s("w%d.weapon" % i)}) for i in (7, 9)),
|
|
"deleted": mk.sset(mk.u32(i) for i in (501, 550, 599)),
|
|
"flags": mk.enum(2, "MF_0"),
|
|
"big": mk.u64(2**60 + 1),
|
|
"small": mk.u64(5),
|
|
"edge": mk.u64(2**53),
|
|
"neg": mk._tv("i64", str(-(2**60)), None), # |v| >= 2^53 -> decimal string (section 3)
|
|
"nothing": mk.null(),
|
|
"w": mk._tv("wstr", "A€\x00", None)})}}},
|
|
{"ts": 1074, "hook": "Mars::ParseBlock", "mode": "trace", "call_id": 2, "thread": 4124, "depth": 1,
|
|
"args": [mk.s('Tab\tKey Quote"d Back\\slash nl\nx cr\rx \x01\x7f\xff €', "text"), mk.u32(2, "len")],
|
|
"ret": mk.jsonv({"weapon": {"count": 3, "damage": 1.5, "name": "Laser\xe9", "ok": True, "range": 2.25,
|
|
"tags": ["a", "b"]}}),
|
|
"side": {"scratch": {"after": mk.lst(mk.f32(v) for v in (1.5, 0.1, -2.5e-7, 1e30))},
|
|
"nanbox": {"after": mk.f32(nan)},
|
|
"infs": {"after": mk.lst([mk._tv("f64", "inf", None), mk._tv("f64", "-inf", None),
|
|
mk._tv("f64", 0.1, None), mk._tv("f64", 1e300, None),
|
|
mk._tv("f64", 0.0, None)])},
|
|
"blob": {"before": None, "after": mk.by(bytes(range(256)) * 2)}}},
|
|
{"ts": 1111, "hook": "CfgVar_RegisterKey", "mode": "compare", "call_id": 3, "thread": 4120,
|
|
"args": [mk._tv("i8", -128, None), mk._tv("i16", 32767, None), mk._tv("u8", 255, None),
|
|
mk._tv("u16", 65535, None), mk.u64(2**53 - 1)],
|
|
"ret": mk.null(), "side": {},
|
|
"ours": {"ret": mk.null(), "side": {}}, "diverged": False, "diff": []},
|
|
{"ts": 1148, "hook": "Manifest_Load", "mode": "compare", "call_id": 4, "thread": 1,
|
|
"args": [], "ret": mk.i32(1), "side": {"r": {"after": mk.by(b"\x01\x02")}},
|
|
"ours": {"ret": mk.i32(2), "side": {"r": {"after": mk.by(b"\x01\x03")}}},
|
|
"diverged": True,
|
|
"diff": [{"path": "ret", "why": "exact", "orig": mk.i32(1), "ours": mk.i32(2)},
|
|
{"path": "side.r.after", "why": "hash", "orig": mk.by(b"\x01\x02"), "ours": mk.by(b"\x01\x03"),
|
|
"first_diff_offset": 1}],
|
|
"note": "hello"},
|
|
{"ts": 1185, "hook": "X", "mode": "compare", "call_id": 5, "thread": 1,
|
|
"args": [], "ret": None, "side": {},
|
|
"diverged": True, "diff": [{"path": "call", "why": "err", "orig": None, "ours": "ours threw"}],
|
|
"err": "ours threw"},
|
|
{"ts": 1222, "hook": "Y", "mode": "replace", "call_id": 6, "thread": 2,
|
|
"args": [mk.boolean(False, "flag")], "ret": mk.ptr(0), "side": {},
|
|
"coverage": {"guards": ["player"], "undeclared": [], "n": 0}},
|
|
{"ts": 1259, "hook": "Y", "mode": "compare", "call_id": 7, "thread": 2,
|
|
"args": [], "ret": mk.null(), "side": {}, "ours": {"ret": mk.null(), "side": {}},
|
|
"diverged": False, "diff": [],
|
|
"coverage": {"guards": ["player", "tree_header"],
|
|
"undeclared": [{"region": "player", "off": 672, "len": 12},
|
|
{"region": "player", "off": 688, "len": 4}], "n": 3}},
|
|
]
|
|
return mk.emit_meta(meta) + "".join(mk.emit_record(r) for r in recs)
|
|
|
|
|
|
def main(argv):
|
|
if len(argv) != 3:
|
|
print(__doc__)
|
|
return 2
|
|
sys.path.insert(0, argv[1])
|
|
import mkfixture as mk # noqa: E402
|
|
want = build(mk)
|
|
with open(argv[2], "r", encoding="utf-8", newline="") as f:
|
|
got = f.read()
|
|
if got == want:
|
|
print("oracle_emit: identical (%d bytes, %d lines)" % (len(want), want.count("\n")))
|
|
return 0
|
|
gl, wl = got.split("\n"), want.split("\n")
|
|
for i, (g, w) in enumerate(zip(gl, wl), 1):
|
|
if g != w:
|
|
j = next((k for k in range(min(len(g), len(w))) if g[k] != w[k]), min(len(g), len(w)))
|
|
print("oracle_emit: line %d differs at column %d" % (i, j + 1))
|
|
print(" cpp: ...%s" % g[max(0, j - 40):j + 60])
|
|
print(" py: ...%s" % w[max(0, j - 40):j + 60])
|
|
return 1
|
|
print("oracle_emit: line count differs (cpp %d, py %d)" % (len(gl), len(wl)))
|
|
return 1
|
|
|
|
|
|
if __name__ == "__main__":
|
|
sys.exit(main(sys.argv))
|