lib misc+ww tests: hand-main plumbing -> assert (@test conversion B7)
toktest documents the per-row signalled pinpoint loss.
This commit is contained in:
@@ -4,9 +4,9 @@
|
|||||||
//
|
//
|
||||||
// The digest is the cgen-correctness oracle for u32 wrapping arithmetic
|
// The digest is the cgen-correctness oracle for u32 wrapping arithmetic
|
||||||
// + the hash-vtable dispatch: any u32-overflow / rotate miscompile shows
|
// + the hash-vtable dispatch: any u32-overflow / rotate miscompile shows
|
||||||
// up as a byte mismatch. Same signalled-then-fail()-with-+10 pattern as
|
// up as a byte mismatch. A failing row aborts via the assert/abort
|
||||||
// the rest of the 9xx stdlib tests; the non-zero exit pinpoints the
|
// builtin (task #5 @test conversion). Expected digests come through the
|
||||||
// failing case. Expected digests come through the (separately tested)
|
// (separately tested)
|
||||||
// hex.decodestr so the vectors stay readable.
|
// hex.decodestr so the vectors stay readable.
|
||||||
package sha256_test;
|
package sha256_test;
|
||||||
|
|
||||||
@@ -16,10 +16,7 @@ import errors;
|
|||||||
import hash;
|
import hash;
|
||||||
import encoding.hex;
|
import encoding.hex;
|
||||||
import strings;
|
import strings;
|
||||||
import os;
|
|
||||||
|
|
||||||
let signalled: i32 = 0;
|
|
||||||
fn fail() void = { os.exit(signalled + 10); };
|
|
||||||
|
|
||||||
// dohash — one-shot hash of `msg` into the caller's `out` (>= 32 bytes).
|
// dohash — one-shot hash of `msg` into the caller's `out` (>= 32 bytes).
|
||||||
// Mirrors the sum()-writes-into-a-buffer API (no array-by-value return).
|
// Mirrors the sum()-writes-into-a-buffer API (no array-by-value return).
|
||||||
@@ -33,9 +30,9 @@ fn dohash(msg: []u8, out: []u8) void = {
|
|||||||
fn checkbytes(got: []u8, want: str) void = {
|
fn checkbytes(got: []u8, want: str) void = {
|
||||||
match (hex.decodestr(want)) {
|
match (hex.decodestr(want)) {
|
||||||
case let w: []u8 => {
|
case let w: []u8 => {
|
||||||
if (!bytes.equal(got, w)) { fail(); };
|
assert(!(!bytes.equal(got, w)));
|
||||||
};
|
};
|
||||||
case let e: errors.invalid => fail();
|
case let e: errors.invalid => abort();
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -105,7 +102,7 @@ fn check(msg: []u8, want: str) void = {
|
|||||||
let out2: [32]u8;
|
let out2: [32]u8;
|
||||||
hash.sum(h, out1[0:32]);
|
hash.sum(h, out1[0:32]);
|
||||||
hash.sum(h, out2[0:32]);
|
hash.sum(h, out2[0:32]);
|
||||||
if (!bytes.equal(out1[0:32], out2[0:32])) { fail(); };
|
assert(!(!bytes.equal(out1[0:32], out2[0:32])));
|
||||||
checkbytes(out1[0:32],
|
checkbytes(out1[0:32],
|
||||||
"ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad");
|
"ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad");
|
||||||
|
|
||||||
@@ -116,23 +113,23 @@ fn check(msg: []u8, want: str) void = {
|
|||||||
hash.sum(h, out3[0:32]);
|
hash.sum(h, out3[0:32]);
|
||||||
let want: [32]u8;
|
let want: [32]u8;
|
||||||
dohash(strings.toutf8("abcdef"), want[0:32]);
|
dohash(strings.toutf8("abcdef"), want[0:32]);
|
||||||
if (!bytes.equal(out3[0:32], want[0:32])) { fail(); };
|
assert(!(!bytes.equal(out3[0:32], want[0:32])));
|
||||||
};
|
};
|
||||||
|
|
||||||
// sz()/bsz() report the SHA-256 constants regardless of state.
|
// sz()/bsz() report the SHA-256 constants regardless of state.
|
||||||
@test fn sizes() void = {
|
@test fn sizes() void = {
|
||||||
let st: sha256.state = sha256.sha256();
|
let st: sha256.state = sha256.sha256();
|
||||||
let h: *hash.hash = (&st): *hash.hash;
|
let h: *hash.hash = (&st): *hash.hash;
|
||||||
if (hash.sz(h) != 32: size) { fail(); };
|
assert(!(hash.sz(h) != 32: size));
|
||||||
if (hash.bsz(h) != 64: size) { fail(); };
|
assert(!(hash.bsz(h) != 64: size));
|
||||||
};
|
};
|
||||||
|
|
||||||
export fn main() i32 = {
|
export fn main() i32 = {
|
||||||
signalled = 1; empty();
|
empty();
|
||||||
signalled = 2; abc();
|
abc();
|
||||||
signalled = 3; twoblockpad();
|
twoblockpad();
|
||||||
signalled = 4; millionas();
|
millionas();
|
||||||
signalled = 5; reentrant();
|
reentrant();
|
||||||
signalled = 6; sizes();
|
sizes();
|
||||||
return 0;
|
return 0;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -26,19 +26,6 @@ import io;
|
|||||||
import memio;
|
import memio;
|
||||||
import strings;
|
import strings;
|
||||||
|
|
||||||
// Direct exit(2) binding rather than `use os;` — os exports
|
|
||||||
// read/write/close, mirroring memio's reasoning (task #7).
|
|
||||||
@symbol("rt_syscall") fn syscall1ww(num: i64, a: i64) i64;
|
|
||||||
fn doexit(code: i32) void = {
|
|
||||||
syscall1ww(60i64, code: i64);
|
|
||||||
};
|
|
||||||
|
|
||||||
// signalled — bumped by main before each test so a failing exit code
|
|
||||||
// pinpoints the offending case.
|
|
||||||
let signalled: i32 = 0;
|
|
||||||
|
|
||||||
fn fail() void = { doexit(signalled + 10); };
|
|
||||||
|
|
||||||
fn streq(a: str, b: str) bool = {
|
fn streq(a: str, b: str) bool = {
|
||||||
if (a.len != b.len) { return false; };
|
if (a.len != b.len) { return false; };
|
||||||
let i: i32 = 0;
|
let i: i32 = 0;
|
||||||
@@ -68,10 +55,10 @@ fn streq(a: str, b: str) bool = {
|
|||||||
let r: (void | getopt.error) = getopt.tryparse(&cmd, argv[0:3], helps[0:5]);
|
let r: (void | getopt.error) = getopt.tryparse(&cmd, argv[0:3], helps[0:5]);
|
||||||
match (r) {
|
match (r) {
|
||||||
case void => {};
|
case void => {};
|
||||||
case let e: getopt.error => fail();
|
case let e: getopt.error => abort();
|
||||||
};
|
};
|
||||||
|
|
||||||
if (cmd.optslen != 4) { fail(); };
|
assert(!(cmd.optslen != 4));
|
||||||
|
|
||||||
// (wantflag, wantval) parallel arrays, indexed by option order.
|
// (wantflag, wantval) parallel arrays, indexed by option order.
|
||||||
let wantf: [4]u8;
|
let wantf: [4]u8;
|
||||||
@@ -84,13 +71,13 @@ fn streq(a: str, b: str) bool = {
|
|||||||
let i: i32 = 0;
|
let i: i32 = 0;
|
||||||
for (i < 4) {
|
for (i < 4) {
|
||||||
let p: *getopt.option = &cmd.optsptr[i];
|
let p: *getopt.option = &cmd.optsptr[i];
|
||||||
if ((p.flag: u8) != wantf[i]) { fail(); };
|
assert(!((p.flag: u8) != wantf[i]));
|
||||||
if (!streq(p.value, wantv[i])) { fail(); };
|
assert(!(!streq(p.value, wantv[i])));
|
||||||
i += 1;
|
i += 1;
|
||||||
};
|
};
|
||||||
|
|
||||||
if (cmd.argslen != 1) { fail(); };
|
assert(!(cmd.argslen != 1));
|
||||||
if (!streq(cmd.argsptr[0], "files.txt")) { fail(); };
|
assert(!(!streq(cmd.argsptr[0], "files.txt")));
|
||||||
|
|
||||||
getopt.finish(&cmd);
|
getopt.finish(&cmd);
|
||||||
};
|
};
|
||||||
@@ -114,10 +101,10 @@ fn streq(a: str, b: str) bool = {
|
|||||||
let r: (void | getopt.error) = getopt.tryparse(&cmd, argv[0:5], helps[0:3]);
|
let r: (void | getopt.error) = getopt.tryparse(&cmd, argv[0:5], helps[0:3]);
|
||||||
match (r) {
|
match (r) {
|
||||||
case void => {};
|
case void => {};
|
||||||
case let e: getopt.error => fail();
|
case let e: getopt.error => abort();
|
||||||
};
|
};
|
||||||
|
|
||||||
if (cmd.optslen != 2) { fail(); };
|
assert(!(cmd.optslen != 2));
|
||||||
|
|
||||||
let wantf: [2]u8;
|
let wantf: [2]u8;
|
||||||
let wantv: [2]str;
|
let wantv: [2]str;
|
||||||
@@ -127,13 +114,13 @@ fn streq(a: str, b: str) bool = {
|
|||||||
let i: i32 = 0;
|
let i: i32 = 0;
|
||||||
for (i < 2) {
|
for (i < 2) {
|
||||||
let p: *getopt.option = &cmd.optsptr[i];
|
let p: *getopt.option = &cmd.optsptr[i];
|
||||||
if ((p.flag: u8) != wantf[i]) { fail(); };
|
assert(!((p.flag: u8) != wantf[i]));
|
||||||
if (!streq(p.value, wantv[i])) { fail(); };
|
assert(!(!streq(p.value, wantv[i])));
|
||||||
i += 1;
|
i += 1;
|
||||||
};
|
};
|
||||||
|
|
||||||
if (cmd.argslen != 1) { fail(); };
|
assert(!(cmd.argslen != 1));
|
||||||
if (!streq(cmd.argsptr[0], "-")) { fail(); };
|
assert(!(!streq(cmd.argsptr[0], "-")));
|
||||||
|
|
||||||
getopt.finish(&cmd);
|
getopt.finish(&cmd);
|
||||||
};
|
};
|
||||||
@@ -177,12 +164,12 @@ fn streq(a: str, b: str) bool = {
|
|||||||
let r: (void | getopt.error) = getopt.tryparse(&cmd, argv, helps[0:2]);
|
let r: (void | getopt.error) = getopt.tryparse(&cmd, argv, helps[0:2]);
|
||||||
match (r) {
|
match (r) {
|
||||||
case void => {};
|
case void => {};
|
||||||
case let e: getopt.error => fail();
|
case let e: getopt.error => abort();
|
||||||
};
|
};
|
||||||
if (cmd.optslen != wantopts[i]) { fail(); };
|
assert(!(cmd.optslen != wantopts[i]));
|
||||||
if (cmd.argslen != wantargs[i]) { fail(); };
|
assert(!(cmd.argslen != wantargs[i]));
|
||||||
if (cmd.argslen > 0) {
|
if (cmd.argslen > 0) {
|
||||||
if (!streq(cmd.argsptr[0], wantarg0[i])) { fail(); };
|
assert(!(!streq(cmd.argsptr[0], wantarg0[i])));
|
||||||
};
|
};
|
||||||
getopt.finish(&cmd);
|
getopt.finish(&cmd);
|
||||||
i += 1;
|
i += 1;
|
||||||
@@ -204,18 +191,18 @@ fn streq(a: str, b: str) bool = {
|
|||||||
let r: (void | getopt.error) = getopt.tryparse(&cmd, argv[0:2], helps[0:2]);
|
let r: (void | getopt.error) = getopt.tryparse(&cmd, argv[0:2], helps[0:2]);
|
||||||
match (r) {
|
match (r) {
|
||||||
case void => {};
|
case void => {};
|
||||||
case let e: getopt.error => fail();
|
case let e: getopt.error => abort();
|
||||||
};
|
};
|
||||||
|
|
||||||
if (cmd.optslen != 3) { fail(); };
|
assert(!(cmd.optslen != 3));
|
||||||
let i: i32 = 0;
|
let i: i32 = 0;
|
||||||
for (i < 3) {
|
for (i < 3) {
|
||||||
let p: *getopt.option = &cmd.optsptr[i];
|
let p: *getopt.option = &cmd.optsptr[i];
|
||||||
if ((p.flag: u8) != ('v': u8)) { fail(); };
|
assert(!((p.flag: u8) != ('v': u8)));
|
||||||
if (p.value.len != 0) { fail(); };
|
assert(!(p.value.len != 0));
|
||||||
i += 1;
|
i += 1;
|
||||||
};
|
};
|
||||||
if (cmd.argslen != 0) { fail(); };
|
assert(!(cmd.argslen != 0));
|
||||||
|
|
||||||
getopt.finish(&cmd);
|
getopt.finish(&cmd);
|
||||||
};
|
};
|
||||||
@@ -257,13 +244,13 @@ fn streq(a: str, b: str) bool = {
|
|||||||
let r: (void | getopt.error) = getopt.tryparse(&cmd, argv, helps[0:2]);
|
let r: (void | getopt.error) = getopt.tryparse(&cmd, argv, helps[0:2]);
|
||||||
match (r) {
|
match (r) {
|
||||||
case void => {};
|
case void => {};
|
||||||
case let e: getopt.error => fail();
|
case let e: getopt.error => abort();
|
||||||
};
|
};
|
||||||
if (cmd.optslen != wantopts[i]) { fail(); };
|
assert(!(cmd.optslen != wantopts[i]));
|
||||||
if (cmd.argslen != wantargs[i]) { fail(); };
|
assert(!(cmd.argslen != wantargs[i]));
|
||||||
// First positional is always the bare "-" in these rows.
|
// First positional is always the bare "-" in these rows.
|
||||||
if (cmd.argslen > 0) {
|
if (cmd.argslen > 0) {
|
||||||
if (!streq(cmd.argsptr[0], "-")) { fail(); };
|
assert(!(!streq(cmd.argsptr[0], "-")));
|
||||||
};
|
};
|
||||||
getopt.finish(&cmd);
|
getopt.finish(&cmd);
|
||||||
i += 1;
|
i += 1;
|
||||||
@@ -307,11 +294,11 @@ fn streq(a: str, b: str) bool = {
|
|||||||
let cmd: getopt.command;
|
let cmd: getopt.command;
|
||||||
let r: (void | getopt.error) = getopt.tryparse(&cmd, argv, helps[0:3]);
|
let r: (void | getopt.error) = getopt.tryparse(&cmd, argv, helps[0:3]);
|
||||||
match (r) {
|
match (r) {
|
||||||
case void => fail();
|
case void => abort();
|
||||||
case let e: getopt.error => {
|
case let e: getopt.error => {
|
||||||
if ((e.kind: i32) != wantk[i]) { fail(); };
|
assert(!((e.kind: i32) != wantk[i]));
|
||||||
if ((e.flag: u8) != wantf[i]) { fail(); };
|
assert(!((e.flag: u8) != wantf[i]));
|
||||||
if (!streq(e.name, "prog")) { fail(); };
|
assert(!(!streq(e.name, "prog")));
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
getopt.finish(&cmd);
|
getopt.finish(&cmd);
|
||||||
@@ -340,7 +327,7 @@ fn streq(a: str, b: str) bool = {
|
|||||||
e.flag = flags[i]: rune;
|
e.flag = flags[i]: rune;
|
||||||
e.name = names[i];
|
e.name = names[i];
|
||||||
let s: str = getopt.strerror(&e);
|
let s: str = getopt.strerror(&e);
|
||||||
if (!streq(s, wants[i])) { fail(); };
|
assert(!(!streq(s, wants[i])));
|
||||||
i += 1;
|
i += 1;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
@@ -381,12 +368,12 @@ fn streq(a: str, b: str) bool = {
|
|||||||
let r: (void | getopt.error) = getopt.tryparse(&cmd, argv, helps[0:2]);
|
let r: (void | getopt.error) = getopt.tryparse(&cmd, argv, helps[0:2]);
|
||||||
match (r) {
|
match (r) {
|
||||||
case void => {};
|
case void => {};
|
||||||
case let e: getopt.error => fail();
|
case let e: getopt.error => abort();
|
||||||
};
|
};
|
||||||
if (cmd.optslen != 0) { fail(); };
|
assert(!(cmd.optslen != 0));
|
||||||
if (cmd.argslen != wantargs[i]) { fail(); };
|
assert(!(cmd.argslen != wantargs[i]));
|
||||||
if (cmd.argslen > 0) {
|
if (cmd.argslen > 0) {
|
||||||
if (!streq(cmd.argsptr[0], wantarg0[i])) { fail(); };
|
assert(!(!streq(cmd.argsptr[0], wantarg0[i])));
|
||||||
};
|
};
|
||||||
getopt.finish(&cmd);
|
getopt.finish(&cmd);
|
||||||
i += 1;
|
i += 1;
|
||||||
@@ -439,10 +426,10 @@ fn streq(a: str, b: str) bool = {
|
|||||||
hs.cap = hcnt[i];
|
hs.cap = hcnt[i];
|
||||||
match (getopt.printusage(h, names[i], hs)) {
|
match (getopt.printusage(h, names[i], hs)) {
|
||||||
case void => {};
|
case void => {};
|
||||||
case let e: io.error => fail();
|
case let e: io.error => abort();
|
||||||
};
|
};
|
||||||
let got: str = memio.string(&ms);
|
let got: str = memio.string(&ms);
|
||||||
if (!streq(got, wants[i])) { fail(); };
|
assert(!(!streq(got, wants[i])));
|
||||||
i += 1;
|
i += 1;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
@@ -482,24 +469,24 @@ fn streq(a: str, b: str) bool = {
|
|||||||
let h: io.handle = s: io.handle;
|
let h: io.handle = s: io.handle;
|
||||||
match (getopt.printhelp(h, names[i], helps[0:hcnt[i]])) {
|
match (getopt.printhelp(h, names[i], helps[0:hcnt[i]])) {
|
||||||
case void => {};
|
case void => {};
|
||||||
case let e: io.error => fail();
|
case let e: io.error => abort();
|
||||||
};
|
};
|
||||||
let got: str = memio.string(&ms);
|
let got: str = memio.string(&ms);
|
||||||
if (!streq(got, wants[i])) { fail(); };
|
assert(!(!streq(got, wants[i])));
|
||||||
i += 1;
|
i += 1;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
export fn main() i32 = {
|
export fn main() i32 = {
|
||||||
signalled = 1; flagcluster();
|
flagcluster();
|
||||||
signalled = 2; paramflag();
|
paramflag();
|
||||||
signalled = 3; separator();
|
separator();
|
||||||
signalled = 4; repeatedflag();
|
repeatedflag();
|
||||||
signalled = 5; baredash();
|
baredash();
|
||||||
signalled = 6; errortable();
|
errortable();
|
||||||
signalled = 7; strerrortext();
|
strerrortext();
|
||||||
signalled = 8; nooptionsbare();
|
nooptionsbare();
|
||||||
signalled = 9; printusage_cases();
|
printusage_cases();
|
||||||
signalled = 10; printhelp_cases();
|
printhelp_cases();
|
||||||
return 0;
|
return 0;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
// pathtest — exercises lib/path (c2-stack subset). Run with
|
// pathtest — exercises lib/path (c2-stack subset). Run with
|
||||||
// `out/bin/ww run lib/path/pathtest.ww`. Same signalled-then-fail()
|
// `out/bin/ww run lib/path/pathtest.ww`. A failing row aborts via the
|
||||||
// -with-+10 pattern as bytes / getopt tests: a non-zero exit code
|
// assert/abort builtin (task #5 @test conversion).
|
||||||
// pinpoints the failing scenario.
|
|
||||||
//
|
//
|
||||||
// Vectors mirror Hare's @test fns in ref/hare/path/stack.ha:77-119
|
// 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
|
// and buffer.ha. The absolute rows (Hare's `local("/")`-seeded) DEFER
|
||||||
@@ -16,10 +15,7 @@
|
|||||||
package path_test;
|
package path_test;
|
||||||
|
|
||||||
import path;
|
import path;
|
||||||
import os;
|
|
||||||
|
|
||||||
let signalled: i32 = 0;
|
|
||||||
fn fail() void = { os.exit(signalled + 10); };
|
|
||||||
|
|
||||||
// ---- push() + appendnorm normalization --------------------------------
|
// ---- push() + appendnorm normalization --------------------------------
|
||||||
// ref/hare/path/stack.ha:77-119 (relative rows only; absolute local()
|
// ref/hare/path/stack.ha:77-119 (relative rows only; absolute local()
|
||||||
@@ -29,7 +25,7 @@ fn fail() void = { os.exit(signalled + 10); };
|
|||||||
|
|
||||||
@test fn push_cases() void = {
|
@test fn push_cases() void = {
|
||||||
let buf = buffer { ... };
|
let buf = buffer { ... };
|
||||||
if (string(&buf) != ".") { fail(); };
|
assert(!(string(&buf) != "."));
|
||||||
|
|
||||||
// current-dir + parent-dir invariants (stack.ha:82-88). Single
|
// current-dir + parent-dir invariants (stack.ha:82-88). Single
|
||||||
// segment per row → table-driven sequential apply.
|
// segment per row → table-driven sequential apply.
|
||||||
@@ -42,13 +38,13 @@ fn fail() void = { os.exit(signalled + 10); };
|
|||||||
segs[4]="."; wants[4]="..";
|
segs[4]="."; wants[4]="..";
|
||||||
let i: i32 = 0;
|
let i: i32 = 0;
|
||||||
for (i < 5) {
|
for (i < 5) {
|
||||||
if (push(&buf, segs[i])! != wants[i]) { fail(); };
|
assert(!(push(&buf, segs[i])! != wants[i]));
|
||||||
i += 1;
|
i += 1;
|
||||||
};
|
};
|
||||||
|
|
||||||
// set(&buf) resets to "." (stack.ha:91). set forwards an EMPTY
|
// set(&buf) resets to "." (stack.ha:91). set forwards an EMPTY
|
||||||
// variadic into push (KEN-oracle flag 1: zero-arg gather+forward).
|
// variadic into push (KEN-oracle flag 1: zero-arg gather+forward).
|
||||||
if (set(&buf)! != ".") { fail(); };
|
assert(!(set(&buf)! != "."));
|
||||||
|
|
||||||
// regular path + parent (stack.ha:101-104, minus the local() row).
|
// regular path + parent (stack.ha:101-104, minus the local() row).
|
||||||
let segs2: [3]str;
|
let segs2: [3]str;
|
||||||
@@ -58,25 +54,25 @@ fn fail() void = { os.exit(signalled + 10); };
|
|||||||
segs2[2]=".."; wants2[2]=".";
|
segs2[2]=".."; wants2[2]=".";
|
||||||
let k: i32 = 0;
|
let k: i32 = 0;
|
||||||
for (k < 3) {
|
for (k < 3) {
|
||||||
if (push(&buf, segs2[k])! != wants2[k]) { fail(); };
|
assert(!(push(&buf, segs2[k])! != wants2[k]));
|
||||||
k += 1;
|
k += 1;
|
||||||
};
|
};
|
||||||
|
|
||||||
// multi-segment (stack.ha:107-111). Variadic arity varies (1 or 2)
|
// multi-segment (stack.ha:107-111). Variadic arity varies (1 or 2)
|
||||||
// → inline.
|
// → inline.
|
||||||
if (push(&buf, "a", "b")! != "a/b") { fail(); };
|
assert(!(push(&buf, "a", "b")! != "a/b"));
|
||||||
if (push(&buf, "..", "c")! != "a/c") { fail(); };
|
assert(!(push(&buf, "..", "c")! != "a/c"));
|
||||||
if (push(&buf, "..")! != "a") { fail(); };
|
assert(!(push(&buf, "..")! != "a"));
|
||||||
// stack.ha:110; local()→literal, SEP='/' on Linux, proper local() rides c3
|
// stack.ha:110; local()→literal, SEP='/' on Linux, proper local() rides c3
|
||||||
if (push(&buf, "/d")! != "a/d") { fail(); };
|
assert(!(push(&buf, "/d")! != "a/d"));
|
||||||
if (push(&buf, "..", "..")! != ".") { fail(); }; // stack.ha:111
|
assert(!(push(&buf, "..", "..")! != ".")); // stack.ha:111
|
||||||
|
|
||||||
// leading-SEP segment into an EMPTY buffer exercises push's
|
// leading-SEP segment into an EMPTY buffer exercises push's
|
||||||
// `j==0 && buf.end==0` root-seed arm (stack.ha:18-20), unreached
|
// `j==0 && buf.end==0` root-seed arm (stack.ha:18-20), unreached
|
||||||
// by the relative rows above. Hare covers it via local("/")-seeded
|
// by the relative rows above. Hare covers it via local("/")-seeded
|
||||||
// rows that defer to c3; literal "/foo" stands in (SEP='/' on Linux).
|
// rows that defer to c3; literal "/foo" stands in (SEP='/' on Linux).
|
||||||
if (set(&buf)! != ".") { fail(); };
|
assert(!(set(&buf)! != "."));
|
||||||
if (push(&buf, "/foo")! != "/foo") { fail(); };
|
assert(!(push(&buf, "/foo")! != "/foo"));
|
||||||
};
|
};
|
||||||
|
|
||||||
// ---- abs() ------------------------------------------------------------
|
// ---- abs() ------------------------------------------------------------
|
||||||
@@ -95,18 +91,18 @@ fn fail() void = { os.exit(signalled + 10); };
|
|||||||
for (i < 4) {
|
for (i < 4) {
|
||||||
let got: i32 = 0;
|
let got: i32 = 0;
|
||||||
if (abs(ins[i])) { got = 1; };
|
if (abs(ins[i])) { got = 1; };
|
||||||
if (got != want[i]) { fail(); };
|
assert(!(got != want[i]));
|
||||||
i += 1;
|
i += 1;
|
||||||
};
|
};
|
||||||
|
|
||||||
// buffer-arm: &buf ptr-ident-widens into the union.
|
// buffer-arm: &buf ptr-ident-widens into the union.
|
||||||
let buf = buffer { ... };
|
let buf = buffer { ... };
|
||||||
if (abs(&buf)) { fail(); }; // empty → false
|
assert(!(abs(&buf))); // empty → false
|
||||||
if (push(&buf, "/foo")! != "/foo") { fail(); };
|
assert(!(push(&buf, "/foo")! != "/foo"));
|
||||||
if (!abs(&buf)) { fail(); }; // "/foo" → true
|
assert(!(!abs(&buf))); // "/foo" → true
|
||||||
buf.end = 0;
|
buf.end = 0;
|
||||||
if (push(&buf, "foo")! != "foo") { fail(); };
|
assert(!(push(&buf, "foo")! != "foo"));
|
||||||
if (abs(&buf)) { fail(); }; // "foo" → false
|
assert(!(abs(&buf))); // "foo" → false
|
||||||
};
|
};
|
||||||
|
|
||||||
// ---- isroot() ---------------------------------------------------------
|
// ---- isroot() ---------------------------------------------------------
|
||||||
@@ -117,22 +113,22 @@ fn fail() void = { os.exit(signalled + 10); };
|
|||||||
@test fn isroot_cases() void = {
|
@test fn isroot_cases() void = {
|
||||||
let buf = buffer { ... };
|
let buf = buffer { ... };
|
||||||
// empty buffer (end 0)
|
// empty buffer (end 0)
|
||||||
if (isroot(&buf)) { fail(); };
|
assert(!(isroot(&buf)));
|
||||||
|
|
||||||
// "/" — root. local() is c3, so seed the SEP byte directly.
|
// "/" — root. local() is c3, so seed the SEP byte directly.
|
||||||
buf.buf[0] = SEP; buf.end = 1;
|
buf.buf[0] = SEP; buf.end = 1;
|
||||||
if (!isroot(&buf)) { fail(); };
|
assert(!(!isroot(&buf)));
|
||||||
if (string(&buf) != "/") { fail(); };
|
assert(!(string(&buf) != "/"));
|
||||||
|
|
||||||
// "foo" — relative, not root.
|
// "foo" — relative, not root.
|
||||||
buf.end = 0;
|
buf.end = 0;
|
||||||
if (push(&buf, "foo")! != "foo") { fail(); };
|
assert(!(push(&buf, "foo")! != "foo"));
|
||||||
if (isroot(&buf)) { fail(); };
|
assert(!(isroot(&buf)));
|
||||||
|
|
||||||
// "/foo" — absolute but not root.
|
// "/foo" — absolute but not root.
|
||||||
buf.buf[0] = SEP; buf.end = 1;
|
buf.buf[0] = SEP; buf.end = 1;
|
||||||
if (push(&buf, "foo")! != "/foo") { fail(); };
|
assert(!(push(&buf, "foo")! != "/foo"));
|
||||||
if (isroot(&buf)) { fail(); };
|
assert(!(isroot(&buf)));
|
||||||
|
|
||||||
// str-arm (buffer.ha:47): only the bare separator is root.
|
// str-arm (buffer.ha:47): only the bare separator is root.
|
||||||
let ins: [4]str;
|
let ins: [4]str;
|
||||||
@@ -145,7 +141,7 @@ fn fail() void = { os.exit(signalled + 10); };
|
|||||||
for (i < 4) {
|
for (i < 4) {
|
||||||
let got: i32 = 0;
|
let got: i32 = 0;
|
||||||
if (isroot(ins[i])) { got = 1; };
|
if (isroot(ins[i])) { got = 1; };
|
||||||
if (got != want[i]) { fail(); };
|
assert(!(got != want[i]));
|
||||||
i += 1;
|
i += 1;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
@@ -156,9 +152,9 @@ fn fail() void = { os.exit(signalled + 10); };
|
|||||||
|
|
||||||
@test fn string_cases() void = {
|
@test fn string_cases() void = {
|
||||||
let buf = buffer { ... };
|
let buf = buffer { ... };
|
||||||
if (string(&buf) != ".") { fail(); };
|
assert(!(string(&buf) != "."));
|
||||||
if (push(&buf, "foo")! != "foo") { fail(); };
|
assert(!(push(&buf, "foo")! != "foo"));
|
||||||
if (string(&buf) != "foo") { fail(); };
|
assert(!(string(&buf) != "foo"));
|
||||||
};
|
};
|
||||||
|
|
||||||
// ---- dirname() / basename() -------------------------------------------
|
// ---- dirname() / basename() -------------------------------------------
|
||||||
@@ -188,8 +184,8 @@ fn fail() void = { os.exit(signalled + 10); };
|
|||||||
inputs[9]="/home//dwc//test"; wantdir[9]="/home//dwc"; wantbase[9]="test";
|
inputs[9]="/home//dwc//test"; wantdir[9]="/home//dwc"; wantbase[9]="test";
|
||||||
let i: i32 = 0;
|
let i: i32 = 0;
|
||||||
for (i < 10) {
|
for (i < 10) {
|
||||||
if (dirname(inputs[i]) != wantdir[i]) { fail(); };
|
assert(!(dirname(inputs[i]) != wantdir[i]));
|
||||||
if (basename(inputs[i]) != wantbase[i]) { fail(); };
|
assert(!(basename(inputs[i]) != wantbase[i]));
|
||||||
i += 1;
|
i += 1;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
@@ -208,7 +204,7 @@ fn fail() void = { os.exit(signalled + 10); };
|
|||||||
ins[3]=""; want[3]="";
|
ins[3]=""; want[3]="";
|
||||||
let i: i32 = 0;
|
let i: i32 = 0;
|
||||||
for (i < 4) {
|
for (i < 4) {
|
||||||
if (local(ins[i])! != want[i]) { fail(); };
|
assert(!(local(ins[i])! != want[i]));
|
||||||
i += 1;
|
i += 1;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
@@ -232,7 +228,7 @@ fn fail() void = { os.exit(signalled + 10); };
|
|||||||
for (i < 5) {
|
for (i < 5) {
|
||||||
buf.end = 0;
|
buf.end = 0;
|
||||||
push(&buf, ins[i])!;
|
push(&buf, ins[i])!;
|
||||||
if (parent(&buf)! != want[i]) { fail(); };
|
assert(!(parent(&buf)! != want[i]));
|
||||||
i += 1;
|
i += 1;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
@@ -247,39 +243,39 @@ fn fail() void = { os.exit(signalled + 10); };
|
|||||||
let buf = buffer { ... };
|
let buf = buffer { ... };
|
||||||
|
|
||||||
// empty
|
// empty
|
||||||
if (!(pop(&buf) is void)) { fail(); };
|
assert(!(!(pop(&buf) is void)));
|
||||||
if (string(&buf) != ".") { fail(); };
|
assert(!(string(&buf) != "."));
|
||||||
|
|
||||||
// root dir
|
// root dir
|
||||||
buf.end = 0;
|
buf.end = 0;
|
||||||
if (push(&buf, "/")! != "/") { fail(); };
|
assert(!(push(&buf, "/")! != "/"));
|
||||||
if (!(pop(&buf) is void)) { fail(); };
|
assert(!(!(pop(&buf) is void)));
|
||||||
if (string(&buf) != "/") { fail(); };
|
assert(!(string(&buf) != "/"));
|
||||||
|
|
||||||
// relative file — peek is NON-mutating
|
// relative file — peek is NON-mutating
|
||||||
buf.end = 0;
|
buf.end = 0;
|
||||||
if (push(&buf, "foo")! != "foo") { fail(); };
|
assert(!(push(&buf, "foo")! != "foo"));
|
||||||
if (peek(&buf) as str != "foo") { fail(); };
|
assert(!(peek(&buf) as str != "foo"));
|
||||||
if (string(&buf) != "foo") { fail(); };
|
assert(!(string(&buf) != "foo"));
|
||||||
if (pop(&buf) as str != "foo") { fail(); };
|
assert(!(pop(&buf) as str != "foo"));
|
||||||
if (string(&buf) != ".") { fail(); };
|
assert(!(string(&buf) != "."));
|
||||||
|
|
||||||
// absolute file
|
// absolute file
|
||||||
buf.end = 0;
|
buf.end = 0;
|
||||||
if (push(&buf, "/foo")! != "/foo") { fail(); };
|
assert(!(push(&buf, "/foo")! != "/foo"));
|
||||||
if (peek(&buf) as str != "foo") { fail(); };
|
assert(!(peek(&buf) as str != "foo"));
|
||||||
if (pop(&buf) as str != "foo") { fail(); };
|
assert(!(pop(&buf) as str != "foo"));
|
||||||
if (string(&buf) != "/") { fail(); };
|
assert(!(string(&buf) != "/"));
|
||||||
};
|
};
|
||||||
|
|
||||||
export fn main() i32 = {
|
export fn main() i32 = {
|
||||||
signalled = 1; push_cases();
|
push_cases();
|
||||||
signalled = 2; isroot_cases();
|
isroot_cases();
|
||||||
signalled = 3; string_cases();
|
string_cases();
|
||||||
signalled = 4; dirname_basename_cases();
|
dirname_basename_cases();
|
||||||
signalled = 5; abs_cases();
|
abs_cases();
|
||||||
signalled = 6; local_cases();
|
local_cases();
|
||||||
signalled = 7; parent_cases();
|
parent_cases();
|
||||||
signalled = 8; popsplit_cases();
|
popsplit_cases();
|
||||||
return 0;
|
return 0;
|
||||||
};
|
};
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -18,19 +18,6 @@ package temp_test;
|
|||||||
import os;
|
import os;
|
||||||
import temp;
|
import temp;
|
||||||
|
|
||||||
// Direct exit(2) binding rather than mixing `use io;` and `use os;` —
|
|
||||||
// they share read/write/close names under the driver's flat-scope
|
|
||||||
// concat (task #7). We don't need lib/io here at all (raw fd ops
|
|
||||||
// via os.read/os.write/os.close suffice), but the binding shape
|
|
||||||
// mirrors memio/getopt for parity.
|
|
||||||
fn doexit(code: i32) void = { os.exit(code); };
|
|
||||||
|
|
||||||
// signalled — bumped by main before each test so a failing exit
|
|
||||||
// code pinpoints the offending case.
|
|
||||||
let signalled: i32 = 0;
|
|
||||||
|
|
||||||
fn fail() void = { doexit(signalled + 10); };
|
|
||||||
|
|
||||||
fn streq(a: str, b: str) bool = {
|
fn streq(a: str, b: str) bool = {
|
||||||
if (a.len != b.len) { return false; };
|
if (a.len != b.len) { return false; };
|
||||||
let i: i32 = 0;
|
let i: i32 = 0;
|
||||||
@@ -58,16 +45,16 @@ fn streq(a: str, b: str) bool = {
|
|||||||
let p: str;
|
let p: str;
|
||||||
match (temp.named(&fd, &p, "/tmp", temp.mode.RDWR, 384i32)) { // 0o600
|
match (temp.named(&fd, &p, "/tmp", temp.mode.RDWR, 384i32)) { // 0o600
|
||||||
case void => {};
|
case void => {};
|
||||||
case let e: os.oserror => fail();
|
case let e: os.oserror => abort();
|
||||||
};
|
};
|
||||||
if (fd < 0) { fail(); };
|
assert(!(fd < 0));
|
||||||
if (p.len < 10) { fail(); }; // at minimum "/tmp/temp.<1 hex>"
|
assert(!(p.len < 10)); // at minimum "/tmp/temp.<1 hex>"
|
||||||
|
|
||||||
// Path bytes must start with "/tmp/temp." and live in temp's
|
// Path bytes must start with "/tmp/temp." and live in temp's
|
||||||
// static buffer (NUL-terminated for syscall handoff).
|
// static buffer (NUL-terminated for syscall handoff).
|
||||||
if (p[0] != 47u8) { fail(); }; // '/'
|
assert(!(p[0] != 47u8)); // '/'
|
||||||
if (!streq(strslice(p, 0, 10), "/tmp/temp.")) { fail(); };
|
assert(!(!streq(strslice(p, 0, 10), "/tmp/temp.")));
|
||||||
if (p.ptr[p.len] != 0u8) { fail(); };
|
assert(!(p.ptr[p.len] != 0u8));
|
||||||
|
|
||||||
// Build fill payload, write it, lseek to 0, read it back.
|
// Build fill payload, write it, lseek to 0, read it back.
|
||||||
let wbuf: [64]u8;
|
let wbuf: [64]u8;
|
||||||
@@ -75,11 +62,11 @@ fn streq(a: str, b: str) bool = {
|
|||||||
for (k < sz[i]) { wbuf[k] = fill[i]; k += 1; };
|
for (k < sz[i]) { wbuf[k] = fill[i]; k += 1; };
|
||||||
if (sz[i] > 0) {
|
if (sz[i] > 0) {
|
||||||
let wr: i64 = os.write(fd, &wbuf[0], sz[i]: u64);
|
let wr: i64 = os.write(fd, &wbuf[0], sz[i]: u64);
|
||||||
if (wr != sz[i]: i64) { fail(); };
|
assert(!(wr != sz[i]: i64));
|
||||||
};
|
};
|
||||||
|
|
||||||
let r: i64 = os.lseek(fd, 0i64, os.whence.SET);
|
let r: i64 = os.lseek(fd, 0i64, os.whence.SET);
|
||||||
if (r != 0i64) { fail(); };
|
assert(!(r != 0i64));
|
||||||
|
|
||||||
let rbuf: [64]u8;
|
let rbuf: [64]u8;
|
||||||
let z: i32 = 0;
|
let z: i32 = 0;
|
||||||
@@ -87,22 +74,22 @@ fn streq(a: str, b: str) bool = {
|
|||||||
let rd: i64 = 0i64;
|
let rd: i64 = 0i64;
|
||||||
if (sz[i] > 0) {
|
if (sz[i] > 0) {
|
||||||
rd = os.read(fd, &rbuf[0], sz[i]: u64);
|
rd = os.read(fd, &rbuf[0], sz[i]: u64);
|
||||||
if (rd != sz[i]: i64) { fail(); };
|
assert(!(rd != sz[i]: i64));
|
||||||
};
|
};
|
||||||
let k2: i32 = 0;
|
let k2: i32 = 0;
|
||||||
for (k2 < sz[i]) {
|
for (k2 < sz[i]) {
|
||||||
if (rbuf[k2] != fill[i]) { fail(); };
|
assert(!(rbuf[k2] != fill[i]));
|
||||||
k2 += 1;
|
k2 += 1;
|
||||||
};
|
};
|
||||||
|
|
||||||
// File exists pre-cleanup.
|
// File exists pre-cleanup.
|
||||||
if (os.access(p, 0i32) != 0) { fail(); };
|
assert(!(os.access(p, 0i32) != 0));
|
||||||
|
|
||||||
if (os.close(fd) != 0) { fail(); };
|
assert(!(os.close(fd) != 0));
|
||||||
if (os.remove(p) != 0) { fail(); };
|
assert(!(os.remove(p) != 0));
|
||||||
|
|
||||||
// Cleanup landed.
|
// Cleanup landed.
|
||||||
if (os.access(p, 0i32) == 0) { fail(); };
|
assert(!(os.access(p, 0i32) == 0));
|
||||||
|
|
||||||
i += 1;
|
i += 1;
|
||||||
};
|
};
|
||||||
@@ -127,7 +114,7 @@ fn strslice(p: str, lo: i32, hi: i32) str = {
|
|||||||
let p1: str;
|
let p1: str;
|
||||||
match (temp.named(&fd1, &p1, "/tmp", temp.mode.WRITE, 384i32)) {
|
match (temp.named(&fd1, &p1, "/tmp", temp.mode.WRITE, 384i32)) {
|
||||||
case void => {};
|
case void => {};
|
||||||
case let e: os.oserror => fail();
|
case let e: os.oserror => abort();
|
||||||
};
|
};
|
||||||
|
|
||||||
// Snapshot p1's bytes BEFORE the second call clobbers the buffer,
|
// Snapshot p1's bytes BEFORE the second call clobbers the buffer,
|
||||||
@@ -146,22 +133,22 @@ fn strslice(p: str, lo: i32, hi: i32) str = {
|
|||||||
let p2: str;
|
let p2: str;
|
||||||
match (temp.named(&fd2, &p2, "/tmp", temp.mode.WRITE, 384i32)) {
|
match (temp.named(&fd2, &p2, "/tmp", temp.mode.WRITE, 384i32)) {
|
||||||
case void => {};
|
case void => {};
|
||||||
case let e: os.oserror => fail();
|
case let e: os.oserror => abort();
|
||||||
};
|
};
|
||||||
|
|
||||||
// Same buffer (Hare docs: "overwritten on subsequent calls"),
|
// Same buffer (Hare docs: "overwritten on subsequent calls"),
|
||||||
// distinct path bytes (random suffix differs).
|
// distinct path bytes (random suffix differs).
|
||||||
if (p1.ptr != p2.ptr) { fail(); };
|
assert(!(p1.ptr != p2.ptr));
|
||||||
if (streq(strslice(p2, 0, p2.len), psnap)) { fail(); };
|
assert(!(streq(strslice(p2, 0, p2.len), psnap)));
|
||||||
|
|
||||||
// Both fds are distinct.
|
// Both fds are distinct.
|
||||||
if (fd1 == fd2) { fail(); };
|
assert(!(fd1 == fd2));
|
||||||
|
|
||||||
if (os.close(fd2) != 0) { fail(); };
|
assert(!(os.close(fd2) != 0));
|
||||||
if (os.remove(p2) != 0) { fail(); };
|
assert(!(os.remove(p2) != 0));
|
||||||
|
|
||||||
if (os.close(fd1) != 0) { fail(); };
|
assert(!(os.close(fd1) != 0));
|
||||||
if (os.remove(psnap) != 0) { fail(); };
|
assert(!(os.remove(psnap) != 0));
|
||||||
};
|
};
|
||||||
|
|
||||||
// NOTE: temp.file() has no test of its own. The function is a thin
|
// NOTE: temp.file() has no test of its own. The function is a thin
|
||||||
@@ -184,12 +171,12 @@ fn strslice(p: str, lo: i32, hi: i32) str = {
|
|||||||
let i: i32 = 0;
|
let i: i32 = 0;
|
||||||
for (i < 2) {
|
for (i < 2) {
|
||||||
let d: str = temp.dir();
|
let d: str = temp.dir();
|
||||||
if (d.len < 6) { fail(); };
|
assert(!(d.len < 6));
|
||||||
if (!streq(strslice(d, 0, 5), "/tmp/")) { fail(); };
|
assert(!(!streq(strslice(d, 0, 5), "/tmp/")));
|
||||||
if (d.ptr[d.len] != 0u8) { fail(); };
|
assert(!(d.ptr[d.len] != 0u8));
|
||||||
|
|
||||||
// Dir exists.
|
// Dir exists.
|
||||||
if (os.access(d, 0i32) != 0) { fail(); };
|
assert(!(os.access(d, 0i32) != 0));
|
||||||
|
|
||||||
// Snapshot the dir path into a local NUL-terminated buffer:
|
// Snapshot the dir path into a local NUL-terminated buffer:
|
||||||
// the os.* path entrypoints now copy through lib/os.pathbuf
|
// the os.* path entrypoints now copy through lib/os.pathbuf
|
||||||
@@ -217,21 +204,21 @@ fn strslice(p: str, lo: i32, hi: i32) str = {
|
|||||||
cview.ptr = &cbuf[0]; cview.len = off;
|
cview.ptr = &cbuf[0]; cview.len = off;
|
||||||
let cflags: os.flag = os.flag.WRONLY | os.flag.CREATE | os.flag.EXCL;
|
let cflags: os.flag = os.flag.WRONLY | os.flag.CREATE | os.flag.EXCL;
|
||||||
let fd: i32 = os.open(cview, cflags, 384i32);
|
let fd: i32 = os.open(cview, cflags, 384i32);
|
||||||
if (fd < 0) { fail(); };
|
assert(!(fd < 0));
|
||||||
let payload: [3]u8;
|
let payload: [3]u8;
|
||||||
payload[0] = 88u8; payload[1] = 89u8; payload[2] = 90u8; // "XYZ"
|
payload[0] = 88u8; payload[1] = 89u8; payload[2] = 90u8; // "XYZ"
|
||||||
let wr: i64 = os.write(fd, &payload[0], 3u64);
|
let wr: i64 = os.write(fd, &payload[0], 3u64);
|
||||||
if (wr != 3i64) { fail(); };
|
assert(!(wr != 3i64));
|
||||||
if (os.close(fd) != 0) { fail(); };
|
assert(!(os.close(fd) != 0));
|
||||||
if (os.remove(cview) != 0) { fail(); };
|
assert(!(os.remove(cview) != 0));
|
||||||
};
|
};
|
||||||
|
|
||||||
// Rmdir uses dview (more robust if the static buffer were
|
// Rmdir uses dview (more robust if the static buffer were
|
||||||
// touched between dir() and here).
|
// touched between dir() and here).
|
||||||
if (os.rmdir(dview) != 0) { fail(); };
|
assert(!(os.rmdir(dview) != 0));
|
||||||
|
|
||||||
// Cleanup landed.
|
// Cleanup landed.
|
||||||
if (os.access(dview, 0i32) == 0) { fail(); };
|
assert(!(os.access(dview, 0i32) == 0));
|
||||||
|
|
||||||
i += 1;
|
i += 1;
|
||||||
};
|
};
|
||||||
@@ -252,18 +239,18 @@ fn strslice(p: str, lo: i32, hi: i32) str = {
|
|||||||
dsnap.len = snaplen;
|
dsnap.len = snaplen;
|
||||||
|
|
||||||
let d2: str = temp.dir();
|
let d2: str = temp.dir();
|
||||||
if (d1.ptr != d2.ptr) { fail(); }; // same static buffer
|
assert(!(d1.ptr != d2.ptr)); // same static buffer
|
||||||
if (streq(strslice(d2, 0, d2.len), dsnap)) { fail(); };
|
assert(!(streq(strslice(d2, 0, d2.len), dsnap)));
|
||||||
|
|
||||||
// Cleanup both, using snap for d1's old contents.
|
// Cleanup both, using snap for d1's old contents.
|
||||||
if (os.rmdir(d2) != 0) { fail(); };
|
assert(!(os.rmdir(d2) != 0));
|
||||||
if (os.rmdir(dsnap) != 0) { fail(); };
|
assert(!(os.rmdir(dsnap) != 0));
|
||||||
};
|
};
|
||||||
|
|
||||||
export fn main() i32 = {
|
export fn main() i32 = {
|
||||||
signalled = 1; namedroundtrip();
|
namedroundtrip();
|
||||||
signalled = 2; namedoverwrite();
|
namedoverwrite();
|
||||||
signalled = 3; dirlifecycle();
|
dirlifecycle();
|
||||||
signalled = 4; diruniqueness();
|
diruniqueness();
|
||||||
return 0;
|
return 0;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,16 +1,12 @@
|
|||||||
// timetest — exercises lib/time. Run with `out/bin/ww run
|
// timetest — exercises lib/time. Run with `out/bin/ww run
|
||||||
// lib/time/timetest.ww`. Same `signalled`-then-fail()-with-+10
|
// lib/time/timetest.ww`. A failing row aborts via the assert/abort
|
||||||
// pattern as fmttest / logtest / stattest so a non-zero exit
|
// builtin (task #5 @test conversion).
|
||||||
// pinpoints the offending scenario.
|
|
||||||
|
|
||||||
package time_test;
|
package time_test;
|
||||||
|
|
||||||
import os;
|
|
||||||
import time;
|
import time;
|
||||||
|
|
||||||
let signalled: i32 = 0;
|
|
||||||
|
|
||||||
fn fail() void = { os.exit(signalled + 10); };
|
|
||||||
|
|
||||||
// ---- constants: load-bearing names + values ----------------------------
|
// ---- constants: load-bearing names + values ----------------------------
|
||||||
//
|
//
|
||||||
@@ -19,16 +15,16 @@ fn fail() void = { os.exit(signalled + 10); };
|
|||||||
// ref/hare/time/duration.ha:9-18.
|
// ref/hare/time/duration.ha:9-18.
|
||||||
|
|
||||||
@test fn constants() void = {
|
@test fn constants() void = {
|
||||||
if ((time.nanosecond: i64) != 1i64) { fail(); };
|
assert(!((time.nanosecond: i64) != 1i64));
|
||||||
if ((time.microsecond: i64) != 1000i64) { fail(); };
|
assert(!((time.microsecond: i64) != 1000i64));
|
||||||
if ((time.millisecond: i64) != 1000000i64) { fail(); };
|
assert(!((time.millisecond: i64) != 1000000i64));
|
||||||
if ((time.second: i64) != 1000000000i64) { fail(); };
|
assert(!((time.second: i64) != 1000000000i64));
|
||||||
|
|
||||||
// "Roundtrip" check: derived multiples land on the canonical
|
// "Roundtrip" check: derived multiples land on the canonical
|
||||||
// nanosecond count. Catches a future re-derivation drift.
|
// nanosecond count. Catches a future re-derivation drift.
|
||||||
if (5i64 * (time.second: i64) != 5000000000i64) { fail(); };
|
assert(!(5i64 * (time.second: i64) != 5000000000i64));
|
||||||
if (3i64 * (time.millisecond: i64) != 3000000i64) { fail(); };
|
assert(!(3i64 * (time.millisecond: i64) != 3000000i64));
|
||||||
if (7i64 * (time.microsecond: i64) != 7000i64) { fail(); };
|
assert(!(7i64 * (time.microsecond: i64) != 7000i64));
|
||||||
};
|
};
|
||||||
|
|
||||||
// ---- now(monotonic) is monotonic across two calls ----------------------
|
// ---- now(monotonic) is monotonic across two calls ----------------------
|
||||||
@@ -38,7 +34,7 @@ fn fail() void = { os.exit(signalled + 10); };
|
|||||||
let b = time.now(time.clock.monotonic);
|
let b = time.now(time.clock.monotonic);
|
||||||
// Two back-to-back calls — b can equal a (same ns tick) but
|
// Two back-to-back calls — b can equal a (same ns tick) but
|
||||||
// must never precede it.
|
// must never precede it.
|
||||||
if (time.compare(a, b) > 0i8) { fail(); };
|
assert(!(time.compare(a, b) > 0i8));
|
||||||
};
|
};
|
||||||
|
|
||||||
// ---- now(realtime) returns a post-2020 epoch ---------------------------
|
// ---- now(realtime) returns a post-2020 epoch ---------------------------
|
||||||
@@ -51,9 +47,9 @@ fn fail() void = { os.exit(signalled + 10); };
|
|||||||
|
|
||||||
@test fn nowrealtime() void = {
|
@test fn nowrealtime() void = {
|
||||||
let t = time.now(time.clock.realtime);
|
let t = time.now(time.clock.realtime);
|
||||||
if (t.sec < 1577836800i64) { fail(); };
|
assert(!(t.sec < 1577836800i64));
|
||||||
if (t.nsec < 0i64) { fail(); };
|
assert(!(t.nsec < 0i64));
|
||||||
if (t.nsec >= 1000000000i64) { fail(); };
|
assert(!(t.nsec >= 1000000000i64));
|
||||||
};
|
};
|
||||||
|
|
||||||
// ---- add: zero duration is identity ------------------------------------
|
// ---- add: zero duration is identity ------------------------------------
|
||||||
@@ -62,8 +58,8 @@ fn fail() void = { os.exit(signalled + 10); };
|
|||||||
let a: time.instant;
|
let a: time.instant;
|
||||||
a.sec = 100i64; a.nsec = 500i64;
|
a.sec = 100i64; a.nsec = 500i64;
|
||||||
let r = time.add(a, 0i64);
|
let r = time.add(a, 0i64);
|
||||||
if (r.sec != 100i64) { fail(); };
|
assert(!(r.sec != 100i64));
|
||||||
if (r.nsec != 500i64) { fail(); };
|
assert(!(r.nsec != 500i64));
|
||||||
};
|
};
|
||||||
|
|
||||||
// ---- add: positive duration, no carry ----------------------------------
|
// ---- add: positive duration, no carry ----------------------------------
|
||||||
@@ -72,8 +68,8 @@ fn fail() void = { os.exit(signalled + 10); };
|
|||||||
let a: time.instant;
|
let a: time.instant;
|
||||||
a.sec = 10i64; a.nsec = 100i64;
|
a.sec = 10i64; a.nsec = 100i64;
|
||||||
let r = time.add(a, 200i64);
|
let r = time.add(a, 200i64);
|
||||||
if (r.sec != 10i64) { fail(); };
|
assert(!(r.sec != 10i64));
|
||||||
if (r.nsec != 300i64) { fail(); };
|
assert(!(r.nsec != 300i64));
|
||||||
};
|
};
|
||||||
|
|
||||||
// ---- add: positive duration, carries into next second ------------------
|
// ---- add: positive duration, carries into next second ------------------
|
||||||
@@ -82,8 +78,8 @@ fn fail() void = { os.exit(signalled + 10); };
|
|||||||
let a: time.instant;
|
let a: time.instant;
|
||||||
a.sec = 10i64; a.nsec = 999999900i64;
|
a.sec = 10i64; a.nsec = 999999900i64;
|
||||||
let r = time.add(a, 200i64);
|
let r = time.add(a, 200i64);
|
||||||
if (r.sec != 11i64) { fail(); };
|
assert(!(r.sec != 11i64));
|
||||||
if (r.nsec != 100i64) { fail(); };
|
assert(!(r.nsec != 100i64));
|
||||||
};
|
};
|
||||||
|
|
||||||
// ---- add: full-second duration -----------------------------------------
|
// ---- add: full-second duration -----------------------------------------
|
||||||
@@ -92,8 +88,8 @@ fn fail() void = { os.exit(signalled + 10); };
|
|||||||
let a: time.instant;
|
let a: time.instant;
|
||||||
a.sec = 5i64; a.nsec = 0i64;
|
a.sec = 5i64; a.nsec = 0i64;
|
||||||
let r = time.add(a, (time.second: i64) * 3i64);
|
let r = time.add(a, (time.second: i64) * 3i64);
|
||||||
if (r.sec != 8i64) { fail(); };
|
assert(!(r.sec != 8i64));
|
||||||
if (r.nsec != 0i64) { fail(); };
|
assert(!(r.nsec != 0i64));
|
||||||
};
|
};
|
||||||
|
|
||||||
// ---- add: negative duration, no borrow ---------------------------------
|
// ---- add: negative duration, no borrow ---------------------------------
|
||||||
@@ -102,8 +98,8 @@ fn fail() void = { os.exit(signalled + 10); };
|
|||||||
let a: time.instant;
|
let a: time.instant;
|
||||||
a.sec = 10i64; a.nsec = 500i64;
|
a.sec = 10i64; a.nsec = 500i64;
|
||||||
let r = time.add(a, -100i64);
|
let r = time.add(a, -100i64);
|
||||||
if (r.sec != 10i64) { fail(); };
|
assert(!(r.sec != 10i64));
|
||||||
if (r.nsec != 400i64) { fail(); };
|
assert(!(r.nsec != 400i64));
|
||||||
};
|
};
|
||||||
|
|
||||||
// ---- add: negative duration, borrows from previous second --------------
|
// ---- add: negative duration, borrows from previous second --------------
|
||||||
@@ -112,8 +108,8 @@ fn fail() void = { os.exit(signalled + 10); };
|
|||||||
let a: time.instant;
|
let a: time.instant;
|
||||||
a.sec = 10i64; a.nsec = 100i64;
|
a.sec = 10i64; a.nsec = 100i64;
|
||||||
let r = time.add(a, -200i64);
|
let r = time.add(a, -200i64);
|
||||||
if (r.sec != 9i64) { fail(); };
|
assert(!(r.sec != 9i64));
|
||||||
if (r.nsec != 999999900i64) { fail(); };
|
assert(!(r.nsec != 999999900i64));
|
||||||
};
|
};
|
||||||
|
|
||||||
// ---- diff: simple subtraction ------------------------------------------
|
// ---- diff: simple subtraction ------------------------------------------
|
||||||
@@ -123,7 +119,7 @@ fn fail() void = { os.exit(signalled + 10); };
|
|||||||
let b: time.instant; b.sec = 12i64; b.nsec = 300i64;
|
let b: time.instant; b.sec = 12i64; b.nsec = 300i64;
|
||||||
let d: i64 = time.diff(a, b): i64;
|
let d: i64 = time.diff(a, b): i64;
|
||||||
// b - a = 2.0000002 sec = 2_000_000_200 ns
|
// b - a = 2.0000002 sec = 2_000_000_200 ns
|
||||||
if (d != 2000000200i64) { fail(); };
|
assert(!(d != 2000000200i64));
|
||||||
};
|
};
|
||||||
|
|
||||||
// ---- diff: reversed sign -----------------------------------------------
|
// ---- diff: reversed sign -----------------------------------------------
|
||||||
@@ -132,7 +128,7 @@ fn fail() void = { os.exit(signalled + 10); };
|
|||||||
let a: time.instant; a.sec = 12i64; a.nsec = 300i64;
|
let a: time.instant; a.sec = 12i64; a.nsec = 300i64;
|
||||||
let b: time.instant; b.sec = 10i64; b.nsec = 100i64;
|
let b: time.instant; b.sec = 10i64; b.nsec = 100i64;
|
||||||
let d: i64 = time.diff(a, b): i64;
|
let d: i64 = time.diff(a, b): i64;
|
||||||
if (d != -2000000200i64) { fail(); };
|
assert(!(d != -2000000200i64));
|
||||||
};
|
};
|
||||||
|
|
||||||
// ---- compare: -1 / 0 / +1 ladder ---------------------------------------
|
// ---- compare: -1 / 0 / +1 ladder ---------------------------------------
|
||||||
@@ -140,43 +136,43 @@ fn fail() void = { os.exit(signalled + 10); };
|
|||||||
@test fn comparelt() void = {
|
@test fn comparelt() void = {
|
||||||
let a: time.instant; a.sec = 1i64; a.nsec = 0i64;
|
let a: time.instant; a.sec = 1i64; a.nsec = 0i64;
|
||||||
let b: time.instant; b.sec = 2i64; b.nsec = 0i64;
|
let b: time.instant; b.sec = 2i64; b.nsec = 0i64;
|
||||||
if (time.compare(a, b) != -1i8) { fail(); };
|
assert(!(time.compare(a, b) != -1i8));
|
||||||
};
|
};
|
||||||
|
|
||||||
@test fn comparegt() void = {
|
@test fn comparegt() void = {
|
||||||
let a: time.instant; a.sec = 2i64; a.nsec = 0i64;
|
let a: time.instant; a.sec = 2i64; a.nsec = 0i64;
|
||||||
let b: time.instant; b.sec = 1i64; b.nsec = 0i64;
|
let b: time.instant; b.sec = 1i64; b.nsec = 0i64;
|
||||||
if (time.compare(a, b) != 1i8) { fail(); };
|
assert(!(time.compare(a, b) != 1i8));
|
||||||
};
|
};
|
||||||
|
|
||||||
@test fn compareeq() void = {
|
@test fn compareeq() void = {
|
||||||
let a: time.instant; a.sec = 5i64; a.nsec = 42i64;
|
let a: time.instant; a.sec = 5i64; a.nsec = 42i64;
|
||||||
let b: time.instant; b.sec = 5i64; b.nsec = 42i64;
|
let b: time.instant; b.sec = 5i64; b.nsec = 42i64;
|
||||||
if (time.compare(a, b) != 0i8) { fail(); };
|
assert(!(time.compare(a, b) != 0i8));
|
||||||
};
|
};
|
||||||
|
|
||||||
@test fn comparensec_only() void = {
|
@test fn comparensec_only() void = {
|
||||||
let a: time.instant; a.sec = 5i64; a.nsec = 100i64;
|
let a: time.instant; a.sec = 5i64; a.nsec = 100i64;
|
||||||
let b: time.instant; b.sec = 5i64; b.nsec = 200i64;
|
let b: time.instant; b.sec = 5i64; b.nsec = 200i64;
|
||||||
if (time.compare(a, b) != -1i8) { fail(); };
|
assert(!(time.compare(a, b) != -1i8));
|
||||||
if (time.compare(b, a) != 1i8) { fail(); };
|
assert(!(time.compare(b, a) != 1i8));
|
||||||
};
|
};
|
||||||
|
|
||||||
export fn main() i32 = {
|
export fn main() i32 = {
|
||||||
signalled = 1; constants();
|
constants();
|
||||||
signalled = 2; nowmonotonic();
|
nowmonotonic();
|
||||||
signalled = 3; nowrealtime();
|
nowrealtime();
|
||||||
signalled = 4; addzero();
|
addzero();
|
||||||
signalled = 5; addpos_nocarry();
|
addpos_nocarry();
|
||||||
signalled = 6; addpos_carry();
|
addpos_carry();
|
||||||
signalled = 7; addpos_fullsecond();
|
addpos_fullsecond();
|
||||||
signalled = 8; addneg_noborrow();
|
addneg_noborrow();
|
||||||
signalled = 9; addneg_borrow();
|
addneg_borrow();
|
||||||
signalled = 10; diffsimple();
|
diffsimple();
|
||||||
signalled = 11; diffneg();
|
diffneg();
|
||||||
signalled = 12; comparelt();
|
comparelt();
|
||||||
signalled = 13; comparegt();
|
comparegt();
|
||||||
signalled = 14; compareeq();
|
compareeq();
|
||||||
signalled = 15; comparensec_only();
|
comparensec_only();
|
||||||
return 0;
|
return 0;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -3,108 +3,105 @@
|
|||||||
// `ww run lib/ww/asttest.ww`.
|
// `ww run lib/ww/asttest.ww`.
|
||||||
//
|
//
|
||||||
// nkname is checked against every nkind value (the full ladder the
|
// nkname is checked against every nkind value (the full ladder the
|
||||||
// switch replaced) plus the out-of-band fallback ("?"). A non-zero
|
// switch replaced) plus the out-of-band fallback ("?"). A failing row
|
||||||
// exit pinpoints the failing row (signalled + 10), same convention as
|
// aborts via the assert/abort builtin (task #5 @test conversion).
|
||||||
// toktest. `package main` + bare `import ast` mirrors wwdump (the
|
// `package main` + bare `import ast` mirrors wwdump (the external
|
||||||
// external astprint consumer).
|
// astprint consumer).
|
||||||
|
|
||||||
package main;
|
package main;
|
||||||
|
|
||||||
import os;
|
|
||||||
import ast;
|
import ast;
|
||||||
|
|
||||||
let signalled: i32 = 0;
|
|
||||||
fn fail() void = { os.exit(signalled + 10); };
|
|
||||||
|
|
||||||
fn checkname(k: nkind, want: str) void = {
|
fn checkname(k: nkind, want: str) void = {
|
||||||
if (nkname(k) != want) { fail(); };
|
assert(!(nkname(k) != want));
|
||||||
};
|
};
|
||||||
|
|
||||||
// One row per nkind value — same string the if-ladder returned. The
|
// One row per nkind value — same string the if-ladder returned. The
|
||||||
// final row pins the unknown-kind fallback ("?").
|
// final row pins the unknown-kind fallback ("?").
|
||||||
@test fn nkname_cases() void = {
|
@test fn nkname_cases() void = {
|
||||||
signalled = 100; checkname(nkind.N_NONE, "none");
|
checkname(nkind.N_NONE, "none");
|
||||||
signalled = 101; checkname(nkind.N_INTLIT, "int");
|
checkname(nkind.N_INTLIT, "int");
|
||||||
signalled = 102; checkname(nkind.N_FLOATLIT, "float");
|
checkname(nkind.N_FLOATLIT, "float");
|
||||||
signalled = 103; checkname(nkind.N_STRLIT, "str");
|
checkname(nkind.N_STRLIT, "str");
|
||||||
signalled = 104; checkname(nkind.N_RUNELIT, "rune");
|
checkname(nkind.N_RUNELIT, "rune");
|
||||||
signalled = 105; checkname(nkind.N_TRUE, "true");
|
checkname(nkind.N_TRUE, "true");
|
||||||
signalled = 106; checkname(nkind.N_FALSE, "false");
|
checkname(nkind.N_FALSE, "false");
|
||||||
signalled = 107; checkname(nkind.N_NIL, "nil");
|
checkname(nkind.N_NIL, "nil");
|
||||||
signalled = 108; checkname(nkind.N_IDENT, "id");
|
checkname(nkind.N_IDENT, "id");
|
||||||
|
|
||||||
signalled = 109; checkname(nkind.N_BIN, "bin");
|
checkname(nkind.N_BIN, "bin");
|
||||||
signalled = 110; checkname(nkind.N_UN, "un");
|
checkname(nkind.N_UN, "un");
|
||||||
signalled = 111; checkname(nkind.N_CALL, "call");
|
checkname(nkind.N_CALL, "call");
|
||||||
signalled = 112; checkname(nkind.N_INDEX, "index");
|
checkname(nkind.N_INDEX, "index");
|
||||||
signalled = 113; checkname(nkind.N_DOT, "dot");
|
checkname(nkind.N_DOT, "dot");
|
||||||
signalled = 114; checkname(nkind.N_CAST, "cast");
|
checkname(nkind.N_CAST, "cast");
|
||||||
signalled = 115; checkname(nkind.N_STRUCTLIT, "structlit");
|
checkname(nkind.N_STRUCTLIT, "structlit");
|
||||||
signalled = 116; checkname(nkind.N_ARRLIT, "arrlit");
|
checkname(nkind.N_ARRLIT, "arrlit");
|
||||||
signalled = 117; checkname(nkind.N_FIELD, "field");
|
checkname(nkind.N_FIELD, "field");
|
||||||
signalled = 118; checkname(nkind.N_ASSIGN, "assign");
|
checkname(nkind.N_ASSIGN, "assign");
|
||||||
signalled = 119; checkname(nkind.N_ALLOC, "alloc");
|
checkname(nkind.N_ALLOC, "alloc");
|
||||||
signalled = 120; checkname(nkind.N_FREE, "free");
|
checkname(nkind.N_FREE, "free");
|
||||||
signalled = 121; checkname(nkind.N_RECV, "recv");
|
checkname(nkind.N_RECV, "recv");
|
||||||
signalled = 122; checkname(nkind.N_SLICE, "slice");
|
checkname(nkind.N_SLICE, "slice");
|
||||||
signalled = 123; checkname(nkind.N_SPREAD, "spread");
|
checkname(nkind.N_SPREAD, "spread");
|
||||||
|
|
||||||
signalled = 124; checkname(nkind.N_BLOCK, "block");
|
checkname(nkind.N_BLOCK, "block");
|
||||||
signalled = 125; checkname(nkind.N_EXPRSTMT, "exprstmt");
|
checkname(nkind.N_EXPRSTMT, "exprstmt");
|
||||||
signalled = 126; checkname(nkind.N_LET, "let");
|
checkname(nkind.N_LET, "let");
|
||||||
signalled = 127; checkname(nkind.N_RETURN, "return");
|
checkname(nkind.N_RETURN, "return");
|
||||||
signalled = 128; checkname(nkind.N_IF, "if");
|
checkname(nkind.N_IF, "if");
|
||||||
signalled = 129; checkname(nkind.N_FOR, "for");
|
checkname(nkind.N_FOR, "for");
|
||||||
signalled = 130; checkname(nkind.N_FORRANGE, "forrange");
|
checkname(nkind.N_FORRANGE, "forrange");
|
||||||
signalled = 131; checkname(nkind.N_DEFER, "defer");
|
checkname(nkind.N_DEFER, "defer");
|
||||||
signalled = 132; checkname(nkind.N_BREAK, "break");
|
checkname(nkind.N_BREAK, "break");
|
||||||
signalled = 133; checkname(nkind.N_CONTINUE, "continue");
|
checkname(nkind.N_CONTINUE, "continue");
|
||||||
signalled = 134; checkname(nkind.N_SWITCH, "switch");
|
checkname(nkind.N_SWITCH, "switch");
|
||||||
signalled = 135; checkname(nkind.N_CASE, "case");
|
checkname(nkind.N_CASE, "case");
|
||||||
|
|
||||||
signalled = 136; checkname(nkind.N_FILE, "file");
|
checkname(nkind.N_FILE, "file");
|
||||||
signalled = 137; checkname(nkind.N_USE, "use");
|
checkname(nkind.N_USE, "use");
|
||||||
signalled = 138; checkname(nkind.N_DEF, "def");
|
checkname(nkind.N_DEF, "def");
|
||||||
signalled = 139; checkname(nkind.N_TYPEDECL, "typedecl");
|
checkname(nkind.N_TYPEDECL, "typedecl");
|
||||||
signalled = 140; checkname(nkind.N_FNDECL, "fn");
|
checkname(nkind.N_FNDECL, "fn");
|
||||||
signalled = 141; checkname(nkind.N_PARAM, "param");
|
checkname(nkind.N_PARAM, "param");
|
||||||
|
|
||||||
signalled = 142; checkname(nkind.N_TNAME, "tname");
|
checkname(nkind.N_TNAME, "tname");
|
||||||
signalled = 143; checkname(nkind.N_TPTR, "tptr");
|
checkname(nkind.N_TPTR, "tptr");
|
||||||
signalled = 144; checkname(nkind.N_TSLICE, "tslice");
|
checkname(nkind.N_TSLICE, "tslice");
|
||||||
signalled = 145; checkname(nkind.N_TARRAY, "tarray");
|
checkname(nkind.N_TARRAY, "tarray");
|
||||||
signalled = 146; checkname(nkind.N_TFN, "tfn");
|
checkname(nkind.N_TFN, "tfn");
|
||||||
signalled = 147; checkname(nkind.N_TSTRUCT, "tstruct");
|
checkname(nkind.N_TSTRUCT, "tstruct");
|
||||||
signalled = 148; checkname(nkind.N_TFIELD, "tfield");
|
checkname(nkind.N_TFIELD, "tfield");
|
||||||
signalled = 149; checkname(nkind.N_TCHAN, "tchan");
|
checkname(nkind.N_TCHAN, "tchan");
|
||||||
|
|
||||||
signalled = 150; checkname(nkind.N_ATTR, "attr");
|
checkname(nkind.N_ATTR, "attr");
|
||||||
signalled = 151; checkname(nkind.N_TTUPLE, "ttuple");
|
checkname(nkind.N_TTUPLE, "ttuple");
|
||||||
signalled = 152; checkname(nkind.N_TTAGGED, "ttagged");
|
checkname(nkind.N_TTAGGED, "ttagged");
|
||||||
signalled = 153; checkname(nkind.N_TUPLE, "tuple");
|
checkname(nkind.N_TUPLE, "tuple");
|
||||||
signalled = 154; checkname(nkind.N_MATCH, "match");
|
checkname(nkind.N_MATCH, "match");
|
||||||
signalled = 155; checkname(nkind.N_MCASE, "mcase");
|
checkname(nkind.N_MCASE, "mcase");
|
||||||
signalled = 156; checkname(nkind.N_TRYPROP, "tryprop");
|
checkname(nkind.N_TRYPROP, "tryprop");
|
||||||
signalled = 157; checkname(nkind.N_TRYUNW, "tryunw");
|
checkname(nkind.N_TRYUNW, "tryunw");
|
||||||
signalled = 158; checkname(nkind.N_MLET, "mlet");
|
checkname(nkind.N_MLET, "mlet");
|
||||||
signalled = 159; checkname(nkind.N_MASSIGN, "massign");
|
checkname(nkind.N_MASSIGN, "massign");
|
||||||
|
|
||||||
signalled = 160; checkname(nkind.N_TYPETEST, "typetest");
|
checkname(nkind.N_TYPETEST, "typetest");
|
||||||
signalled = 161; checkname(nkind.N_TYPEASSERT, "typeassert");
|
checkname(nkind.N_TYPEASSERT, "typeassert");
|
||||||
signalled = 162; checkname(nkind.N_VOIDLIT, "voidlit");
|
checkname(nkind.N_VOIDLIT, "voidlit");
|
||||||
signalled = 163; checkname(nkind.N_TBANG, "tbang");
|
checkname(nkind.N_TBANG, "tbang");
|
||||||
signalled = 164; checkname(nkind.N_YIELD, "yield");
|
checkname(nkind.N_YIELD, "yield");
|
||||||
signalled = 165; checkname(nkind.N_TENUM, "tenum");
|
checkname(nkind.N_TENUM, "tenum");
|
||||||
signalled = 166; checkname(nkind.N_TENUMMEMBER, "tenummember");
|
checkname(nkind.N_TENUMMEMBER, "tenummember");
|
||||||
signalled = 167; checkname(nkind.N_TPARAM, "tparam");
|
checkname(nkind.N_TPARAM, "tparam");
|
||||||
signalled = 168; checkname(nkind.N_LAST, "last");
|
checkname(nkind.N_LAST, "last");
|
||||||
|
|
||||||
// Unknown kind → the post-switch fallback. N_LAST is the highest
|
// Unknown kind → the post-switch fallback. N_LAST is the highest
|
||||||
// named value (68); 69 is out of band, exercising the "?" tail.
|
// named value (68); 69 is out of band, exercising the "?" tail.
|
||||||
signalled = 169; checkname(69: nkind, "?");
|
checkname(69: nkind, "?");
|
||||||
};
|
};
|
||||||
|
|
||||||
export fn main() i32 = {
|
export fn main() i32 = {
|
||||||
signalled = 1; nkname_cases();
|
nkname_cases();
|
||||||
return 0;
|
return 0;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -13,9 +13,11 @@
|
|||||||
// \r, the c<0x20 and c==0x7f \xNN arms, and the printable tail) —
|
// \r, the c<0x20 and c==0x7f \xNN arms, and the printable tail) —
|
||||||
// branches the 990_selfhost corpus does not exercise (source tokens
|
// branches the 990_selfhost corpus does not exercise (source tokens
|
||||||
// hold raw `\`+`n`, never a literal control byte).
|
// hold raw `\`+`n`, never a literal control byte).
|
||||||
// A non-zero exit pinpoints the failing row (signalled + 10), same
|
// A failing row aborts via the assert/abort builtin (task #5 @test
|
||||||
// convention as asciitest. `package main` + bare `import tok/lex`
|
// conversion); per-row exit-code pinpoint is intentionally dropped (the
|
||||||
// mirrors wwdump (the only other external lex consumer).
|
// abort reports the file, not the row; drew-t2-conversion-spec sec.5).
|
||||||
|
// `package main` + bare `import tok/lex` mirrors wwdump (the only other
|
||||||
|
// external lex consumer).
|
||||||
|
|
||||||
package main;
|
package main;
|
||||||
|
|
||||||
@@ -23,129 +25,126 @@ import os;
|
|||||||
import tok;
|
import tok;
|
||||||
import lex;
|
import lex;
|
||||||
|
|
||||||
let signalled: i32 = 0;
|
|
||||||
fn fail() void = { os.exit(signalled + 10); };
|
|
||||||
|
|
||||||
fn checkname(k: tkind, want: str) void = {
|
fn checkname(k: tkind, want: str) void = {
|
||||||
if (tokname(k) != want) { fail(); };
|
assert(!(tokname(k) != want));
|
||||||
};
|
};
|
||||||
|
|
||||||
// One row per tkind value — same string the if-ladder returned. The
|
// One row per tkind value — same string the if-ladder returned. The
|
||||||
// final row pins the unknown-kind fallback ("<?>").
|
// final row pins the unknown-kind fallback ("<?>").
|
||||||
@test fn tokname_cases() void = {
|
@test fn tokname_cases() void = {
|
||||||
signalled = 100; checkname(tkind.TK_NONE, "<none>");
|
checkname(tkind.TK_NONE, "<none>");
|
||||||
signalled = 101; checkname(tkind.TK_EOF, "EOF");
|
checkname(tkind.TK_EOF, "EOF");
|
||||||
signalled = 102; checkname(tkind.TK_ERR, "ERR");
|
checkname(tkind.TK_ERR, "ERR");
|
||||||
signalled = 103; checkname(tkind.TK_IDENT, "IDENT");
|
checkname(tkind.TK_IDENT, "IDENT");
|
||||||
signalled = 104; checkname(tkind.TK_INT, "INT");
|
checkname(tkind.TK_INT, "INT");
|
||||||
signalled = 105; checkname(tkind.TK_FLOAT, "FLOAT");
|
checkname(tkind.TK_FLOAT, "FLOAT");
|
||||||
signalled = 106; checkname(tkind.TK_RUNE, "RUNE");
|
checkname(tkind.TK_RUNE, "RUNE");
|
||||||
signalled = 107; checkname(tkind.TK_STR, "STR");
|
checkname(tkind.TK_STR, "STR");
|
||||||
|
|
||||||
signalled = 108; checkname(tkind.TK_FN, "fn");
|
checkname(tkind.TK_FN, "fn");
|
||||||
signalled = 109; checkname(tkind.TK_LET, "let");
|
checkname(tkind.TK_LET, "let");
|
||||||
signalled = 110; checkname(tkind.TK_DEF, "def");
|
checkname(tkind.TK_DEF, "def");
|
||||||
signalled = 111; checkname(tkind.TK_IF, "if");
|
checkname(tkind.TK_IF, "if");
|
||||||
signalled = 112; checkname(tkind.TK_ELSE, "else");
|
checkname(tkind.TK_ELSE, "else");
|
||||||
signalled = 113; checkname(tkind.TK_FOR, "for");
|
checkname(tkind.TK_FOR, "for");
|
||||||
signalled = 114; checkname(tkind.TK_SWITCH, "switch");
|
checkname(tkind.TK_SWITCH, "switch");
|
||||||
signalled = 115; checkname(tkind.TK_CASE, "case");
|
checkname(tkind.TK_CASE, "case");
|
||||||
signalled = 116; checkname(tkind.TK_RETURN, "return");
|
checkname(tkind.TK_RETURN, "return");
|
||||||
signalled = 117; checkname(tkind.TK_USE, "import");
|
checkname(tkind.TK_USE, "import");
|
||||||
signalled = 118; checkname(tkind.TK_TYPE, "type");
|
checkname(tkind.TK_TYPE, "type");
|
||||||
signalled = 119; checkname(tkind.TK_STRUCT, "struct");
|
checkname(tkind.TK_STRUCT, "struct");
|
||||||
signalled = 120; checkname(tkind.TK_DEFER, "defer");
|
checkname(tkind.TK_DEFER, "defer");
|
||||||
signalled = 121; checkname(tkind.TK_BREAK, "break");
|
checkname(tkind.TK_BREAK, "break");
|
||||||
signalled = 122; checkname(tkind.TK_CONTINUE, "continue");
|
checkname(tkind.TK_CONTINUE, "continue");
|
||||||
signalled = 123; checkname(tkind.TK_EXPORT, "export");
|
checkname(tkind.TK_EXPORT, "export");
|
||||||
signalled = 124; checkname(tkind.TK_PROC, "proc");
|
checkname(tkind.TK_PROC, "proc");
|
||||||
signalled = 125; checkname(tkind.TK_CHAN, "chan");
|
checkname(tkind.TK_CHAN, "chan");
|
||||||
signalled = 126; checkname(tkind.TK_NIL, "nil");
|
checkname(tkind.TK_NIL, "nil");
|
||||||
signalled = 127; checkname(tkind.TK_TRUE, "true");
|
checkname(tkind.TK_TRUE, "true");
|
||||||
signalled = 128; checkname(tkind.TK_FALSE, "false");
|
checkname(tkind.TK_FALSE, "false");
|
||||||
signalled = 129; checkname(tkind.TK_AS, "as");
|
checkname(tkind.TK_AS, "as");
|
||||||
signalled = 130; checkname(tkind.TK_IS, "is");
|
checkname(tkind.TK_IS, "is");
|
||||||
signalled = 131; checkname(tkind.TK_VOID, "void");
|
checkname(tkind.TK_VOID, "void");
|
||||||
signalled = 132; checkname(tkind.TK_YIELD, "yield");
|
checkname(tkind.TK_YIELD, "yield");
|
||||||
signalled = 133; checkname(tkind.TK_STATIC, "static");
|
checkname(tkind.TK_STATIC, "static");
|
||||||
signalled = 134; checkname(tkind.TK_MATCH, "match");
|
checkname(tkind.TK_MATCH, "match");
|
||||||
signalled = 135; checkname(tkind.TK_CONST, "const");
|
checkname(tkind.TK_CONST, "const");
|
||||||
signalled = 136; checkname(tkind.TK_UNDER, "_");
|
checkname(tkind.TK_UNDER, "_");
|
||||||
signalled = 137; checkname(tkind.TK_ENUM, "enum");
|
checkname(tkind.TK_ENUM, "enum");
|
||||||
signalled = 138; checkname(tkind.TK_MODULE, "package");
|
checkname(tkind.TK_MODULE, "package");
|
||||||
|
|
||||||
signalled = 139; checkname(tkind.TK_LPAREN, "(");
|
checkname(tkind.TK_LPAREN, "(");
|
||||||
signalled = 140; checkname(tkind.TK_RPAREN, ")");
|
checkname(tkind.TK_RPAREN, ")");
|
||||||
signalled = 141; checkname(tkind.TK_LBRACE, "{");
|
checkname(tkind.TK_LBRACE, "{");
|
||||||
signalled = 142; checkname(tkind.TK_RBRACE, "}");
|
checkname(tkind.TK_RBRACE, "}");
|
||||||
signalled = 143; checkname(tkind.TK_LBRACK, "[");
|
checkname(tkind.TK_LBRACK, "[");
|
||||||
signalled = 144; checkname(tkind.TK_RBRACK, "]");
|
checkname(tkind.TK_RBRACK, "]");
|
||||||
signalled = 145; checkname(tkind.TK_COMMA, ",");
|
checkname(tkind.TK_COMMA, ",");
|
||||||
signalled = 146; checkname(tkind.TK_SEMI, ";");
|
checkname(tkind.TK_SEMI, ";");
|
||||||
signalled = 147; checkname(tkind.TK_COLON, ":");
|
checkname(tkind.TK_COLON, ":");
|
||||||
signalled = 148; checkname(tkind.TK_DOT, ".");
|
checkname(tkind.TK_DOT, ".");
|
||||||
signalled = 149; checkname(tkind.TK_ELLIPSIS, "...");
|
checkname(tkind.TK_ELLIPSIS, "...");
|
||||||
signalled = 150; checkname(tkind.TK_DOTDOT, "..");
|
checkname(tkind.TK_DOTDOT, "..");
|
||||||
signalled = 151; checkname(tkind.TK_AT, "@");
|
checkname(tkind.TK_AT, "@");
|
||||||
signalled = 152; checkname(tkind.TK_QUESTION, "?");
|
checkname(tkind.TK_QUESTION, "?");
|
||||||
|
|
||||||
signalled = 153; checkname(tkind.TK_ASSIGN, "=");
|
checkname(tkind.TK_ASSIGN, "=");
|
||||||
signalled = 154; checkname(tkind.TK_PLUSEQ, "+=");
|
checkname(tkind.TK_PLUSEQ, "+=");
|
||||||
signalled = 155; checkname(tkind.TK_MINUSEQ, "-=");
|
checkname(tkind.TK_MINUSEQ, "-=");
|
||||||
signalled = 156; checkname(tkind.TK_STAREQ, "*=");
|
checkname(tkind.TK_STAREQ, "*=");
|
||||||
signalled = 157; checkname(tkind.TK_SLASHEQ, "/=");
|
checkname(tkind.TK_SLASHEQ, "/=");
|
||||||
signalled = 158; checkname(tkind.TK_PERCENTEQ, "%=");
|
checkname(tkind.TK_PERCENTEQ, "%=");
|
||||||
signalled = 159; checkname(tkind.TK_AMPEQ, "&=");
|
checkname(tkind.TK_AMPEQ, "&=");
|
||||||
signalled = 160; checkname(tkind.TK_PIPEEQ, "|=");
|
checkname(tkind.TK_PIPEEQ, "|=");
|
||||||
signalled = 161; checkname(tkind.TK_CARETEQ, "^=");
|
checkname(tkind.TK_CARETEQ, "^=");
|
||||||
signalled = 162; checkname(tkind.TK_LSHIFTEQ, "<<=");
|
checkname(tkind.TK_LSHIFTEQ, "<<=");
|
||||||
signalled = 163; checkname(tkind.TK_RSHIFTEQ, ">>=");
|
checkname(tkind.TK_RSHIFTEQ, ">>=");
|
||||||
|
|
||||||
signalled = 164; checkname(tkind.TK_PLUS, "+");
|
checkname(tkind.TK_PLUS, "+");
|
||||||
signalled = 165; checkname(tkind.TK_MINUS, "-");
|
checkname(tkind.TK_MINUS, "-");
|
||||||
signalled = 166; checkname(tkind.TK_STAR, "*");
|
checkname(tkind.TK_STAR, "*");
|
||||||
signalled = 167; checkname(tkind.TK_SLASH, "/");
|
checkname(tkind.TK_SLASH, "/");
|
||||||
signalled = 168; checkname(tkind.TK_PERCENT, "%");
|
checkname(tkind.TK_PERCENT, "%");
|
||||||
signalled = 169; checkname(tkind.TK_AMP, "&");
|
checkname(tkind.TK_AMP, "&");
|
||||||
signalled = 170; checkname(tkind.TK_PIPE, "|");
|
checkname(tkind.TK_PIPE, "|");
|
||||||
signalled = 171; checkname(tkind.TK_CARET, "^");
|
checkname(tkind.TK_CARET, "^");
|
||||||
signalled = 172; checkname(tkind.TK_TILDE, "~");
|
checkname(tkind.TK_TILDE, "~");
|
||||||
signalled = 173; checkname(tkind.TK_LSHIFT, "<<");
|
checkname(tkind.TK_LSHIFT, "<<");
|
||||||
signalled = 174; checkname(tkind.TK_RSHIFT, ">>");
|
checkname(tkind.TK_RSHIFT, ">>");
|
||||||
|
|
||||||
signalled = 175; checkname(tkind.TK_EQ, "==");
|
checkname(tkind.TK_EQ, "==");
|
||||||
signalled = 176; checkname(tkind.TK_NEQ, "!=");
|
checkname(tkind.TK_NEQ, "!=");
|
||||||
signalled = 177; checkname(tkind.TK_LT, "<");
|
checkname(tkind.TK_LT, "<");
|
||||||
signalled = 178; checkname(tkind.TK_LE, "<=");
|
checkname(tkind.TK_LE, "<=");
|
||||||
signalled = 179; checkname(tkind.TK_GT, ">");
|
checkname(tkind.TK_GT, ">");
|
||||||
signalled = 180; checkname(tkind.TK_GE, ">=");
|
checkname(tkind.TK_GE, ">=");
|
||||||
|
|
||||||
signalled = 181; checkname(tkind.TK_AND, "&&");
|
checkname(tkind.TK_AND, "&&");
|
||||||
signalled = 182; checkname(tkind.TK_OR, "||");
|
checkname(tkind.TK_OR, "||");
|
||||||
signalled = 183; checkname(tkind.TK_NOT, "!");
|
checkname(tkind.TK_NOT, "!");
|
||||||
|
|
||||||
signalled = 184; checkname(tkind.TK_LARROW, "<-");
|
checkname(tkind.TK_LARROW, "<-");
|
||||||
signalled = 185; checkname(tkind.TK_ARROW, "->");
|
checkname(tkind.TK_ARROW, "->");
|
||||||
signalled = 186; checkname(tkind.TK_FATARROW, "=>");
|
checkname(tkind.TK_FATARROW, "=>");
|
||||||
|
|
||||||
signalled = 187; checkname(tkind.TK_MODRESET, "//ww:module-reset");
|
checkname(tkind.TK_MODRESET, "//ww:module-reset");
|
||||||
signalled = 188; checkname(tkind.TK_LAST, "<last>");
|
checkname(tkind.TK_LAST, "<last>");
|
||||||
|
|
||||||
// Unknown kind → the post-switch fallback. TK_LAST is the highest
|
// Unknown kind → the post-switch fallback. TK_LAST is the highest
|
||||||
// named value (88); 89 is out of band, exercising the "<?>" tail.
|
// named value (88); 89 is out of band, exercising the "<?>" tail.
|
||||||
signalled = 189; checkname(89: tkind, "<?>");
|
checkname(89: tkind, "<?>");
|
||||||
};
|
};
|
||||||
|
|
||||||
fn checkkw(s: str, want: tkind) void = {
|
fn checkkw(s: str, want: tkind) void = {
|
||||||
if (kwlookup(s.ptr, s.len) != want) { fail(); };
|
assert(!(kwlookup(s.ptr, s.len) != want));
|
||||||
};
|
};
|
||||||
|
|
||||||
// Table-driven (parallel-array idiom; tuple rows blocked by #111). The
|
// Table-driven (parallel-array idiom; tuple rows blocked by #111). The
|
||||||
// kw rows pin all 30 keywords kwlookup recognises, 1:1 with the
|
// kw rows pin all 30 keywords kwlookup recognises, 1:1 with the
|
||||||
// kwnames/kwkinds table (and cmd/wcc/tok.c:18-47), incl. the two remaps
|
// kwnames/kwkinds table (and cmd/wcc/tok.c:18-47), incl. the two remaps
|
||||||
// import->TK_USE and package->TK_MODULE. The nk rows pin the
|
// import->TK_USE and package->TK_MODULE. The nk rows pin the
|
||||||
// fall-through to TK_NONE. signalled = base + row keeps a failure
|
// fall-through to TK_NONE. Explicit dims, NOT [_]: [_] static-init silently
|
||||||
// pinpointable. Explicit dims, NOT [_]: [_] static-init silently
|
|
||||||
// miscompiles to a zero-length array in-tree (probe, cc69daf), which
|
// miscompiles to a zero-length array in-tree (probe, cc69daf), which
|
||||||
// would void the loop body — the very hole a table test must not have.
|
// would void the loop body — the very hole a table test must not have.
|
||||||
@test fn kwlookup_cases() void = {
|
@test fn kwlookup_cases() void = {
|
||||||
@@ -167,7 +166,6 @@ fn checkkw(s: str, want: tkind) void = {
|
|||||||
];
|
];
|
||||||
let i: i32 = 0;
|
let i: i32 = 0;
|
||||||
for (i < len(kwin)) {
|
for (i < len(kwin)) {
|
||||||
signalled = 200 + i;
|
|
||||||
checkkw(kwin[i], kwexp[i]);
|
checkkw(kwin[i], kwexp[i]);
|
||||||
i += 1;
|
i += 1;
|
||||||
};
|
};
|
||||||
@@ -200,7 +198,6 @@ fn checkkw(s: str, want: tkind) void = {
|
|||||||
];
|
];
|
||||||
let j: i32 = 0;
|
let j: i32 = 0;
|
||||||
for (j < len(nk)) {
|
for (j < len(nk)) {
|
||||||
signalled = 230 + j;
|
|
||||||
checkkw(nk[j], tkind.TK_NONE);
|
checkkw(nk[j], tkind.TK_NONE);
|
||||||
j += 1;
|
j += 1;
|
||||||
};
|
};
|
||||||
@@ -211,17 +208,17 @@ fn checkkw(s: str, want: tkind) void = {
|
|||||||
// before each write so earlier (possibly longer) content past want.len
|
// before each write so earlier (possibly longer) content past want.len
|
||||||
// is irrelevant — only want.len bytes from offset 0 are compared.
|
// is irrelevant — only want.len bytes from offset 0 are compared.
|
||||||
fn checkprint(fd: i32, t: *tok, want: str) void = {
|
fn checkprint(fd: i32, t: *tok, want: str) void = {
|
||||||
if (os.lseek(fd, 0i64, os.whence.SET) != 0i64) { fail(); };
|
assert(!(os.lseek(fd, 0i64, os.whence.SET) != 0i64));
|
||||||
tokprint(fd, t);
|
tokprint(fd, t);
|
||||||
if (os.lseek(fd, 0i64, os.whence.SET) != 0i64) { fail(); };
|
assert(!(os.lseek(fd, 0i64, os.whence.SET) != 0i64));
|
||||||
let rbuf: [256]u8;
|
let rbuf: [256]u8;
|
||||||
let z: i32 = 0;
|
let z: i32 = 0;
|
||||||
for (z < 256) { rbuf[z] = 0u8; z += 1; };
|
for (z < 256) { rbuf[z] = 0u8; z += 1; };
|
||||||
let rd: i64 = os.read(fd, &rbuf[0], want.len: u64);
|
let rd: i64 = os.read(fd, &rbuf[0], want.len: u64);
|
||||||
if (rd != want.len: i64) { fail(); };
|
assert(!(rd != want.len: i64));
|
||||||
let j: i32 = 0;
|
let j: i32 = 0;
|
||||||
for (j < want.len) {
|
for (j < want.len) {
|
||||||
if (rbuf[j] != want.ptr[j]) { fail(); };
|
assert(!(rbuf[j] != want.ptr[j]));
|
||||||
j += 1;
|
j += 1;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
@@ -232,45 +229,39 @@ fn checkprint(fd: i32, t: *tok, want: str) void = {
|
|||||||
@test fn tokprint_cases() void = {
|
@test fn tokprint_cases() void = {
|
||||||
let flags: os.flag = os.flag.RDWR | os.flag.CREATE | os.flag.TRUNC;
|
let flags: os.flag = os.flag.RDWR | os.flag.CREATE | os.flag.TRUNC;
|
||||||
let fd: i32 = os.open("/tmp/ww_s9_tok.tmp", flags, 384i32);
|
let fd: i32 = os.open("/tmp/ww_s9_tok.tmp", flags, 384i32);
|
||||||
if (fd < 0) { fail(); };
|
assert(!(fd < 0));
|
||||||
|
|
||||||
let t: tok;
|
let t: tok;
|
||||||
t.file = "t";
|
t.file = "t";
|
||||||
t.line = 1;
|
t.line = 1;
|
||||||
t.col = 1;
|
t.col = 1;
|
||||||
|
|
||||||
signalled = 300;
|
|
||||||
t.kind = tkind.TK_STR;
|
t.kind = tkind.TK_STR;
|
||||||
t.text = "\\\"\n\t\r\x01\x7fA";
|
t.text = "\\\"\n\t\r\x01\x7fA";
|
||||||
checkprint(fd, &t, "t:1:1 STR \"\\\\\\\"\\n\\t\\r\\x01\\x7fA\"\n");
|
checkprint(fd, &t, "t:1:1 STR \"\\\\\\\"\\n\\t\\r\\x01\\x7fA\"\n");
|
||||||
|
|
||||||
signalled = 301;
|
|
||||||
t.kind = tkind.TK_IDENT;
|
t.kind = tkind.TK_IDENT;
|
||||||
t.text = "name";
|
t.text = "name";
|
||||||
checkprint(fd, &t, "t:1:1 IDENT \"name\"\n");
|
checkprint(fd, &t, "t:1:1 IDENT \"name\"\n");
|
||||||
|
|
||||||
signalled = 302;
|
|
||||||
t.kind = tkind.TK_ERR;
|
t.kind = tkind.TK_ERR;
|
||||||
t.text = "oops";
|
t.text = "oops";
|
||||||
checkprint(fd, &t, "t:1:1 ERR \"oops\"\n");
|
checkprint(fd, &t, "t:1:1 ERR \"oops\"\n");
|
||||||
|
|
||||||
signalled = 303;
|
|
||||||
t.kind = tkind.TK_INT;
|
t.kind = tkind.TK_INT;
|
||||||
t.uval = 42u64;
|
t.uval = 42u64;
|
||||||
checkprint(fd, &t, "t:1:1 INT 42\n");
|
checkprint(fd, &t, "t:1:1 INT 42\n");
|
||||||
|
|
||||||
signalled = 304;
|
|
||||||
t.kind = tkind.TK_RUNE;
|
t.kind = tkind.TK_RUNE;
|
||||||
t.uval = 65u64;
|
t.uval = 65u64;
|
||||||
checkprint(fd, &t, "t:1:1 RUNE 65\n");
|
checkprint(fd, &t, "t:1:1 RUNE 65\n");
|
||||||
|
|
||||||
// Default arm: a kind outside the switch appends no value.
|
// Default arm: a kind outside the switch appends no value.
|
||||||
signalled = 305;
|
|
||||||
t.kind = tkind.TK_NONE;
|
t.kind = tkind.TK_NONE;
|
||||||
checkprint(fd, &t, "t:1:1 <none>\n");
|
checkprint(fd, &t, "t:1:1 <none>\n");
|
||||||
|
|
||||||
if (os.close(fd) != 0) { fail(); };
|
assert(!(os.close(fd) != 0));
|
||||||
if (os.remove("/tmp/ww_s9_tok.tmp") != 0) { fail(); };
|
assert(!(os.remove("/tmp/ww_s9_tok.tmp") != 0));
|
||||||
};
|
};
|
||||||
|
|
||||||
fn checkfloat(src: str, want: u64) void = {
|
fn checkfloat(src: str, want: u64) void = {
|
||||||
@@ -278,8 +269,8 @@ fn checkfloat(src: str, want: u64) void = {
|
|||||||
lexinit(&l, "t", src.ptr, src.len: u64);
|
lexinit(&l, "t", src.ptr, src.len: u64);
|
||||||
let t: tok;
|
let t: tok;
|
||||||
lexnext(&l, &t);
|
lexnext(&l, &t);
|
||||||
if (t.kind != tkind.TK_FLOAT) { fail(); };
|
assert(!(t.kind != tkind.TK_FLOAT));
|
||||||
if (t.uval != want) { fail(); };
|
assert(!(t.uval != want));
|
||||||
};
|
};
|
||||||
|
|
||||||
// #62 pin: lexnum's float fold routes through strconv.stof64 and must
|
// #62 pin: lexnum's float fold routes through strconv.stof64 and must
|
||||||
@@ -293,42 +284,34 @@ fn checkfloat(src: str, want: u64) void = {
|
|||||||
// boundary (tie rounds to even, tie+1 rounds up — also the only
|
// boundary (tie rounds to even, tie+1 rounds up — also the only
|
||||||
// >19-digit FRACTION rows), and an exact power of two.
|
// >19-digit FRACTION rows), and an exact power of two.
|
||||||
@test fn floatfold_cases() void = {
|
@test fn floatfold_cases() void = {
|
||||||
signalled = 400; checkfloat("1.0000000000000002", 0x3FF0000000000001u64);
|
checkfloat("1.0000000000000002", 0x3FF0000000000001u64);
|
||||||
signalled = 401; checkfloat("9007199254740993.0", 0x4340000000000000u64);
|
checkfloat("9007199254740993.0", 0x4340000000000000u64);
|
||||||
signalled = 402; checkfloat("1.2345e67", 0x4DDD4E421712C0B7u64);
|
checkfloat("1.2345e67", 0x4DDD4E421712C0B7u64);
|
||||||
signalled = 403; checkfloat("0.1", 0x3FB999999999999Au64);
|
checkfloat("0.1", 0x3FB999999999999Au64);
|
||||||
signalled = 404; checkfloat("1.1", 0x3FF199999999999Au64);
|
checkfloat("1.1", 0x3FF199999999999Au64);
|
||||||
signalled = 405;
|
|
||||||
checkfloat("123456789012345678901234567890.0", 0x45F8EE90FF6C373Eu64);
|
checkfloat("123456789012345678901234567890.0", 0x45F8EE90FF6C373Eu64);
|
||||||
signalled = 406;
|
|
||||||
checkfloat("2.2250738585072014e-308", 0x0010000000000000u64);
|
checkfloat("2.2250738585072014e-308", 0x0010000000000000u64);
|
||||||
signalled = 407; checkfloat("0.3", 0x3FD3333333333333u64);
|
checkfloat("0.3", 0x3FD3333333333333u64);
|
||||||
signalled = 408; checkfloat("3.141592653589793", 0x400921FB54442D18u64);
|
checkfloat("3.141592653589793", 0x400921FB54442D18u64);
|
||||||
signalled = 409;
|
|
||||||
checkfloat("1.7976931348623157e308", 0x7FEFFFFFFFFFFFFFu64);
|
checkfloat("1.7976931348623157e308", 0x7FEFFFFFFFFFFFFFu64);
|
||||||
signalled = 410;
|
|
||||||
checkfloat("1.7976931348623158e308", 0x7FEFFFFFFFFFFFFFu64);
|
checkfloat("1.7976931348623158e308", 0x7FEFFFFFFFFFFFFFu64);
|
||||||
signalled = 411; checkfloat("7.2057594037927933e16", 0x4370000000000000u64);
|
checkfloat("7.2057594037927933e16", 0x4370000000000000u64);
|
||||||
signalled = 412;
|
|
||||||
checkfloat("1000000000000000000000.0", 0x444B1AE4D6E2EF50u64);
|
checkfloat("1000000000000000000000.0", 0x444B1AE4D6E2EF50u64);
|
||||||
signalled = 413; checkfloat("1_000.5", 0x408F440000000000u64);
|
checkfloat("1_000.5", 0x408F440000000000u64);
|
||||||
signalled = 414;
|
|
||||||
checkfloat("1.00000000000000011102230246251565404236316680908203125",
|
checkfloat("1.00000000000000011102230246251565404236316680908203125",
|
||||||
0x3FF0000000000000u64);
|
0x3FF0000000000000u64);
|
||||||
signalled = 415;
|
|
||||||
checkfloat("1.00000000000000011102230246251565404236316680908203126",
|
checkfloat("1.00000000000000011102230246251565404236316680908203126",
|
||||||
0x3FF0000000000001u64);
|
0x3FF0000000000001u64);
|
||||||
signalled = 416; checkfloat("4503599627370497.5", 0x4330000000000002u64);
|
checkfloat("4503599627370497.5", 0x4330000000000002u64);
|
||||||
signalled = 417; checkfloat("0.5", 0x3FE0000000000000u64);
|
checkfloat("0.5", 0x3FE0000000000000u64);
|
||||||
signalled = 418; checkfloat("1.0e308", 0x7FE1CCF385EBC8A0u64);
|
checkfloat("1.0e308", 0x7FE1CCF385EBC8A0u64);
|
||||||
signalled = 419;
|
|
||||||
checkfloat("2.225073858507202e-308", 0x0010000000000001u64);
|
checkfloat("2.225073858507202e-308", 0x0010000000000001u64);
|
||||||
};
|
};
|
||||||
|
|
||||||
export fn main() i32 = {
|
export fn main() i32 = {
|
||||||
signalled = 1; tokname_cases();
|
tokname_cases();
|
||||||
signalled = 2; kwlookup_cases();
|
kwlookup_cases();
|
||||||
signalled = 3; tokprint_cases();
|
tokprint_cases();
|
||||||
signalled = 4; floatfold_cases();
|
floatfold_cases();
|
||||||
return 0;
|
return 0;
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user