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,14 +42,6 @@
|
||||
* | mis-marshals — rc=11.
|
||||
* | Post-fix both stages
|
||||
* | rc=0.
|
||||
* same_module_same_leaf | non-regression: two
|
||||
* | fns in the same module
|
||||
* | sharing a leaf (one
|
||||
* | variadic, one not).
|
||||
* | mklabel seq stays
|
||||
* | distinct + each call
|
||||
* | dispatches to its own
|
||||
* | shape.
|
||||
* bare_leaf_no_collision | control: variadic fn
|
||||
* | declared in only one
|
||||
* | module, called via
|
||||
@@ -60,10 +52,16 @@
|
||||
* | through bare
|
||||
* | fnparamslookup
|
||||
* | (post-#4d).
|
||||
*
|
||||
* The standalone same_module_same_leaf runtime control now lives in
|
||||
* test/wcc/data/r75_modparam_same_module_same_leaf/case.ww. This wrapper
|
||||
* retains only the two package-layout rows that require separately named
|
||||
* imported source files and therefore are not expressible by case.ww.
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/wait.h>
|
||||
@@ -126,34 +124,6 @@ static const struct row rows[] = {
|
||||
"};\n" },
|
||||
"main.ww" },
|
||||
|
||||
/* Non-regression. Same module declares two fns sharing a leaf
|
||||
* (one variadic, one not). The N_IDENT bare-leaf path still
|
||||
* graduates via fnparamslookup's same-module-first walk (#4d);
|
||||
* the N_DOT arm doesn't fire because there's no `mod.fn` use
|
||||
* site. */
|
||||
{ "same_module_same_leaf", 0, 1,
|
||||
{ "main.ww",
|
||||
"package main;\n"
|
||||
"fn variadic_foo(a: i32, xs: i32...) i32 = {\n"
|
||||
"\treturn a + xs.len;\n"
|
||||
"};\n"
|
||||
"fn scalar_foo(a: i32, n: (u8 | []u8)) i32 = {\n"
|
||||
"\tmatch (n) {\n"
|
||||
"\tcase let c: u8 => return a + (c: i32);\n"
|
||||
"\tcase let s: []u8 => return a + s.len;\n"
|
||||
"\t};\n"
|
||||
"\treturn 0;\n"
|
||||
"};\n"
|
||||
"export fn main() i32 = {\n"
|
||||
"\tlet n: (u8 | []u8) = 5u8;\n"
|
||||
"\tlet a: i32 = variadic_foo(1, 2, 3, 4);\n"
|
||||
"\tlet b: i32 = scalar_foo(10, n);\n"
|
||||
"\tif (a != 4) { return 30; };\n"
|
||||
"\tif (b != 15) { return 31; };\n"
|
||||
"\treturn 0;\n"
|
||||
"};\n" },
|
||||
"main.ww" },
|
||||
|
||||
/* Control. A variadic fn exists in only one imported module;
|
||||
* the caller calls it via N_DOT. No same-leaf collision, so
|
||||
* fnparamslookupmod's same-module hint and the head-walk
|
||||
@@ -179,39 +149,79 @@ static const struct row rows[] = {
|
||||
};
|
||||
|
||||
static int
|
||||
write_one(const char *dir, const char *rel, const char *src)
|
||||
write_one(const char *dir, const char *rel, const char *src,
|
||||
int *parent_owned)
|
||||
{
|
||||
char path[512];
|
||||
snprintf(path, sizeof path, "%s/%s", dir, rel);
|
||||
char *slash = strchr(path + strlen(dir) + 1, '/');
|
||||
if (slash) {
|
||||
*slash = '\0';
|
||||
mkdir(path, 0755);
|
||||
if (mkdir(path, 0755) != 0) return -1;
|
||||
*parent_owned = 1;
|
||||
*slash = '/';
|
||||
}
|
||||
FILE *f = fopen(path, "wb");
|
||||
if (!f) return -1;
|
||||
fputs(src, f);
|
||||
fclose(f);
|
||||
return 0;
|
||||
int rc = fputs(src, f) == EOF ? -1 : 0;
|
||||
if (fclose(f) != 0) rc = -1;
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int
|
||||
cleanup_row(const char *tmpdir, const struct row *r,
|
||||
const int *parent_owned)
|
||||
{
|
||||
char path[512], cmd[640], entry[512];
|
||||
int rc = 0;
|
||||
|
||||
for (int k = 0; k < r->n_files; k++) {
|
||||
snprintf(path, sizeof path, "%s/%s", tmpdir, r->files[2 * k]);
|
||||
char *slash = strchr(path + strlen(tmpdir) + 1, '/');
|
||||
if (slash && !parent_owned[k]) continue;
|
||||
if (unlink(path) != 0 && errno != ENOENT) rc = -1;
|
||||
}
|
||||
|
||||
snprintf(entry, sizeof entry, "%s/%s", tmpdir, r->entry);
|
||||
char *dot = strrchr(entry, '.');
|
||||
if (dot && strcmp(dot, ".ww") == 0) *dot = '\0';
|
||||
if (unlink(entry) != 0 && errno != ENOENT) rc = -1;
|
||||
snprintf(cmd, sizeof cmd, "rm -rf %s.sepwork", entry);
|
||||
if (runwait(cmd) != 0) rc = -1;
|
||||
|
||||
for (int k = 0; k < r->n_files; k++) {
|
||||
snprintf(path, sizeof path, "%s/%s", tmpdir, r->files[2 * k]);
|
||||
char *slash = strchr(path + strlen(tmpdir) + 1, '/');
|
||||
if (slash && parent_owned[k]) {
|
||||
*slash = '\0';
|
||||
if (rmdir(path) != 0 && errno != ENOENT) rc = -1;
|
||||
}
|
||||
}
|
||||
if (rmdir(tmpdir) != 0) rc = -1;
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int
|
||||
run_row(const char *driver, const struct row *r, int idx, const char *tag)
|
||||
{
|
||||
char tmpdir[64];
|
||||
snprintf(tmpdir, sizeof tmpdir, "/tmp/modparam_%s_%d_%d",
|
||||
tag, getpid(), idx);
|
||||
mkdir(tmpdir, 0755);
|
||||
(void)idx;
|
||||
char tmpdir[] = "/tmp/modparam_XXXXXX";
|
||||
if (mkdtemp(tmpdir) == NULL) {
|
||||
fprintf(stderr, "modparam_callee[%s][%s]: mkdtemp failed\n",
|
||||
tag, r->label);
|
||||
return 1;
|
||||
}
|
||||
int fail = 0;
|
||||
int parent_owned[4] = { 0 };
|
||||
|
||||
for (int k = 0; k < r->n_files; k++) {
|
||||
if (write_one(tmpdir, r->files[2 * k],
|
||||
r->files[2 * k + 1]) != 0) {
|
||||
r->files[2 * k + 1], &parent_owned[k]) != 0) {
|
||||
fprintf(stderr,
|
||||
"modparam_callee[%s][%s]: write %s failed\n",
|
||||
tag, r->label, r->files[2 * k]);
|
||||
return 1;
|
||||
fail++;
|
||||
goto cleanup;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -239,8 +249,11 @@ run_row(const char *driver, const struct row *r, int idx, const char *tag)
|
||||
}
|
||||
|
||||
cleanup:
|
||||
snprintf(cmd, sizeof cmd, "rm -rf %s", tmpdir);
|
||||
(void)runwait(cmd);
|
||||
if (cleanup_row(tmpdir, r, parent_owned) != 0) {
|
||||
fprintf(stderr, "modparam_callee[%s][%s]: cleanup failed\n",
|
||||
tag, r->label);
|
||||
if (fail == 0) fail++;
|
||||
}
|
||||
return fail;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user