Files
ww/test/lang/str_elem_cap_test.ww
Hojun-Cho 08975c11c9 test: migrate str-elem-cap/size-in-type behavior to test/lang @test
Two more value-observable families ported additively (the .c sources
keep running in $(TESTS); de-dup deferred to fold 6).

  932_str_elem_cap -> str_elem_cap_test: a str-element N_INDEX value
    read must load the full 24B {ptr,len,cap}, not {ptr,len} (F2); each
    shape poisons cap != len so a 2-word read fails the .cap assert.
    Template for the 933-939 cap family.
  957_size_type -> size_type_test: `size` binds in type position and
    coexists with the size(T) operator (#85); a green row is the bind
    proof.
2026-06-22 03:01:09 +09:00

59 lines
2.1 KiB
Plaintext

// str_elem_cap_test — a str-element VALUE read via N_INDEX must load the full
// 24B {ptr,len,cap} header, not just {ptr,len}, migrated from test/wcc/
// 932_str_elem_cap_run.c (F2 fold). str is 24B since Phase 2 (#1); pre-F2 the
// N_INDEX str-element arms dropped the cap word, so reading `.cap` off an
// indexed str element returned garbage (the missing third word) — cs==ww held,
// so the 990-997 byte-id gates were GREEN while the runtime was wrong.
//
// Each shape POISONS the element so cap != len (a `.cap =` pseudo-field write,
// no malloc / no import), then observes cap through `let e: str = <index>` (a
// 3-word copy into the slot) and `e.cap` (an N_IDENT pseudo-field read off the
// slot). A 2-word read leaves cap = len (N_IDENT base) or a stale slice-cap
// (fallback base), so the read-back .cap mismatches the poisoned value. .len is
// the control. The shapes (index base form), not the data, are what vary, so
// per-shape asserts — this file is the template for the 933-939 cap family.
package str_elem_cap_test;
type box = struct { items: []str };
@test fn sitea_ident_base() void = {
// N_IDENT base: xs[0] on a local [N]str, constant index. Poison cap=8
// (len=2); a broken 2-word read leaves cap = len = 2.
let p: str = "hi";
p.cap = 8i32;
let xs: [2]str;
xs[0] = p;
let e: str = xs[0];
assert(e.cap: i32 == 8);
assert(e.len: i32 == 2);
};
@test fn sitea_var_index() void = {
// N_IDENT base indexed by a VARIABLE (not a constant) — the index
// source must not change which words the element load reads.
let p: str = "hey";
p.cap = 12i32;
let xs: [2]str;
let i: i32 = 1;
xs[i] = p;
let e: str = xs[i];
assert(e.cap: i32 == 12);
assert(e.len: i32 == 3);
};
@test fn siteb_fallback_base() void = {
// Fallback base: the element sits behind an N_DOT slice field, so the
// N_INDEX base isn't a plain ident. Poison cap=9 (len=5); a broken read
// leaves cap = the slice header's own cap, not the element's.
let q: str = "world";
q.cap = 9i32;
let arr: [2]str;
arr[0] = q;
let b: box;
b.items = arr[0:2];
let e: str = b.items[0];
assert(e.cap: i32 == 9);
assert(e.len: i32 == 5);
};