ww test: omit marker for empty list results

This commit is contained in:
2026-08-21 14:11:24 +09:00
parent 8a5fc8977f
commit 2b7fafde0c
5 changed files with 290 additions and 4 deletions

View File

@@ -7628,6 +7628,149 @@ unchanged artifact and binary bytes; build/no-test/compile-only/rejection
nonexecution; unchanged raw/direct compatibility; exact tool locale/TMPDIR; and
stage, transaction, capture, and workdir cleanup.
### 11.37 Implemented empty list-mode output
A valid directory-owned `ww test -list` request now emits one qualified test
name per selected descriptor and emits no harness list bytes when its filters
select zero tests. The test product still starts, package initialization still
runs, the harness returns success without accounting, and the coordinator still
emits the normal package `ok` result. Ordinary non-list execution with zero
selected tests remains distinct: it keeps `[no matches]` and its
discovered/selected/started/completed accounting.
#### Pinned Go evidence and fact classification
The sole authority is official Go 1.26.5 at commit
`c19862e5f8415b4f24b189d065ed739517c548ba`:
- `cmd/go` registers `-list` among the flags forwarded to the test binary
([`cmd/go/internal/test/testflag.go`, function `init`, lines 3280](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/internal/test/testflag.go#L32-L80)).
- `testing.(*M).Run` calls `listTests`, sets exit code 0, and returns before the
ordinary test execution and no-tests warning
([`testing/testing.go`, lines 24072411](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/testing/testing.go#L2407-L2411)
and [24402458](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/testing/testing.go#L2440-L2458)).
- `listTests` validates the pattern and prints only inside successful match
branches. It has no zero-match output branch
([`testing/testing.go`, function `listTests`, lines 25092535](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/testing/testing.go#L2509-L2535)).
- `testShowPass` retains successful list output, while the successful run actor
adds a no-tests suffix only if the captured bytes contain the ordinary
no-tests warning
([`cmd/go/internal/test/test.go`, function `testShowPass`, lines 649652](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/internal/test/test.go#L649-L652)
and method `(*runTestActor).Act`, lines 17061732](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/internal/test/test.go#L1706-L1732)).
- Official `list_test_simple.txt` asserts that list mode emits the matching Test,
Benchmark, and Example names
([`cmd/go/testdata/script/list_test_simple.txt`, lines 314](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/testdata/script/list_test_simple.txt#L3-L14)).
Those source branches and official positive assertions are behavior directly
implemented or asserted by pinned Go. That a zero-match `go test -list` run has
no list payload, avoids the ordinary no-tests warning, and may still receive the
command's normal successful package result is behavior derived from their
composition. WW retains its local `-list` plus `-run`/`-filter` syntax; only the
applicable selected-name and empty-result behavior is aligned.
#### Fresh four-axis audit and direct pre-fix measurements
The bounded audit examined all four permanent axes before selecting this test
runtime difference:
- **Go-like build:** pinned `(*ErrorReporter).errorUnresolved` gives a missing
`main.main` a dedicated failure
([`cmd/link/internal/ld/errors.go`, lines 2967](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/link/internal/ld/errors.go#L29-L67)),
asserted by `TestUndefinedRelocErrors` and official `issue10978`
([`cmd/link/internal/ld/ld_test.go`, lines 1945](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/link/internal/ld/ld_test.go#L19-L45),
[`testdata/issue10978/main.go`, lines 527](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/link/internal/ld/testdata/issue10978/main.go#L5-L27)).
Both WW stages rejected a selected command package without `fn main`, emitted
zero stdout and the same 50 stderr bytes (SHA-256
`9ed4d7684412c6d2e615041902072c81e9e09acb3970246d89a2c8bdddd2fcfa`),
and published no output. This audited applicable property was aligned.
- **Go-like test:** for a directory containing one `visible` test, both stages
ran `test -list -run no_such_test`, exited 0 with empty stderr, and emitted the
same 78 stdout bytes (SHA-256
`d59638ab03a27803ca8e3fd884f341bbb1535ec9604fb69bdff1de4f608a8da0`):
`[no matches]\n` followed by the normal package result. Positive list
selection printed `list_nomatch.visible` once in both stages. This synthetic
empty-result line was the selected difference.
- **Go-like package:** pinned `MultiplePackageError` and directory scanning
reject conflicting declarations
([`go/build/build.go`, lines 538549](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/go/build/build.go#L538-L549)
and [939967](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/go/build/build.go#L939-L967)),
asserted by `TestMultiplePackageImport` and official `testdata/multi`
([`go/build/build_test.go`, lines 105133](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/go/build/build_test.go#L105-L133)).
Both WW stages rejected an `alpha`/`beta` directory with zero stdout and the
same 159 stderr bytes (SHA-256
`eaaa0c91f41b5d3deac4caf4299d5c7c650a1330be9b43edd090b8bfea906076`).
This audited applicable property was aligned.
- **Go-like import:** pinned `unusedImports` and `errorUnusedPkg` reject a
nonblank unused alias
([`cmd/compile/internal/types2/resolver.go`, lines 706740](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/compile/internal/types2/resolver.go#L706-L740)),
asserted by official `importdecl0`
([`internal/types/testdata/check/importdecl0/importdecl0a.go`, lines 926](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/internal/types/testdata/check/importdecl0/importdecl0a.go#L9-L26)).
Both WW stages rejected an unused `spare` alias for dotted import `dep` with
zero stdout and the same diagnostic after only private scratch-PID
normalization (SHA-256
`a429b027e92d52de1c5ec581b1f45c860b0e85b459c3ac7347e2719900cec511`).
This audited applicable property was aligned without changing dotted import
identity.
The command observations and byte hashes are directly measured WW behavior.
The linked source branches and testdata assertions are behavior directly
implemented or asserted by pinned Go. Applying the empty-list rule to WW's one
local directory-owned test product while retaining its manifest-free input and
filter syntax is behavior derived from that pinned execution boundary.
Pre-fix `test -c` products were byte-identical between Cstage and WWstage:
112829 bytes, SHA-256
`d2994ef440d7ceb9be0a7caf53c90dd19d208e847e51ff41ecb89504f825c4c8`.
Directly running either retained product with the same nonmatching list filter
already emitted no stdout or stderr because it had no coordinator-supplied
package prefix. Explicit raw-file requests with package options remained a
separate rejected CLI shape in both stages.
#### Ownership, final behavior, and preserved boundaries
`lib/test.run` is the semantic owner. Its existing descriptor loop still
qualifies, filters, and prints every positive list match in order; its list
return now emits nothing extra when the selected count is zero. The package
coordinator does not recognize or strip a magic line, so identical bytes written
by package initialization or user code remain ordinary captured output.
Loading and platform source selection are unchanged. Production,
internal-test, external-test, recompiled-for-test, support, and generated-main
nodes and actions remain unchanged. Exact dotted import identity, declared
package names, aliases, variants, physical runtime directories, graph edges,
initialization order, symbols, and publication names keep their existing roles.
The product process and package initialization still run in list mode; no
per-test child starts. Positive matching, option diagnostics and precedence,
ordinary non-list no-match output, no-test-file results, and raw-file rejection
are unchanged.
The shared support implementation change legitimately changes its object,
archive, and linked test-product bytes. Its exported signature and `.wwi` byte
contract do not change. Existing content invalidation rebuilds the affected
support/link actions; there is no test-result cache and no new graph identity.
Running `-o` still executes the private product before guarded publication, and
`-c`, destination safety, transaction rollback, prior-output preservation, and
artifact modes are unchanged.
Load, compile, assemble, archive, link, initialization, signal, timeout,
interruption, child-start, publication, and cleanup failure paths retain their
existing diagnostics and precedence. Parallel products keep independent
processes, captures, environments, working directories, input descriptors, and
ordered result slots. The changed runtime branch allocates and publishes no
file, and existing cleanup remains responsible for `.new`, `.install`,
`.wwtxn.*`, captures, process groups, and request scratch.
The WW-native `list_mode_with_no_matches_emits_no_sentinel` observer proves
both stages across concurrent combined and test-only products, package
initialization, cold and warm persistent work, absence of list/accounting
sentinels, positive deterministic selection, running `-o` retention, later
direct execution, stage stdout/stderr equality, retained executable byte
identity, and `.new` cleanup. The existing routing observer separately keeps
ordinary non-list `[no matches]` plus accounting pinned.
No persisted-byte contract changed: build workdir format remains `18`, test
workdir format remains `19`, and semantic storage format remains `3`.
## 12. Candidate architectures and hard-gate decision
Five candidates were developed as coherent systems, not as feature bins.

View File

@@ -803,6 +803,17 @@ 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.
List mode starts the same directory-owned product and therefore performs its
ordinary package initialization, but it does not start any selected test child.
The harness emits exactly one newline-terminated qualified name for each test
selected by the command's filters, in descriptor order. If the selected set is
empty, the harness emits no list payload, no `[no matches]` sentinel, and no
accounting, and returns success; the coordinator still emits the ordinary
successful package result. This does not alter non-list execution: a valid
filter selecting no tests continues to emit `[no matches]` and the
discovered/selected/started/completed accounting. A retained binary invoked
directly has no coordinator package result.
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

View File

@@ -219,6 +219,16 @@ every `-j` level, and `-j 1` — the default — matches the former sequential
run loop exactly. Measured on the 31-package `lib/...` walk:
7.0s sequential, 2.4s at `-j 4`.
List mode uses that same product process and initialization boundary but starts
no per-test child. The shared language harness emits only selected qualified
test names, one per line in descriptor order. A valid filter selecting no tests
therefore produces no harness list bytes, no `[no matches]` marker, and no
accounting while the process returns success; the coordinator continues with
the package's normal `ok` result. Ordinary non-list zero-selection execution
retains its `[no matches]` marker and accounting. Concurrent products keep
independent empty or nonempty captures, and persistent work never caches a test
result.
Directory test binaries are always linked under the coordinator's temporary
product root. `-c` independently requests a caller-visible executable copy and
suppresses execution. `-o` independently requests a copy and still runs the