Migrate the slice/str-header core of drew's Family 1 from bespoke build+run C twins to test/lang @test, retiring each now-redundant twin in the same commit. Runtime coverage MOVES from $(TESTS) to test-lang (T1 runs+asserts via `ww test`) + test-lang-byteid (T2 keeps cs==ww .s byte-id); coverage is preserved, the $(TESTS) headline drops 6 (440->434). All asserts are primitive int/u8/bool comparisons (no fmt/strconv in the assert path); the slice-store families poison the slot (cap!=len) and read it back so a dropped data word FAILS. 928_str_abi_run.c -> str_abi_test.ww (str 24B ABI: .len/.cap across literal/arg/return/field/tuple/deref/index/tagged) 941_slice_store_cap_run.c -> slice_store_cap_test.ww (slice value store through indexed/field/chained lhs writes full 24B header; cap==8) 942_subslice_cap_run.c -> subslice_cap_test.ww (sub-slice cap = base_cap-lo; array/slice/str/append-no-realloc/hi-default) 943_subslice_ptresz_run.c -> subslice_ptresz_test.ww (sub-slice ptr advances lo*esz bytes; esz 2/4/8, let + call-arg) 944_deref_slice_store_run.c-> deref_slice_store_test.ww(*p=sliceval whole-deref store writes 24B header; cap==8) 949_f6_header_run.c -> f6_header_test.ww (str/slice header partial load/store; .cap/.len after clobber) Bump LANGBYTEID_EXPECTED_MIN 16->22 to ratchet the new corpus floor.
94 lines
3.4 KiB
Plaintext
94 lines
3.4 KiB
Plaintext
// slice_store_cap_test — a []T (slice-typed) VALUE stored through an indexed /
|
|
// field / chained lhs and read back must move the full 24B {ptr,len,cap}
|
|
// header, not just {ptr}, migrated from test/wcc/941_slice_store_cap_run.c
|
|
// (task #7). str IS []u8 since Phase 2 (#1), so the str 3-word machinery
|
|
// applies to slices verbatim; the G-cluster store+read arms were kind-gated on
|
|
// str ONLY, so a slice value fell to the 1-word default and silently DROPPED
|
|
// len+cap. cs==ww held (byte-id-blind), so a behavioral @test is the net.
|
|
//
|
|
// BOTH the store AND the read were 1-word pre-fix, so each row is a store->read
|
|
// ROUNDTRIP. POISON: rows B/C/D seed the dst with a DIFFERENT slice q
|
|
// (len=4,cap=5) via a PROVEN 3-word store (single-dot field, NOT the site under
|
|
// test); a broken stage keeps q's cap=5 while the read returns stale words —
|
|
// either way cap != 8. Row A is a bare roundtrip (no proven 3-word store
|
|
// targets a bare array-element header). The full {ptr,len,cap} triple is
|
|
// asserted (ptr via s[0]==104, len==2, cap==8; cap!=len catches a dropped len
|
|
// OR cap).
|
|
|
|
package slice_store_cap_test;
|
|
|
|
type recb = struct { f: []u8 };
|
|
type innerc = struct { f: []u8 };
|
|
type outerc = struct { sym: *innerc };
|
|
type innerd = struct { f: []u8 };
|
|
type outerd = struct { i: innerd };
|
|
|
|
@test fn slice_store_wholeelem() void = {
|
|
// A — whole-element `xs[0] = p` into a [2][]u8 local array, read back via
|
|
// `xs[0]`. No proven poison for a bare array-element header; the roundtrip
|
|
// is the probe.
|
|
let hb: [8]u8; hb[0] = 104u8;
|
|
let p: []u8; p.ptr = &hb[0]; p.len = 2; p.cap = 8;
|
|
let xs: [2][]u8;
|
|
xs[0] = p;
|
|
let e: []u8 = xs[0];
|
|
assert(e.cap: i32 == 8);
|
|
assert(e.len: i32 == 2);
|
|
assert(e[0] == 104u8);
|
|
};
|
|
|
|
@test fn slice_store_arrfield() void = {
|
|
// B — `arr[i].f = p` into a [N]rec field (G1-twin). Poison arr[1].f
|
|
// (cap=5,len=4,'q') via &arr[1] + the proven single-dot *struct field
|
|
// store; then the field-of-indexed store lands p (cap=8,len=2,'h').
|
|
let qb: [8]u8; qb[0] = 113u8;
|
|
let hb: [8]u8; hb[0] = 104u8;
|
|
let q: []u8; q.ptr = &qb[0]; q.len = 4; q.cap = 5;
|
|
let p: []u8; p.ptr = &hb[0]; p.len = 2; p.cap = 8;
|
|
let arr: [3]recb;
|
|
let pr: *recb = &arr[1];
|
|
pr.f = q;
|
|
arr[1].f = p;
|
|
let s: []u8 = arr[1].f;
|
|
assert(s.cap: i32 == 8);
|
|
assert(s.len: i32 == 2);
|
|
assert(s[0] == 104u8);
|
|
};
|
|
|
|
@test fn slice_store_chained_ptr() void = {
|
|
// C — chained `r.sym.f = p` where r.sym is a *innerc (G2-twin). Poison the
|
|
// pointee field via the proven direct field store (`st.f = q`); the
|
|
// chained store derefs r.sym and overwrites st.f.
|
|
let qb: [8]u8; qb[0] = 113u8;
|
|
let hb: [8]u8; hb[0] = 104u8;
|
|
let q: []u8; q.ptr = &qb[0]; q.len = 4; q.cap = 5;
|
|
let p: []u8; p.ptr = &hb[0]; p.len = 2; p.cap = 8;
|
|
let st: innerc;
|
|
st.f = q;
|
|
let r: outerc;
|
|
r.sym = &st;
|
|
r.sym.f = p;
|
|
let s: []u8 = r.sym.f;
|
|
assert(s.cap: i32 == 8);
|
|
assert(s.len: i32 == 2);
|
|
assert(s[0] == 104u8);
|
|
};
|
|
|
|
@test fn slice_store_valuespine() void = {
|
|
// D — value-spine `o.i.f = p` where o.i is a value-struct field (not a
|
|
// pointer). Poison o.i.f via &o.i + the proven via-ptr field store
|
|
// (`pi.f = q`); the value-spine store walks o.i and overwrites .f.
|
|
let qb: [8]u8; qb[0] = 113u8;
|
|
let hb: [8]u8; hb[0] = 104u8;
|
|
let q: []u8; q.ptr = &qb[0]; q.len = 4; q.cap = 5;
|
|
let p: []u8; p.ptr = &hb[0]; p.len = 2; p.cap = 8;
|
|
let o: outerd;
|
|
let pi: *innerd = &o.i;
|
|
pi.f = q;
|
|
o.i.f = p;
|
|
let s: []u8 = o.i.f;
|
|
assert(s.cap: i32 == 8);
|
|
assert(s.len: i32 == 2);
|
|
assert(s[0] == 104u8);
|
|
};
|