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:
@@ -42,7 +42,6 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/wait.h>
|
||||
#include "wwtestpkg.h"
|
||||
|
||||
@@ -57,7 +56,8 @@ runwait(const char *cmd)
|
||||
|
||||
/* ---- 1. same-module EXEC rows (compile+link+run) -------------------- */
|
||||
|
||||
struct row { const char *label; const char *src; int want; };
|
||||
/* Runtime ownership: test/wcc/data/r732_def_{sibling,chain,shift,widening}_*. */
|
||||
struct row { const char *label; const char *src; };
|
||||
|
||||
static const struct row exec_rows[] = {
|
||||
/* Bare sibling reference: `def B = A;`. Pre-#88 the rhs (N_IDENT)
|
||||
@@ -69,8 +69,7 @@ static const struct row exec_rows[] = {
|
||||
"\tlet x: i32 = B;\n"
|
||||
"\tif (x == 7) { return 42; };\n"
|
||||
"\treturn 1;\n"
|
||||
"};\n",
|
||||
42 },
|
||||
"};\n" },
|
||||
|
||||
/* Sibling + arithmetic: the headline `def B = A + 1;`. */
|
||||
{ "sibling-add",
|
||||
@@ -80,8 +79,7 @@ static const struct row exec_rows[] = {
|
||||
"\tlet x: i32 = B;\n"
|
||||
"\tif (x == 6) { return 42; };\n"
|
||||
"\treturn 1;\n"
|
||||
"};\n",
|
||||
42 },
|
||||
"};\n" },
|
||||
|
||||
/* def -> def -> def chain: C resolves through B through A. Pins
|
||||
* the recursive resolve (and that the depth guard doesn't trip on
|
||||
@@ -94,8 +92,7 @@ static const struct row exec_rows[] = {
|
||||
"\tlet x: i32 = C;\n"
|
||||
"\tif (x == 30) { return 42; };\n"
|
||||
"\treturn 1;\n"
|
||||
"};\n",
|
||||
42 },
|
||||
"};\n" },
|
||||
|
||||
/* Pure arithmetic with a shift: `(1 << 7) - 1` == 127. Exercises
|
||||
* the fold_binop shift + subtract path off any sibling ref. */
|
||||
@@ -105,8 +102,7 @@ static const struct row exec_rows[] = {
|
||||
"\tlet x: i32 = MASK;\n"
|
||||
"\tif (x == 127) { return 42; };\n"
|
||||
"\treturn 1;\n"
|
||||
"};\n",
|
||||
42 },
|
||||
"};\n" },
|
||||
|
||||
/* Widening cast over a sibling ref: `A: i64` where A: i32 = 5.
|
||||
* The N_CAST is stripped (i32->i64 widens, value fits), so W folds
|
||||
@@ -118,42 +114,9 @@ static const struct row exec_rows[] = {
|
||||
"\tlet x: i64 = W;\n"
|
||||
"\tif (x == 5i64) { return 42; };\n"
|
||||
"\treturn 1;\n"
|
||||
"};\n",
|
||||
42 },
|
||||
"};\n" },
|
||||
};
|
||||
|
||||
static int
|
||||
run_driver(const char *driver, const struct row *r, int i)
|
||||
{
|
||||
char tmpdir[64], src[128], outbin[128], rmcmd[160], cmd[1024];
|
||||
snprintf(tmpdir, sizeof tmpdir, "/tmp/dcf_%d_d_%d", getpid(), i);
|
||||
mkdir(tmpdir, 0755);
|
||||
snprintf(src, sizeof src, "%s/dcf_%d_%d.ww", tmpdir, getpid(), i);
|
||||
snprintf(outbin, sizeof outbin, "%s/dcf_%d_%d", tmpdir, getpid(), i);
|
||||
snprintf(rmcmd, sizeof rmcmd, "rm -rf %s", tmpdir);
|
||||
|
||||
FILE *f = fopen(src, "wb");
|
||||
if (!f) { runwait(rmcmd); return -1; }
|
||||
wwtest_fputs(r->src, f);
|
||||
fclose(f);
|
||||
|
||||
/* timeout 180 per repo convention (990-997); test/run does not bound
|
||||
* individual binaries, so an unguarded hang would stall make test. */
|
||||
snprintf(cmd, sizeof cmd, "timeout 180 %s build -o %s %s 2>/dev/null",
|
||||
driver, outbin, src);
|
||||
if (runwait(cmd) != 0) {
|
||||
fprintf(stderr, "row[%s]: build via %s failed\n",
|
||||
r->label, driver);
|
||||
runwait(rmcmd);
|
||||
return -1;
|
||||
}
|
||||
|
||||
int got = runwait(outbin);
|
||||
|
||||
runwait(rmcmd);
|
||||
return got;
|
||||
}
|
||||
|
||||
/* ---- shared .s emit + slurp ----------------------------------------- */
|
||||
|
||||
static int
|
||||
@@ -282,13 +245,8 @@ xmod_fold_present(const char *w6c, const char *stage)
|
||||
struct failrow { const char *label; const char *src; };
|
||||
|
||||
static const struct failrow fail_rows[] = {
|
||||
/* Same-module cycle: the depth guard must trip and fail loud, not
|
||||
* hang and not silently drop the row. */
|
||||
{ "same-module-cycle",
|
||||
"def A: i32 = B;\n"
|
||||
"def B: i32 = A;\n"
|
||||
"export fn main() i32 = { return A; };\n" },
|
||||
|
||||
/* Residual combined-source artifact: cannot use the ordinary
|
||||
* single-package //ww:error carrier. */
|
||||
/* Cross-module cycle (combined source): a.J -> b.K -> a.J. */
|
||||
{ "cross-module-cycle",
|
||||
"package a;\n"
|
||||
@@ -298,12 +256,6 @@ static const struct failrow fail_rows[] = {
|
||||
"import a;\n"
|
||||
"export def K: i32 = a.J;\n"
|
||||
"export fn main() i32 = { return 0; };\n" },
|
||||
|
||||
/* Narrowing cast that loses the value: 0x1FF (511) does not fit a
|
||||
* u8, so the cast must fail loud rather than silently truncate. */
|
||||
{ "narrowing-cast",
|
||||
"def Z: u8 = 0x1FF: u8;\n"
|
||||
"export fn main() i32 = { let z: u8 = Z; return z: i32; };\n" },
|
||||
};
|
||||
|
||||
/* Compile via w6c only (no link/run); success means the build FAILED as
|
||||
@@ -355,42 +307,14 @@ main(void)
|
||||
bin = absbin;
|
||||
}
|
||||
|
||||
char cdrv[1024], wdrv[1024], w6c[1024], w6c_ww[1024];
|
||||
snprintf(cdrv, sizeof cdrv, "%s/ww", bin);
|
||||
snprintf(wdrv, sizeof wdrv, "%s/ww_ww", bin);
|
||||
char w6c[1024], w6c_ww[1024];
|
||||
snprintf(w6c, sizeof w6c, "%s/w6c", bin);
|
||||
snprintf(w6c_ww, sizeof w6c_ww, "%s/w6c_ww", bin);
|
||||
|
||||
int have_ww = (access(w6c_ww, X_OK) == 0);
|
||||
int total = 0, fail = 0;
|
||||
|
||||
/* 1. same-module exec via cstage `ww` (+ wwstage `ww_ww` if built) */
|
||||
struct { const char *name; const char *path; int gated; }
|
||||
drivers[] = {
|
||||
{ "cstage", cdrv, 0 },
|
||||
{ "wwstage", wdrv, 1 },
|
||||
{ NULL, NULL, 0 },
|
||||
};
|
||||
int nexec = (int)(sizeof exec_rows / sizeof exec_rows[0]);
|
||||
for (int d = 0; drivers[d].name; d++) {
|
||||
if (drivers[d].gated && access(drivers[d].path, X_OK) != 0) {
|
||||
fprintf(stderr, "def_const_fold: skip %s (no %s)\n",
|
||||
drivers[d].name, drivers[d].path);
|
||||
continue;
|
||||
}
|
||||
for (int i = 0; i < nexec; i++) {
|
||||
int got = run_driver(drivers[d].path, &exec_rows[i], i);
|
||||
total++;
|
||||
if (got != exec_rows[i].want) {
|
||||
fprintf(stderr,
|
||||
"def_const_fold[%s][%s]: exit=%d want=%d\n",
|
||||
drivers[d].name, exec_rows[i].label,
|
||||
got, exec_rows[i].want);
|
||||
fail++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* 2. byte-id on every exec row (only when wwstage is built) */
|
||||
if (have_ww) {
|
||||
for (int i = 0; i < nexec; i++) {
|
||||
|
||||
Reference in New Issue
Block a user