// Emitter golden tests (byte-exact strings derived from TRACE_FORMAT.md section 4 and the // mkfixture.py reference emitter) + a fixture file that oracle_emit.py regenerates with // mkfixture's own emit_record() and compares byte for byte. #include "shim/trace/emitter.h" #include #include #include #include #include #include #include "check.h" #include "harness.h" using namespace shim::trace; static std::string esc(const std::string& s) { Buf b; emit_esc(b, s); return b.str(); } static std::string escw(std::vector u) { Buf b; emit_esc_w(b, u.data(), u.size()); return b.str(); } static std::string tvs(const Tv& v) { return canonical(v); } static const char* kSha512 = "110009dcee21620b166f3abfecb5eff7a873be729d1c2d53822e7acc5f34eb9b"; static void golden_strings() { // section 4 rule 2; the same inputs test_tracecmp.py feeds mkfixture.esc() CHECK_STR(esc("plain"), "\"plain\""); CHECK_STR(esc("R\xe9sum\xe9"), "\"R\\u00e9sum\\u00e9\""); CHECK_STR(esc("Tab\tKey"), "\"Tab\\tKey\""); CHECK_STR(esc("Quote\"d"), "\"Quote\\\"d\""); CHECK_STR(esc("Back\\slash"), "\"Back\\\\slash\""); CHECK_STR(esc("nl\nx"), "\"nl\\nx\""); CHECK_STR(esc("cr\rx"), "\"cr\\rx\""); CHECK_STR(esc("\x01\x7f\xff\x80"), "\"\\u0001\\u007f\\u00ff\\u0080\""); CHECK_STR(esc("\x08\x0c"), "\"\\u0008\\u000c\""); CHECK_STR(esc(std::string("a\0b", 3)), "\"a\\u0000b\""); CHECK_STR(escw({0x41, 0x20ac, 0x7e, 0x7f, 0xffff, 0x0a}), "\"A\\u20ac~\\u007f\\uffff\\n\""); } static void golden_numbers() { CHECK_STR(tvs(tv::f32(1.5f)), "{\"t\":\"f32\",\"v\":1.5}"); CHECK_STR(tvs(tv::f32(0.1f)), "{\"t\":\"f32\",\"v\":0.100000001}"); CHECK_STR(tvs(tv::f32(-2.5e-7f)), "{\"t\":\"f32\",\"v\":-2.49999999e-07}"); CHECK_STR(tvs(tv::f32(1e30f)), "{\"t\":\"f32\",\"v\":1.00000002e+30}"); CHECK_STR(tvs(tv::f32(3.0f)), "{\"t\":\"f32\",\"v\":3}"); CHECK_STR(tvs(tv::f32(123456789.0f)), "{\"t\":\"f32\",\"v\":123456792}"); CHECK_STR(tvs(tv::f32(std::numeric_limits::quiet_NaN())), "{\"t\":\"f32\",\"v\":\"nan\"}"); CHECK_STR(tvs(tv::f32(-std::numeric_limits::infinity())), "{\"t\":\"f32\",\"v\":\"-inf\"}"); CHECK_STR(tvs(tv::f64(std::numeric_limits::infinity())), "{\"t\":\"f64\",\"v\":\"inf\"}"); CHECK_STR(tvs(tv::f64(0.1)), "{\"t\":\"f64\",\"v\":0.10000000000000001}"); CHECK_STR(tvs(tv::f64(1e300)), "{\"t\":\"f64\",\"v\":1.0000000000000001e+300}"); CHECK_STR(tvs(tv::f64(0.0)), "{\"t\":\"f64\",\"v\":0}"); CHECK_STR(tvs(tv::f64(-0.0)), "{\"t\":\"f64\",\"v\":-0}"); CHECK_STR(tvs(tv::u64(18446744073709551615ull)), "{\"t\":\"u64\",\"v\":\"18446744073709551615\"}"); CHECK_STR(tvs(tv::u64(9007199254740992ull)), "{\"t\":\"u64\",\"v\":\"9007199254740992\"}"); // 2^53 -> string CHECK_STR(tvs(tv::u64(9007199254740991ull)), "{\"t\":\"u64\",\"v\":9007199254740991}"); // 2^53-1 -> int CHECK_STR(tvs(tv::i64(-9007199254740992ll)), "{\"t\":\"i64\",\"v\":\"-9007199254740992\"}"); CHECK_STR(tvs(tv::i64(-9007199254740991ll)), "{\"t\":\"i64\",\"v\":-9007199254740991}"); CHECK_STR(tvs(tv::i8(-128)), "{\"t\":\"i8\",\"v\":-128}"); CHECK_STR(tvs(tv::i16(32767)), "{\"t\":\"i16\",\"v\":32767}"); CHECK_STR(tvs(tv::i32(-3).named("value")), "{\"t\":\"i32\",\"v\":-3,\"n\":\"value\"}"); CHECK_STR(tvs(tv::u8(255)), "{\"t\":\"u8\",\"v\":255}"); CHECK_STR(tvs(tv::u16(65535)), "{\"t\":\"u16\",\"v\":65535}"); CHECK_STR(tvs(tv::u32(4294967295u)), "{\"t\":\"u32\",\"v\":4294967295}"); CHECK_STR(tvs(tv::boolean(true)), "{\"t\":\"bool\",\"v\":true}"); CHECK_STR(tvs(tv::null()), "{\"t\":\"null\",\"v\":null}"); CHECK_STR(tvs(tv::ptr(static_cast(0xa36fd0)).named("table")), "{\"t\":\"ptr\",\"v\":\"0x00a36fd0\",\"n\":\"table\"}"); CHECK_STR(tvs(tv::ptr(static_cast(0))), "{\"t\":\"ptr\",\"v\":\"0x00000000\"}"); CHECK_STR(tvs(tv::enum_(2, "MF_0").named("f")), "{\"t\":\"enum\",\"v\":2,\"name\":\"MF_0\",\"n\":\"f\"}"); CHECK_STR(tvs(tv::enum_(-1)), "{\"t\":\"enum\",\"v\":-1}"); CHECK_STR(tvs(tv::str("R\xe9sum\xe9").named("key")), "{\"t\":\"str\",\"v\":\"R\\u00e9sum\\u00e9\",\"n\":\"key\"}"); CHECK_STR(tvs(tv::str(nullptr)), "{\"t\":\"ptr\",\"v\":\"0x00000000\"}"); const std::uint16_t w[] = {0x41, 0x20ac}; CHECK_STR(tvs(tv::wstr(w, 2)), "{\"t\":\"wstr\",\"v\":\"A\\u20ac\"}"); CHECK_STR(tvs(tv::json("{\"a\":[1,2.5,\"x\"]}")), "{\"t\":\"json\",\"v\":{\"a\":[1,2.5,\"x\"]}}"); } static void golden_bytes_and_containers() { CHECK_STR(tvs(tv::bytes("\x00\xff", 2, 256)), "{\"t\":\"bytes\",\"n\":2,\"sha256\":\"06eb7d6a69ee19e5fbdf749018d3d2abfa04bcbd1365db312eb86dc7169389b8\",\"hex\":\"00ff\"}"); CHECK_STR(tvs(tv::bytes("", 0, 256)), "{\"t\":\"bytes\",\"n\":0,\"sha256\":\"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855\",\"hex\":\"\"}"); std::vector big; for (int k = 0; k < 2; ++k) for (int i = 0; i < 256; ++i) big.push_back(static_cast(i)); CHECK_STR(tvs(tv::bytes(big.data(), big.size(), 256)), std::string("{\"t\":\"bytes\",\"n\":512,\"sha256\":\"") + kSha512 + "\",\"head\":\"000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f\"}"); // exactly inline_max stays inline; inline_max+1 does not CHECK(tvs(tv::bytes(big.data(), 256, 256)).find("\"hex\"") != std::string::npos); CHECK(tvs(tv::bytes(big.data(), 257, 256)).find("\"head\"") != std::string::npos); // bytes never carry a name even if one is set CHECK_STR(tvs(tv::bytes("", 0, 256).named("x")), "{\"t\":\"bytes\",\"n\":0,\"sha256\":\"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855\",\"hex\":\"\"}"); std::vector items; items.push_back(tv::i32(1)); items.push_back(tv::str("a")); CHECK_STR(tvs(tv::list(items)), "{\"t\":\"list\",\"v\":[{\"t\":\"i32\",\"v\":1},{\"t\":\"str\",\"v\":\"a\"}]}"); CHECK_STR(tvs(tv::set(items).named("s")), "{\"t\":\"set\",\"v\":[{\"t\":\"i32\",\"v\":1},{\"t\":\"str\",\"v\":\"a\"}],\"n\":\"s\"}"); CHECK_STR(tvs(tv::list({})), "{\"t\":\"list\",\"v\":[]}"); Tv st = tv::struct_(); st.add("id", tv::u32(7)).add("na\"me", tv::str("w7")); CHECK_STR(tvs(st), "{\"t\":\"struct\",\"v\":{\"id\":{\"t\":\"u32\",\"v\":7},\"na\\\"me\":{\"t\":\"str\",\"v\":\"w7\"}}}"); CHECK_STR(tvs(tv::struct_()), "{\"t\":\"struct\",\"v\":{}}"); } static void golden_records() { Record r; r.ts = 1; r.hook = "X"; r.mode = Mode::Trace; r.call_id = 900; r.thread = 1; Buf b; emit_record(b, r); // == mkfixture.invalid_lines()[0], the harness's own minimal valid record CHECK_STR(b.str(), "{\"ts\":1,\"hook\":\"X\",\"mode\":\"trace\",\"call_id\":900,\"thread\":1,\"args\":[],\"ret\":null,\"side\":{}}\n"); Record c; c.ts = 1; c.hook = "X"; c.mode = Mode::Compare; c.call_id = 4; c.thread = 1; c.depth = 0; c.args.push_back(tv::i32(1).named("a")); c.ret = tv::boolean(true); SideEntry se; se.name = "r"; se.before_kind = SideEntry::Value; se.before = tv::null(); se.after = tv::i32(2); c.side.push_back(se); SideEntry sn; sn.name = "q"; sn.before_kind = SideEntry::IsNull; sn.after = tv::i32(0); c.side.push_back(sn); c.has_ours = true; c.ours_ret = tv::boolean(false); c.ours_side.push_back({"r", tv::i32(3)}); c.ours_side.push_back({"q", tv::i32(0)}); c.diverged = 1; c.has_diff = true; DiffEntry d; d.path = "ret"; d.why = "exact"; d.orig = tv::boolean(true); d.ours = tv::boolean(false); c.diff.push_back(d); DiffEntry d2; d2.path = "side.r.after"; d2.why = "hash"; d2.first_diff_offset = 1; d2.note = "x"; c.diff.push_back(d2); DiffEntry d3; d3.path = "side.x.after"; d3.why = "len"; d3.orig_raw = "3"; d3.ours_raw = "2"; c.diff.push_back(d3); c.err = "e"; c.note = "n\xe9"; Buf cb; emit_record(cb, c); CHECK_STR(cb.str(), "{\"ts\":1,\"hook\":\"X\",\"mode\":\"compare\",\"call_id\":4,\"thread\":1,\"depth\":0," "\"args\":[{\"t\":\"i32\",\"v\":1,\"n\":\"a\"}],\"ret\":{\"t\":\"bool\",\"v\":true}," "\"side\":{\"r\":{\"before\":{\"t\":\"null\",\"v\":null},\"after\":{\"t\":\"i32\",\"v\":2}}," "\"q\":{\"before\":null,\"after\":{\"t\":\"i32\",\"v\":0}}}," "\"ours\":{\"ret\":{\"t\":\"bool\",\"v\":false},\"side\":{\"r\":{\"after\":{\"t\":\"i32\",\"v\":3}}," "\"q\":{\"after\":{\"t\":\"i32\",\"v\":0}}}},\"diverged\":true," "\"diff\":[{\"path\":\"ret\",\"why\":\"exact\",\"orig\":{\"t\":\"bool\",\"v\":true},\"ours\":{\"t\":\"bool\",\"v\":false}}," "{\"path\":\"side.r.after\",\"why\":\"hash\",\"orig\":null,\"ours\":null,\"first_diff_offset\":1,\"note\":\"x\"}," "{\"path\":\"side.x.after\",\"why\":\"len\",\"orig\":3,\"ours\":2}]," "\"err\":\"e\",\"note\":\"n\\u00e9\"}\n"); // replace record: no ours/diverged/diff; empty diff list still emits "diff":[] when flagged Record p; p.ts = 22; p.hook = "Mars::ParseBlock"; p.mode = Mode::Replace; p.call_id = 7; p.thread = 3; p.has_diff = true; p.diverged = 0; Buf pb; emit_record(pb, p); CHECK_STR(pb.str(), "{\"ts\":22,\"hook\":\"Mars::ParseBlock\",\"mode\":\"replace\",\"call_id\":7,\"thread\":3,\"args\":[],\"ret\":null,\"side\":{},\"diverged\":false,\"diff\":[]}\n"); Meta m; m.build = "sots-engine test"; m.exe_sha256 = std::string(64, '0'); m.started = "2026-09-07T00:00:00Z"; m.inline_max = 256; HookPolicy pa; HookPolicy pb2; pb2.ftol = 1e-6; pb2.ftol_kind = "rel"; pb2.ptr_exact = true; pb2.unordered = {"ret.v.items"}; m.hooks.emplace_back("Hook::A", pa); m.hooks.emplace_back("Mars::ParseBlock", pb2); Buf mb; emit_meta(mb, m); CHECK_STR(mb.str(), "{\"meta\":{\"format\":1,\"build\":\"sots-engine test\",\"exe_sha256\":\"" + std::string(64, '0') + "\",\"started\":\"2026-09-07T00:00:00Z\",\"inline_max\":256,\"hooks\":{" "\"Hook::A\":{\"ftol\":0,\"ftol_kind\":\"abs\",\"ptr\":\"ignore\"}," "\"Mars::ParseBlock\":{\"ftol\":9.9999999999999995e-07,\"ftol_kind\":\"rel\",\"ptr\":\"exact\",\"unordered\":[\"ret.v.items\"]}}}}\n"); Meta m0; Buf m0b; emit_meta(m0b, m0); CHECK_STR(m0b.str(), "{\"meta\":{\"format\":1,\"build\":\"\",\"exe_sha256\":\"\",\"started\":\"\",\"inline_max\":256,\"hooks\":{}}}\n"); } static void buf_growth() { Buf b; std::string big(100000, 'z'); b.put(big.data(), big.size()); b.printf("%s", big.c_str()); // > 128 chars: takes the grow path CHECK_EQ(b.size(), static_cast(200000)); CHECK(b.ok()); b.clear(); CHECK_EQ(b.size(), static_cast(0)); // a 1 MiB bytes value inlines only when inline_max allows std::vector mb(1 << 20, 7); Buf big1; emit_tv(big1, tv::bytes(mb.data(), mb.size(), 1 << 20)); CHECK_EQ(big1.size(), static_cast(2 * (1 << 20)) + std::string("{\"t\":\"bytes\",\"n\":1048576,\"sha256\":\"\",\"hex\":\"\"}").size() + 64); CHECK(big1.ok()); } // ---- oracle fixture: mirrored line for line in oracle_emit.py ---------------------------------- static std::vector range_bytes(int n) { std::vector v; for (int i = 0; i < n; ++i) v.push_back(static_cast(i)); return v; } static void write_oracle_fixture(const std::string& path) { Buf out; Meta m; m.build = "shim-trace test"; m.exe_sha256 = std::string(64, '0'); m.started = "2026-09-07T00:00:00Z"; m.inline_max = 256; HookPolicy pa; HookPolicy pb; pb.ftol = 1e-6; pb.ftol_kind = "rel"; pb.ptr_exact = true; pb.unordered = {"ret.v.items"}; m.hooks.emplace_back("Hook::A", pa); m.hooks.emplace_back("Mars::ParseBlock", pb); emit_meta(out, m); { // rec0: str/i32/ptr args, bool ret, inline bytes region before/after Record r; r.ts = 1000; r.hook = "CfgVar_RegisterKey"; r.mode = Mode::Trace; r.call_id = 0; r.thread = 4120; r.depth = 0; r.args.push_back(tv::str("R\xe9sum\xe9").named("key")); r.args.push_back(tv::i32(-3).named("value")); r.args.push_back(tv::ptr(static_cast(0x00a36fd0)).named("table")); r.ret = tv::boolean(true); auto fwd = range_bytes(16); auto rev = fwd; std::reverse(rev.begin(), rev.end()); SideEntry s; s.name = "cfg_table"; s.before_kind = SideEntry::Value; s.before = tv::bytes(fwd.data(), fwd.size(), 256); s.after = tv::bytes(rev.data(), rev.size(), 256); r.side.push_back(s); emit_record(out, r); } { // rec1: struct / list / set / enum / big ints / null / wstr Record r; r.ts = 1037; r.hook = "Manifest_Load"; r.mode = Mode::Trace; r.call_id = 1; r.thread = 4120; r.args.push_back(tv::str("Weapons/_weapons.txt").named("path")); r.ret = tv::i32(2).named("count"); Tv reg = tv::struct_(); std::vector entries; for (unsigned id : {7u, 9u}) { Tv e = tv::struct_(); e.add("id", tv::u32(id)); e.add("name", tv::str(("w" + std::to_string(id) + ".weapon").c_str())); entries.push_back(e); } reg.add("entries", tv::list(entries)); reg.add("deleted", tv::set({tv::u32(501), tv::u32(550), tv::u32(599)})); reg.add("flags", tv::enum_(2, "MF_0")); reg.add("big", tv::u64((1ull << 60) + 1)); reg.add("small", tv::u64(5)); reg.add("edge", tv::u64(1ull << 53)); reg.add("neg", tv::i64(-(1ll << 60))); reg.add("nothing", tv::null()); const std::uint16_t w[] = {0x41, 0x20ac, 0x0000}; reg.add("w", tv::wstr(w, 3)); SideEntry s; s.name = "registry"; s.after = reg; r.side.push_back(s); emit_record(out, r); } { // rec2: every escape, json ret, f32/f64 lists, nan, before:null, hashed region Record r; r.ts = 1074; r.hook = "Mars::ParseBlock"; r.mode = Mode::Trace; r.call_id = 2; r.thread = 4124; r.depth = 1; r.args.push_back(tv::str("Tab\tKey Quote\"d Back\\slash nl\nx cr\rx \x01\x7f\xff \x80").named("text")); r.args.push_back(tv::u32(2).named("len")); r.ret = tv::json("{\"weapon\":{\"count\":3,\"damage\":1.5,\"name\":\"Laser\\u00e9\",\"ok\":true,\"range\":2.25,\"tags\":[\"a\",\"b\"]}}"); SideEntry sc; sc.name = "scratch"; sc.after = tv::list({tv::f32(1.5f), tv::f32(0.1f), tv::f32(-2.5e-7f), tv::f32(1e30f)}); r.side.push_back(sc); SideEntry nb; nb.name = "nanbox"; nb.after = tv::f32(std::numeric_limits::quiet_NaN()); r.side.push_back(nb); SideEntry inf; inf.name = "infs"; inf.after = tv::list({tv::f64(std::numeric_limits::infinity()), tv::f64(-std::numeric_limits::infinity()), tv::f64(0.1), tv::f64(1e300), tv::f64(0.0)}); r.side.push_back(inf); auto big = range_bytes(256); big.insert(big.end(), big.begin(), big.end()); SideEntry bl; bl.name = "blob"; bl.before_kind = SideEntry::IsNull; bl.after = tv::bytes(big.data(), big.size(), 256); r.side.push_back(bl); emit_record(out, r); } { // rec3: compare, clean, small ints Record r; r.ts = 1111; r.hook = "CfgVar_RegisterKey"; r.mode = Mode::Compare; r.call_id = 3; r.thread = 4120; r.args = {tv::i8(-128), tv::i16(32767), tv::u8(255), tv::u16(65535), tv::u64((1ull << 53) - 1)}; r.ret = tv::null(); r.has_ours = true; r.ours_ret = tv::null(); r.diverged = 0; r.has_diff = true; emit_record(out, r); } { // rec4: compare with divergences + note Record r; r.ts = 1148; r.hook = "Manifest_Load"; r.mode = Mode::Compare; r.call_id = 4; r.thread = 1; r.ret = tv::i32(1); SideEntry s; s.name = "r"; s.after = tv::bytes("\x01\x02", 2, 256); r.side.push_back(s); r.has_ours = true; r.ours_ret = tv::i32(2); r.ours_side.push_back({"r", tv::bytes("\x01\x03", 2, 256)}); r.diverged = 1; r.has_diff = true; DiffEntry d1; d1.path = "ret"; d1.why = "exact"; d1.orig = tv::i32(1); d1.ours = tv::i32(2); r.diff.push_back(d1); DiffEntry d2; d2.path = "side.r.after"; d2.why = "hash"; d2.orig = tv::bytes("\x01\x02", 2, 256); d2.ours = tv::bytes("\x01\x03", 2, 256); d2.first_diff_offset = 1; r.diff.push_back(d2); r.note = "hello"; emit_record(out, r); } { // rec5: compare err (no ours) Record r; r.ts = 1185; r.hook = "X"; r.mode = Mode::Compare; r.call_id = 5; r.thread = 1; r.diverged = 1; r.has_diff = true; DiffEntry d; d.path = "call"; d.why = "err"; d.ours_raw = "\"ours threw\""; r.diff.push_back(d); r.err = "ours threw"; emit_record(out, r); } { // rec6: replace Record r; r.ts = 1222; r.hook = "Y"; r.mode = Mode::Replace; r.call_id = 6; r.thread = 2; r.args.push_back(tv::boolean(false).named("flag")); r.ret = tv::ptr(static_cast(0)); emit_record(out, r); } CHECK(out.ok()); std::FILE* f = std::fopen(path.c_str(), "wb"); CHECK(f != nullptr); if (f) { std::fwrite(out.data(), 1, out.size(), f); std::fclose(f); } } int main(int argc, char** argv) { golden_strings(); golden_numbers(); golden_bytes_and_containers(); golden_records(); buf_growth(); const std::string fixture = argc > 1 ? argv[1] : "emitter_oracle.jsonl"; write_oracle_fixture(fixture); std::printf("oracle fixture: %s\n", fixture.c_str()); if (tracetest::harness_present()) { // byte-exact against mkfixture.emit_record / emit_meta const std::string script = argc > 2 ? argv[2] : "oracle_emit.py"; const int rc = tracetest::run_python(script, tracetest::harness_dir() + " " + fixture); CHECK_EQ(rc, 0); // and the harness reads it back as valid, with the injected divergence counted const int tc = tracetest::run_tracecmp(fixture); CHECK_EQ(tc, 1); } else { std::printf(" SKIP python oracle (harness absent)\n"); } return tracetest::finish("shim_trace_emitter"); }