Files
ww/test/lang/subslice_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

77 lines
2.7 KiB
Plaintext

// subslice_cap_test — a sub-slice `base[lo:hi]` must set its capacity word to
// base_cap - lo (storage remaining to the underlying end; Go/Hare-identical),
// NOT hi - lo (the new length), migrated from test/wcc/942_subslice_cap_run.c
// (task #20). base_cap is the array length N for [N]T, or the carried .capacity
// for a slice/str base. Cite (drew): harec ref/harec/src/eval.c:1017 (slice cap
// -= start), eval.c:1024 (array cap = length - start), check.c:596 (cap>=len),
// ref/hare/rt/ensure.ha:4-8 (capacity is a distinct field).
//
// Before the fix BOTH stages emitted cap = hi - lo (== len). Every row picks a
// shape where base_cap - lo != hi - lo, so a stale `cap = len` stage is
// observably wrong (cap reads hi-lo, or the append row reallocs instead of
// filling the base's spare). cap != len in every row.
package subslice_cap_test;
@test fn subslice_array_hilt_n() void = {
// A — array base, hi < N. cap = N(8) - lo(1) = 7 != len(2).
let a: [8]u8;
let i: i32 = 0;
for (i < 8) { a[i] = (20 + i): u8; i += 1; };
let s: []u8 = a[1:3];
assert(s.cap: i32 == 7);
assert(s.len: i32 == 2);
assert(s[0] == 21u8);
};
@test fn subslice_slice_spare_cap() void = {
// B — slice base with spare cap. cap = base.cap(8) - lo(1) = 7 != len(3);
// base.cap is read from the header +16, not re-derived.
let a: [8]u8;
let i: i32 = 0;
for (i < 8) { a[i] = (40 + i): u8; i += 1; };
let p: []u8; p.ptr = &a[0]; p.len = 6; p.cap = 8;
let s: []u8 = p[1:4];
assert(s.cap: i32 == 7);
assert(s.len: i32 == 3);
assert(s[0] == 41u8);
};
@test fn subslice_str_base() void = {
// C — str base (str[lo:hi] yields str, real .capacity, no downgrade).
// cap = sb.cap(5) - lo(1) = 4 != len(2).
let sb: str = "hello";
let s: str = sb[1:3];
assert(s.cap: i32 == 4);
assert(s.len: i32 == 2);
assert(s[0] == 101u8);
};
@test fn subslice_append_no_realloc() void = {
// D — append-no-realloc (strongest). s = buf[1:3] has cap 7 > len 2, so
// append(s,99) fills buf's spare at lo+len = 3. A cap=len stage sees
// len==cap (full) and reallocs, leaving buf[3] == 0.
let buf: [8]u8;
let i: i32 = 0;
for (i < 8) { buf[i] = 0u8; i += 1; };
let s: []u8 = buf[1:3];
append(s, 99u8);
assert(s.cap: i32 == 7);
assert(s.len: i32 == 3);
assert(s[2] == 99u8);
assert(buf[3] == 99u8);
};
@test fn subslice_hidefault_spare_cap() void = {
// E — hi-default with spare cap. p{len=6,cap=8}; `p[2:]` defaults hi to
// base.len=6, so len = 4, but cap = base.cap(8) - lo(2) = 6 != len.
let a: [8]u8;
let i: i32 = 0;
for (i < 8) { a[i] = (60 + i): u8; i += 1; };
let p: []u8; p.ptr = &a[0]; p.len = 6; p.cap = 8;
let s: []u8 = p[2:];
assert(s.cap: i32 == 6);
assert(s.len: i32 == 4);
assert(s[0] == 62u8);
};