test/wcc: carrier ownership repair and driver-contract adaptation

Every surviving carrier now owns its artifacts: checked mkdir/mkdtemp/
fopen acquisition, one all-exit cleanup funnel per carrier, ENOENT-
tolerant checked unlinks, exact-path deletion (rm -rf only for an
owned pid-keyed dir or a .sepwork beneath one), and cleanup failure
fails a passing carrier without overwriting its diagnostic. In the
same pass the carriers adapt to the driver contract this branch lands:
--sep and WW_PKGCACHE are gone, -S and the /tmp/ww_run_<pid> scratch
contract are asserted, and rows whose runtime or reject coverage moved
to test/wcc/data fixtures or test/lang @test owners are trimmed to the
byte/artifact/diagnostic observations only they can make.

Repair and adaptation ride together because most files interleave both
in the same hunks; splitting would manufacture intermediate carrier
states that never existed and cannot run against either driver.
This commit is contained in:
2026-08-07 23:02:47 +09:00
parent b2899dd8d3
commit a95a7a316b
132 changed files with 7573 additions and 6172 deletions

View File

@@ -19,12 +19,13 @@
* already used (LEAQ off(BP), DI). Local rows pin no regression at the
* shared cgassign / cglet sret-receive sites.
*
* Each row runs on BOTH cstage (ww) and wwstage (ww_ww), and the
* generated asm is checked byte-identical (cs.s == ww.s, rule 10).
* Runtime behavior is carried by the r940_global_sret_* wwfixtures. This
* wrapper retains the separate-build assembly artifacts and their byte
* identity (cs.s == ww.s, rule 10).
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <sys/stat.h>
#include <sys/wait.h>
@@ -144,49 +145,62 @@ static int
byteid(const char *dir, int i)
{
char cs[256], ws[256], cmd[1024];
int rc;
snprintf(cs, sizeof cs, "%s/bid_cs_%d.s", dir, i);
snprintf(ws, sizeof ws, "%s/bid_ww_%d.s", dir, i);
/* an unmatched sepwork glob must be a loud harness error — two
* empty concatenations would otherwise cmp equal (vacuous green). */
snprintf(cmd, sizeof cmd, "cat %s/gsret_c_%d.sepwork/*.s > %s 2>/dev/null",
dir, i, cs);
if (system(cmd)) {}
if (runwait(cmd) != 0) {
rc = -1;
goto cleanup;
}
snprintf(cmd, sizeof cmd, "cat %s/gsret_w_%d.sepwork/*.s > %s 2>/dev/null",
dir, i, ws);
if (system(cmd)) {}
if (runwait(cmd) != 0) {
rc = -1;
goto cleanup;
}
snprintf(cmd, sizeof cmd, "cmp -s %s %s", cs, ws);
int rc = runwait(cmd);
unlink(cs); unlink(ws);
return rc == 0 ? 0 : 1;
rc = runwait(cmd) == 0 ? 0 : 1;
cleanup:
if (unlink(cs) != 0 && errno != ENOENT) { perror(cs); if (rc == 0) rc = -1; }
if (unlink(ws) != 0 && errno != ENOENT) { perror(ws); if (rc == 0) rc = -1; }
return rc;
}
/* Build `r` with `driver` via `--sep -o <dir>/<stem>` (per-package asm in
* <dir>/<stem>.sepwork/), run the binary, return its exit code (or -1 on
* build failure). `cachetag` keys a private WW_PKGCACHE. */
/* Build `r` with `driver -o <dir>/<stem>` (per-package asm in
* <dir>/<stem>.sepwork/), returning zero on build success. */
static int
run_driver(const char *driver, const struct row *r, const char *dir,
int i, const char *stem, const char *cachetag)
int i, const char *stem)
{
char src[256], cmd[1024];
char src[256], taggedstem[128], cmd[1024];
snprintf(src, sizeof src, "%s/gsret_%d.ww", dir, i);
snprintf(taggedstem, sizeof taggedstem, "%s_%d", stem, i);
FILE *f = fopen(src, "wb");
if (!f) return -1;
wwtest_fputs(r->src, f);
fclose(f);
int werr = ferror(f);
if (fclose(f) != 0 || werr) {
fprintf(stderr, "row[%s]: writing %s failed\n", r->label, src);
return -1;
}
snprintf(cmd, sizeof cmd,
"cd %s && WW_PKGCACHE=%s/pkgc_%s %s build --sep -o %s/%s %s",
dir, dir, cachetag, driver, dir, stem, src);
"cd %s && %s build -S -o %s/%s %s",
dir, driver, dir, taggedstem, src);
if (runwait(cmd) != 0) {
fprintf(stderr, "row[%s]: build via %s failed\n",
r->label, driver);
return -1;
}
char outbin[256];
snprintf(outbin, sizeof outbin, "%s/%s", dir, stem);
return runwait(outbin);
return 0;
}
int
@@ -217,26 +231,26 @@ main(void)
}
int n = (int)(sizeof rows / sizeof rows[0]);
int total = 0, fail = 0;
int total = 0, fail = 0, cleanfail = 0;
for (int i = 0; i < n; i++) {
/* cstage: --sep build + run → <dir>/gsret_c_<i>.sepwork/. */
int gc = run_driver(cdrv, &rows[i], dir, i, "gsret_c", "c");
/* cstage separate build → <dir>/gsret_c_<i>.sepwork/. */
int gc = run_driver(cdrv, &rows[i], dir, i, "gsret_c");
total++;
if (gc != rows[i].want) {
fprintf(stderr, "global_sret_run[cstage][%s]: "
"exit=%d want=%d\n", rows[i].label, gc,
"build=%d want=%d\n", rows[i].label, gc,
rows[i].want);
fail++;
}
/* wwstage: --sep build + run → <dir>/gsret_w_<i>.sepwork/. */
/* wwstage separate build → <dir>/gsret_w_<i>.sepwork/. */
if (have_ww) {
int gw = run_driver(wdrv, &rows[i], dir, i, "gsret_w", "w");
int gw = run_driver(wdrv, &rows[i], dir, i, "gsret_w");
total++;
if (gw != rows[i].want) {
fprintf(stderr, "global_sret_run[wwstage][%s]: "
"exit=%d want=%d\n", rows[i].label, gw,
"build=%d want=%d\n", rows[i].label, gw,
rows[i].want);
fail++;
}
@@ -257,14 +271,25 @@ main(void)
}
char p[640];
snprintf(p, sizeof p, "%s/gsret_%d.ww", dir, i); unlink(p);
snprintf(p, sizeof p, "%s/gsret_%d.ww", dir, i);
/* ENOENT = the row failed before writing the source. */
if (unlink(p) != 0 && errno != ENOENT) {
perror(p);
cleanfail = 1;
}
snprintf(p, sizeof p, "rm -rf %s/gsret_c_%d.sepwork "
"%s/gsret_w_%d.sepwork %s/gsret_c_%d %s/gsret_w_%d "
"%s/pkgc_c %s/pkgc_w", dir, i, dir, i, dir, i, dir, i,
dir, dir);
if (system(p)) {}
"%s/gsret_w_%d.sepwork %s/gsret_c_%d %s/gsret_w_%d",
dir, i, dir, i, dir, i, dir, i);
if (runwait(p) != 0) {
fprintf(stderr, "global_sret_run: cleanup row %d "
"failed\n", i);
cleanfail = 1;
}
}
if (rmdir(dir) != 0) {
perror(dir);
cleanfail = 1;
}
rmdir(dir);
if (!have_ww)
fprintf(stderr, "global_sret_run: skip wwstage (no %s)\n", wdrv);
@@ -274,6 +299,9 @@ main(void)
fail, total);
return 1;
}
/* cleanup diagnostics already printed; must not stay green. */
if (cleanfail)
return 1;
printf("global_sret_run: %d/%d ok\n", total, total);
return 0;
}