lib/path: #138 c2-stack buffer port — buffer/push/appendnorm/appendlit/string/isroot/set + dot/dotdot, cstage @test
Faithful realignment of lib/path to Hare's buffer-centric API
(ref/hare/path/{stack,buffer}.ha). Replaces the old str-only path.ww
wholesale (zero consumers). Scope = stack-core: init() deferred (returns
~4KB (buffer|error), rides the #40 arc / #147); abs/dirname/basename land
in c3; extension/join dropped.
appendlit uses the #145 slice-copy-assign arm (buf.buf[lo:hi]=bs), no hand
loop. dot/dotdot are faithful module-global []u8 (D2 #148). MAX =
os.PATH_MAX-1. Divergences (size->i32 indices, frombytes, module-global
consts) cited inline.
Tests: lib/path/pathtest.ww (table-driven), wired at test/wcc/989_path_run.c;
push rows mirror stack.ha:107-111 verbatim incl the restored "/d"
intermediate. Slot 989 (overflow bucket) since 970 is taken.
C-first: cstage @test green; wwstage byte-id deferred to the #125 batch.
path classified M_WWREJECT in 989_lib_byteid (w6c_ww rejects the module-
global slice consts = #120/#29; + the #148 twin #151) — self-graduates back
to M_ID the day wwstage accepts. path moved off the 900_stdlib standalone
list (import-dependent: os.PATH_MAX def-dim + match over imported error
types; coverage at 989_path_run), per the bytes/fmt/os precedent.
Gate: all 324 passed, byte-id 990-997 green, w6c/w6c_ww unchanged
(lib-only, non-embedded).
This commit is contained in:
123
lib/path/pathtest.ww
Normal file
123
lib/path/pathtest.ww
Normal file
@@ -0,0 +1,123 @@
|
||||
// pathtest — exercises lib/path (c2-stack subset). Run with
|
||||
// `out/bin/ww run lib/path/pathtest.ww`. Same signalled-then-fail()
|
||||
// -with-+10 pattern as bytes / getopt tests: a non-zero exit code
|
||||
// pinpoints the failing scenario.
|
||||
//
|
||||
// Vectors mirror Hare's @test fns in ref/hare/path/stack.ha:77-119
|
||||
// and buffer.ha. The absolute rows (Hare's `local("/")`-seeded) DEFER
|
||||
// to c3 (abs/local unimplemented); only the relative rows run here.
|
||||
//
|
||||
// Parallel `[N]str` row arrays (rather than `[N]struct{...}`) sidestep
|
||||
// the cstage cgen chained `arr[i].field` store gap (getopttest.ww:6).
|
||||
// push is stateful, so each row is applied in sequence to one buffer;
|
||||
// the table holds {segment, expected-string} pairs (stack.ha:36-42 is
|
||||
// the normalization spec these rows encode).
|
||||
|
||||
package path;
|
||||
|
||||
import path;
|
||||
import os;
|
||||
|
||||
let signalled: i32 = 0;
|
||||
fn fail() void = { os.exit(signalled + 10); };
|
||||
|
||||
// ---- push() + appendnorm normalization --------------------------------
|
||||
// ref/hare/path/stack.ha:77-119 (relative rows only; absolute local()
|
||||
// rows defer to c3). The dot/dotdot handling exercised here IS the
|
||||
// appendnorm normalization spec (stack.ha:36-42), so no separate
|
||||
// appendnorm @test is needed.
|
||||
|
||||
@test fn push_cases() void = {
|
||||
let buf = buffer { ... };
|
||||
if (string(&buf) != ".") { fail(); };
|
||||
|
||||
// current-dir + parent-dir invariants (stack.ha:82-88). Single
|
||||
// segment per row → table-driven sequential apply.
|
||||
let segs: [5]str;
|
||||
let wants: [5]str;
|
||||
segs[0]=""; wants[0]=".";
|
||||
segs[1]="."; wants[1]=".";
|
||||
segs[2]=".."; wants[2]="..";
|
||||
segs[3]=""; wants[3]="..";
|
||||
segs[4]="."; wants[4]="..";
|
||||
let i: i32 = 0;
|
||||
for (i < 5) {
|
||||
if (push(&buf, segs[i])! != wants[i]) { fail(); };
|
||||
i += 1;
|
||||
};
|
||||
|
||||
// set(&buf) resets to "." (stack.ha:91). set forwards an EMPTY
|
||||
// variadic into push (KEN-oracle flag 1: zero-arg gather+forward).
|
||||
if (set(&buf)! != ".") { fail(); };
|
||||
|
||||
// regular path + parent (stack.ha:101-104, minus the local() row).
|
||||
let segs2: [3]str;
|
||||
let wants2: [3]str;
|
||||
segs2[0]="foo"; wants2[0]="foo";
|
||||
segs2[1]="."; wants2[1]="foo";
|
||||
segs2[2]=".."; wants2[2]=".";
|
||||
let k: i32 = 0;
|
||||
for (k < 3) {
|
||||
if (push(&buf, segs2[k])! != wants2[k]) { fail(); };
|
||||
k += 1;
|
||||
};
|
||||
|
||||
// multi-segment (stack.ha:107-111). Variadic arity varies (1 or 2)
|
||||
// → inline.
|
||||
if (push(&buf, "a", "b")! != "a/b") { fail(); };
|
||||
if (push(&buf, "..", "c")! != "a/c") { fail(); };
|
||||
if (push(&buf, "..")! != "a") { fail(); };
|
||||
// stack.ha:110; local()→literal, SEP='/' on Linux, proper local() rides c3
|
||||
if (push(&buf, "/d")! != "a/d") { fail(); };
|
||||
if (push(&buf, "..", "..")! != ".") { fail(); }; // stack.ha:111
|
||||
|
||||
// leading-SEP segment into an EMPTY buffer exercises push's
|
||||
// `j==0 && buf.end==0` root-seed arm (stack.ha:18-20), unreached
|
||||
// by the relative rows above. Hare covers it via local("/")-seeded
|
||||
// rows that defer to c3; literal "/foo" stands in (SEP='/' on Linux).
|
||||
if (set(&buf)! != ".") { fail(); };
|
||||
if (push(&buf, "/foo")! != "/foo") { fail(); };
|
||||
};
|
||||
|
||||
// ---- isroot() ---------------------------------------------------------
|
||||
// ref/hare/path/buffer.ha:44-51 (*buffer arm). Heterogeneous seeds
|
||||
// (manual root seed vs push) → inline rather than a uniform table.
|
||||
|
||||
@test fn isroot_cases() void = {
|
||||
let buf = buffer { ... };
|
||||
// empty buffer (end 0)
|
||||
if (isroot(&buf)) { fail(); };
|
||||
|
||||
// "/" — root. local() is c3, so seed the SEP byte directly.
|
||||
buf.buf[0] = SEP; buf.end = 1;
|
||||
if (!isroot(&buf)) { fail(); };
|
||||
if (string(&buf) != "/") { fail(); };
|
||||
|
||||
// "foo" — relative, not root.
|
||||
buf.end = 0;
|
||||
if (push(&buf, "foo")! != "foo") { fail(); };
|
||||
if (isroot(&buf)) { fail(); };
|
||||
|
||||
// "/foo" — absolute but not root.
|
||||
buf.buf[0] = SEP; buf.end = 1;
|
||||
if (push(&buf, "foo")! != "/foo") { fail(); };
|
||||
if (isroot(&buf)) { fail(); };
|
||||
};
|
||||
|
||||
// ---- string() ---------------------------------------------------------
|
||||
// ref/hare/path/buffer.ha:28-31. Empty buffer views as "."; a filled
|
||||
// buffer views the byte prefix.
|
||||
|
||||
@test fn string_cases() void = {
|
||||
let buf = buffer { ... };
|
||||
if (string(&buf) != ".") { fail(); };
|
||||
if (push(&buf, "foo")! != "foo") { fail(); };
|
||||
if (string(&buf) != "foo") { fail(); };
|
||||
};
|
||||
|
||||
export fn main() i32 = {
|
||||
signalled = 1; push_cases();
|
||||
signalled = 2; isroot_cases();
|
||||
signalled = 3; string_cases();
|
||||
return 0;
|
||||
};
|
||||
Reference in New Issue
Block a user