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:
@@ -4,8 +4,9 @@
|
||||
*
|
||||
* Root cause it guards: `lib/ww/syntax/` exports the fns wcc calls, and
|
||||
* those fns' signatures name frontend types (tok, tinfo, tctx, ...). When
|
||||
* the `--sep` producer emits syntax's `.wwi`, check_exported_type recurses
|
||||
* every exported decl — and, for an exported struct, its FIELDS too (the
|
||||
* the separate-compilation producer emits syntax's `.wwi`,
|
||||
* check_exported_type recurses every exported decl — and, for an exported
|
||||
* struct, its FIELDS too (the
|
||||
* harec STORAGE_STRUCT precedent, wwi.c wwi_check_type N_TSTRUCT). Any
|
||||
* referenced type that is itself unexported aborts the producer with
|
||||
* "exported declaration references unexported type". Pre-fix, syntax's
|
||||
@@ -21,24 +22,24 @@
|
||||
* (#75). It happens to link + run end-to-end, which also shows the
|
||||
* qualified-ref path resolves across the sep boundary.
|
||||
*
|
||||
* Asserts (all COLD — per-stage WW_PKGCACHE wipes the package cache):
|
||||
* Asserts (direct builds compile every package):
|
||||
* 1. Build + run, BOTH stages -> exit EXPECT_EXIT (`syntax.tokname(
|
||||
* TK_INT)` == "int", len 3). Pre-fix the syntax producer exited 1, so
|
||||
* the build never produced a binary.
|
||||
* 2. syntax's `.wwi` is produced and carries the 16 `export type` decls.
|
||||
* 3. cs==ww (rule 10): syntax's `.wwi`/`.s`/`.unit.ww` AND the final
|
||||
* binary are byte-identical between `ww --sep` and `ww_ww --sep`.
|
||||
* binary are byte-identical between `ww` and `ww_ww`.
|
||||
* 4. NON-VACUITY (the bug, isolated, BOTH compilers): replay the producer
|
||||
* `w6c -c -I` on the produced `syntax.unit.ww` -> exits 0 (exports
|
||||
* present). On a copy with `export ` stripped from the type decls ->
|
||||
* MUST exit non-zero (the export-check fires). Proven for w6c + w6c_ww.
|
||||
*
|
||||
* Light wwstage-driver test (CLAUDE.md rule 14): all intermediates are
|
||||
* `-o`-redirected to /tmp, so it is phase-1 parallel-safe; it only READS
|
||||
* All intermediates are `-o`-redirected to /tmp; it only reads
|
||||
* the in-tree `lib/ww/syntax`. Models 989_seproot_export_run.c.
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/wait.h>
|
||||
@@ -118,9 +119,8 @@ write_file(const char *path, const char *body)
|
||||
{
|
||||
FILE *f = fopen(path, "wb");
|
||||
if (!f) return -1;
|
||||
fputs(body, f);
|
||||
fclose(f);
|
||||
return 0;
|
||||
if (fputs(body, f) == EOF) { fclose(f); return -1; }
|
||||
return fclose(f);
|
||||
}
|
||||
|
||||
int
|
||||
@@ -131,13 +131,11 @@ main(void)
|
||||
char root[1024];
|
||||
if (getcwd(root, sizeof root) == NULL) return 1;
|
||||
|
||||
char td[64], cmd[8192];
|
||||
int fail = 0;
|
||||
char td[] = "/tmp/wwsynexp_XXXXXX";
|
||||
char cmd[8192];
|
||||
int fail = 0, cleanup_fail = 0;
|
||||
|
||||
snprintf(td, sizeof td, "/tmp/wwsynexp_%d", getpid());
|
||||
snprintf(cmd, sizeof cmd, "rm -rf %s", td);
|
||||
runwait(cmd);
|
||||
mkdir(td, 0755);
|
||||
if (mkdtemp(td) == NULL) return 1;
|
||||
|
||||
/* Root: QUALIFIED refs into the real syntax package — `syntax.tokname`
|
||||
* over `syntax.tkind`. The producer must serialize syntax's `.wwi`
|
||||
@@ -158,15 +156,15 @@ main(void)
|
||||
|
||||
for (int s = 0; s < 2; s++) {
|
||||
snprintf(stg[s].prog, sizeof stg[s].prog, "%s/prog.%s", td, stg[s].tag);
|
||||
/* COLD: per-stage WW_PKGCACHE -> syntax compiles fresh, so the
|
||||
* `.wwi`/`.s`/`.unit.ww` this gate inspects are always produced. */
|
||||
/* Direct builds produce the `.wwi`/`.s`/`.unit.ww` artifacts this
|
||||
* gate inspects. */
|
||||
snprintf(cmd, sizeof cmd,
|
||||
"WW_PKGCACHE='%s/cache.%s' timeout 240 %s/%s build --sep "
|
||||
"timeout 240 %s/%s build "
|
||||
"-I %s/lib/ww -o %s %s >%s/build.%s.log 2>&1",
|
||||
td, stg[s].tag, bin, stg[s].drv, root, stg[s].prog, rootww,
|
||||
bin, stg[s].drv, root, stg[s].prog, rootww,
|
||||
td, stg[s].tag);
|
||||
if (runwait(cmd) != 0) {
|
||||
fprintf(stderr, "syntaxexport FAIL: %s build --sep (pre-fix: syntax "
|
||||
fprintf(stderr, "syntaxexport FAIL: %s build (pre-fix: syntax "
|
||||
"producer rejects export-fn-over-unexported-type)\n", stg[s].drv);
|
||||
fail++;
|
||||
continue;
|
||||
@@ -268,8 +266,34 @@ main(void)
|
||||
}
|
||||
|
||||
out:
|
||||
snprintf(cmd, sizeof cmd, "rm -rf %s", td);
|
||||
runwait(cmd);
|
||||
for (int s = 0; s < 2; s++) {
|
||||
const char *tag = s == 0 ? "cs" : "ww";
|
||||
char path[1200];
|
||||
snprintf(path, sizeof path, "%s/prog.%s.sepwork", td, tag);
|
||||
snprintf(cmd, sizeof cmd, "rm -rf -- '%s'", path);
|
||||
if (runwait(cmd) != 0) cleanup_fail = 1;
|
||||
snprintf(path, sizeof path, "%s/prog.%s", td, tag);
|
||||
if (unlink(path) != 0 && errno != ENOENT) cleanup_fail = 1;
|
||||
snprintf(path, sizeof path, "%s/build.%s.log", td, tag);
|
||||
if (unlink(path) != 0 && errno != ENOENT) cleanup_fail = 1;
|
||||
}
|
||||
{
|
||||
const char *files[] = {
|
||||
"root.ww", "syntax.noexport.ww",
|
||||
"nv.w6c.wwi", "nv.w6c.s",
|
||||
"nv.w6c_ww.wwi", "nv.w6c_ww.s",
|
||||
};
|
||||
for (size_t i = 0; i < sizeof files / sizeof files[0]; i++) {
|
||||
char path[1200];
|
||||
snprintf(path, sizeof path, "%s/%s", td, files[i]);
|
||||
if (unlink(path) != 0 && errno != ENOENT) cleanup_fail = 1;
|
||||
}
|
||||
}
|
||||
if (rmdir(td) != 0) cleanup_fail = 1;
|
||||
if (cleanup_fail) {
|
||||
fprintf(stderr, "syntaxexport FAIL: cleanup incomplete under %s\n", td);
|
||||
fail++;
|
||||
}
|
||||
if (fail) {
|
||||
fprintf(stderr, "syntaxexport: %d check(s) failed\n", fail);
|
||||
return 1;
|
||||
|
||||
Reference in New Issue
Block a user