test/wcc: extend carrier ownership to the bootstrap and platform gates
Same contract as the 27 repaired byte/artifact survivors: checked acquisition, one all-exit cleanup funnel per carrier, ENOENT-tolerant checked unlinks, exact-path deletion, and cleanup failure fails a passing carrier without overwriting its diagnostic. Also closes the vacuous-green channels: empty-artifact pairs no longer byte-compare equal, capture and staging failures fail their row loudly, 950 requires a clean checker exit on no-error rows and hard-fails on a missing wwdump_ww, 992 keys its scratch per invocation so a failed cleanup cannot leak stale objects into the next tool's compare, and 995 no longer pre-sweeps a workdir it never created. No assertion is weakened; 990_selfhost is retired in the next commit rather than repaired.
This commit is contained in:
@@ -14,6 +14,7 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/wait.h>
|
||||
@@ -48,11 +49,14 @@ slurp_eq(const char *a, const char *b)
|
||||
FILE *fb = fopen(b, "rb");
|
||||
if (!fa || !fb) { if (fa) fclose(fa); if (fb) fclose(fb); return -1; }
|
||||
int rc = 0;
|
||||
int any = 0;
|
||||
for (;;) {
|
||||
int ca = fgetc(fa);
|
||||
int cb = fgetc(fb);
|
||||
if (ca != cb) { rc = -1; break; }
|
||||
if (ca == EOF) break;
|
||||
/* a produced executable can never be legitimately empty. */
|
||||
if (ca == EOF) { if (!any) rc = -1; break; }
|
||||
any = 1;
|
||||
}
|
||||
fclose(fa); fclose(fb);
|
||||
return rc;
|
||||
@@ -92,29 +96,35 @@ diff_one(const char *bin, const char *cwd, const char *label,
|
||||
snprintf(dw, sizeof dw, "/tmp/ww_d_%d_w", getpid());
|
||||
|
||||
char cmd[256];
|
||||
int rc = -1;
|
||||
snprintf(cmd, sizeof cmd, "rm -rf %s %s && mkdir -p %s %s", dc, dw, dc, dw);
|
||||
if (runwait(cmd) != 0) return -1;
|
||||
if (runwait(cmd) != 0) goto cleanup;
|
||||
|
||||
if (build_via(bin, "ww", src, dc, incs, out_basename) != 0) {
|
||||
fprintf(stderr, "ww_ww FAIL: C ww errored on %s\n", label);
|
||||
return -1;
|
||||
goto cleanup;
|
||||
}
|
||||
if (build_via(bin, "ww_ww", src, dw, incs, out_basename) != 0) {
|
||||
fprintf(stderr, "ww_ww FAIL: ww ww errored on %s\n", label);
|
||||
return -1;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
char co[1024], wo[1024];
|
||||
snprintf(co, sizeof co, "%s/%s", dc, out_basename);
|
||||
snprintf(wo, sizeof wo, "%s/%s", dw, out_basename);
|
||||
|
||||
int rc = 0;
|
||||
if (slurp_eq(co, wo) != 0) {
|
||||
if (slurp_eq(co, wo) != 0)
|
||||
fprintf(stderr, "ww_ww FAIL: %s — driver outputs differ\n", label);
|
||||
rc = -1;
|
||||
}
|
||||
else
|
||||
rc = 0;
|
||||
|
||||
cleanup:
|
||||
/* `ww build` retains the caller-owned .sepwork tree inside the
|
||||
* workdir; rm -rf of the exact pid-keyed pair covers it, and is
|
||||
* safe even after a partial mkdir. */
|
||||
snprintf(cmd, sizeof cmd, "rm -rf %s %s", dc, dw);
|
||||
runwait(cmd);
|
||||
if (runwait(cmd) != 0 && rc == 0)
|
||||
rc = -1;
|
||||
(void)cwd;
|
||||
return rc;
|
||||
}
|
||||
@@ -132,12 +142,21 @@ run_exit_code(const char *bin, const char *driver, int code)
|
||||
if (!f) return -1;
|
||||
fprintf(f, "package main;\nexport fn main() i32 = {\n\treturn %d;\n};\n",
|
||||
code);
|
||||
fclose(f);
|
||||
if (fclose(f) != 0) {
|
||||
perror(src);
|
||||
if (unlink(src) != 0 && errno != ENOENT)
|
||||
perror(src);
|
||||
return -1;
|
||||
}
|
||||
|
||||
char cmd[256];
|
||||
snprintf(cmd, sizeof cmd, "%s/%s run %s 2>/dev/null", bin, driver, src);
|
||||
int rc = runwait(cmd);
|
||||
unlink(src);
|
||||
if (unlink(src) != 0 && errno != ENOENT) {
|
||||
perror(src);
|
||||
if (rc == code)
|
||||
rc = -1;
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
@@ -152,14 +171,28 @@ run_build_fail(const char *bin, const char *driver)
|
||||
char src[64];
|
||||
snprintf(src, sizeof src, "/tmp/ww_badbuild_%d.ww", getpid());
|
||||
FILE *f = fopen(src, "w");
|
||||
if (!f) return -1;
|
||||
if (!f) {
|
||||
perror(src);
|
||||
return -1;
|
||||
}
|
||||
wwtest_fputs("export fn main() i32 = {\n\treturn 1\n", f); /* no ; no } */
|
||||
fclose(f);
|
||||
if (fclose(f) != 0) {
|
||||
perror(src);
|
||||
if (unlink(src) != 0 && errno != ENOENT)
|
||||
perror(src);
|
||||
return -1;
|
||||
}
|
||||
|
||||
char cmd[256];
|
||||
snprintf(cmd, sizeof cmd, "%s/%s run %s 2>/dev/null", bin, driver, src);
|
||||
int rc = runwait(cmd);
|
||||
unlink(src);
|
||||
if (unlink(src) != 0 && errno != ENOENT) {
|
||||
perror(src);
|
||||
/* cleanup failure maps onto the -1 sentinel the caller rejects;
|
||||
* a real rc==0 (driver failed to fail) keeps its diagnostic. */
|
||||
if (rc != 0)
|
||||
rc = -1;
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
@@ -173,13 +206,21 @@ run_missing_pkg(const char *bin, const char *driver)
|
||||
{
|
||||
char tmpdir[80], src[160], errf[160], outbin[160], rmcmd[200];
|
||||
snprintf(tmpdir, sizeof tmpdir, "/tmp/ww_mp_%s_%d", driver, getpid());
|
||||
mkdir(tmpdir, 0755);
|
||||
if (mkdir(tmpdir, 0755) != 0) {
|
||||
perror(tmpdir);
|
||||
return 1;
|
||||
}
|
||||
snprintf(src, sizeof src, "%s/mp.ww", tmpdir);
|
||||
snprintf(errf, sizeof errf, "%s/mp.err", tmpdir);
|
||||
snprintf(outbin, sizeof outbin, "%s/mp", tmpdir);
|
||||
snprintf(rmcmd, sizeof rmcmd, "rm -rf %s", tmpdir);
|
||||
FILE *f = fopen(src, "w");
|
||||
if (!f) { runwait(rmcmd); return 1; }
|
||||
if (!f) {
|
||||
perror(src);
|
||||
if (runwait(rmcmd) != 0)
|
||||
fprintf(stderr, "ww_ww: cleanup of %s failed\n", tmpdir);
|
||||
return 1;
|
||||
}
|
||||
wwtest_fputs("import nosuchpkg;\nexport fn main() i32 = { return 0; };\n", f);
|
||||
fclose(f);
|
||||
|
||||
@@ -200,12 +241,16 @@ run_missing_pkg(const char *bin, const char *driver)
|
||||
buf[n] = '\0';
|
||||
found = strstr(buf, "cannot find package nosuchpkg") != NULL;
|
||||
}
|
||||
runwait(rmcmd);
|
||||
int cleanfail = runwait(rmcmd) != 0;
|
||||
if (rc == 0 || !found) {
|
||||
fprintf(stderr, "ww_ww FAIL: %s missing-pkg rc=%d found=%d "
|
||||
"(want nonzero + 'cannot find package')\n", driver, rc, found);
|
||||
return 1;
|
||||
}
|
||||
if (cleanfail) {
|
||||
fprintf(stderr, "ww_ww: cleanup of %s failed\n", tmpdir);
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -232,7 +277,12 @@ main(void)
|
||||
"\tos.write(1, \"hi\\n\".ptr, 3u64);\n"
|
||||
"\treturn 0;\n"
|
||||
"};\n", f);
|
||||
fclose(f);
|
||||
if (fclose(f) != 0) {
|
||||
perror(hello_src);
|
||||
if (unlink(hello_src) != 0 && errno != ENOENT)
|
||||
perror(hello_src);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
struct {
|
||||
@@ -260,13 +310,17 @@ main(void)
|
||||
|
||||
int fail = 0;
|
||||
int n = 0;
|
||||
int cleanfail = 0;
|
||||
for (int i = 0; cases[i].label; i++) {
|
||||
if (diff_one(bin, cwd, cases[i].label, cases[i].src,
|
||||
cases[i].out, cases[i].incs) != 0)
|
||||
fail++;
|
||||
n++;
|
||||
}
|
||||
unlink(hello_src);
|
||||
if (unlink(hello_src) != 0 && errno != ENOENT) {
|
||||
perror(hello_src);
|
||||
cleanfail = 1;
|
||||
}
|
||||
|
||||
/* #16: `ww_ww run` must propagate the child program's real exit code.
|
||||
* Table-driven; the non-zero rows fail under the old collapse-to-1.
|
||||
@@ -296,7 +350,9 @@ main(void)
|
||||
* failure (non-zero), and both drivers must agree. */
|
||||
int cbad = run_build_fail(bin, "ww");
|
||||
int wbad = run_build_fail(bin, "ww_ww");
|
||||
if (cbad == 0 || wbad == 0 || cbad != wbad) {
|
||||
/* <= 0 rejects the -1 staging/cleanup sentinel: equal sentinels must
|
||||
* not pass as build-fail parity when neither driver ever ran. */
|
||||
if (cbad <= 0 || wbad <= 0 || cbad != wbad) {
|
||||
fprintf(stderr, "ww_ww FAIL: build-fail exit C ww=%d ww_ww=%d "
|
||||
"(want equal and non-zero)\n", cbad, wbad);
|
||||
rcfail++;
|
||||
@@ -307,7 +363,7 @@ main(void)
|
||||
rcfail += run_missing_pkg(bin, "ww");
|
||||
rcfail += run_missing_pkg(bin, "ww_ww");
|
||||
|
||||
if (fail || rcfail) {
|
||||
if (fail || rcfail || cleanfail) {
|
||||
fprintf(stderr, "ww_ww: %d/%d diff(s) failed, %d exit-code "
|
||||
"row(s) failed\n", fail, n, rcfail);
|
||||
return 1;
|
||||
|
||||
Reference in New Issue
Block a user