ww: report no test files for empty test packages

This commit is contained in:
2026-08-21 11:59:46 +09:00
parent 394e46ff2f
commit bcc3aa9336
6 changed files with 195 additions and 50 deletions

View File

@@ -3180,7 +3180,7 @@ still checked; that is a real zero-test package and runs one empty combined
harness. A directory with no selected test files instead follows the no-real-run harness. A directory with no selected test files instead follows the no-real-run
path: validate/compile ordinary production as needed, publish status only, and path: validate/compile ordinary production as needed, publish status only, and
create no support action, generated main, link, binary, result, or process. The create no support action, generated main, link, binary, result, or process. The
coordinator alone emits its `[no tests]` report. coordinator alone emits its `[no test files]` report.
Persistent workdirs keep a global driver/compiler/assembler/stamp identity and Persistent workdirs keep a global driver/compiler/assembler/stamp identity and
per-action committed units. When that global identity is stale, the command per-action committed units. When that global identity is stale, the command
@@ -5593,12 +5593,14 @@ precise body/export and target-removal/re-addition invalidation, combined-graph
allocation failure, repeated late internal/external/main/link rollback, and a allocation failure, repeated late internal/external/main/link rollback, and a
complete work-directory sweep for staged residue. complete work-directory sweep for staged residue.
Deliberately unchanged or unsupported behavior includes the raw single-file At completion of this earlier topology slice, deliberately unchanged or
compatibility path, WW's `[no tests]` presentation text, Go modules and build unsupported behavior included the raw single-file compatibility path, the
cache, network resolution, manifests, coverage/vet/fuzz/benchmark generation, then-current `[no tests]` presentation text, Go modules and build cache, network
source-level build expressions, quoted/grouped/dot imports, and targets other resolution, manifests, coverage/vet/fuzz/benchmark generation, source-level
than the separately specified fixed `linux/amd64` filename selection. None is build expressions, quoted/grouped/dot imports, and targets other than the
used to define canonical package or directory-product identity. separately specified fixed `linux/amd64` filename selection. Section 11.35
subsequently closes only that presentation-text gap. None is used to define
canonical package or directory-product identity.
### 11.23 Implemented case-fold collision preflight ### 11.23 Implemented case-fold collision preflight
@@ -6271,9 +6273,9 @@ selected package; missing parents are created with `0777` subject to umask. A
non-directory destination accepts exactly one selected package. Exact non-directory destination accepts exactly one selected package. Exact
`/dev/null` suppresses retained copies, permits duplicate visible names, and `/dev/null` suppresses retained copies, permits duplicate visible names, and
does not suppress execution unless `-c` is also present. A no-test package does not suppress execution unless `-c` is also present. A no-test package
performs ordinary production validation, reports `[no tests]`, and creates no performs ordinary production validation, reports `[no test files]`, and creates
binary or otherwise-unused output directory. Successful compile-only products no binary or otherwise-unused output directory. Successful test-bearing
are silent, matching Go's no-op print action. compile-only products are silent, matching Go's no-op print action.
For `-c`, the driver copies the private runnable bytes to a distinct `.new` For `-c`, the driver copies the private runnable bytes to a distinct `.new`
inode opened with executable mode `0777` subject to umask. Temporary runnable, inode opened with executable mode `0777` subject to umask. Temporary runnable,
@@ -7343,6 +7345,127 @@ Existing directory execution observers cover signals, timeouts, child cleanup,
and canonical-order behavior with the new final line, while build-mode controls and canonical-order behavior with the new final line, while build-mode controls
prove that the other command axis remains silent. prove that the other command axis remains silent.
### 11.35 Implemented Go-like no-test-files package result
A source-bearing directory test product with no selected `*_test.ww` file now
reports exactly `? <package> [no test files]\n` after ordinary production
validation. It continues to create no test-support action, generated main,
link, runnable, retained binary, captured runtime result, or process. The rule
is shared by explicit directories, implicit current-directory selection,
logical/dotted targets, recursive discovery, and compile-only or retained-output
requests. Platform-ineligible test filenames do not prevent the result. A
selected helper-only test file remains a real test product with an empty
harness; the raw single-file compatibility route remains outside the
directory-owned selected-test-file classification.
#### Pinned Go evidence and fact classification
The sole authority is official Go 1.26.5 at commit
`c19862e5f8415b4f24b189d065ed739517c548ba`:
- `builderTest` detects
`len(p.TestGoFiles)+len(p.XTestGoFiles) == 0`, keeps ordinary production as a
dependency, constructs output-preparation and print actions, and creates no
real test binary or run action
([`cmd/go/internal/test/test.go`, lines 11331169](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/internal/test/test.go#L1133-L1169)).
- `(*runTestActor).Act` owns that print action and writes exactly
`? \t%s\t[no test files]\n` in the ordinary non-coverage case
([`cmd/go/internal/test/test.go`, lines 15241557, especially 15511552](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/internal/test/test.go#L1524-L1557)).
- Official `test_no_tests.txt` invokes `go test testnorun`, requires the
`[no test files]` result, and gives production an initializer that panics if a
test binary is linked and executed
([`cmd/go/testdata/script/test_no_tests.txt`, lines 114](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/testdata/script/test_no_tests.txt#L1-L14)).
Those source rules and the script expectation are behavior directly implemented
or asserted by pinned Go. That the ordinary case compiles production, prints the
package result, and does not execute initialization is behavior derived from the
pinned action graph. Applying the bracketed status to WW's established local
package presentation is likewise derived: WW has no module import path, but its
directory product already owns the corresponding selected-test-file decision
and no-process action branch. This does not import Go's coverage behavior,
module loader, cache, manifest, registry, or network resolution.
#### Fresh four-axis audit and direct pre-fix measurements
The bounded audit considered all four permanent axes and selected only this
test-result wording gap:
- **Go-like build:** pinned unresolved-symbol handling and its special missing
`main` case are implemented by `(*ErrorReporter).errorUnresolved`
([`cmd/link/internal/ld/errors.go`, lines 2967](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/link/internal/ld/errors.go#L29-L67))
and asserted by `TestUndefinedRelocErrors`
([`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))
using `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 `package main` without `fn main`, emitted
identical 50-byte linker diagnostics, and created no output. This candidate
was aligned.
- **Go-like test:** a production directory with an aborting initializer and no
test file made both stages exit 0 with empty stderr and byte-identical 55-byte
stdout (SHA-256
`36adf30792e2900b60ec8cd02ba86e0387acebd41c4d9aab186af2c649ffe67c`):
`? /tmp/ww-go1265-four-axis.Wq8d8H/notest [no tests]\n`.
Bare implicit, logical `-I`, and `-c` forms produced the same bytes; `-c`
created no binary. A platform-excluded test file produced the same old status
class without observing its missing import or test body. These are directly
measured pre-fix WW facts and establish the selected external difference.
- **Go-like package:** `MultiplePackageError` and the package scan reject
conflicting selected declarations
([`go/build/build.go`, lines 538548 and 931967](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/go/build/build.go#L538-L548));
`TestMultiplePackageImport` asserts the file/name pairs
([`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` production directory identically
before tools. This candidate was aligned.
- **Go-like import:** `unusedImports` and `errorUnusedPkg` implement unused
ordinary and renamed-import diagnostics
([`cmd/compile/internal/types2/resolver.go`, lines 706740](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/compile/internal/types2/resolver.go#L706-L740));
official `importdecl0` asserts both forms
([`internal/types/testdata/check/importdecl0/importdecl0a.go`, lines 927](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 rejected an
unused renamed dotted import with the same diagnostic and no output. This
candidate was aligned.
The command observations in that list are directly measured WW behavior. The
linked source and testdata are behavior directly implemented or asserted by
pinned Go. Selecting only the no-test-files presentation while keeping build,
package, and import semantics fixed is behavior derived from the pinned action
boundary and WW's already aligned no-process topology.
#### Ownership, final behavior, and preserved boundaries
`internal/wwpackage.pkgemitgroup` is the sole semantic owner of the directory
package result. The loader still sets `g.notests` only after exact filename and
platform eligibility have selected the source set. Product construction still
compiles ordinary production and omits support/main/link/output/status actions;
the scheduler still skips execution. The successful result literal changes
only after that work succeeds. Loading, import, package, graph, compiler,
assembler, archiver, linker, or publication failure therefore retains its prior
diagnostic and precedence and cannot be hidden by a no-test-files result.
Canonical dotted package/import identity, declared names, file-local import
bindings, graph nodes and edges, action keys, physical-directory metadata,
symbols, `.wwi`, source units, assembly, objects, archives, and executable bytes
are unchanged. There is no new artifact or publication destination. `-c` and
`-o` still omit a binary and do not create an otherwise-unused output hierarchy;
prior caller state and persistent generations are preserved on every producer
failure. Warm reuse and invalidation still concern production actions only.
Concurrent products retain canonical ordered emission because the text remains
inside the existing group emitter. Interruption before emission makes no new
promise; the branch starts no child that can be signalled or timed out. Cleanup
still removes only request-private plan state, creates no `.new` or `.install`
stage, and leaves no test-process residue. Cstage and WWstage use the same
coordinator owner and therefore emit byte-identical diagnostics and results.
The WW-native `empty_and_invalid_package_classes` observer now requires the
exact explicit and implicit result in both stages and uses an aborting production
initializer to prove no process starts. Existing package observers cover
logical and recursive selection, platform filtering, helper-only selected test
files, compile-only/output omission, persistent cold/warm/invalidation behavior,
large scheduling sets, failure rollback, stage parity, and artifact-byte
identity. 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 ## 12. Candidate architectures and hard-gate decision
Five candidates were developed as coherent systems, not as feature bins. Five candidates were developed as coherent systems, not as feature bins.

View File

@@ -710,7 +710,9 @@ runtime lets, and init declarations found only in `*_test.ww` never enter an
ordinary production build. Test-only same-package, external-package, and valid ordinary production build. Test-only same-package, external-package, and valid
mixed directories are accepted from their selected test files. A directory mixed directories are accepted from their selected test files. A directory
with no selected test file validates ordinary production but creates no test with no selected test file validates ordinary production but creates no test
support, generated main, link, binary, result, or process. support, generated main, link, binary, captured runtime result, or process. The
coordinator reports that successful validation exactly as
`? <package> [no test files]\n`.
Every test-bearing directory product links one request-private runnable. Every test-bearing directory product links one request-private runnable.
`-c` retains an executable copy and suppresses its execution; `-o` retains a `-c` retains an executable copy and suppresses its execution; `-o` retains a

View File

@@ -207,9 +207,10 @@ not followed. A wildcard cannot consume a non-terminal exact `vendor` element,
while an explicitly vendor-rooted pattern remains legal. Every selected while an explicitly vendor-rooted pattern remains legal. Every selected
test-bearing directory becomes exactly one package run, binary, and result even test-bearing directory becomes exactly one package run, binary, and result even
when both internal and external actions exist. Selected source-bearing when both internal and external actions exist. Selected source-bearing
directories without selected test files report the usual `?` line after directories without selected test files report exactly
ordinary production validation, with no support, generated main, link, binary, `? <package> [no test files]\n` after ordinary production validation, with
result, or process. The coordinator first no support, generated main, link, binary, captured runtime result, or process.
The coordinator first
launches one driver plan for the complete command-global package/action union. launches one driver plan for the complete command-global package/action union.
After that shared build completes, `-j N` schedules up to N successful selected After that shared build completes, `-j N` schedules up to N successful selected
test binaries concurrently under `os.exec` start/poll supervision (no threads); test binaries concurrently under `os.exec` start/poll supervision (no threads);
@@ -230,9 +231,10 @@ names reject before tools; exact `/dev/null` discards every copy and permits
duplicate names. The private test link still runs unless `-c` suppresses it; duplicate names. The private test link still runs unless `-c` suppresses it;
the raw single-file compatibility route also links into driver-owned private the raw single-file compatibility route also links into driver-owned private
storage instead of using `/dev/null` as an artifact or `.sepwork` stem. A storage instead of using `/dev/null` as an artifact or `.sepwork` stem. A
package with no selected test source validates production package with no selected test source validates production, reports the same
but publishes nothing and does not create an otherwise unneeded output `[no test files]` result, publishes nothing, and does not create an otherwise
directory. Successful `-c` output is silent apart from no-test reporting. unneeded output directory. Successful `-c` output is silent apart from that
no-test-files report.
The package suite also pins the adjacent `ww build` output-directory branch. The package suite also pins the adjacent `ww build` output-directory branch.
After normal loading, an existing directory (including a symlink to one) or an After normal loading, an existing directory (including a symlink to one) or an

View File

@@ -1720,7 +1720,7 @@ fn pkgemitgroup(g: *pkggroup, compileonly: bool,
if (g.notests) { if (g.notests) {
pkgput(os.STDOUT_FILENO, "? "); pkgput(os.STDOUT_FILENO, "? ");
pkgput(os.STDOUT_FILENO, g.dir); pkgput(os.STDOUT_FILENO, g.dir);
pkgputln(os.STDOUT_FILENO, " [no tests]"); pkgputln(os.STDOUT_FILENO, " [no test files]");
return true; return true;
}; };
if (compileonly) { if (compileonly) {

View File

@@ -1,3 +1,5 @@
package no_tests; package no_tests;
fn init() void = { abort(); };
export fn value() int = { return 1; }; export fn value() int = { return 1; };

View File

@@ -1407,8 +1407,8 @@ fn cwdwritedata(dir: str, label: str) void = {
expectexit(&outw, 0); expectexit(&outw, 0);
assert(same(outc.stdout, outw.stdout)); assert(same(outc.stdout, outw.stdout));
assert(same(outc.stderr, outw.stderr) && outc.stderr.len == 0); assert(same(outc.stderr, outw.stderr) && outc.stderr.len == 0);
assert(has(outc.stdout, strings.concat("? ", plain, " [no tests]\n"))); assert(has(outc.stdout, strings.concat("? ", plain, " [no test files]\n")));
assert(has(outc.stdout, strings.concat("? ", cmdno, " [no tests]\n"))); assert(has(outc.stdout, strings.concat("? ", cmdno, " [no test files]\n")));
assert(!has(outc.stdout, "plain-init")); assert(!has(outc.stdout, "plain-init"));
assert(!has(outc.stdout, "cmdno-init")); assert(!has(outc.stdout, "cmdno-init"));
assert(!has(outc.stdout, "cmdno-main")); assert(!has(outc.stdout, "cmdno-main"));
@@ -1968,13 +1968,29 @@ fn cwdwritedata(dir: str, label: str) void = {
@test fn empty_and_invalid_package_classes() void = { @test fn empty_and_invalid_package_classes() void = {
let root: str = fresh(); let root: str = fresh();
let av: []str = [driver("ww"), "test", packagepath("no_tests")]; let stages: []str = ["ww", "ww_ww"];
let out: commandout; let out: commandout;
runcommand(root, "notests", av, let nofiles: str = strings.concat("? ", packagepath("no_tests"),
(30i64 * (time.second: i64)): time.duration, &out); " [no test files]\n");
expectexit(&out, 0); let si: i32 = 0;
assert(has(out.stdout, " [no tests]\n")); for (si < stages.len) {
assert(!has(out.stdout, " ... ok")); let av: []str = [driver(stages[si]), "test", packagepath("no_tests")];
runcommand(root, strings.concat("notests-explicit-", stages[si]), av,
(30i64 * (time.second: i64)): time.duration, &out);
expectexit(&out, 0);
assert(same(out.stdout, nofiles));
assert(out.stderr.len == 0);
assert(!has(out.stdout, " ... ok"));
let implicit: []str = [driver(stages[si]), "test"];
runcommanddir(root, strings.concat("notests-implicit-", stages[si]),
packagepath("no_tests"), implicit,
(30i64 * (time.second: i64)): time.duration, &out);
expectexit(&out, 0);
assert(same(out.stdout, nofiles));
assert(out.stderr.len == 0);
si += 1;
};
let bad: []str = [driver("ww"), "test", packagepath("bad_external")]; let bad: []str = [driver("ww"), "test", packagepath("bad_external")];
runcommand(root, "badexternal", bad, runcommand(root, "badexternal", bad,
@@ -2000,7 +2016,7 @@ fn cwdwritedata(dir: str, label: str) void = {
(30i64 * (time.second: i64)): time.duration, &out); (30i64 * (time.second: i64)): time.duration, &out);
expectexit(&out, 1); expectexit(&out, 1);
assert(has(out.stderr, "cannot find package nowhere")); assert(has(out.stderr, "cannot find package nowhere"));
assert(!has(out.stdout, "[no tests]")); assert(!has(out.stdout, "[no test files]"));
// A test file is part of its variant even when it only supplies helpers. // A test file is part of its variant even when it only supplies helpers.
// Its imports and package clause must therefore reach the shared loader; // Its imports and package clause must therefore reach the shared loader;
@@ -2011,8 +2027,7 @@ fn cwdwritedata(dir: str, label: str) void = {
"package helperbad;\nexport fn value() i32 = { return 1; };\n"); "package helperbad;\nexport fn value() i32 = { return 1; };\n");
writefile(strings.concat(helperbad, "/helper_test.ww"), writefile(strings.concat(helperbad, "/helper_test.ww"),
"package helperbad_test;\nimport nowhere;\nfn helper() void = { };\n"); "package helperbad_test;\nimport nowhere;\nfn helper() void = { };\n");
let stages: []str = ["ww", "ww_ww"]; si = 0;
let si: i32 = 0;
for (si < stages.len) { for (si < stages.len) {
let helperav: []str = [driver(stages[si]), "test", helperbad]; let helperav: []str = [driver(stages[si]), "test", helperbad];
runcommand(root, strings.concat("helper-only-", stages[si]), helperav, runcommand(root, strings.concat("helper-only-", stages[si]), helperav,
@@ -2078,7 +2093,7 @@ fn cwdwritedata(dir: str, label: str) void = {
(30i64 * (time.second: i64)): time.duration, &out); (30i64 * (time.second: i64)): time.duration, &out);
expectexit(&out, 0); expectexit(&out, 0);
assert(has(out.stdout, "multiline.actually_runs ... ok\n")); assert(has(out.stdout, "multiline.actually_runs ... ok\n"));
assert(!has(out.stdout, "[no tests]")); assert(!has(out.stdout, "[no test files]"));
let commented: str = strings.concat(root, "/commented-test"); let commented: str = strings.concat(root, "/commented-test");
assert(os.mkdir(commented, 448i32) == 0); assert(os.mkdir(commented, 448i32) == 0);
@@ -2093,7 +2108,7 @@ fn cwdwritedata(dir: str, label: str) void = {
(30i64 * (time.second: i64)): time.duration, &out); (30i64 * (time.second: i64)): time.duration, &out);
expectexit(&out, 0); expectexit(&out, 0);
assert(has(out.stdout, "ok ")); assert(has(out.stdout, "ok "));
assert(!has(out.stdout, " [no tests]\n")); assert(!has(out.stdout, " [no test files]\n"));
assert(!has(out.stdout, "phantom")); assert(!has(out.stdout, "phantom"));
// Go's complete empty-package matrix: production-only, internal-only, // Go's complete empty-package matrix: production-only, internal-only,
@@ -2163,9 +2178,9 @@ fn cwdwritedata(dir: str, label: str) void = {
}; };
shi += 1; shi += 1;
}; };
assert(has(shaperefs[0], " [no tests]\n")); assert(has(shaperefs[0], " [no test files]\n"));
assert(occurrences(shaperefs[0], strings.concat( assert(occurrences(shaperefs[0], strings.concat(
"? ", prodonly, " [no tests]\n")) == 1); "? ", prodonly, " [no test files]\n")) == 1);
assert(has(shaperefs[1], "shapeinternal.internal_runs ... ok\n")); assert(has(shaperefs[1], "shapeinternal.internal_runs ... ok\n"));
assert(has(shaperefs[2], "shapeexternal.external_runs ... ok\n")); assert(has(shaperefs[2], "shapeexternal.external_runs ... ok\n"));
assert(occurrences(shaperefs[3], " ... ok\n") == 2); assert(occurrences(shaperefs[3], " ... ok\n") == 2);
@@ -3979,7 +3994,7 @@ fn cwdwritedata(dir: str, label: str) void = {
expectexit(&out, 0); expectexit(&out, 0);
assert(occurrences(out.stdout, "built ") == 0); assert(occurrences(out.stdout, "built ") == 0);
assert(has(out.stdout, strings.concat( assert(has(out.stdout, strings.concat(
"? ", gamma, " [no tests]\n"))); "? ", gamma, " [no test files]\n")));
assert(os.exists(publicalpha) && os.exists(publicbeta)); assert(os.exists(publicalpha) && os.exists(publicbeta));
assert(!os.exists(publicgamma)); assert(!os.exists(publicgamma));
assert(!os.exists(strings.concat(alpha, "/alpha_test.test"))); assert(!os.exists(strings.concat(alpha, "/alpha_test.test")));
@@ -5039,7 +5054,7 @@ fn cwdwritedata(dir: str, label: str) void = {
assert(has(out.stdout, strings.concat("ok ", suite, assert(has(out.stdout, strings.concat("ok ", suite,
"/p051 [p051]\n"))); "/p051 [p051]\n")));
assert(has(out.stdout, strings.concat("? ", suite, assert(has(out.stdout, strings.concat("? ", suite,
"/p256 [no tests]\n"))); "/p256 [no test files]\n")));
let beforecompiler: i32 = readfile(compilertraces[si]).len; let beforecompiler: i32 = readfile(compilertraces[si]).len;
runcommandenv(root, strings.concat("dynamic-coordinator-warm-", runcommandenv(root, strings.concat("dynamic-coordinator-warm-",
@@ -8228,7 +8243,7 @@ fn cwdwritedata(dir: str, label: str) void = {
assert(has(out.stdout, "selected_internal_pair ... ok\n")); assert(has(out.stdout, "selected_internal_pair ... ok\n"));
assert(has(out.stdout, "selected_external_pair ... ok\n")); assert(has(out.stdout, "selected_external_pair ... ok\n"));
assert(has(out.stdout, strings.concat("? ", notests, assert(has(out.stdout, strings.concat("? ", notests,
" [no tests]\n"))); " [no test files]\n")));
assert(!has(out.stdout, "wrong_target_test")); assert(!has(out.stdout, "wrong_target_test"));
assert(!has(out.stderr, "only_windows")); assert(!has(out.stderr, "only_windows"));
assert(!has(readfile(compilertrace), "dep.wrong")); assert(!has(readfile(compilertrace), "dep.wrong"));
@@ -9307,11 +9322,11 @@ fn cwdwritedata(dir: str, label: str) void = {
assert(has(seq, strings.concat("ok ", tree, assert(has(seq, strings.concat("ok ", tree,
"/domain/app [app]\n"))); "/domain/app [app]\n")));
assert(has(seq, strings.concat("? ", tree, assert(has(seq, strings.concat("? ", tree,
"/gamma [no tests]\n"))); "/gamma [no test files]\n")));
assert(has(seq, strings.concat("? ", tree, assert(has(seq, strings.concat("? ", tree,
"/vendor [no tests]\n"))); "/vendor [no test files]\n")));
assert(has(seq, strings.concat("? ", tree, assert(has(seq, strings.concat("? ", tree,
"/vendorx [no tests]\n"))); "/vendorx [no test files]\n")));
let rootreport: i32 = pos(seq, strings.concat("ok ", tree, let rootreport: i32 = pos(seq, strings.concat("ok ", tree,
" [rootpkg]\n")); " [rootpkg]\n"));
let alphareport: i32 = pos(seq, strings.concat("ok ", tree, let alphareport: i32 = pos(seq, strings.concat("ok ", tree,
@@ -9323,11 +9338,11 @@ fn cwdwritedata(dir: str, label: str) void = {
let domainreport: i32 = pos(seq, strings.concat("ok ", tree, let domainreport: i32 = pos(seq, strings.concat("ok ", tree,
"/domain/app [app]\n")); "/domain/app [app]\n"));
let gammareport: i32 = pos(seq, strings.concat("? ", tree, let gammareport: i32 = pos(seq, strings.concat("? ", tree,
"/gamma [no tests]\n")); "/gamma [no test files]\n"));
let vendorreport: i32 = pos(seq, strings.concat("? ", tree, let vendorreport: i32 = pos(seq, strings.concat("? ", tree,
"/vendor [no tests]\n")); "/vendor [no test files]\n"));
let vendorxreport: i32 = pos(seq, strings.concat("? ", tree, let vendorxreport: i32 = pos(seq, strings.concat("? ", tree,
"/vendorx [no tests]\n")); "/vendorx [no test files]\n"));
assert(rootreport >= 0 && rootreport < alphareport assert(rootreport >= 0 && rootreport < alphareport
&& alphareport < appreport && appreport < innerreport && alphareport < appreport && appreport < innerreport
&& innerreport < domainreport && domainreport < gammareport && innerreport < domainreport && domainreport < gammareport
@@ -9342,11 +9357,11 @@ fn cwdwritedata(dir: str, label: str) void = {
assert(occurrences(seq, strings.concat("ok ", tree, assert(occurrences(seq, strings.concat("ok ", tree,
"/domain/app [app]\n")) == 1); "/domain/app [app]\n")) == 1);
assert(occurrences(seq, strings.concat("? ", tree, assert(occurrences(seq, strings.concat("? ", tree,
"/gamma [no tests]\n")) == 1); "/gamma [no test files]\n")) == 1);
assert(occurrences(seq, strings.concat("? ", tree, assert(occurrences(seq, strings.concat("? ", tree,
"/vendor [no tests]\n")) == 1); "/vendor [no test files]\n")) == 1);
assert(occurrences(seq, strings.concat("? ", tree, assert(occurrences(seq, strings.concat("? ", tree,
"/vendorx [no tests]\n")) == 1); "/vendorx [no test files]\n")) == 1);
assert(!has(seq, ".hidden")); assert(!has(seq, ".hidden"));
assert(!has(seq, "_skip")); assert(!has(seq, "_skip"));
assert(!has(seq, "/testdata")); assert(!has(seq, "/testdata"));
@@ -9488,7 +9503,7 @@ fn cwdwritedata(dir: str, label: str) void = {
assert(same(outc.stdout, outw.stdout)); assert(same(outc.stdout, outw.stdout));
assert(same(outc.stderr, outw.stderr)); assert(same(outc.stderr, outw.stderr));
assert(has(outc.stdout, strings.concat("? ", tree, assert(has(outc.stdout, strings.concat("? ", tree,
"/vendor [no tests]\n"))); "/vendor [no test files]\n")));
assert(has(outc.stdout, strings.concat("ok ", tree, assert(has(outc.stdout, strings.concat("ok ", tree,
"/vendor/bad [bad]\n"))); "/vendor/bad [bad]\n")));
assert(!has(outc.stdout, "/vendor/bad/vendor/deep")); assert(!has(outc.stdout, "/vendor/bad/vendor/deep"));
@@ -9506,14 +9521,14 @@ fn cwdwritedata(dir: str, label: str) void = {
assert(same(outc.stdout, outw.stdout)); assert(same(outc.stdout, outw.stdout));
assert(same(outc.stderr, outw.stderr)); assert(same(outc.stderr, outw.stderr));
assert(has(outc.stdout, strings.concat("? ", tree, assert(has(outc.stdout, strings.concat("? ", tree,
"/app/vendor/lib/math [no tests]\n"))); "/app/vendor/lib/math [no test files]\n")));
let vendorroots: []str = [driver("ww"), "test", "-I", tree, let vendorroots: []str = [driver("ww"), "test", "-I", tree,
strings.concat(tree, "/app/vendor/...")]; strings.concat(tree, "/app/vendor/...")];
runcommand(root, "tree-pattern-below-vendor", vendorroots, runcommand(root, "tree-pattern-below-vendor", vendorroots,
(30i64 * (time.second: i64)): time.duration, &outc); (30i64 * (time.second: i64)): time.duration, &outc);
expectexit(&outc, 0); expectexit(&outc, 0);
assert(has(outc.stdout, strings.concat("? ", tree, assert(has(outc.stdout, strings.concat("? ", tree,
"/app/vendor/lib/math [no tests]\n"))); "/app/vendor/lib/math [no test files]\n")));
// A child symlink is never traversed. The same symlink is followed when it // A child symlink is never traversed. The same symlink is followed when it
// is itself the explicit traversal root, then canonical output names it once. // is itself the explicit traversal root, then canonical output names it once.
@@ -12690,7 +12705,8 @@ fn runtimepath(relative: str) str = {
let fanpkg: str = strings.concat(fanarg, "pkg.test"); let fanpkg: str = strings.concat(fanarg, "pkg.test");
assert(os.exists(fanabin) && os.exists(fanpkg)); assert(os.exists(fanabin) && os.exists(fanpkg));
assert(!os.exists(strings.concat(fanarg, "znone.test"))); assert(!os.exists(strings.concat(fanarg, "znone.test")));
assert(has(out.stdout, strings.concat("? ", none, " [no tests]\n"))); assert(has(out.stdout, strings.concat("? ", none,
" [no test files]\n")));
if (i == 0) { if (i == 0) {
fanabytes = readfile(fanabin); fanabytes = readfile(fanabin);
fanpkgbytes = readfile(fanpkg); fanpkgbytes = readfile(fanpkg);
@@ -12945,7 +12961,7 @@ fn runtimepath(relative: str) str = {
(60i64 * (time.second: i64)): time.duration, &out); (60i64 * (time.second: i64)): time.duration, &out);
expectexit(&out, 0); expectexit(&out, 0);
assert(has(out.stdout, strings.concat("? ", none, assert(has(out.stdout, strings.concat("? ", none,
" [no tests]\n"))); " [no test files]\n")));
assert(out.stderr.len == 0 && !os.exists(noneroot)); assert(out.stderr.len == 0 && !os.exists(noneroot));
// Pinned builderTest makes the install action depend on the run action. // Pinned builderTest makes the install action depend on the run action.