177 lines
6.5 KiB
Plaintext
177 lines
6.5 KiB
Plaintext
package wwdump_test;
|
|
|
|
// wwdump_ww observer gates. Ports of the retired native carriers
|
|
// test/wcc/901_asserttyped_gap.c and 989_wwdumpgate_run.c; every
|
|
// assertion preserved. WWSTAGE-ONLY by construction: the cstage
|
|
// wwdump implements only -t/-a, and the asserttyped pass lives in
|
|
// wwstage check.ww — there is no cstage twin for either claim
|
|
// (wwstage-warn-audit rule: drive the wwstage checker with *_ww
|
|
// binaries, never cstage tools).
|
|
//
|
|
// asserttyped (#15 / A.6.2.1e) — the wwstage checker's post-checker
|
|
// nil-type invariant gate is UNOBSERVED by every other suite (the
|
|
// ordinary suites drive cstage check.c; only -t/-a run elsewhere).
|
|
// Run `wwdump_ww -c` over the gap-bearing manifest and pin the count
|
|
// of line-leading "asserttyped:" stderr diagnostics per fixture; the
|
|
// manifest is the all-closed floor (every class A-G at zero), so any
|
|
// fresh nil-gap or regressed class fails loud and names its fixture.
|
|
// wwdump_ww's exit code is deliberately NOT gated: the diagnostics
|
|
// land on stderr regardless, and the armed bail flips the exit code —
|
|
// the line count is the one signal stable across the fold sequence.
|
|
// #90 sep-feed: `ww build -S` resolves import-bearing fixtures to an
|
|
// owner unit and direct exports; this raw wwdump-only gate explicitly
|
|
// composes those artifacts because wwdump has no package-input CLI. The
|
|
// import-free test/wcc/901_*.ww companions stay raw-fed.
|
|
//
|
|
// wwdumpgate (#52, F15 c4) — the -c and -r arms gate on parse-stage
|
|
// errors instead of silently emitting over a broken AST: parse-errored
|
|
// input under -c exits nonzero with exactly 0 stdout bytes (pre-fix:
|
|
// rc=0 with truncated asm — and -c IS the 994 byte-identity probe
|
|
// arm); -r likewise exits nonzero; the valid-file -c control exits 0
|
|
// with asm on stdout. The C carrier's wwdump_ww-missing wiring check
|
|
// is carried by the Make prerequisite plus runcommand's launch
|
|
// assert.
|
|
|
|
import os;
|
|
import os.exec;
|
|
import strings;
|
|
import testenv;
|
|
import time;
|
|
|
|
fn fail(label: str, why: str) void = {
|
|
let m: str = strings.concat("wwdump FAIL: ", label, " -- ", why,
|
|
"\n");
|
|
os.write(2, m.ptr, m.len: u64);
|
|
assert(false);
|
|
};
|
|
|
|
fn tmo() time.duration = {
|
|
return (180i64 * (time.second: i64)): time.duration;
|
|
};
|
|
|
|
// Line-leading occurrences; the '\n' prepend counts a stream-leading
|
|
// diagnostic too.
|
|
fn countdiag(stderr: str) i32 = {
|
|
return testenv.occurrences(strings.concat("\n", stderr),
|
|
"\nasserttyped:");
|
|
};
|
|
|
|
// Gap classes A-G (residual-carrier-audit.json 901 entry); want is
|
|
// the all-closed floor. sep rows compose the resolved unit first.
|
|
@test fn asserttyped() void = {
|
|
let rels: []str = [
|
|
"lib/math/checked/checked_test.ww",
|
|
"test/wcc/data/selfhost_smoke/case.ww",
|
|
"lib/encoding/utf8/utf8.ww",
|
|
"lib/fnmatch/fnmatch_test.ww",
|
|
"lib/math/random/random_test.ww",
|
|
"test/wcc/901_enum_corpus.ww",
|
|
"test/wcc/901_forrange_tuple.ww",
|
|
"test/wcc/901_massign_blank.ww"];
|
|
let classes: []str = [
|
|
"A module-qual N_DOT call result",
|
|
"B fn-ptr struct-field call",
|
|
"C abort intrinsic callee",
|
|
"D module-leaf == type/fn name",
|
|
"D module-leaf == type/fn name",
|
|
"E computed enum-member value-expr",
|
|
"F for-range tuple-destructure bind",
|
|
"G tuple multi-assign discard `_`"];
|
|
let seps: []bool = [true, true, true, true, true, false, false,
|
|
false];
|
|
let wants: []i32 = [0, 0, 0, 0, 0, 0, 0, 0];
|
|
let i: i32 = 0;
|
|
for (i < rels.len) {
|
|
let td: str = testenv.fresh();
|
|
let src: str = strings.concat(testenv.repo(), "/", rels[i]);
|
|
if (seps[i]) {
|
|
let stem: str = strings.concat(td, "/unit");
|
|
let bo: testenv.commandout;
|
|
let bav: []str = [testenv.driver("ww"), "build", "-S", "-o",
|
|
stem, src];
|
|
testenv.runcommand(td, td, "resolve", bav, tmo(), &bo);
|
|
if (bo.termination != exec.termination.EXIT || bo.code != 0) {
|
|
fail(classes[i], strings.concat(rels[i],
|
|
": no resolved sep unit (ww build -S failed)"));
|
|
};
|
|
let work: str = strings.concat(stem, ".sepwork/");
|
|
let owner: str = strings.concat(work, "__root.unit.ww");
|
|
if (!testenv.exists(owner)) {
|
|
fail(classes[i], strings.concat(rels[i],
|
|
": __root.unit.ww missing after ww build -S"));
|
|
};
|
|
let deps: []str = [];
|
|
if (i == 0) { append(deps, "math.checked"); append(deps, "types"); };
|
|
if (i == 1) {
|
|
append(deps, "ascii"); append(deps, "os"); append(deps, "strconv");
|
|
};
|
|
if (i == 3) { append(deps, "fnmatch"); };
|
|
if (i == 4) { append(deps, "math.random"); append(deps, "test"); };
|
|
let composed: str = "";
|
|
let di: i32 = 0;
|
|
for (di < deps.len) {
|
|
composed = strings.concat(composed, "//ww:module ", deps[di],
|
|
"\n", testenv.readfile(strings.concat(work, deps[di],
|
|
".wwi")), "\n");
|
|
di += 1;
|
|
};
|
|
composed = strings.concat(composed, testenv.readfile(owner));
|
|
src = strings.concat(td, "/wwdump.raw.ww");
|
|
testenv.writefile(src, composed);
|
|
};
|
|
let co: testenv.commandout;
|
|
let av: []str = [testenv.driver("wwdump_ww"), "-c", src];
|
|
testenv.runcommand(td, td, "check", av, tmo(), &co);
|
|
assert(co.termination == exec.termination.EXIT);
|
|
let got: i32 = countdiag(co.stderr);
|
|
if (got != wants[i]) {
|
|
// surface the drifted diagnostics before the abort
|
|
os.write(2, co.stderr.ptr, co.stderr.len: u64);
|
|
fail(classes[i], strings.concat(rels[i],
|
|
": asserttyped count drifted from the manifest"));
|
|
};
|
|
testenv.clean(td);
|
|
i += 1;
|
|
};
|
|
};
|
|
|
|
fn dumprow(td: str, name: str, mode: str, src: str,
|
|
out: *testenv.commandout) void = {
|
|
let av: []str = [testenv.driver("wwdump_ww"), mode, src];
|
|
testenv.runcommand(td, td, name, av, tmo(), out);
|
|
assert(out.termination == exec.termination.EXIT);
|
|
};
|
|
|
|
@test fn wwdumpgate() void = {
|
|
let td: str = testenv.fresh();
|
|
let badp: str = strings.concat(td, "/bad.ww");
|
|
testenv.writefile(badp, strings.concat(
|
|
"package main;\n\n",
|
|
"export fn main(argc: i32, argv: **u8) i32 = {\n",
|
|
"\treturn 0;\n};\n\n",
|
|
"fn broken( {\n"));
|
|
let okp: str = strings.concat(td, "/ok.ww");
|
|
testenv.writefile(okp,
|
|
"package main;\nexport fn main() i32 = { return 0; };\n");
|
|
|
|
let co: testenv.commandout;
|
|
dumprow(td, "bad_a", "-a", badp, &co);
|
|
if (co.code == 0) {
|
|
fail("bad_a", "AST dump returned rc=0 on parse-errored input");
|
|
};
|
|
dumprow(td, "bad_c", "-c", badp, &co);
|
|
if (co.code == 0 || co.stdout.len != 0) {
|
|
fail("bad_c",
|
|
"asm emitted or rc=0 on parse-errored input (#52)");
|
|
};
|
|
dumprow(td, "bad_r", "-r", badp, &co);
|
|
if (co.code == 0) {
|
|
fail("bad_r", "resolve report with rc=0 on parse-errored input");
|
|
};
|
|
dumprow(td, "ok_c", "-c", okp, &co);
|
|
if (co.code != 0 || co.stdout.len == 0) {
|
|
fail("ok_c", "healthy file rejected or produced no asm");
|
|
};
|
|
testenv.clean(td);
|
|
};
|