Files
ww/test/wcc/815_fmt_int_run.c
Hojun-Cho a95a7a316b 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.
2026-08-07 23:21:04 +09:00

100 lines
3.9 KiB
C

/*
* 815: residual separated-package cstage/wwstage assembly identity.
* Runtime is owned by r815_*; -S stops both driver legs before assembly,
* archive creation, and linking. The sorted package-assembly concatenation
* remains the byte oracle.
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/stat.h>
#include <sys/wait.h>
struct row { const char *label, *path; };
static const struct row rows[] = {
{ "bare_int", "test/wcc/data/r815_bare_int/case.ww" },
{ "bare_int_neg", "test/wcc/data/r815_bare_int_neg/case.ww" },
{ "bare_uint", "test/wcc/data/r815_bare_uint/case.ww" },
{ "uint_highbit", "test/wcc/data/r815_uint_highbit/case.ww" },
{ "int_printf", "test/wcc/data/r815_int_printf/case.ww" },
{ "unaffected_i64", "test/wcc/data/r815_unaffected_i64/case.ww" },
{ "unaffected_str", "test/wcc/data/r815_unaffected_str/case.ww" },
{ "mixed", "test/wcc/data/r815_mixed/case.ww" },
};
static int runwait(const char *cmd) {
int rc = system(cmd);
return rc != -1 && WIFEXITED(rc) ? WEXITSTATUS(rc) : -1;
}
static int copyfile(const char *src, const char *dst) {
char buf[8192]; size_t n; int rc = 0;
FILE *in = fopen(src, "rb"), *out;
if (!in) return -1;
out = fopen(dst, "wb");
if (!out) { fclose(in); return -1; }
while ((n = fread(buf, 1, sizeof buf, in)) != 0)
if (fwrite(buf, 1, n, out) != n) { rc = -1; break; }
if (ferror(in)) rc = -1;
if (fclose(out) != 0) rc = -1;
fclose(in); return rc;
}
static int samefile(const char *a, const char *b) {
FILE *fa = fopen(a, "rb"), *fb = fopen(b, "rb"); int rc = 0;
if (!fa || !fb) rc = -1;
else for (;;) { int ca = fgetc(fa), cb = fgetc(fb); if (ca != cb) { rc = -1; break; } if (ca == EOF) break; }
if (fa) fclose(fa); if (fb) fclose(fb); return rc;
}
static int byteid(const char *cdrv, const char *wdrv, const char *cwd,
const struct row *r, int seq) {
char tmp[256], src[512], cs[512], ws[512], cmd[2048]; int rc = -1;
snprintf(tmp, sizeof tmp, "/tmp/fic_%d_b_%d", getpid(), seq);
snprintf(src, sizeof src, "%s/main815b.ww", tmp);
snprintf(cs, sizeof cs, "%s/all_cs.s", tmp);
snprintf(ws, sizeof ws, "%s/all_ww.s", tmp);
/* an unowned path (stale dir, full /tmp) must not be built in — or
* rm -rf'd — below. */
if (mkdir(tmp, 0755) != 0) { perror(tmp); return -1; }
if (copyfile(r->path, src) != 0) goto out;
snprintf(cmd, sizeof cmd,
"cd %s && timeout 180 %s build -S -I %s/lib "
"-o %s/main815b_c %s 2>/dev/null", tmp, cdrv, cwd, tmp, src);
if (runwait(cmd) != 0) goto out;
snprintf(cmd, sizeof cmd,
"cd %s && timeout 180 %s build -S -I %s/lib "
"-o %s/main815b_w %s 2>/dev/null", tmp, wdrv, cwd, tmp, src);
if (runwait(cmd) != 0) goto out;
snprintf(cmd, sizeof cmd,
"cat %s/main815b_c.sepwork/*.s > %s 2>/dev/null", tmp, cs);
if (runwait(cmd) != 0) goto out;
snprintf(cmd, sizeof cmd,
"cat %s/main815b_w.sepwork/*.s > %s 2>/dev/null", tmp, ws);
if (runwait(cmd) != 0) goto out;
rc = samefile(cs, ws);
out:
if (rc != 0) fprintf(stderr, "fmt_int_run[%s]: byte mismatch/error\n", r->label);
snprintf(cmd, sizeof cmd, "rm -rf %s", tmp);
if (runwait(cmd) != 0) {
fprintf(stderr, "fmt_int_run[%s]: cleanup %s failed\n", r->label, tmp);
if (rc == 0) rc = -1;
}
return rc;
}
int main(void) {
const char *bin = getenv("BIN"); char cwd[1024], absbin[1024];
char cdrv[1024], wdrv[1024];
if (!getcwd(cwd, sizeof cwd)) return 1;
if (!bin) bin = "out/bin";
if (bin[0] != '/') { snprintf(absbin, sizeof absbin, "%s/%s", cwd, bin); bin = absbin; }
snprintf(cdrv, sizeof cdrv, "%s/ww", bin);
snprintf(wdrv, sizeof wdrv, "%s/ww_ww", bin);
if (access(wdrv, X_OK) != 0) { fprintf(stderr, "fmt_int_run: skip wwstage\n"); return 0; }
int n = (int)(sizeof rows / sizeof rows[0]), fail = 0;
for (int i = 0; i < n; i++) if (byteid(cdrv, wdrv, cwd, &rows[i], i) != 0) fail++;
if (fail) { fprintf(stderr, "fmt_int_run: %d/%d byte rows failed\n", fail, n); return 1; }
printf("fmt_int_run: %d/%d byte rows ok\n", n, n); return 0;
}