test/wcc: 989_septest run-exit rows — userman/badsig reject, collide_run coexist (M4 E2-C2a, #22)
Extends the ww test --sep run-exit gate with 3 rows on both stages: userman and badsig REJECT (exit!=0; explicit main under -T, bad @test signature), collide_run ACCEPT exit==0 (user fn run + lib test.run coexist post #80/#84). Reuses the 910/997 fixtures unchanged (SSoT; they outlive the .c gates the E3 flip retires). Under sep a regressed run/test.run collision is a hard w6l duplicate-symbol link error so exit==0 is non-vacuous; collide_run also pins cs==ww byte-id (1 TEXT main, 1 CALL test.run) for the rule-10 stage-symmetry the combined coexist_run carried. Test-only; all 5 binary pins hold.
This commit is contained in:
@@ -15,6 +15,13 @@
|
||||
* fails. The failing row is the non-vacuity teeth: it proves the @tests
|
||||
* genuinely RUN under sep (a no-op --sep that linked an empty main would
|
||||
* exit 0 on the failing fixture and the gate would catch it).
|
||||
* This same RUN-EXIT path also hosts the @test user-facing reject +
|
||||
* coexist legs ported from 910/997 (C2a, #83), which die at the M4 flip
|
||||
* that deletes 910/997: `userman` (explicit user main collides with the
|
||||
* -T synth entry) and `badsig` (non-`fn() void` @test) must reject
|
||||
* (exit != 0) on both stages; `collide_run` (user `fn run` coexists with
|
||||
* lib/test's bound runner) must accept and run to exit 0 — under sep the
|
||||
* two land in distinct units, so a regressed collision fails the link.
|
||||
* 2. cs==ww (rule 10): the cstage `ww` and wwstage `ww_ww` sep-drivers emit
|
||||
* byte-identical per-package .s/.wwi for the passing fixture — including
|
||||
* __root.s, which carries the synth `CALL test.run`.
|
||||
@@ -153,8 +160,10 @@ cmp_sepwork(const char *csdir, const char *wwdir, const char *label)
|
||||
struct tcase {
|
||||
const char *label;
|
||||
const char *src; /* inline fixture written to <td>/<label>.ww */
|
||||
int expect; /* expected `ww test --sep` run-exit */
|
||||
const char *path; /* when set, use this on-disk fixture instead of src */
|
||||
int expect; /* expected `ww test --sep` run-exit (when !reject) */
|
||||
int byteid; /* run the cs==ww + synth-presence checks */
|
||||
int reject; /* @test user-facing reject: assert run-exit != 0 */
|
||||
};
|
||||
|
||||
static struct tcase cases[] = {
|
||||
@@ -168,15 +177,35 @@ static struct tcase cases[] = {
|
||||
"@test fn t_again() void = {\n"
|
||||
" let s: str = \"ok\";\n"
|
||||
" if (len(s) != 2) { abort(); };\n"
|
||||
"};\n", 0, 1 },
|
||||
"};\n", NULL, 0, 1, 0 },
|
||||
/* a failing @test → run-exit 1: proves the tests actually RUN under
|
||||
* sep (the non-vacuity teeth). */
|
||||
{ "fail",
|
||||
"package septest;\n"
|
||||
"@test fn t_bad() void = {\n"
|
||||
" if (1 + 1 == 2) { abort(); };\n"
|
||||
"};\n", 1, 0 },
|
||||
{ NULL, NULL, 0, 0 },
|
||||
"};\n", NULL, 1, 0, 0 },
|
||||
/* C2a (#83): the @test user-facing reject + coexist paths, re-hosted
|
||||
* from 910/997 (deleted at the M4 flip) onto the live `ww test --sep`
|
||||
* gate. Fixtures are the unchanged 910/997 flat @test fixtures, reused
|
||||
* in place (single source of truth) — they survive the flip; only the
|
||||
* .c gates move. */
|
||||
|
||||
/* an explicit user `main` collides with the -T synth entry → reject. */
|
||||
{ "userman", NULL, "test/wcc/data/attest_userman.ww", 0, 0, 1 },
|
||||
/* a non-`fn() void` @test signature must loud-reject, not be coerced. */
|
||||
{ "badsig", NULL, "test/wcc/data/attest_badsig.ww", 0, 0, 1 },
|
||||
/* a user `fn run` COEXISTS with lib/test's bound runner (post-#80 synth
|
||||
* `use test;` keys the runner under "test", #84 mangles the user `run`
|
||||
* bare) → accept and run to exit 0. Under sep the two land in distinct
|
||||
* units (`run` in __root.s, `test.run` in test.s), so a regressed #84
|
||||
* collision re-mangles the user `run` to `test.run` and the force-loaded
|
||||
* root `.o` + test's `.a` both define `test.run` → w6l duplicate-symbol
|
||||
* → non-zero; exit 0 is the teeth (empirically confirmed). byteid=1 also
|
||||
* pins this coexist path's cs==ww per-pkg asm + synth presence — the
|
||||
* rule-10 leg the ported 997 `coexist_run` carried over the #84 mangle. */
|
||||
{ "collide_run", NULL, "test/wcc/data/attest_userrun.ww", 0, 1, 0 },
|
||||
{ NULL, NULL, NULL, 0, 0, 0 },
|
||||
};
|
||||
|
||||
int
|
||||
@@ -195,8 +224,12 @@ main(void)
|
||||
for (int i = 0; cases[i].label; i++) {
|
||||
struct tcase *t = &cases[i];
|
||||
char rootww[1024];
|
||||
snprintf(rootww, sizeof rootww, "%s/%s.ww", td, t->label);
|
||||
if (write_file(rootww, t->src)) { fail++; continue; }
|
||||
if (t->path) {
|
||||
snprintf(rootww, sizeof rootww, "%s", t->path);
|
||||
} else {
|
||||
snprintf(rootww, sizeof rootww, "%s/%s.ww", td, t->label);
|
||||
if (write_file(rootww, t->src)) { fail++; continue; }
|
||||
}
|
||||
|
||||
struct { const char *drv, *tag; int rc; }
|
||||
stg[] = { { "ww", "cs", -1 }, { "ww_ww", "ww", -1 } };
|
||||
@@ -216,8 +249,17 @@ main(void)
|
||||
stg[s].rc = runwait(cmd);
|
||||
}
|
||||
|
||||
/* 1. RUN-EXIT: both stages exit with the expected code. */
|
||||
if (stg[0].rc != t->expect || stg[1].rc != t->expect) {
|
||||
/* 1. RUN-EXIT: a reject row must exit non-zero on BOTH stages (the
|
||||
* user-facing path is how `ww test` surfaces the diagnostic; the
|
||||
* exact code is a driver detail, so assert != 0 not == N). An
|
||||
* accept row exits with the exact expected code. */
|
||||
if (t->reject) {
|
||||
if (stg[0].rc == 0 || stg[1].rc == 0) {
|
||||
fprintf(stderr, "septest FAIL: %s accepted cs=%d ww=%d "
|
||||
"(expected reject)\n", t->label, stg[0].rc, stg[1].rc);
|
||||
fail++;
|
||||
}
|
||||
} else if (stg[0].rc != t->expect || stg[1].rc != t->expect) {
|
||||
fprintf(stderr, "septest FAIL: %s exits cs=%d ww=%d (expected %d)\n",
|
||||
t->label, stg[0].rc, stg[1].rc, t->expect);
|
||||
fail++;
|
||||
|
||||
Reference in New Issue
Block a user