package packedwwi_test; // `struct @packed` legs no fixture can host, ported from the retired // native carrier test/wcc/671_struct_packed.c (#51). The 15 // layout/runtime value rows are fixture-shaped and move to the // declarative corpus per the residual audit port split; harec // references live in that carrier's header (type_store.c:206-213, // :886, :193; types.c:517,621). // // wwiroundtrip: a library package exports ONLY the packed type; the // importer computes size+offset ITSELF, so the value depends on the // .wwi producer re-emitting `struct @packed {` and the importer // re-parsing it (unparse re-emit per ref/hare/hare/unparse/ // type.ha:122-126). Both driver stages must build the -I tree and run // exit 91 (9*10+1; a dropped @packed gives 168). Strengthened over // the carrier: the re-emitted `struct @packed {` is also asserted in // the retained sepwork pk2.wwi. A single-file two-package form produces // only one raw `__root.wwi`, not an independently importable pk2 package, // so the real directory-package -I tree is irreducible here. // // identityreject: assigning packed A to a structurally-identical // unpacked B — packed is type identity (harec types.c:621). STAGE- // ASYMMETRIC divergence pin: cstage must reject WITH "not assignable" // while wwstage must build AND run exit 0 through its pre-existing // broadly-lenient nominal-lossy struct assignability (#224/#10 — a // documented deferred arc, NOT desired behavior and NOT a #51 // regression). A wwstage tighten fails the row and demands graduation // to a //ww:error two-frag fixture. import os; import os.exec; import strings; import testenv; import time; fn fail(label: str, why: str) void = { let m: str = strings.concat("packedwwi FAIL: ", label, " -- ", why, "\n"); os.write(2, m.ptr, m.len: u64); assert(false); }; fn tmo() time.duration = { return (240i64 * (time.second: i64)): time.duration; }; fn rundir(dir: str, name: str, argv: []str, out: *testenv.commandout) i32 = { testenv.runcommand(dir, dir, name, argv, tmo(), out); if (out.termination != exec.termination.EXIT) { return -1; }; return out.code; }; @test fn wwiroundtrip() void = { let drvs: []str = ["ww", "ww_ww"]; let s: i32 = 0; for (s < 2) { let td: str = testenv.fresh(); assert(os.mkdir(strings.concat(td, "/lib"), 493) == 0); assert(os.mkdir(strings.concat(td, "/lib/pk2"), 493) == 0); assert(os.mkdir(strings.concat(td, "/app"), 493) == 0); testenv.writefile(strings.concat(td, "/lib/pk2/pk2.ww"), strings.concat( "package pk2;\n", "export type Ev = struct @packed { tag: u8, data: u64 };\n")); testenv.writefile(strings.concat(td, "/app/main.ww"), strings.concat( "package main;\n", "import pk2;\n", "export fn main() i32 = {\n", "\tlet e: pk2.Ev = pk2.Ev { tag = 1u8, data = 2u64 };\n", "\treturn size(pk2.Ev): i32 * 10 + offset(e.data): i32;\n", "};\n")); let app: str = strings.concat(td, "/app"); let co: testenv.commandout; let av: []str = [testenv.driver(drvs[s]), "build", "-I", strings.concat(td, "/lib"), "-o", "m", "main.ww"]; if (rundir(app, strings.concat("build_", drvs[s]), av, &co) != 0) { fail(drvs[s], "-I tree build failed"); }; let rav: []str = [strings.concat(app, "/m")]; if (rundir(app, strings.concat("run_", drvs[s]), rav, &co) != 91) { fail(drvs[s], strings.concat("importer-side run-exit ", "!= 91 (@packed dropped in the .wwi re-emit ", "gives 168)")); }; let wwi: str = testenv.readfile( strings.concat(app, "/m.sepwork/pk2.wwi")); if (!testenv.has(wwi, "struct @packed {")) { fail(drvs[s], "pk2.wwi lost the `struct @packed {` re-emit"); }; testenv.clean(td); s += 1; }; }; @test fn identityreject() void = { let src: str = strings.concat( "package main;\n", "type A = struct @packed { x: u8, y: u64 };\n", "type B = struct { x: u8, y: u64 };\n", "export fn main() i32 = {\n", "\tlet a: A = A { x = 1u8, y = 2u64 };\n", "\tlet b: B = a;\n", "\treturn 0;\n", "};\n"); let td: str = testenv.fresh(); testenv.writefile(strings.concat(td, "/id.ww"), src); let co: testenv.commandout; let cav: []str = [testenv.driver("ww"), "build", "-o", "idc", "id.ww"]; if (rundir(td, "build_cstage", cav, &co) == 0) { fail("identity_reject", "cstage accepted packed->unpacked assignment"); }; if (!testenv.has(co.stderr, "not assignable")) { fail("identity_reject", strings.concat("cstage reject lost ", "its `not assignable` diagnostic (crash is vacuous)")); }; let wav: []str = [testenv.driver("ww_ww"), "build", "-o", "idw", "id.ww"]; if (rundir(td, "build_wwstage", wav, &co) != 0) { fail("identity_reject", strings.concat("wwstage rejected -- ", "#224/#10 leniency closed; graduate this row to a ", "//ww:error fixture")); }; let rav: []str = [strings.concat(td, "/idw")]; if (rundir(td, "run_wwstage", rav, &co) != 0) { fail("identity_reject", "wwstage run-exit != 0"); }; testenv.clean(td); };