/* * 910_at_test — drives the compiler's `-T` @test mode (task #15). * * Under `w6c -T`, the checker collects every @test fn and synthesizes * `export fn main() i32 { t0(); t1(); ...; return 0; }`, calling each in * source order; a test that runs to completion passes, an abort/div0/ * nonzero exit FAILS the run. This replaces the old driver-side regex * scan (find_attest) — the @test set now comes from the AST, the single * source of truth (rob #15 ruling). cgen is untouched: the synthesized * entry rides the existing cgfn path. * * Probes: * 1. RUN — `w6c -T` the @test-only fixture, assemble, link, run; the * synthesized entry must exit 0 (every @test passed). Imports are * resolved by `ww build` into a *.combined.ww (the fixture uses * `alloc`, whose rt_malloc symbol the driver concatenates); we then * compile that combined unit with `-T`. * 2. REJECT — `-T` of a fixture that also defines a user `main` must * exit nonzero (the synth entry owns main). * 3. GUARD — `-T` of a fixture whose @test fn is not `fn() void` must * exit nonzero (rule-7 loud, no silent skip/coerce). */ #include #include #include #include static int runwait(const char *cmd) { int rc = system(cmd); if (rc == -1) return -1; if (WIFEXITED(rc)) return WEXITSTATUS(rc); return 1; } static const char * absbin(void) { const char *b = getenv("BIN"); if (!b) b = "out/bin"; if (b[0] == '/') return b; static char buf[2048]; char cwd[1024]; if (getcwd(cwd, sizeof cwd) == NULL) return NULL; snprintf(buf, sizeof buf, "%s/%s", cwd, b); return buf; } /* run_fixture — ` -T` the @test fixture (import-resolved into a * combined unit by build), assemble, link, run; the synthesized * entry must exit 0. Returns 0 on success. */ static int run_fixture(const char *bin, const char *comp, const char *drv) { int pid = getpid(); char src[256], comb[256], asmf[256], obj[256], exe[256]; char rt[1024], cmd[4096]; snprintf(src, sizeof src, "/tmp/at910_%s_%d.ww", comp, pid); snprintf(comb, sizeof comb, "/tmp/at910_%s_%d.combined.ww", comp, pid); snprintf(asmf, sizeof asmf, "/tmp/at910_%s_%d.s", comp, pid); snprintf(obj, sizeof obj, "/tmp/at910_%s_%d.o", comp, pid); snprintf(exe, sizeof exe, "/tmp/at910_%s_%d.exe", comp, pid); snprintf(rt, sizeof rt, "%s/../lib/libwwrt.a", bin); snprintf(cmd, sizeof cmd, "cp test/wcc/data/attest_pass.ww %s", src); if (runwait(cmd) != 0) { fprintf(stderr, "910 FAIL: cp\n"); return 1; } /* Driver resolves `import rt` into .combined.ww. The build * itself exits nonzero (the @test-only fixture has no main — that * is exactly what -T synthesizes), but the combined unit is written * before any compile step, so we depend on the ARTIFACT, not the * exit code. */ snprintf(cmd, sizeof cmd, "%s/%s build %s > /dev/null 2>&1", bin, drv, src); runwait(cmd); if (access(comb, 0) != 0) { fprintf(stderr, "910 FAIL: %s build produced no %s\n", drv, comb); return 1; } snprintf(cmd, sizeof cmd, "%s/%s -T %s -o %s 2>/dev/null", bin, comp, comb, asmf); if (runwait(cmd) != 0) { fprintf(stderr, "910 FAIL: %s -T errored\n", comp); return 1; } snprintf(cmd, sizeof cmd, "%s/w6a -o %s %s 2>/dev/null", bin, obj, asmf); if (runwait(cmd) != 0) { fprintf(stderr, "910 FAIL: w6a\n"); return 1; } snprintf(cmd, sizeof cmd, "%s/w6l -o %s %s %s 2>/dev/null", bin, exe, obj, rt); if (runwait(cmd) != 0) { fprintf(stderr, "910 FAIL: w6l\n"); return 1; } int rc = runwait(exe); if (rc != 0) { fprintf(stderr, "910 FAIL: synth entry exited %d (a @test failed)\n", rc); return 1; } unlink(src); unlink(comb); unlink(asmf); unlink(obj); unlink(exe); return 0; } /* reject — ` -T ` must exit nonzero. */ static int reject(const char *bin, const char *comp, const char *fixture, const char *what) { char cmd[4096]; snprintf(cmd, sizeof cmd, "%s/%s -T %s -o /dev/null 2>/dev/null", bin, comp, fixture); if (runwait(cmd) == 0) { fprintf(stderr, "910 FAIL: %s -T accepted %s (expected reject)\n", comp, what); return 1; } return 0; } /* Each row: a fixture `-T` must loud-reject, and why. */ static const struct { const char *fixture; const char *what; } rejects[] = { { "test/wcc/data/attest_userman.ww", "user main" }, { "test/wcc/data/attest_badsig.ww", "non-void @test" }, }; int main(void) { const char *bin = absbin(); if (!bin) { fprintf(stderr, "910 FAIL: getcwd\n"); return 1; } if (run_fixture(bin, "w6c", "ww") != 0) return 1; for (size_t i = 0; i < sizeof rejects / sizeof rejects[0]; i++) if (reject(bin, "w6c", rejects[i].fixture, rejects[i].what) != 0) return 1; printf("@test -T: run ok + user-main and bad-signature rejected\n"); return 0; }