build: omit named test source operands
This commit is contained in:
@@ -10080,6 +10080,170 @@ No serialized format changes. Build workdir format remains `18`, test workdir
|
||||
format remains `19`, semantic storage format remains `3`, and there is no test
|
||||
result cache.
|
||||
|
||||
### 11.51 Implemented explicit named test-source build omission
|
||||
|
||||
A single existing raw `ww build` operand whose requested final basename ends
|
||||
exactly `_test.ww` is now a test-only named source. WW syntax-observes only the
|
||||
package clause and its initial contiguous import section, preserves any read/header
|
||||
diagnostic, then omits the valid test-only root before logical resolution or
|
||||
action construction. This is deliberately distinct from the leading-dot and
|
||||
underscore rule in 11.50: `_test.ww` reaches that earlier exclusion, whereas a
|
||||
visible `x_test.ww` reaches this test-only omission.
|
||||
|
||||
#### Pinned authority, tests, and applicability
|
||||
|
||||
- **behavior directly implemented or asserted by pinned Go** — official Go
|
||||
1.26.5 commit `c19862e5f8415b4f24b189d065ed739517c548ba` recognizes an
|
||||
existing non-directory named `.go` operand in `PackagesAndErrors`
|
||||
([`cmd/go/internal/load/pkg.go`, lines 2903–2918](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/internal/load/pkg.go#L2903-L2918)),
|
||||
builds its synthetic command-line package with `UseAllFiles`
|
||||
([lines 3244–3315](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/internal/load/pkg.go#L3244-L3315)),
|
||||
and classifies `_test.go` separately from `GoFiles`
|
||||
([`go/build/build.go`, lines 930–1036](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/go/build/build.go#L930-L1036)).
|
||||
`UseAllFiles` bypasses ordinary target and build-expression rejection, but
|
||||
not that test-file classification
|
||||
([lines 1438–1509](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/go/build/build.go#L1438-L1509)).
|
||||
- **behavior directly implemented or asserted by pinned Go** — on a
|
||||
successfully scanned header, `readGoInfo` reads the initial package/import
|
||||
header and one stop byte, then removes that byte before parsing; on header
|
||||
syntax recovery it deliberately drains the remaining source
|
||||
([`go/build/read.go`, lines 265–315](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/go/build/read.go#L265-L315)).
|
||||
Every raw NUL reached by its reader is a read error
|
||||
([lines 71–89](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/go/build/read.go#L71-L89));
|
||||
`parser.ImportsOnly` stops before ordinary declarations
|
||||
([`go/parser/parser.go`, lines 2887–2923](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/go/parser/parser.go#L2887-L2923)).
|
||||
Thus a package or initial-import header error precedes omission, while a
|
||||
later declaration/body error does not become an ordinary-build error.
|
||||
- **behavior directly implemented or asserted by pinned Go** — ordinary
|
||||
initial loading does not recursively resolve test imports
|
||||
([`cmd/go/internal/load/pkg.go`, lines 350–358](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/internal/load/pkg.go#L350-L358));
|
||||
`go/build` records their metadata at `go/build/build.go:1037–1040`.
|
||||
Build checks loader errors first and then omits a test-only root before
|
||||
output/action construction
|
||||
([`cmd/go/internal/work/build.go`, lines 459–559 and 731–745](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/internal/work/build.go#L459-L559)).
|
||||
- **behavior directly implemented or asserted by pinned Go** — related
|
||||
official anchors are `go/build/build_test.go:382–421` (`TestMatchFile`),
|
||||
`go/build/build_test.go:812–831` (`TestDirectives` and `XTestDirectives`),
|
||||
`go/build/read_test.go:17–73,120–159,165–249` (header boundary, NUL, and
|
||||
syntax recovery),
|
||||
`cmd/go/testdata/script/test_relative_cmdline.txt:1–49`, and
|
||||
`cmd/go/testdata/script/build_test_only.txt:1–18`. The pinned official
|
||||
repository has no script that directly invokes `go build NAME_test.go`; the
|
||||
exact named-build result below is derived from its pinned loader and action
|
||||
ordering, not presented as an unanchored direct script assertion.
|
||||
- **behavior derived from the pinned implementation** — one valid named test
|
||||
source produces no build action. No effective `-o` and exact `/dev/null`
|
||||
succeed silently; a non-directory output reports `ww: no packages to
|
||||
build\n`; an existing or trailing-slash output directory reports
|
||||
`ww: no main packages to build\n`. Header loading occurs before those
|
||||
empty-selection branches.
|
||||
- **behavior derived from the pinned implementation** — the pinned body
|
||||
boundary is byte-sensitive: an ordinary non-`i` stop byte, a first malformed
|
||||
UTF-8 byte, or a later BOM byte is excluded, while a reached NUL and an
|
||||
unterminated comment remain load errors; a following byte `i` is attempted as
|
||||
another import. WW applies the corresponding rule at its lexical `import`
|
||||
boundary: it never lexes the first ordinary body token, but preserves NUL and
|
||||
comment diagnostics encountered while skipping header trivia.
|
||||
|
||||
The rule honestly applies to WW's local, manifest-free literal `.ww` model:
|
||||
`*_test.ww` already means test source for directory selection and `ww test`.
|
||||
It introduces no module, manifest, registry, lock, network resolver, cache,
|
||||
generalized import grammar, source build expression, or test-result cache.
|
||||
|
||||
#### Source and identity ownership
|
||||
|
||||
- **behavior directly implemented or asserted by pinned Go** — named-source
|
||||
package construction presents `Stat`-derived file information through its
|
||||
synthetic directory. The operand spelling remains the file name presented
|
||||
to selection, even though `Stat` follows a symlink.
|
||||
- **behavior derived from the pinned implementation** — the twin true owners
|
||||
are `cmd/ww/main.c::do_build` and `selfhost/cmd/ww/main.ww::dobuild`, after
|
||||
the existing hidden-prefix check and before `resolve_module` / `resolvemodule`.
|
||||
A requested visible non-directory spelling ending `_test.ww` is classified
|
||||
from that spelling; a symlink to a directory remains a directory request.
|
||||
The finite-stream header reader is not a regular-file restriction: a supplied
|
||||
finite FIFO is read as a source, while an unreadable entry reports its header
|
||||
read failure. Physical parent directories and symlink targets remain loader
|
||||
metadata, never canonical package or import identity.
|
||||
- **behavior derived from the pinned implementation** — platform-looking
|
||||
visible names such as `x_windows_test.ww` remain test-only named sources.
|
||||
Multiple named sources, logical operands without `.ww`, directories,
|
||||
recursive requests, `ww run`, and all visible non-test raw operands retain
|
||||
their prior routes. In particular, this does not implement Go's multiple
|
||||
named-source package collection.
|
||||
- **behavior derived from the pinned implementation** — the header observation
|
||||
is discarded after classification. It creates no canonical package,
|
||||
command-line package representative, dotted import identity, qualifier,
|
||||
symbol namespace, `.wwi`, action, archive, publication, or persistence key.
|
||||
Initial import syntax is checked solely for load-error precedence; omitted
|
||||
test-source imports are not resolved and create no graph edge or action.
|
||||
|
||||
#### Build, test, package, and import effects
|
||||
|
||||
- **behavior directly measured WW behavior** — before this change, both stages
|
||||
compiled, linked, published, persisted, and ran a valid visible
|
||||
`only_test.ww`; `ww build -w WORK -o OUT only_test.ww` exited 0 with empty
|
||||
streams, a byte-identical mode-0755 executable, populated work state, and
|
||||
runtime status 19. A missing test-only import likewise reached ordinary
|
||||
import resolution.
|
||||
- **behavior derived from the pinned implementation** — post-contract build
|
||||
behavior is an empty production selection after a valid header: no compiler,
|
||||
assembler, archiver, linker, generated main, test harness, test child, or
|
||||
program process starts. `-S` follows the same no-action rule. No runtime
|
||||
result can occur.
|
||||
- **behavior derived from the pinned implementation** — package behavior is
|
||||
confined to the transient header check; no production/test variant or
|
||||
package action remains. Import behavior is likewise confined to syntax;
|
||||
missing test-only dotted imports, late imports, body syntax/type errors, and
|
||||
runtime faults cannot enter the production graph.
|
||||
- **behavior derived from the pinned implementation** — test behavior is an
|
||||
explicit non-effect. Raw `ww test`, `ww test -c`, and `ww test -S` continue
|
||||
to select named test files. Directory and recursive `ww build` already
|
||||
exclude selected test sources and remain unchanged.
|
||||
|
||||
#### Diagnostics, artifacts, and lifecycle
|
||||
|
||||
- **behavior derived from the pinned implementation** — CLI-shape and
|
||||
multiple-operand delegation retain their prior precedence; 11.50 prefix
|
||||
exclusion precedes this header reader. Header read/package/initial-import
|
||||
diagnostics precede output policy. A first ordinary malformed UTF-8/BOM body
|
||||
byte is excluded, while a reached NUL or unterminated header-trivia comment
|
||||
is a header diagnostic. Once the header is valid, no unresolved import,
|
||||
graph, producer, linker, or runtime diagnostic may surface. Both
|
||||
stages use the same header boundary and must produce byte-identical status,
|
||||
stdout, and stderr.
|
||||
- **behavior derived from the pinned implementation** — cold no-action success
|
||||
creates no default/explicit output, output directory, `.wwi`, unit, assembly,
|
||||
object, archive, init product, `.sepwork`, workdir, stamp, transaction,
|
||||
capture, result, or private build temporary. Output-policy diagnostics also
|
||||
create none of those products.
|
||||
- **behavior derived from the pinned implementation** — a warm request starts
|
||||
no transaction, mutation, invalidation, reuse check, timestamp refresh, or
|
||||
producer. Existing output, sidecar, workdir and artifacts remain
|
||||
byte-identical on success and failure; no `.new`, `.install`, `.wwtxn.*`,
|
||||
backup, or recovery residue remains. Restoring a visible non-test source
|
||||
reuses prior valid warm state by the unchanged ordinary route.
|
||||
- **behavior derived from the pinned implementation** — no action means no
|
||||
publication, rollback work, producer/runtime failure path, shared lock, or
|
||||
child process. Concurrent Cstage/WWstage no-action and header-diagnostic
|
||||
requests are isolated. Interruption during header reading leaves no owned
|
||||
persistent state; after a valid header there is no child or publication window
|
||||
to clean up. Every reader closes its descriptor and releases request-local
|
||||
storage before return.
|
||||
- **behavior derived from the pinned implementation** — focused proof covers
|
||||
valid, malformed-header, missing-test-import, wrong-platform, symlink and
|
||||
finite-stream operands; default/file/directory/null/assembly output modes;
|
||||
cold/warm preservation; trace-proven tool and runtime absence; rollback,
|
||||
interruption, concurrency, cleanup, complete per-stage work preservation, and
|
||||
Cstage/WWstage semantic-artifact parity. The complete per-stage snapshot
|
||||
includes `.wwtool.ww`; cross-stage comparison excludes only that intentionally
|
||||
different producer binary snapshot. Unaffected visible production controls
|
||||
retain byte-identical outputs.
|
||||
|
||||
No serialized format changes accompany this omission. Build workdir format
|
||||
remains `18`, test workdir format remains `19`, semantic storage format remains
|
||||
`3`, and the slice adds no cache or persistent record.
|
||||
|
||||
## 12. Candidate architectures and hard-gate decision
|
||||
|
||||
Five candidates were developed as coherent systems, not as feature bins.
|
||||
|
||||
50
docs/spec.md
50
docs/spec.md
@@ -326,15 +326,38 @@ ImportPath = ident { "." ident } .
|
||||
eligible. Only the requested basename participates: a hidden parent does not
|
||||
hide visible `main.ww`, a hidden symlink spelling stays hidden for any
|
||||
existing non-directory target, and a visible symlink spelling stays eligible.
|
||||
The excluded operand creates no package, declaration, import binding/edge,
|
||||
action, artifact, initialization, test,
|
||||
publication, or persistent state. `ww build` reports the existing
|
||||
`directory contains no WW package sources` condition; an explicit running
|
||||
raw `ww test` also emits its command-owned `FAIL`, while `-c` and `-S` do not.
|
||||
This rule does not add multiple named-source package support, does not change
|
||||
visible `*_test.ww` handling, and does not apply to logical operands,
|
||||
directory/recursive requests, imports, or `ww run`. The diagnostic parent is
|
||||
presentation metadata and never canonical identity.
|
||||
The prefix-excluded operand creates no package, declaration, import
|
||||
binding/edge, action, artifact, initialization, test, publication, or
|
||||
persistent state. `ww build` reports the existing `directory contains no WW
|
||||
package sources` condition; an explicit running raw `ww test` also emits its
|
||||
command-owned `FAIL`, while `-c` and `-S` do not.
|
||||
- A visible single raw operand passed to `ww build` whose requested final
|
||||
basename ends exactly `_test.ww` is test-only after its package clause and
|
||||
contiguous initial import section have been read. Prefix exclusion remains
|
||||
first, so a bare `_test.ww` is never opened. Header read, package-clause, and
|
||||
initial-import syntax errors retain their ordinary precedence; after a valid
|
||||
header the sole root is omitted. Its dotted imports are not resolved, and a
|
||||
late import, body parse/type error, or runtime behavior is not observed. The
|
||||
first ordinary body token is not lexed, so an immediately following malformed
|
||||
UTF-8 byte or non-leading BOM is outside the header. A raw NUL reached while
|
||||
locating that token and an unterminated comment in header trivia remain load
|
||||
errors. Go's byte reader probes a following `i` as a possible `import`; the
|
||||
corresponding WW boundary is the exact lexical `import` token, so an ordinary
|
||||
WW identifier merely beginning with `i` is body syntax. This named-source
|
||||
rule retains all-files platform behavior: a
|
||||
visible `x_windows_test.ww` is still test-only. It classifies the requested
|
||||
basename of a visible symlink, not its target name; a symlink whose target is
|
||||
a directory remains a directory request.
|
||||
- Omission creates no canonical package, command-line package node, import
|
||||
binding or edge, graph/action, symbol, initializer, executable, archive,
|
||||
interface, publication, transaction, default `.sepwork`, or work-state
|
||||
mutation. It does not alter `ww test`, `ww test -c`, `ww test -S`, logical
|
||||
operands, directory/recursive selection, multiple named-source support,
|
||||
imports, or `ww run`. Physical directory and symlink-target data remain
|
||||
observation metadata, never package, import, graph, action, artifact,
|
||||
symbol, `.wwi`, publication, or persistence identity. Build workdir format
|
||||
remains 18, test workdir format remains 19, and semantic storage format
|
||||
remains 3.
|
||||
- `import acme.codec;` loads the canonical package `acme.codec`. If that
|
||||
package declares `package wire;`, the importing file sees its exported names
|
||||
as `wire.Name`; `codec.Name` is not an additional binding. An explicit alias
|
||||
@@ -467,6 +490,15 @@ ImportPath = ident { "." ident } .
|
||||
Output paths and directory metadata never become package, import, graph, action,
|
||||
symbol, artifact, `.wwi`, or persistence identity.
|
||||
|
||||
A valid omitted single raw `*_test.ww` build has an empty selection. With no
|
||||
effective `-o`, including an assembly-only request, and with exact
|
||||
`-o /dev/null`, it succeeds silently. A non-directory effective output fails
|
||||
with `ww: no packages to build`; an output-directory effective output fails
|
||||
with `ww: no main packages to build`. These empty-selection outcomes occur
|
||||
only after the raw test source's header has loaded successfully, create no
|
||||
output path or parent, and preserve every pre-existing output and work-state
|
||||
byte unchanged.
|
||||
|
||||
Every caller-visible build installation checks its destination after all
|
||||
applicable compile, assemble, archive, and link producers finish. Ordinary
|
||||
`stat` follows symlinks. An existing directory rejects as
|
||||
|
||||
@@ -239,6 +239,32 @@ platform classification, symlink spelling, output rollback, residue, and
|
||||
diagnostic/artifact parity. Directory package coordination and test process,
|
||||
filter, timeout, signal, and descendant topology are unchanged.
|
||||
|
||||
The corresponding focused dual-stage named-test-source build observer proves
|
||||
the distinct `ww build` rule for one visible raw operand ending exactly
|
||||
`_test.ww`. It requires each stage to read the package clause and contiguous
|
||||
initial imports before omitting the sole root: unreadable/header-syntax inputs
|
||||
retain their diagnostics, while a valid header prevents import resolution,
|
||||
graph/action creation, producers, runtime, publication, persistence, and all
|
||||
ordinary body-derived diagnostics. It separately proves that a first malformed
|
||||
UTF-8 or non-leading BOM body byte is outside the header, while a reached NUL
|
||||
and an unterminated header-trivia comment retain loader diagnostics. It also
|
||||
proves WW's grammar-level adaptation of Go's following-`i` byte probe: only the
|
||||
exact lexical `import` token continues the header, while an identifier such as
|
||||
`imported` begins the ordinary body. It covers
|
||||
normal, `-S`, and `/dev/null` successful
|
||||
empty selections; the exact `no packages to build` and `no main packages to
|
||||
build` output branches; requested-basename prefix, symlink, symlink-directory,
|
||||
and wrong-platform spelling controls; cold absence and warm preservation of
|
||||
outputs/work state; tool/process absence, interruption, concurrency, and
|
||||
residue cleanup. Cstage and WWstage agree on status, stdout, stderr,
|
||||
diagnostics, semantic artifact/work snapshots, and unaffected-control artifact
|
||||
bytes. Complete per-stage warm snapshots additionally cover the intentionally
|
||||
stage-specific `.wwtool.ww` producer-provenance file.
|
||||
Raw `ww test`, `-c`, and `-S` test routes retain explicit test-file selection;
|
||||
directory/recursive selection, package/import identities, graph/action
|
||||
identities, persistence formats (build 18, test 19, semantic 3), and test
|
||||
process topology are explicit non-effects.
|
||||
|
||||
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
|
||||
|
||||
Reference in New Issue
Block a user