ww: print final status for explicit test failures
This commit is contained in:
@@ -7190,6 +7190,159 @@ must match exactly. Existing package execution, timeout, interruption,
|
||||
transaction, persistence, byte-identity, and cleanup owners continue to prove
|
||||
the mechanisms this slice does not alter.
|
||||
|
||||
### 11.34 Implemented final `FAIL` for explicit ordinary test failures
|
||||
|
||||
An ordinary `ww test` request with an explicit target now ends its ordered
|
||||
standard output with exactly one command-owned `FAIL\n` when test setup, build,
|
||||
or execution fails. The line follows every package result, including successful
|
||||
packages ordered after an earlier failure. It applies to one or many explicit
|
||||
directory, recursive, dotted-directory, or raw-file targets; filters and list
|
||||
mode; and the private execution of a retained test. It does not apply to bare
|
||||
implicit-current-directory `ww test`, `-c`, `-S`, `ww build`, command-line
|
||||
usage/shape or output preflight rejection, publication-only failure,
|
||||
capture-only failure, cleanup-only failure, allocation/systemic coordinator
|
||||
failure, or later direct execution of a retained binary.
|
||||
|
||||
#### Pinned Go evidence and classification
|
||||
|
||||
The sole authority is official Go 1.26.5 at commit
|
||||
`c19862e5f8415b4f24b189d065ed739517c548ba`:
|
||||
|
||||
- `runTest` reports setup errors, writes the per-package setup-failure result,
|
||||
and sets the command exit status
|
||||
([`cmd/go/internal/test/test.go`, lines 1010–1061](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/internal/test/test.go#L1010-L1061)).
|
||||
It then creates a root `go test` action owned by `printExitStatus`, orders all
|
||||
package print actions, and executes that root
|
||||
([lines 1099–1124](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/internal/test/test.go#L1099-L1124)).
|
||||
- `builderTest` constructs the ordinary build/run/clean/print chain and gives
|
||||
the run and print boundaries the failure handling needed to reach ordered
|
||||
output; its compile-only branch instead uses a dependency-sensitive nop
|
||||
print action
|
||||
([lines 1133–1169 and 1185–1366](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/internal/test/test.go#L1133-L1366)).
|
||||
- `(*runTestActor).Act` turns a dependency build failure into a package test
|
||||
result and sets exit status 1
|
||||
([lines 1436–1521](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/internal/test/test.go#L1436-L1521)).
|
||||
Every non-nil execution error, including nonzero exit or abnormal/start
|
||||
failure, likewise sets the exit status and emits the package failure result
|
||||
([lines 1644–1774](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/internal/test/test.go#L1644-L1774)).
|
||||
- `builderCleanTest` and `builderPrintTest` put cleanup and captured package
|
||||
output before the root status action
|
||||
([lines 2237–2259](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/internal/test/test.go#L2237-L2259)).
|
||||
`printExitStatus` then prints exactly `FAIL\n` when at least one package
|
||||
argument was explicit and the global exit status is nonzero
|
||||
([lines 2262–2284](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/internal/test/test.go#L2262-L2284)).
|
||||
- Official `test_status.txt` requires a failing package, a later successful
|
||||
package, and a final standalone `FAIL\n`
|
||||
([lines 3–6](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/testdata/script/test_status.txt#L3-L6)).
|
||||
Official `test_syntax_error_says_fail.txt` requires `FAIL` for an explicit
|
||||
test build/setup syntax failure
|
||||
([lines 1–13](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/testdata/script/test_syntax_error_says_fail.txt#L1-L13)).
|
||||
- `testFlags` records explicit file operands in `pkgArgs`
|
||||
([`cmd/go/internal/test/testflag.go`, lines 219–290](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/internal/test/testflag.go#L219-L290));
|
||||
`PackagesAndErrors` turns those files into the command-line package
|
||||
([`cmd/go/internal/load/pkg.go`, lines 2895–2918](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/internal/load/pkg.go#L2895-L2918)),
|
||||
which `GoFilesPackage` constructs
|
||||
([lines 3244–3315](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/internal/load/pkg.go#L3244-L3315)).
|
||||
|
||||
Those source rules and official assertions are behavior directly implemented
|
||||
or asserted by pinned Go. The single-explicit-package and raw-file cases are
|
||||
derived from `len(pkgArgs) != 0` and the explicit-file loading path. The bare
|
||||
implicit exclusion is derived from empty `pkgArgs`. The compile-only and
|
||||
publication-only exclusions are derived from their uncleared dependency
|
||||
failure preventing the root actor under the pinned work executor
|
||||
([`cmd/go/internal/work/exec.go`, lines 134–205](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/internal/work/exec.go#L134-L205)).
|
||||
|
||||
#### Fresh four-axis audit and direct pre-fix measurements
|
||||
|
||||
The bounded audit considered all four permanent axes and selected only this
|
||||
test-command status gap:
|
||||
|
||||
- **Go-like build:** pinned unresolved-symbol handling and its undeclared-main
|
||||
case are owned by `(*ErrorReporter).errorUnresolved`
|
||||
([`cmd/link/internal/ld/errors.go`, lines 29–65](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/link/internal/ld/errors.go#L29-L65)),
|
||||
with official assertions in `TestUndefinedRelocErrors`
|
||||
([`cmd/link/internal/ld/ld_test.go`, lines 19–45](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/link/internal/ld/ld_test.go#L19-L45))
|
||||
and `issue10978/main.go`
|
||||
([lines 5–27](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/link/internal/ld/testdata/issue10978/main.go#L5-L27)).
|
||||
Direct Cstage and WWstage no-main builds both exited 1 with identical linker
|
||||
diagnostics and no output. This candidate was aligned.
|
||||
- **Go-like test:** an explicit failing directory made both stages exit 1 with
|
||||
empty stderr and byte-identical 207-byte stdout (SHA-256
|
||||
`3d0d44d5d9c4d4d95446382807ee092a611f19b43dc3013cf8df76f135cb5c46`),
|
||||
ending at its package failure rather than a standalone marker. A failing then
|
||||
successful `-j 2` request had byte-identical 384-byte stdout (SHA-256
|
||||
`4623567924df78375fcca84ff797b7cb89d06d3fd5382704d8b9ebb79916b9d9`)
|
||||
ending at the successful `ok` result. A raw-file failure had byte-identical
|
||||
121-byte stdout (SHA-256
|
||||
`8db356ffc5b3a6d9df3308bfba8301329c5c07ce30c5ccd5cc5ee22a6c43331c`)
|
||||
ending at harness accounting. Explicit missing-import build failure likewise
|
||||
lacked the final marker. These directly measured pre-fix WW facts establish
|
||||
the selected external difference. Bare implicit and `-c` failures already
|
||||
omitted the marker and were aligned exclusions.
|
||||
- **Go-like package:** `MultiplePackageError` and package scanning implement
|
||||
conflicting selected declarations
|
||||
([`go/build/build.go`, lines 538–548 and 931–967](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/go/build/build.go#L538-L548));
|
||||
`TestMultiplePackageImport` asserts the rule
|
||||
([`go/build/build_test.go`, lines 105–133](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/go/build/build_test.go#L105-L133)).
|
||||
Both WW stages rejected an `alpha`/`beta` directory identically before tools.
|
||||
This candidate was aligned.
|
||||
- **Go-like import:** `unusedImports` and `errorUnusedPkg` implement the unused
|
||||
renamed-import diagnostic
|
||||
([`cmd/compile/internal/types2/resolver.go`, lines 706–740](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/compile/internal/types2/resolver.go#L706-L740));
|
||||
official `importdecl0` asserts ordinary and renamed forms
|
||||
([lines 9–27](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/internal/types/testdata/check/importdecl0/importdecl0a.go#L9-L27)).
|
||||
After normalizing only PID-bearing scratch roots, both WW stages produced the
|
||||
same unused-renamed-import diagnostic and no output. This candidate was
|
||||
aligned.
|
||||
|
||||
The command results in that list are directly measured WW behavior; the linked
|
||||
source and tests are behavior directly implemented or asserted by pinned Go.
|
||||
The conclusion that only test presentation changes while build, package, and
|
||||
import identity remain fixed is behavior derived from the pinned action and
|
||||
final-status placement.
|
||||
|
||||
#### Ownership, final behavior, and preserved boundaries
|
||||
|
||||
The directory owner is `internal/wwpackage.packagecommand`: its private
|
||||
explicit-target bit affects only final status, and `pkgemitplan`/`pkgemitgroup`
|
||||
record attributable build/run failure while preserving canonical result order.
|
||||
After all package captures, package results, install attempts, and temporary-root
|
||||
cleanup, the coordinator emits one final line. Attributable setup/load rejection
|
||||
uses the same status helper. The two public drivers own the raw-file equivalent:
|
||||
they remember the producer or process result, finish their existing cleanup,
|
||||
then emit the line. A successful run followed only by install or cleanup failure
|
||||
does not acquire test-failure status.
|
||||
|
||||
Loading and source selection, canonical package and import identity, graph
|
||||
nodes, action construction, scheduling, compiler/assembler/linker invocation,
|
||||
generated main, child argv/environment/cwd/stdin, capture bytes, package
|
||||
diagnostics, and diagnostic precedence are unchanged. Runtime nonzero exit,
|
||||
signal, timeout, and executable-start failure keep their existing
|
||||
classification; only the command status line follows. One command-global bit
|
||||
is isolated from every product-local capture, so parallel completion order
|
||||
cannot duplicate or reorder it. If the coordinator itself is interrupted before
|
||||
final emission no post-termination output is promised; an observed child
|
||||
interruption is an ordinary run failure.
|
||||
|
||||
Artifact construction and bytes are unchanged. A failing running-retained test
|
||||
still preserves prior public bytes and creates no new executable; successful
|
||||
products in a mixed request retain their existing independent install results.
|
||||
Producer failure, publication rejection, transaction rollback, cleanup, and
|
||||
residue ownership are unchanged, and the marker creates no file. Physical
|
||||
directories and the private explicit-target signal do not enter package,
|
||||
import, graph, action, artifact, symbol, `.wwi`, publication, or persistence
|
||||
identity. No persisted byte or key changed, so build workdir format remains
|
||||
`18`, test workdir format remains `19`, and semantic storage format remains `3`.
|
||||
|
||||
The WW-native `explicit_test_failure_has_final_status` observer covers both
|
||||
stages for single and concurrent failing/succeeding packages, filters, list
|
||||
mode, raw files, setup/build and runtime failure, success, bare implicit and
|
||||
compile-only exclusions, running retained rollback, artifact-byte equality,
|
||||
diagnostic equality, exact cardinality/order, and `.new`/transaction cleanup.
|
||||
Existing directory execution observers cover signals, timeouts, child cleanup,
|
||||
and canonical-order behavior with the new final line, while build-mode controls
|
||||
prove that the other command axis remains silent.
|
||||
|
||||
## 12. Candidate architectures and hard-gate decision
|
||||
|
||||
Five candidates were developed as coherent systems, not as feature bins.
|
||||
|
||||
13
docs/spec.md
13
docs/spec.md
@@ -790,6 +790,19 @@ linker, and other build failures retain their diagnostic standard-error
|
||||
channel; build-action stdout and stderr remain separate. Parallel products own
|
||||
independent captures and are still emitted in canonical product order.
|
||||
|
||||
After those ordered results, an ordinary explicit `ww test` request that records
|
||||
an attributable setup, build, or execution failure emits exactly one standalone
|
||||
`FAIL\n` on standard output. The line is command-owned: it follows even a later
|
||||
successful package result, and a single explicit directory, recursive or dotted
|
||||
directory, or raw source file is sufficient. Runtime nonzero exit, signal,
|
||||
timeout, or executable-start failure all set that status. Filters, list mode,
|
||||
and the private execution of a retained test keep the same rule. Bare implicit
|
||||
current-directory `ww test`, `-c`, `-S`, build requests, CLI usage/shape or
|
||||
output preflight, publication-only failure, capture-only failure, cleanup-only
|
||||
failure, and later direct execution of a retained binary do not emit it. The
|
||||
marker changes no capture, diagnostic, executable, package/import/action
|
||||
identity, publication decision, or persistent byte.
|
||||
|
||||
The coordinator does not change its own cwd or environment. Parallel products
|
||||
receive independent child environments and each uses its own source directory.
|
||||
Relative ordinary files, `testdata`, and writes resolve there for every
|
||||
|
||||
@@ -322,6 +322,18 @@ has a distinct capture, while canonical group-order emission remains
|
||||
byte-stable across `-j` values. Build-plan stdout and stderr stay distinct, and
|
||||
loader/build diagnostics stay on stderr.
|
||||
|
||||
After canonical result emission, an ordinary test command with any explicit
|
||||
directory, recursive, dotted-directory, or raw-file target emits exactly one
|
||||
final standalone `FAIL\n` when attributable setup, build, or test execution
|
||||
failed. It follows later successful package output and applies to filters, list
|
||||
mode, signals, timeouts, executable-start failures, and running retained tests.
|
||||
The bare implicit-current-directory form, `-c`, `-S`, build requests, CLI
|
||||
usage/shape or output preflight, publication-only, capture-only, cleanup-only,
|
||||
and direct retained-binary execution do not receive the command marker.
|
||||
Directory coordination and both raw-file drivers own only this final
|
||||
presentation state; test captures, result trailers, diagnostics, scheduling,
|
||||
rollback, artifact bytes, and persisted action identity remain unchanged.
|
||||
|
||||
The physical directory remains distinct from exact dotted package identity and
|
||||
from production, internal, external, recompiled, support, and generated-main
|
||||
action identity. Only product execution uses it. Compiler, assembler, archiver,
|
||||
|
||||
Reference in New Issue
Block a user