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:
@@ -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;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user