Files
ww/test/lang/slice_store_cap_test.ww
Hojun-Cho 374e97b9e8 test: migrate str/slice header family-1 batch to test/lang @test, retire C twins (fold-2)
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.
2026-06-22 09:02:40 +09:00

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);
};