diff --git a/Makefile b/Makefile index b5695881..53a94c56 100644 --- a/Makefile +++ b/Makefile @@ -935,6 +935,9 @@ sizelint: test: all sizelint $(TESTS) @WW=$(BIN)/ww BIN=$(BIN) sh test/run +test-unit: all sizelint $(TESTS) + @WW=$(BIN)/ww BIN=$(BIN) UNIT=1 sh test/run + install: all mkdir -p $(PREFIX)/bin $(PREFIX)/lib cp $(BIN)/ww $(PREFIX)/bin/ @@ -1080,4 +1083,4 @@ nocc: @echo @echo "NOCC OK: $(STAGE0)/* reproduces itself from source. cc not invoked." -.PHONY: all cstage wwstage test sizelint install clean bootstrap nocc bootstrap-snapshot +.PHONY: all cstage wwstage test test-unit sizelint install clean bootstrap nocc bootstrap-snapshot diff --git a/test/run b/test/run index 7a2499e3..4f547b02 100755 --- a/test/run +++ b/test/run @@ -46,15 +46,34 @@ trap 'rm -rf "$RESULTS"' EXIT JOBS=${JOBS:-$(nproc 2>/dev/null || echo 4)} -# Emit (prefix, testpath) pairs NUL-separated. The prefix carries the -# test's _ stem so the collector iterates in lexical order, -# yielding deterministic output even though workers interleave. +# Phase 2 runs the wwstage byte-id gates (990-997) + 950_selfcheck +# sequentially. ww_ww writes intermediates next to every traversed source +# (task #15), so 991/992/994's reads of selfhost/cmd//main.{s,o, +# combined.ww} race against any concurrent driver-using test that emits +# a sibling .combined.ww (task #16). Phase 1 stays parallel for unit +# coverage; phase 2 sequential keeps the byte-id gates honest. for t in test/wcc/*.c; do [ -f "$t" ] || continue + case ${t##*/} in + 950_*|990_*|991_*|992_*|993_*|994_*|995_*|996_*|997_*) continue ;; + esac name=${t##*/}; name=${name%.c} printf '%s/%s\0%s\0' "$RESULTS" "$name" "$t" done | xargs -0 -n2 -P "$JOBS" "$0" --one || true +# UNIT=1 (make test-unit) is the inner-loop short path: skip the wwstage +# byte-id gates (990-997) and 950_selfcheck entirely. Pre-push uses +# `make test` for the full suite. +if [ "${UNIT:-0}" != "1" ]; then + for t in test/wcc/950_*.c test/wcc/990_*.c test/wcc/991_*.c \ + test/wcc/992_*.c test/wcc/993_*.c test/wcc/994_*.c \ + test/wcc/995_*.c test/wcc/996_*.c test/wcc/997_*.c; do + [ -f "$t" ] || continue + name=${t##*/}; name=${name%.c} + "$0" --one "$RESULTS/$name" "$t" || true + done +fi + fail=0 ran=0 for s in "$RESULTS"/*.status; do diff --git a/test/wcc/995_self_rebuild.c b/test/wcc/995_self_rebuild.c index ac0f072a..a188c15c 100644 --- a/test/wcc/995_self_rebuild.c +++ b/test/wcc/995_self_rebuild.c @@ -82,21 +82,18 @@ struct buildjob { /* Fork a child that runs the `ww_ww build` for this tool. The child * inherits no concurrent siblings — system() spawns a fresh /bin/sh -c. * stderr lands in /build.err so concurrent builds don't merge - * their diagnostics. - * - * The source is staged at /build.ww before the build so the - * driver writes its .combined.ww/.s/.o intermediates inside workdir — - * not next to the canonical selfhost/cmd//main.ww, where 991/992/ - * 994 read main.s as a fixture. Without staging, parallel test/run sees - * 991 race against 995's wwdump-build mid-write of main.s. */ + * their diagnostics. The driver leaves intermediates next to every + * source it traverses (selfhost/cmd//main.s, etc.) — task #15 in + * the queue will let us redirect via `-o `; until then, test/run + * serializes 990/995 after the parallel phase. */ static int spawn_build(const char *bin, const char *cwd, struct buildjob *j) { snprintf(j->workdir, sizeof j->workdir, "/tmp/wwsr_%d_%s", getpid(), j->tool); - char setup[4096]; - snprintf(setup, sizeof setup, "rm -rf %s && mkdir -p %s && cp %s/%s %s/build.ww", - j->workdir, j->workdir, cwd, j->src_rel, j->workdir); + char setup[256]; + snprintf(setup, sizeof setup, "rm -rf %s && mkdir -p %s", + j->workdir, j->workdir); if (runwait(setup) != 0) return -1; char cmd[4096]; @@ -104,15 +101,15 @@ spawn_build(const char *bin, const char *cwd, struct buildjob *j) snprintf(cmd, sizeof cmd, "cd %s && timeout 180 %s/ww_ww build -I %s/%s " "-I %s/lib/ww -I %s/lib/ww/lex -I %s/lib/ww/parse " - "-I %s/selfhost/cmd/wcc build.ww >/dev/null 2>%s/build.err", + "-I %s/selfhost/cmd/wcc %s/%s >/dev/null 2>%s/build.err", j->workdir, bin, cwd, j->inc_local, - cwd, cwd, cwd, cwd, j->workdir); + cwd, cwd, cwd, cwd, cwd, j->src_rel, j->workdir); } else { snprintf(cmd, sizeof cmd, "cd %s && timeout 180 %s/ww_ww build " "-I %s/lib/ww -I %s/lib/ww/lex -I %s/lib/ww/parse " - "-I %s/selfhost/cmd/wcc build.ww >/dev/null 2>%s/build.err", - j->workdir, bin, cwd, cwd, cwd, cwd, j->workdir); + "-I %s/selfhost/cmd/wcc %s/%s >/dev/null 2>%s/build.err", + j->workdir, bin, cwd, cwd, cwd, cwd, cwd, j->src_rel, j->workdir); } pid_t p = fork(); @@ -152,7 +149,7 @@ collect_build(const char *bin, struct buildjob *j) rc = -1; } else { char rebuilt[256], canonical[256]; - snprintf(rebuilt, sizeof rebuilt, "%s/build", j->workdir); + snprintf(rebuilt, sizeof rebuilt, "%s/main", j->workdir); snprintf(canonical, sizeof canonical, "%s/%s_ww", bin, j->tool); rc = slurp_eq(rebuilt, canonical); if (rc != 0) {