Files
ww/lib/strings/dup_test.ww
Hojun-Cho aadc6618f0 lib: banner purge + WHY-only comment sweep (rule 8)
Every // ---- section banner dies (132 -> 0): names carry the WHAT.
Narration deleted (filename restatements, run-with lines, what-the-
next-line-does); every ref/hare cite, task cite, divergence, ABI/
layout contract, and ownership qualifier kept (borrowed-view lines
restored where the sweep over-cut). Comment-only proven: all 442
walk-workdir .s and 32 import-probe .s byte-identical before/after;
libbyteid 56-roster all-ID.
2026-08-08 21:10:18 +09:00

111 lines
2.9 KiB
Plaintext

// Vectors mirror ref/hare/strings/dup.ha where ww can express them.
// External strings_test package per the Go foo_test idiom (rule-5/9
// carve-out, task #16); the shared streq helper lives in
// helpers_test.ww — same-package test files compose in dir-mode
// (the package, not the file, is the unit of testing).
package strings_test;
import strings;
import os;
// ref/hare/strings/dup.ha:45.
@test fn dup_cases() void = {
let e: str = strings.dup("");
assert(!(!streq(e, "")));
assert(!(e.len != 0));
let h: str = strings.dup("hello");
assert(!(!streq(h, "hello")));
defer os.free(h.ptr: *void, h.len: u64);
// multi-byte UTF-8: dup must copy raw bytes, not aliased view.
let m: str = strings.dup("こんにちは");
assert(!(m.len != 15));
assert(!(!streq(m, "こんにちは")));
assert(!(m.ptr == "こんにちは".ptr)); // fresh alloc
defer os.free(m.ptr: *void, m.len: u64);
};
// ref/hare/strings/dup.ha:55 (#6). Element reads go through
// `&toks.ptr[i]: *str`
// per the splitn cases (16B element copy gap, cgen.c:6515).
@test fn dupall_cases() void = {
// Empty input — empty result, mirrors Hare's `payload = []`.
let empty: []str;
empty.ptr = nil: *str;
empty.len = 0;
empty.cap = 0;
match (strings.dupall(empty)) {
case let r: []str => {
assert(!(r.len != 0));
strings.freeall(r);
};
case nomem => { abort(); };
};
// Two-element ASCII — each output element is a fresh allocation
// independent of the input (ptr differs from the borrowed source).
let in2: [2]str;
in2[0] = "hello";
in2[1] = "world";
let src2: []str;
src2.ptr = &in2[0];
src2.len = 2;
src2.cap = 2;
match (strings.dupall(src2)) {
case let r: []str => {
assert(!(r.len != 2));
expect_str(r, 0, "hello");
expect_str(r, 1, "world");
let p0: *str = &r.ptr[0];
assert(!(p0.ptr == in2[0].ptr));
let p1: *str = &r.ptr[1];
assert(!(p1.ptr == in2[1].ptr));
strings.freeall(r);
};
case nomem => { abort(); };
};
// Singleton — `only` rune-equivalent of Hare's `["only"]`.
let in1: [1]str;
in1[0] = "only";
let src1: []str;
src1.ptr = &in1[0];
src1.len = 1;
src1.cap = 1;
match (strings.dupall(src1)) {
case let r: []str => {
assert(!(r.len != 1));
expect_str(r, 0, "only");
strings.freeall(r);
};
case nomem => { abort(); };
};
// Multibyte — UTF-8 bytes (5-byte and 15-byte) round-trip.
let inm: [2]str;
inm[0] = "héllo";
inm[1] = "こんにちは";
let srcm: []str;
srcm.ptr = &inm[0];
srcm.len = 2;
srcm.cap = 2;
match (strings.dupall(srcm)) {
case let r: []str => {
assert(!(r.len != 2));
expect_str(r, 0, "héllo");
expect_str(r, 1, "こんにちは");
let p0: *str = &r.ptr[0];
assert(!(p0.len != 6)); // é is 2 bytes
assert(!(p0.ptr == inm[0].ptr));
let p1: *str = &r.ptr[1];
assert(!(p1.len != 15)); // each kana is 3 bytes
assert(!(p1.ptr == inm[1].ptr));
strings.freeall(r);
};
case nomem => { abort(); };
};
};