From b2899dd8d3f1ba6c54cb1266257540590cc34de9 Mon Sep 17 00:00:00 2001 From: Hojun-Cho Date: Fri, 7 Aug 2026 23:02:47 +0900 Subject: [PATCH] test/wcc: run the unit loops fully in process 000_smoke drops its popen ww -V leg (driver version parity moves to 949_driver_flagargs); 400_w6c feeds its sources through lex/parse/ check/cgen into open_memstream instead of spawning w6c. The five unit binaries now hold zero subprocess calls. --- test/wcc/000_smoke.c | 39 +------------ test/wcc/400_w6c.c | 133 ++++++++++++++++++++++++------------------- 2 files changed, 76 insertions(+), 96 deletions(-) diff --git a/test/wcc/000_smoke.c b/test/wcc/000_smoke.c index d9f8ccb2..81ddce69 100644 --- a/test/wcc/000_smoke.c +++ b/test/wcc/000_smoke.c @@ -1,10 +1,8 @@ /* * 000_smoke — Phase 0 smoke test. * - * Asserts: - * - libwcc symbols (newarena/amalloc/freearena, fatal/errorf/warnf) - * are linkable. - * - `ww -V` exits 0 and prints the configured version. + * Asserts arena allocation and growth through libwcc, plus the configured + * version constant. Driver behavior belongs to the driver integration tests. */ #include "ww.h" #include @@ -44,44 +42,11 @@ test_version(void) } } -static void -test_ww_minus_v(void) -{ - const char *bin = getenv("BIN"); - if (bin == NULL) - bin = "out/bin"; - char cmd[512]; - snprintf(cmd, sizeof cmd, "%s/ww -V", bin); - FILE *p = popen(cmd, "r"); - if (p == NULL) { - fprintf(stderr, "smoke: popen %s\n", cmd); - exit(1); - } - char buf[128]; - size_t n = fread(buf, 1, sizeof buf - 1, p); - buf[n] = '\0'; - int rc = pclose(p); - if (rc != 0) { - fprintf(stderr, "smoke: ww -V exit %d\n", rc); - exit(1); - } - if (strstr(buf, "ww ") != buf) { - fprintf(stderr, "smoke: ww -V output not 'ww ...': %s\n", buf); - exit(1); - } - if (strstr(buf, WW_VERSION) == NULL) { - fprintf(stderr, "smoke: ww -V missing version %s in: %s\n", - WW_VERSION, buf); - exit(1); - } -} - int main(void) { test_arena(); test_version(); - test_ww_minus_v(); puts("smoke: ok"); return 0; } diff --git a/test/wcc/400_w6c.c b/test/wcc/400_w6c.c index b4921a04..08694421 100644 --- a/test/wcc/400_w6c.c +++ b/test/wcc/400_w6c.c @@ -1,91 +1,106 @@ /* - * 400_6c — codegen smoke tests. Each row supplies a tiny ww source - * and a list of substrings expected in the emitted .s. We don't - * golden-match the whole file (too brittle); we just verify that - * key opcodes and operand shapes show up. + * 400_w6c — in-process codegen smoke tests. Each row supplies one tiny ww + * source and the assembly fragments it must emit. Full-file golden matches + * would bind the test to unrelated output details. */ +#include "gc.h" #include #include #include -#include #include "wwtestpkg.h" -static int -run6c(const char *src, char **out) +static char * +codegen(const char *src) { - char path[64]; - snprintf(path, sizeof path, "/tmp/wwt_%d.ww", getpid()); - FILE *f = fopen(path, "wb"); - if (f == NULL) return -1; - wwtest_fputs(src, f); - fclose(f); + Arena *a = newarena(); + char *wrapped = wwtest_wrap(src); + Lex l; + Parser p; + Checker c; + Cg cg; - char cmd[256]; - const char *bin = getenv("BIN"); - if (!bin) bin = "out/bin"; - snprintf(cmd, sizeof cmd, "%s/w6c %s 2>&1", bin, path); - FILE *p = popen(cmd, "r"); - if (p == NULL) { unlink(path); return -1; } - size_t cap = 4096, n = 0; - char *buf = malloc(cap); - int c; - while ((c = fgetc(p)) != EOF) { - if (n + 1 >= cap) { cap *= 2; buf = realloc(buf, cap); } - buf[n++] = (char)c; + lexinit(&l, a, "", wrapped, strlen(wrapped)); + parserinit(&p, a, &l); + Node *file = parsefile(&p); + if (l.errs || p.errs) + goto fail; + check_init(&c, a); + check_file(&c, file); + if (c.errs) + goto fail; + + char *out = NULL; + size_t outlen = 0; + FILE *f = open_memstream(&out, &outlen); + if (f == NULL) + goto fail; + cg_init(&cg, a); + cg_file(&cg, f, file); + if (fclose(f) != 0) { + free(out); + out = NULL; } - buf[n] = '\0'; - int rc = pclose(p); - unlink(path); - *out = buf; - return rc; + free(wrapped); + freearena(a); + return out; + +fail: + free(wrapped); + freearena(a); + return NULL; } -static int -contains(const char *hay, const char *needle) -{ - return strstr(hay, needle) != NULL; -} - -struct row { const char *src; const char *needle; }; +struct row { + const char *src; + const char *needle[3]; +}; static const struct row rows[] = { - { "fn main() i32 = { return 42; };", "MOVQ\t$42, AX" }, - { "fn main() i32 = { return 42; };", "RET" }, - { "fn id(x: i32) i32 = { return x; };","MOVQ\tDI, -8(BP)" }, - { "fn add(a: i32, b: i32) i32 = { return a + b; };", "ADDQ\tBX, AX" }, - { "fn sub(a: i32, b: i32) i32 = { return a - b; };", "SUBQ\tBX, AX" }, - { "fn mul(a: i32, b: i32) i32 = { return a * b; };", "IMULQ\tBX, AX" }, - { "fn neg(x: i32) i32 = { return -x; };", "NEGQ\tAX" }, - { "fn cmp(a: i32, b: i32) bool = { return a == b; };", "CMPQ\tBX, AX" }, - { "fn cmp(a: i32, b: i32) bool = { return a == b; };", "JE" }, + { "fn main() i32 = { return 42; };", { "MOVQ\t$42, AX", "RET" } }, + { "fn id(x: i32) i32 = { return x; };", { "MOVQ\tDI, -8(BP)" } }, + { "fn add(a: i32, b: i32) i32 = { return a + b; };", { "ADDQ\tBX, AX" } }, + { "fn sub(a: i32, b: i32) i32 = { return a - b; };", { "SUBQ\tBX, AX" } }, + { "fn mul(a: i32, b: i32) i32 = { return a * b; };", { "IMULQ\tBX, AX" } }, + { "fn neg(x: i32) i32 = { return -x; };", { "NEGQ\tAX" } }, + { "fn cmp(a: i32, b: i32) bool = { return a == b; };", + { "CMPQ\tBX, AX", "JE" } }, { "fn cond(x: i32) i32 = { if (x > 0) { return 1; }; return 0; };", - "CMPQ\t$0, AX" }, - { "fn lo() void = { for (let i: i32 = 0; i < 10; i += 1) { }; };", "JMP" }, - { "fn callit() i32 = { return 1; };", "TEXT main.callit,$0" }, + { "CMPQ\t$0, AX" } }, + { "fn lo() void = { for (let i: i32 = 0; i < 10; i += 1) { }; };", + { "JMP" } }, + { "fn callit() i32 = { return 1; };", { "TEXT main.callit,$0" } }, }; int main(void) { int n = sizeof rows / sizeof rows[0]; + int nfrag = 0; int fail = 0; for (int i = 0; i < n; i++) { - char *out = NULL; - int rc = run6c(rows[i].src, &out); - if (rc != 0) { - fprintf(stderr, "row %d: w6c rc=%d\n", i, rc); - fail++; - free(out); + int want = 0; + while (want < 3 && rows[i].needle[want] != NULL) + want++; + nfrag += want; + char *out = codegen(rows[i].src); + if (out == NULL) { + fprintf(stderr, "row %d: frontend/codegen failed\n", i); + fail += want; continue; } - if (!contains(out, rows[i].needle)) { + for (int j = 0; j < want; j++) { + if (strstr(out, rows[i].needle[j]) != NULL) + continue; fprintf(stderr, "row %d: missing '%s' in:\n%s\n", - i, rows[i].needle, out); + i, rows[i].needle[j], out); fail++; } free(out); } - if (fail) { fprintf(stderr, "%d/%d w6c tests failed\n", fail, n); return 1; } - printf("w6c: %d/%d ok\n", n, n); + if (fail) { + fprintf(stderr, "%d/%d w6c fragments failed\n", fail, nfrag); + return 1; + } + printf("w6c: %d/%d fragments ok in %d sources\n", nfrag, nfrag, n); return 0; }