1// Copyright 2011 The Go Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style
3// license that can be found in the LICENSE file.
4
5package test
6
7import (
8	"bytes"
9	"context"
10	"errors"
11	"fmt"
12	"internal/coverage"
13	"internal/platform"
14	"io"
15	"io/fs"
16	"os"
17	"os/exec"
18	"path/filepath"
19	"regexp"
20	"slices"
21	"strconv"
22	"strings"
23	"sync"
24	"sync/atomic"
25	"time"
26
27	"cmd/go/internal/base"
28	"cmd/go/internal/cache"
29	"cmd/go/internal/cfg"
30	"cmd/go/internal/load"
31	"cmd/go/internal/lockedfile"
32	"cmd/go/internal/modload"
33	"cmd/go/internal/search"
34	"cmd/go/internal/str"
35	"cmd/go/internal/trace"
36	"cmd/go/internal/work"
37	"cmd/internal/test2json"
38
39	"golang.org/x/mod/module"
40)
41
42// Break init loop.
43func init() {
44	CmdTest.Run = runTest
45}
46
47const testUsage = "go test [build/test flags] [packages] [build/test flags & test binary flags]"
48
49var CmdTest = &base.Command{
50	CustomFlags: true,
51	UsageLine:   testUsage,
52	Short:       "test packages",
53	Long: `
54'Go test' automates testing the packages named by the import paths.
55It prints a summary of the test results in the format:
56
57	ok   archive/tar   0.011s
58	FAIL archive/zip   0.022s
59	ok   compress/gzip 0.033s
60	...
61
62followed by detailed output for each failed package.
63
64'Go test' recompiles each package along with any files with names matching
65the file pattern "*_test.go".
66These additional files can contain test functions, benchmark functions, fuzz
67tests and example functions. See 'go help testfunc' for more.
68Each listed package causes the execution of a separate test binary.
69Files whose names begin with "_" (including "_test.go") or "." are ignored.
70
71Test files that declare a package with the suffix "_test" will be compiled as a
72separate package, and then linked and run with the main test binary.
73
74The go tool will ignore a directory named "testdata", making it available
75to hold ancillary data needed by the tests.
76
77As part of building a test binary, go test runs go vet on the package
78and its test source files to identify significant problems. If go vet
79finds any problems, go test reports those and does not run the test
80binary. Only a high-confidence subset of the default go vet checks are
81used. That subset is: atomic, bool, buildtags, directive, errorsas,
82ifaceassert, nilfunc, printf, and stringintconv. You can see
83the documentation for these and other vet tests via "go doc cmd/vet".
84To disable the running of go vet, use the -vet=off flag. To run all
85checks, use the -vet=all flag.
86
87All test output and summary lines are printed to the go command's
88standard output, even if the test printed them to its own standard
89error. (The go command's standard error is reserved for printing
90errors building the tests.)
91
92The go command places $GOROOT/bin at the beginning of $PATH
93in the test's environment, so that tests that execute
94'go' commands use the same 'go' as the parent 'go test' command.
95
96Go test runs in two different modes:
97
98The first, called local directory mode, occurs when go test is
99invoked with no package arguments (for example, 'go test' or 'go
100test -v'). In this mode, go test compiles the package sources and
101tests found in the current directory and then runs the resulting
102test binary. In this mode, caching (discussed below) is disabled.
103After the package test finishes, go test prints a summary line
104showing the test status ('ok' or 'FAIL'), package name, and elapsed
105time.
106
107The second, called package list mode, occurs when go test is invoked
108with explicit package arguments (for example 'go test math', 'go
109test ./...', and even 'go test .'). In this mode, go test compiles
110and tests each of the packages listed on the command line. If a
111package test passes, go test prints only the final 'ok' summary
112line. If a package test fails, go test prints the full test output.
113If invoked with the -bench or -v flag, go test prints the full
114output even for passing package tests, in order to display the
115requested benchmark results or verbose logging. After the package
116tests for all of the listed packages finish, and their output is
117printed, go test prints a final 'FAIL' status if any package test
118has failed.
119
120In package list mode only, go test caches successful package test
121results to avoid unnecessary repeated running of tests. When the
122result of a test can be recovered from the cache, go test will
123redisplay the previous output instead of running the test binary
124again. When this happens, go test prints '(cached)' in place of the
125elapsed time in the summary line.
126
127The rule for a match in the cache is that the run involves the same
128test binary and the flags on the command line come entirely from a
129restricted set of 'cacheable' test flags, defined as -benchtime, -cpu,
130-list, -parallel, -run, -short, -timeout, -failfast, -fullpath and -v.
131If a run of go test has any test or non-test flags outside this set,
132the result is not cached. To disable test caching, use any test flag
133or argument other than the cacheable flags. The idiomatic way to disable
134test caching explicitly is to use -count=1. Tests that open files within
135the package's source root (usually $GOPATH) or that consult environment
136variables only match future runs in which the files and environment
137variables are unchanged. A cached test result is treated as executing
138in no time at all, so a successful package test result will be cached and
139reused regardless of -timeout setting.
140
141In addition to the build flags, the flags handled by 'go test' itself are:
142
143	-args
144	    Pass the remainder of the command line (everything after -args)
145	    to the test binary, uninterpreted and unchanged.
146	    Because this flag consumes the remainder of the command line,
147	    the package list (if present) must appear before this flag.
148
149	-c
150	    Compile the test binary to pkg.test in the current directory but do not run it
151	    (where pkg is the last element of the package's import path).
152	    The file name or target directory can be changed with the -o flag.
153
154	-exec xprog
155	    Run the test binary using xprog. The behavior is the same as
156	    in 'go run'. See 'go help run' for details.
157
158	-json
159	    Convert test output to JSON suitable for automated processing.
160	    See 'go doc test2json' for the encoding details.
161
162	-o file
163	    Compile the test binary to the named file.
164	    The test still runs (unless -c or -i is specified).
165	    If file ends in a slash or names an existing directory,
166	    the test is written to pkg.test in that directory.
167
168The test binary also accepts flags that control execution of the test; these
169flags are also accessible by 'go test'. See 'go help testflag' for details.
170
171For more about build flags, see 'go help build'.
172For more about specifying packages, see 'go help packages'.
173
174See also: go build, go vet.
175`,
176}
177
178var HelpTestflag = &base.Command{
179	UsageLine: "testflag",
180	Short:     "testing flags",
181	Long: `
182The 'go test' command takes both flags that apply to 'go test' itself
183and flags that apply to the resulting test binary.
184
185Several of the flags control profiling and write an execution profile
186suitable for "go tool pprof"; run "go tool pprof -h" for more
187information. The --alloc_space, --alloc_objects, and --show_bytes
188options of pprof control how the information is presented.
189
190The following flags are recognized by the 'go test' command and
191control the execution of any test:
192
193	-bench regexp
194	    Run only those benchmarks matching a regular expression.
195	    By default, no benchmarks are run.
196	    To run all benchmarks, use '-bench .' or '-bench=.'.
197	    The regular expression is split by unbracketed slash (/)
198	    characters into a sequence of regular expressions, and each
199	    part of a benchmark's identifier must match the corresponding
200	    element in the sequence, if any. Possible parents of matches
201	    are run with b.N=1 to identify sub-benchmarks. For example,
202	    given -bench=X/Y, top-level benchmarks matching X are run
203	    with b.N=1 to find any sub-benchmarks matching Y, which are
204	    then run in full.
205
206	-benchtime t
207	    Run enough iterations of each benchmark to take t, specified
208	    as a time.Duration (for example, -benchtime 1h30s).
209	    The default is 1 second (1s).
210	    The special syntax Nx means to run the benchmark N times
211	    (for example, -benchtime 100x).
212
213	-count n
214	    Run each test, benchmark, and fuzz seed n times (default 1).
215	    If -cpu is set, run n times for each GOMAXPROCS value.
216	    Examples are always run once. -count does not apply to
217	    fuzz tests matched by -fuzz.
218
219	-cover
220	    Enable coverage analysis.
221	    Note that because coverage works by annotating the source
222	    code before compilation, compilation and test failures with
223	    coverage enabled may report line numbers that don't correspond
224	    to the original sources.
225
226	-covermode set,count,atomic
227	    Set the mode for coverage analysis for the package[s]
228	    being tested. The default is "set" unless -race is enabled,
229	    in which case it is "atomic".
230	    The values:
231		set: bool: does this statement run?
232		count: int: how many times does this statement run?
233		atomic: int: count, but correct in multithreaded tests;
234			significantly more expensive.
235	    Sets -cover.
236
237	-coverpkg pattern1,pattern2,pattern3
238	    Apply coverage analysis in each test to packages matching the patterns.
239	    The default is for each test to analyze only the package being tested.
240	    See 'go help packages' for a description of package patterns.
241	    Sets -cover.
242
243	-cpu 1,2,4
244	    Specify a list of GOMAXPROCS values for which the tests, benchmarks or
245	    fuzz tests should be executed. The default is the current value
246	    of GOMAXPROCS. -cpu does not apply to fuzz tests matched by -fuzz.
247
248	-failfast
249	    Do not start new tests after the first test failure.
250
251	-fullpath
252	    Show full file names in the error messages.
253
254	-fuzz regexp
255	    Run the fuzz test matching the regular expression. When specified,
256	    the command line argument must match exactly one package within the
257	    main module, and regexp must match exactly one fuzz test within
258	    that package. Fuzzing will occur after tests, benchmarks, seed corpora
259	    of other fuzz tests, and examples have completed. See the Fuzzing
260	    section of the testing package documentation for details.
261
262	-fuzztime t
263	    Run enough iterations of the fuzz target during fuzzing to take t,
264	    specified as a time.Duration (for example, -fuzztime 1h30s).
265		The default is to run forever.
266	    The special syntax Nx means to run the fuzz target N times
267	    (for example, -fuzztime 1000x).
268
269	-fuzzminimizetime t
270	    Run enough iterations of the fuzz target during each minimization
271	    attempt to take t, as specified as a time.Duration (for example,
272	    -fuzzminimizetime 30s).
273		The default is 60s.
274	    The special syntax Nx means to run the fuzz target N times
275	    (for example, -fuzzminimizetime 100x).
276
277	-json
278	    Log verbose output and test results in JSON. This presents the
279	    same information as the -v flag in a machine-readable format.
280
281	-list regexp
282	    List tests, benchmarks, fuzz tests, or examples matching the regular
283	    expression. No tests, benchmarks, fuzz tests, or examples will be run.
284	    This will only list top-level tests. No subtest or subbenchmarks will be
285	    shown.
286
287	-parallel n
288	    Allow parallel execution of test functions that call t.Parallel, and
289	    fuzz targets that call t.Parallel when running the seed corpus.
290	    The value of this flag is the maximum number of tests to run
291	    simultaneously.
292	    While fuzzing, the value of this flag is the maximum number of
293	    subprocesses that may call the fuzz function simultaneously, regardless of
294	    whether T.Parallel is called.
295	    By default, -parallel is set to the value of GOMAXPROCS.
296	    Setting -parallel to values higher than GOMAXPROCS may cause degraded
297	    performance due to CPU contention, especially when fuzzing.
298	    Note that -parallel only applies within a single test binary.
299	    The 'go test' command may run tests for different packages
300	    in parallel as well, according to the setting of the -p flag
301	    (see 'go help build').
302
303	-run regexp
304	    Run only those tests, examples, and fuzz tests matching the regular
305	    expression. For tests, the regular expression is split by unbracketed
306	    slash (/) characters into a sequence of regular expressions, and each
307	    part of a test's identifier must match the corresponding element in
308	    the sequence, if any. Note that possible parents of matches are
309	    run too, so that -run=X/Y matches and runs and reports the result
310	    of all tests matching X, even those without sub-tests matching Y,
311	    because it must run them to look for those sub-tests.
312	    See also -skip.
313
314	-short
315	    Tell long-running tests to shorten their run time.
316	    It is off by default but set during all.bash so that installing
317	    the Go tree can run a sanity check but not spend time running
318	    exhaustive tests.
319
320	-shuffle off,on,N
321	    Randomize the execution order of tests and benchmarks.
322	    It is off by default. If -shuffle is set to on, then it will seed
323	    the randomizer using the system clock. If -shuffle is set to an
324	    integer N, then N will be used as the seed value. In both cases,
325	    the seed will be reported for reproducibility.
326
327	-skip regexp
328	    Run only those tests, examples, fuzz tests, and benchmarks that
329	    do not match the regular expression. Like for -run and -bench,
330	    for tests and benchmarks, the regular expression is split by unbracketed
331	    slash (/) characters into a sequence of regular expressions, and each
332	    part of a test's identifier must match the corresponding element in
333	    the sequence, if any.
334
335	-timeout d
336	    If a test binary runs longer than duration d, panic.
337	    If d is 0, the timeout is disabled.
338	    The default is 10 minutes (10m).
339
340	-v
341	    Verbose output: log all tests as they are run. Also print all
342	    text from Log and Logf calls even if the test succeeds.
343
344	-vet list
345	    Configure the invocation of "go vet" during "go test"
346	    to use the comma-separated list of vet checks.
347	    If list is empty, "go test" runs "go vet" with a curated list of
348	    checks believed to be always worth addressing.
349	    If list is "off", "go test" does not run "go vet" at all.
350
351The following flags are also recognized by 'go test' and can be used to
352profile the tests during execution:
353
354	-benchmem
355	    Print memory allocation statistics for benchmarks.
356	    Allocations made in C or using C.malloc are not counted.
357
358	-blockprofile block.out
359	    Write a goroutine blocking profile to the specified file
360	    when all tests are complete.
361	    Writes test binary as -c would.
362
363	-blockprofilerate n
364	    Control the detail provided in goroutine blocking profiles by
365	    calling runtime.SetBlockProfileRate with n.
366	    See 'go doc runtime.SetBlockProfileRate'.
367	    The profiler aims to sample, on average, one blocking event every
368	    n nanoseconds the program spends blocked. By default,
369	    if -test.blockprofile is set without this flag, all blocking events
370	    are recorded, equivalent to -test.blockprofilerate=1.
371
372	-coverprofile cover.out
373	    Write a coverage profile to the file after all tests have passed.
374	    Sets -cover.
375
376	-cpuprofile cpu.out
377	    Write a CPU profile to the specified file before exiting.
378	    Writes test binary as -c would.
379
380	-memprofile mem.out
381	    Write an allocation profile to the file after all tests have passed.
382	    Writes test binary as -c would.
383
384	-memprofilerate n
385	    Enable more precise (and expensive) memory allocation profiles by
386	    setting runtime.MemProfileRate. See 'go doc runtime.MemProfileRate'.
387	    To profile all memory allocations, use -test.memprofilerate=1.
388
389	-mutexprofile mutex.out
390	    Write a mutex contention profile to the specified file
391	    when all tests are complete.
392	    Writes test binary as -c would.
393
394	-mutexprofilefraction n
395	    Sample 1 in n stack traces of goroutines holding a
396	    contended mutex.
397
398	-outputdir directory
399	    Place output files from profiling in the specified directory,
400	    by default the directory in which "go test" is running.
401
402	-trace trace.out
403	    Write an execution trace to the specified file before exiting.
404
405Each of these flags is also recognized with an optional 'test.' prefix,
406as in -test.v. When invoking the generated test binary (the result of
407'go test -c') directly, however, the prefix is mandatory.
408
409The 'go test' command rewrites or removes recognized flags,
410as appropriate, both before and after the optional package list,
411before invoking the test binary.
412
413For instance, the command
414
415	go test -v -myflag testdata -cpuprofile=prof.out -x
416
417will compile the test binary and then run it as
418
419	pkg.test -test.v -myflag testdata -test.cpuprofile=prof.out
420
421(The -x flag is removed because it applies only to the go command's
422execution, not to the test itself.)
423
424The test flags that generate profiles (other than for coverage) also
425leave the test binary in pkg.test for use when analyzing the profiles.
426
427When 'go test' runs a test binary, it does so from within the
428corresponding package's source code directory. Depending on the test,
429it may be necessary to do the same when invoking a generated test
430binary directly. Because that directory may be located within the
431module cache, which may be read-only and is verified by checksums, the
432test must not write to it or any other directory within the module
433unless explicitly requested by the user (such as with the -fuzz flag,
434which writes failures to testdata/fuzz).
435
436The command-line package list, if present, must appear before any
437flag not known to the go test command. Continuing the example above,
438the package list would have to appear before -myflag, but could appear
439on either side of -v.
440
441When 'go test' runs in package list mode, 'go test' caches successful
442package test results to avoid unnecessary repeated running of tests. To
443disable test caching, use any test flag or argument other than the
444cacheable flags. The idiomatic way to disable test caching explicitly
445is to use -count=1.
446
447To keep an argument for a test binary from being interpreted as a
448known flag or a package name, use -args (see 'go help test') which
449passes the remainder of the command line through to the test binary
450uninterpreted and unaltered.
451
452For instance, the command
453
454	go test -v -args -x -v
455
456will compile the test binary and then run it as
457
458	pkg.test -test.v -x -v
459
460Similarly,
461
462	go test -args math
463
464will compile the test binary and then run it as
465
466	pkg.test math
467
468In the first example, the -x and the second -v are passed through to the
469test binary unchanged and with no effect on the go command itself.
470In the second example, the argument math is passed through to the test
471binary, instead of being interpreted as the package list.
472`,
473}
474
475var HelpTestfunc = &base.Command{
476	UsageLine: "testfunc",
477	Short:     "testing functions",
478	Long: `
479The 'go test' command expects to find test, benchmark, and example functions
480in the "*_test.go" files corresponding to the package under test.
481
482A test function is one named TestXxx (where Xxx does not start with a
483lower case letter) and should have the signature,
484
485	func TestXxx(t *testing.T) { ... }
486
487A benchmark function is one named BenchmarkXxx and should have the signature,
488
489	func BenchmarkXxx(b *testing.B) { ... }
490
491A fuzz test is one named FuzzXxx and should have the signature,
492
493	func FuzzXxx(f *testing.F) { ... }
494
495An example function is similar to a test function but, instead of using
496*testing.T to report success or failure, prints output to os.Stdout.
497If the last comment in the function starts with "Output:" then the output
498is compared exactly against the comment (see examples below). If the last
499comment begins with "Unordered output:" then the output is compared to the
500comment, however the order of the lines is ignored. An example with no such
501comment is compiled but not executed. An example with no text after
502"Output:" is compiled, executed, and expected to produce no output.
503
504Godoc displays the body of ExampleXxx to demonstrate the use
505of the function, constant, or variable Xxx. An example of a method M with
506receiver type T or *T is named ExampleT_M. There may be multiple examples
507for a given function, constant, or variable, distinguished by a trailing _xxx,
508where xxx is a suffix not beginning with an upper case letter.
509
510Here is an example of an example:
511
512	func ExamplePrintln() {
513		Println("The output of\nthis example.")
514		// Output: The output of
515		// this example.
516	}
517
518Here is another example where the ordering of the output is ignored:
519
520	func ExamplePerm() {
521		for _, value := range Perm(4) {
522			fmt.Println(value)
523		}
524
525		// Unordered output: 4
526		// 2
527		// 1
528		// 3
529		// 0
530	}
531
532The entire test file is presented as the example when it contains a single
533example function, at least one other function, type, variable, or constant
534declaration, and no tests, benchmarks, or fuzz tests.
535
536See the documentation of the testing package for more information.
537`,
538}
539
540var (
541	testBench        string                            // -bench flag
542	testC            bool                              // -c flag
543	testCoverPkgs    []*load.Package                   // -coverpkg flag
544	testCoverProfile string                            // -coverprofile flag
545	testFailFast     bool                              // -failfast flag
546	testFuzz         string                            // -fuzz flag
547	testJSON         bool                              // -json flag
548	testList         string                            // -list flag
549	testO            string                            // -o flag
550	testOutputDir    outputdirFlag                     // -outputdir flag
551	testShuffle      shuffleFlag                       // -shuffle flag
552	testTimeout      time.Duration                     // -timeout flag
553	testV            testVFlag                         // -v flag
554	testVet          = vetFlag{flags: defaultVetFlags} // -vet flag
555)
556
557type testVFlag struct {
558	on   bool // -v is set in some form
559	json bool // -v=test2json is set, to make output better for test2json
560}
561
562func (*testVFlag) IsBoolFlag() bool { return true }
563
564func (f *testVFlag) Set(arg string) error {
565	if v, err := strconv.ParseBool(arg); err == nil {
566		f.on = v
567		f.json = false
568		return nil
569	}
570	if arg == "test2json" {
571		f.on = true
572		f.json = arg == "test2json"
573		return nil
574	}
575	return fmt.Errorf("invalid flag -test.v=%s", arg)
576}
577
578func (f *testVFlag) String() string {
579	if f.json {
580		return "test2json"
581	}
582	if f.on {
583		return "true"
584	}
585	return "false"
586}
587
588var (
589	testArgs []string
590	pkgArgs  []string
591	pkgs     []*load.Package
592
593	testHelp bool // -help option passed to test via -args
594
595	testKillTimeout    = 100 * 365 * 24 * time.Hour // backup alarm; defaults to about a century if no timeout is set
596	testWaitDelay      time.Duration                // how long to wait for output to close after a test binary exits; zero means unlimited
597	testCacheExpire    time.Time                    // ignore cached test results before this time
598	testShouldFailFast atomic.Bool                  // signals pending tests to fail fast
599
600	testBlockProfile, testCPUProfile, testMemProfile, testMutexProfile, testTrace string // profiling flag that limits test to one package
601
602	testODir = false
603)
604
605// testProfile returns the name of an arbitrary single-package profiling flag
606// that is set, if any.
607func testProfile() string {
608	switch {
609	case testBlockProfile != "":
610		return "-blockprofile"
611	case testCPUProfile != "":
612		return "-cpuprofile"
613	case testMemProfile != "":
614		return "-memprofile"
615	case testMutexProfile != "":
616		return "-mutexprofile"
617	case testTrace != "":
618		return "-trace"
619	default:
620		return ""
621	}
622}
623
624// testNeedBinary reports whether the test needs to keep the binary around.
625func testNeedBinary() bool {
626	switch {
627	case testBlockProfile != "":
628		return true
629	case testCPUProfile != "":
630		return true
631	case testMemProfile != "":
632		return true
633	case testMutexProfile != "":
634		return true
635	case testO != "":
636		return true
637	default:
638		return false
639	}
640}
641
642// testShowPass reports whether the output for a passing test should be shown.
643func testShowPass() bool {
644	return testV.on || testList != "" || testHelp
645}
646
647var defaultVetFlags = []string{
648	// TODO(rsc): Decide which tests are enabled by default.
649	// See golang.org/issue/18085.
650	// "-asmdecl",
651	// "-assign",
652	"-atomic",
653	"-bool",
654	"-buildtags",
655	// "-cgocall",
656	// "-composites",
657	// "-copylocks",
658	"-directive",
659	"-errorsas",
660	// "-httpresponse",
661	"-ifaceassert",
662	// "-lostcancel",
663	// "-methods",
664	"-nilfunc",
665	"-printf",
666	// "-rangeloops",
667	// "-shift",
668	"-slog",
669	"-stringintconv",
670	// "-structtags",
671	// "-tests",
672	// "-unreachable",
673	// "-unsafeptr",
674	// "-unusedresult",
675}
676
677func runTest(ctx context.Context, cmd *base.Command, args []string) {
678	pkgArgs, testArgs = testFlags(args)
679	modload.InitWorkfile() // The test command does custom flag processing; initialize workspaces after that.
680
681	if cfg.DebugTrace != "" {
682		var close func() error
683		var err error
684		ctx, close, err = trace.Start(ctx, cfg.DebugTrace)
685		if err != nil {
686			base.Fatalf("failed to start trace: %v", err)
687		}
688		defer func() {
689			if err := close(); err != nil {
690				base.Fatalf("failed to stop trace: %v", err)
691			}
692		}()
693	}
694
695	ctx, span := trace.StartSpan(ctx, fmt.Sprint("Running ", cmd.Name(), " command"))
696	defer span.Done()
697
698	work.FindExecCmd() // initialize cached result
699
700	work.BuildInit()
701	work.VetFlags = testVet.flags
702	work.VetExplicit = testVet.explicit
703
704	pkgOpts := load.PackageOpts{ModResolveTests: true}
705	pkgs = load.PackagesAndErrors(ctx, pkgOpts, pkgArgs)
706	load.CheckPackageErrors(pkgs)
707	if len(pkgs) == 0 {
708		base.Fatalf("no packages to test")
709	}
710
711	if testFuzz != "" {
712		if !platform.FuzzSupported(cfg.Goos, cfg.Goarch) {
713			base.Fatalf("-fuzz flag is not supported on %s/%s", cfg.Goos, cfg.Goarch)
714		}
715		if len(pkgs) != 1 {
716			base.Fatalf("cannot use -fuzz flag with multiple packages")
717		}
718		if testCoverProfile != "" {
719			base.Fatalf("cannot use -coverprofile flag with -fuzz flag")
720		}
721		if profileFlag := testProfile(); profileFlag != "" {
722			base.Fatalf("cannot use %s flag with -fuzz flag", profileFlag)
723		}
724
725		// Reject the '-fuzz' flag if the package is outside the main module.
726		// Otherwise, if fuzzing identifies a failure it could corrupt checksums in
727		// the module cache (or permanently alter the behavior of std tests for all
728		// users) by writing the failing input to the package's testdata directory.
729		// (See https://golang.org/issue/48495 and test_fuzz_modcache.txt.)
730		mainMods := modload.MainModules
731		if m := pkgs[0].Module; m != nil && m.Path != "" {
732			if !mainMods.Contains(m.Path) {
733				base.Fatalf("cannot use -fuzz flag on package outside the main module")
734			}
735		} else if pkgs[0].Standard && modload.Enabled() {
736			// Because packages in 'std' and 'cmd' are part of the standard library,
737			// they are only treated as part of a module in 'go mod' subcommands and
738			// 'go get'. However, we still don't want to accidentally corrupt their
739			// testdata during fuzzing, nor do we want to fail with surprising errors
740			// if GOROOT isn't writable (as is often the case for Go toolchains
741			// installed through package managers).
742			//
743			// If the user is requesting to fuzz a standard-library package, ensure
744			// that they are in the same module as that package (just like when
745			// fuzzing any other package).
746			if strings.HasPrefix(pkgs[0].ImportPath, "cmd/") {
747				if !mainMods.Contains("cmd") || !mainMods.InGorootSrc(module.Version{Path: "cmd"}) {
748					base.Fatalf("cannot use -fuzz flag on package outside the main module")
749				}
750			} else {
751				if !mainMods.Contains("std") || !mainMods.InGorootSrc(module.Version{Path: "std"}) {
752					base.Fatalf("cannot use -fuzz flag on package outside the main module")
753				}
754			}
755		}
756	}
757	if testProfile() != "" && len(pkgs) != 1 {
758		base.Fatalf("cannot use %s flag with multiple packages", testProfile())
759	}
760
761	if testO != "" {
762		if strings.HasSuffix(testO, "/") || strings.HasSuffix(testO, string(os.PathSeparator)) {
763			testODir = true
764		} else if fi, err := os.Stat(testO); err == nil && fi.IsDir() {
765			testODir = true
766		}
767	}
768
769	if len(pkgs) > 1 && (testC || testO != "") && !base.IsNull(testO) {
770		if testO != "" && !testODir {
771			base.Fatalf("with multiple packages, -o must refer to a directory or %s", os.DevNull)
772		}
773
774		pkgsForBinary := map[string][]*load.Package{}
775
776		for _, p := range pkgs {
777			testBinary := testBinaryName(p)
778			pkgsForBinary[testBinary] = append(pkgsForBinary[testBinary], p)
779		}
780
781		for testBinary, pkgs := range pkgsForBinary {
782			if len(pkgs) > 1 {
783				var buf strings.Builder
784				for _, pkg := range pkgs {
785					buf.WriteString(pkg.ImportPath)
786					buf.WriteString("\n")
787				}
788
789				base.Errorf("cannot write test binary %s for multiple packages:\n%s", testBinary, buf.String())
790			}
791		}
792
793		base.ExitIfErrors()
794	}
795
796	initCoverProfile()
797	defer closeCoverProfile()
798
799	// If a test timeout is finite, set our kill timeout
800	// to that timeout plus one minute. This is a backup alarm in case
801	// the test wedges with a goroutine spinning and its background
802	// timer does not get a chance to fire.
803	// Don't set this if fuzzing, since it should be able to run
804	// indefinitely.
805	if testTimeout > 0 && testFuzz == "" {
806		// The WaitDelay for the test process depends on both the OS I/O and
807		// scheduling overhead and the amount of I/O generated by the test just
808		// before it exits. We set the minimum at 5 seconds to account for the OS
809		// overhead, and scale it up from there proportional to the overall test
810		// timeout on the assumption that the time to write and read a goroutine
811		// dump from a timed-out test process scales roughly with the overall
812		// running time of the test.
813		//
814		// This is probably too generous when the timeout is very long, but it seems
815		// better to hard-code a scale factor than to hard-code a constant delay.
816		if wd := testTimeout / 10; wd < 5*time.Second {
817			testWaitDelay = 5 * time.Second
818		} else {
819			testWaitDelay = wd
820		}
821
822		// We expect the test binary to terminate itself (and dump stacks) after
823		// exactly testTimeout. We give it up to one WaitDelay or one minute,
824		// whichever is longer, to finish dumping stacks before we send it an
825		// external signal: if the process has a lot of goroutines, dumping stacks
826		// after the timeout can take a while.
827		//
828		// After the signal is delivered, the test process may have up to one
829		// additional WaitDelay to finish writing its output streams.
830		if testWaitDelay < 1*time.Minute {
831			testKillTimeout = testTimeout + 1*time.Minute
832		} else {
833			testKillTimeout = testTimeout + testWaitDelay
834		}
835	}
836
837	// Read testcache expiration time, if present.
838	// (We implement go clean -testcache by writing an expiration date
839	// instead of searching out and deleting test result cache entries.)
840	if dir, _ := cache.DefaultDir(); dir != "off" {
841		if data, _ := lockedfile.Read(filepath.Join(dir, "testexpire.txt")); len(data) > 0 && data[len(data)-1] == '\n' {
842			if t, err := strconv.ParseInt(string(data[:len(data)-1]), 10, 64); err == nil {
843				testCacheExpire = time.Unix(0, t)
844			}
845		}
846	}
847
848	b := work.NewBuilder("")
849	defer func() {
850		if err := b.Close(); err != nil {
851			base.Fatal(err)
852		}
853	}()
854
855	var builds, runs, prints []*work.Action
856	var writeCoverMetaAct *work.Action
857
858	if cfg.BuildCoverPkg != nil {
859		match := make([]func(*load.Package) bool, len(cfg.BuildCoverPkg))
860		for i := range cfg.BuildCoverPkg {
861			match[i] = load.MatchPackage(cfg.BuildCoverPkg[i], base.Cwd())
862		}
863
864		// Select for coverage all dependencies matching the -coverpkg
865		// patterns.
866		plist := load.TestPackageList(ctx, pkgOpts, pkgs)
867		testCoverPkgs = load.SelectCoverPackages(plist, match, "test")
868		if cfg.Experiment.CoverageRedesign && len(testCoverPkgs) > 0 {
869			// create a new singleton action that will collect up the
870			// meta-data files from all of the packages mentioned in
871			// "-coverpkg" and write them to a summary file. This new
872			// action will depend on all the build actions for the
873			// test packages, and all the run actions for these
874			// packages will depend on it. Motivating example:
875			// supposed we have a top level directory with three
876			// package subdirs, "a", "b", and "c", and
877			// from the top level, a user runs "go test -coverpkg=./... ./...".
878			// This will result in (roughly) the following action graph:
879			//
880			//	build("a")       build("b")         build("c")
881			//	    |               |                   |
882			//	link("a.test")   link("b.test")     link("c.test")
883			//	    |               |                   |
884			//	run("a.test")    run("b.test")      run("c.test")
885			//	    |               |                   |
886			//	  print          print              print
887			//
888			// When -coverpkg=<pattern> is in effect, we want to
889			// express the coverage percentage for each package as a
890			// fraction of *all* the statements that match the
891			// pattern, hence if "c" doesn't import "a", we need to
892			// pass as meta-data file for "a" (emitted during the
893			// package "a" build) to the package "c" run action, so
894			// that it can be incorporated with "c"'s regular
895			// metadata. To do this, we add edges from each compile
896			// action to a "writeCoverMeta" action, then from the
897			// writeCoverMeta action to each run action. Updated
898			// graph:
899			//
900			//	build("a")       build("b")         build("c")
901			//	    |   \       /   |               /   |
902			//	    |    v     v    |              /    |
903			//	    |   writemeta <-|-------------+     |
904			//	    |         |||   |                   |
905			//	    |         ||\   |                   |
906			//	link("a.test")/\ \  link("b.test")      link("c.test")
907			//	    |        /  \ +-|--------------+    |
908			//	    |       /    \  |               \   |
909			//	    |      v      v |                v  |
910			//	run("a.test")    run("b.test")      run("c.test")
911			//	    |               |                   |
912			//	  print          print              print
913			//
914			writeCoverMetaAct = &work.Action{
915				Mode:   "write coverage meta-data file",
916				Actor:  work.ActorFunc(work.WriteCoverMetaFilesFile),
917				Objdir: b.NewObjdir(),
918			}
919			for _, p := range testCoverPkgs {
920				p.Internal.Cover.GenMeta = true
921			}
922		}
923	}
924
925	// Inform the compiler that it should instrument the binary at
926	// build-time when fuzzing is enabled.
927	if testFuzz != "" {
928		// Don't instrument packages which may affect coverage guidance but are
929		// unlikely to be useful. Most of these are used by the testing or
930		// internal/fuzz packages concurrently with fuzzing.
931		var skipInstrumentation = map[string]bool{
932			"context":       true,
933			"internal/fuzz": true,
934			"reflect":       true,
935			"runtime":       true,
936			"sync":          true,
937			"sync/atomic":   true,
938			"syscall":       true,
939			"testing":       true,
940			"time":          true,
941		}
942		for _, p := range load.TestPackageList(ctx, pkgOpts, pkgs) {
943			if !skipInstrumentation[p.ImportPath] {
944				p.Internal.FuzzInstrument = true
945			}
946		}
947	}
948
949	// Collect all the packages imported by the packages being tested.
950	allImports := make(map[*load.Package]bool)
951	for _, p := range pkgs {
952		if p.Error != nil && p.Error.IsImportCycle {
953			continue
954		}
955		for _, p1 := range p.Internal.Imports {
956			allImports[p1] = true
957		}
958	}
959
960	if cfg.BuildCover {
961		for _, p := range pkgs {
962			// sync/atomic import is inserted by the cover tool if
963			// we're using atomic mode (and not compiling
964			// sync/atomic package itself). See #18486 and #57445.
965			// Note that this needs to be done prior to any of the
966			// builderTest invocations below, due to the fact that
967			// a given package in the 'pkgs' list may import
968			// package Q which appears later in the list (if this
969			// happens we'll wind up building the Q compile action
970			// before updating its deps to include sync/atomic).
971			if cfg.BuildCoverMode == "atomic" && p.ImportPath != "sync/atomic" {
972				load.EnsureImport(p, "sync/atomic")
973			}
974			// Tag the package for static meta-data generation if no
975			// test files (this works only with the new coverage
976			// design). Do this here (as opposed to in builderTest) so
977			// as to handle the case where we're testing multiple
978			// packages and one of the earlier packages imports a
979			// later package. Note that if -coverpkg is in effect
980			// p.Internal.Cover.GenMeta will wind up being set for
981			// all matching packages.
982			if len(p.TestGoFiles)+len(p.XTestGoFiles) == 0 &&
983				cfg.BuildCoverPkg == nil &&
984				cfg.Experiment.CoverageRedesign {
985				p.Internal.Cover.GenMeta = true
986			}
987		}
988	}
989
990	// Prepare build + run + print actions for all packages being tested.
991	for _, p := range pkgs {
992		buildTest, runTest, printTest, err := builderTest(b, ctx, pkgOpts, p, allImports[p], writeCoverMetaAct)
993		if err != nil {
994			str := err.Error()
995			str = strings.TrimPrefix(str, "\n")
996			if p.ImportPath != "" {
997				base.Errorf("# %s\n%s", p.ImportPath, str)
998			} else {
999				base.Errorf("%s", str)
1000			}
1001			fmt.Printf("FAIL\t%s [setup failed]\n", p.ImportPath)
1002			continue
1003		}
1004		builds = append(builds, buildTest)
1005		runs = append(runs, runTest)
1006		prints = append(prints, printTest)
1007	}
1008
1009	// Order runs for coordinating start JSON prints.
1010	ch := make(chan struct{})
1011	close(ch)
1012	for _, a := range runs {
1013		if r, ok := a.Actor.(*runTestActor); ok {
1014			r.prev = ch
1015			ch = make(chan struct{})
1016			r.next = ch
1017		}
1018	}
1019
1020	// Ultimately the goal is to print the output.
1021	root := &work.Action{Mode: "go test", Actor: work.ActorFunc(printExitStatus), Deps: prints}
1022
1023	// Force the printing of results to happen in order,
1024	// one at a time.
1025	for i, a := range prints {
1026		if i > 0 {
1027			a.Deps = append(a.Deps, prints[i-1])
1028		}
1029	}
1030
1031	// Force benchmarks to run in serial.
1032	if !testC && (testBench != "") {
1033		// The first run must wait for all builds.
1034		// Later runs must wait for the previous run's print.
1035		for i, run := range runs {
1036			if i == 0 {
1037				run.Deps = append(run.Deps, builds...)
1038			} else {
1039				run.Deps = append(run.Deps, prints[i-1])
1040			}
1041		}
1042	}
1043
1044	b.Do(ctx, root)
1045}
1046
1047var windowsBadWords = []string{
1048	"install",
1049	"patch",
1050	"setup",
1051	"update",
1052}
1053
1054func builderTest(b *work.Builder, ctx context.Context, pkgOpts load.PackageOpts, p *load.Package, imported bool, writeCoverMetaAct *work.Action) (buildAction, runAction, printAction *work.Action, err error) {
1055	if len(p.TestGoFiles)+len(p.XTestGoFiles) == 0 {
1056		if cfg.BuildCover && cfg.Experiment.CoverageRedesign {
1057			if p.Internal.Cover.GenMeta {
1058				p.Internal.Cover.Mode = cfg.BuildCoverMode
1059			}
1060		}
1061		build := b.CompileAction(work.ModeBuild, work.ModeBuild, p)
1062		run := &work.Action{
1063			Mode:       "test run",
1064			Actor:      new(runTestActor),
1065			Deps:       []*work.Action{build},
1066			Objdir:     b.NewObjdir(),
1067			Package:    p,
1068			IgnoreFail: true, // run (prepare output) even if build failed
1069		}
1070		if writeCoverMetaAct != nil && build.Actor != nil {
1071			// There is no real "run" for this package (since there
1072			// are no tests), but if coverage is turned on, we can
1073			// collect coverage data for the code in the package by
1074			// asking cmd/cover for a static meta-data file as part of
1075			// the package build. This static meta-data file is then
1076			// consumed by a pseudo-action (writeCoverMetaAct) that
1077			// adds it to a summary file, then this summary file is
1078			// consumed by the various "run test" actions. Below we
1079			// add a dependence edge between the build action and the
1080			// "write meta files" pseudo-action, and then another dep
1081			// from writeCoverMetaAct to the run action. See the
1082			// comment in runTest() at the definition of
1083			// writeCoverMetaAct for more details.
1084			run.Deps = append(run.Deps, writeCoverMetaAct)
1085			writeCoverMetaAct.Deps = append(writeCoverMetaAct.Deps, build)
1086		}
1087		addTestVet(b, p, run, nil)
1088		print := &work.Action{
1089			Mode:       "test print",
1090			Actor:      work.ActorFunc(builderPrintTest),
1091			Deps:       []*work.Action{run},
1092			Package:    p,
1093			IgnoreFail: true, // print even if test failed
1094		}
1095		return build, run, print, nil
1096	}
1097
1098	// Build Package structs describing:
1099	//	pmain - pkg.test binary
1100	//	ptest - package + test files
1101	//	pxtest - package of external test files
1102	var cover *load.TestCover
1103	if cfg.BuildCover {
1104		cover = &load.TestCover{
1105			Mode:  cfg.BuildCoverMode,
1106			Local: cfg.BuildCoverPkg == nil,
1107			Pkgs:  testCoverPkgs,
1108			Paths: cfg.BuildCoverPkg,
1109		}
1110	}
1111	pmain, ptest, pxtest, err := load.TestPackagesFor(ctx, pkgOpts, p, cover)
1112	if err != nil {
1113		return nil, nil, nil, err
1114	}
1115
1116	// If imported is true then this package is imported by some
1117	// package being tested. Make building the test version of the
1118	// package depend on building the non-test version, so that we
1119	// only report build errors once. Issue #44624.
1120	if imported && ptest != p {
1121		buildTest := b.CompileAction(work.ModeBuild, work.ModeBuild, ptest)
1122		buildP := b.CompileAction(work.ModeBuild, work.ModeBuild, p)
1123		buildTest.Deps = append(buildTest.Deps, buildP)
1124	}
1125
1126	testBinary := testBinaryName(p)
1127
1128	testDir := b.NewObjdir()
1129	if err := b.BackgroundShell().Mkdir(testDir); err != nil {
1130		return nil, nil, nil, err
1131	}
1132
1133	pmain.Dir = testDir
1134	pmain.Internal.OmitDebug = !testC && !testNeedBinary()
1135	if pmain.ImportPath == "runtime.test" {
1136		// The runtime package needs a symbolized binary for its tests.
1137		// See runtime/unsafepoint_test.go.
1138		pmain.Internal.OmitDebug = false
1139	}
1140
1141	if !cfg.BuildN {
1142		// writeTestmain writes _testmain.go,
1143		// using the test description gathered in t.
1144		if err := os.WriteFile(testDir+"_testmain.go", *pmain.Internal.TestmainGo, 0666); err != nil {
1145			return nil, nil, nil, err
1146		}
1147	}
1148
1149	// Set compile objdir to testDir we've already created,
1150	// so that the default file path stripping applies to _testmain.go.
1151	b.CompileAction(work.ModeBuild, work.ModeBuild, pmain).Objdir = testDir
1152
1153	a := b.LinkAction(work.ModeBuild, work.ModeBuild, pmain)
1154	a.Target = testDir + testBinary + cfg.ExeSuffix
1155	if cfg.Goos == "windows" {
1156		// There are many reserved words on Windows that,
1157		// if used in the name of an executable, cause Windows
1158		// to try to ask for extra permissions.
1159		// The word list includes setup, install, update, and patch,
1160		// but it does not appear to be defined anywhere.
1161		// We have run into this trying to run the
1162		// go.codereview/patch tests.
1163		// For package names containing those words, use test.test.exe
1164		// instead of pkgname.test.exe.
1165		// Note that this file name is only used in the Go command's
1166		// temporary directory. If the -c or other flags are
1167		// given, the code below will still use pkgname.test.exe.
1168		// There are two user-visible effects of this change.
1169		// First, you can actually run 'go test' in directories that
1170		// have names that Windows thinks are installer-like,
1171		// without getting a dialog box asking for more permissions.
1172		// Second, in the Windows process listing during go test,
1173		// the test shows up as test.test.exe, not pkgname.test.exe.
1174		// That second one is a drawback, but it seems a small
1175		// price to pay for the test running at all.
1176		// If maintaining the list of bad words is too onerous,
1177		// we could just do this always on Windows.
1178		for _, bad := range windowsBadWords {
1179			if strings.Contains(testBinary, bad) {
1180				a.Target = testDir + "test.test" + cfg.ExeSuffix
1181				break
1182			}
1183		}
1184	}
1185	buildAction = a
1186	var installAction, cleanAction *work.Action
1187	if testC || testNeedBinary() {
1188		// -c or profiling flag: create action to copy binary to ./test.out.
1189		target := filepath.Join(base.Cwd(), testBinary+cfg.ExeSuffix)
1190		isNull := false
1191
1192		if testO != "" {
1193			target = testO
1194
1195			if testODir {
1196				if filepath.IsAbs(target) {
1197					target = filepath.Join(target, testBinary+cfg.ExeSuffix)
1198				} else {
1199					target = filepath.Join(base.Cwd(), target, testBinary+cfg.ExeSuffix)
1200				}
1201			} else {
1202				if base.IsNull(target) {
1203					isNull = true
1204				} else if !filepath.IsAbs(target) {
1205					target = filepath.Join(base.Cwd(), target)
1206				}
1207			}
1208		}
1209
1210		if isNull {
1211			runAction = buildAction
1212		} else {
1213			pmain.Target = target
1214			installAction = &work.Action{
1215				Mode:    "test build",
1216				Actor:   work.ActorFunc(work.BuildInstallFunc),
1217				Deps:    []*work.Action{buildAction},
1218				Package: pmain,
1219				Target:  target,
1220			}
1221			runAction = installAction // make sure runAction != nil even if not running test
1222		}
1223	}
1224
1225	var vetRunAction *work.Action
1226	if testC {
1227		printAction = &work.Action{Mode: "test print (nop)", Package: p, Deps: []*work.Action{runAction}} // nop
1228		vetRunAction = printAction
1229	} else {
1230		// run test
1231		rta := &runTestActor{
1232			writeCoverMetaAct: writeCoverMetaAct,
1233		}
1234		runAction = &work.Action{
1235			Mode:       "test run",
1236			Actor:      rta,
1237			Deps:       []*work.Action{buildAction},
1238			Package:    p,
1239			IgnoreFail: true, // run (prepare output) even if build failed
1240			TryCache:   rta.c.tryCache,
1241		}
1242		if writeCoverMetaAct != nil {
1243			// If writeCoverMetaAct != nil, this indicates that our
1244			// "go test -coverpkg" run actions will need to read the
1245			// meta-files summary file written by writeCoverMetaAct,
1246			// so add a dependence edge from writeCoverMetaAct to the
1247			// run action.
1248			runAction.Deps = append(runAction.Deps, writeCoverMetaAct)
1249			if !p.IsTestOnly() {
1250				// Package p is not test only, meaning that the build
1251				// action for p may generate a static meta-data file.
1252				// Add a dependence edge from p to writeCoverMetaAct,
1253				// which needs to know the name of that meta-data
1254				// file.
1255				compileAction := b.CompileAction(work.ModeBuild, work.ModeBuild, p)
1256				writeCoverMetaAct.Deps = append(writeCoverMetaAct.Deps, compileAction)
1257			}
1258		}
1259		runAction.Objdir = testDir
1260		vetRunAction = runAction
1261		cleanAction = &work.Action{
1262			Mode:       "test clean",
1263			Actor:      work.ActorFunc(builderCleanTest),
1264			Deps:       []*work.Action{runAction},
1265			Package:    p,
1266			IgnoreFail: true, // clean even if test failed
1267			Objdir:     testDir,
1268		}
1269		printAction = &work.Action{
1270			Mode:       "test print",
1271			Actor:      work.ActorFunc(builderPrintTest),
1272			Deps:       []*work.Action{cleanAction},
1273			Package:    p,
1274			IgnoreFail: true, // print even if test failed
1275		}
1276	}
1277
1278	if len(ptest.GoFiles)+len(ptest.CgoFiles) > 0 {
1279		addTestVet(b, ptest, vetRunAction, installAction)
1280	}
1281	if pxtest != nil {
1282		addTestVet(b, pxtest, vetRunAction, installAction)
1283	}
1284
1285	if installAction != nil {
1286		if runAction != installAction {
1287			installAction.Deps = append(installAction.Deps, runAction)
1288		}
1289		if cleanAction != nil {
1290			cleanAction.Deps = append(cleanAction.Deps, installAction)
1291		}
1292	}
1293
1294	return buildAction, runAction, printAction, nil
1295}
1296
1297func addTestVet(b *work.Builder, p *load.Package, runAction, installAction *work.Action) {
1298	if testVet.off {
1299		return
1300	}
1301
1302	vet := b.VetAction(work.ModeBuild, work.ModeBuild, p)
1303	runAction.Deps = append(runAction.Deps, vet)
1304	// Install will clean the build directory.
1305	// Make sure vet runs first.
1306	// The install ordering in b.VetAction does not apply here
1307	// because we are using a custom installAction (created above).
1308	if installAction != nil {
1309		installAction.Deps = append(installAction.Deps, vet)
1310	}
1311}
1312
1313var noTestsToRun = []byte("\ntesting: warning: no tests to run\n")
1314var noFuzzTestsToFuzz = []byte("\ntesting: warning: no fuzz tests to fuzz\n")
1315var tooManyFuzzTestsToFuzz = []byte("\ntesting: warning: -fuzz matches more than one fuzz test, won't fuzz\n")
1316
1317// runTestActor is the actor for running a test.
1318type runTestActor struct {
1319	c runCache
1320
1321	// writeCoverMetaAct points to the pseudo-action for collecting
1322	// coverage meta-data files for selected -cover test runs. See the
1323	// comment in runTest at the definition of writeCoverMetaAct for
1324	// more details.
1325	writeCoverMetaAct *work.Action
1326
1327	// sequencing of json start messages, to preserve test order
1328	prev <-chan struct{} // wait to start until prev is closed
1329	next chan<- struct{} // close next once the next test can start.
1330}
1331
1332// runCache is the cache for running a single test.
1333type runCache struct {
1334	disableCache bool // cache should be disabled for this run
1335
1336	buf *bytes.Buffer
1337	id1 cache.ActionID
1338	id2 cache.ActionID
1339}
1340
1341// stdoutMu and lockedStdout provide a locked standard output
1342// that guarantees never to interlace writes from multiple
1343// goroutines, so that we can have multiple JSON streams writing
1344// to a lockedStdout simultaneously and know that events will
1345// still be intelligible.
1346var stdoutMu sync.Mutex
1347
1348type lockedStdout struct{}
1349
1350func (lockedStdout) Write(b []byte) (int, error) {
1351	stdoutMu.Lock()
1352	defer stdoutMu.Unlock()
1353	return os.Stdout.Write(b)
1354}
1355
1356func (r *runTestActor) Act(b *work.Builder, ctx context.Context, a *work.Action) error {
1357	sh := b.Shell(a)
1358
1359	// Wait for previous test to get started and print its first json line.
1360	select {
1361	case <-r.prev:
1362		// If should fail fast then release next test and exit.
1363		if testShouldFailFast.Load() {
1364			close(r.next)
1365			return nil
1366		}
1367	case <-base.Interrupted:
1368		// We can't wait for the previous test action to complete: we don't start
1369		// new actions after an interrupt, so if that action wasn't already running
1370		// it might never happen. Instead, just don't log anything for this action.
1371		base.SetExitStatus(1)
1372		return nil
1373	}
1374
1375	var stdout io.Writer = os.Stdout
1376	var err error
1377	if testJSON {
1378		json := test2json.NewConverter(lockedStdout{}, a.Package.ImportPath, test2json.Timestamp)
1379		defer func() {
1380			json.Exited(err)
1381			json.Close()
1382		}()
1383		stdout = json
1384	}
1385
1386	// Release next test to start (test2json.NewConverter writes the start event).
1387	close(r.next)
1388
1389	if a.Failed {
1390		// We were unable to build the binary.
1391		a.Failed = false
1392		fmt.Fprintf(stdout, "FAIL\t%s [build failed]\n", a.Package.ImportPath)
1393		// Tell the JSON converter that this was a failure, not a passing run.
1394		err = errors.New("build failed")
1395		base.SetExitStatus(1)
1396		return nil
1397	}
1398
1399	coverProfTempFile := func(a *work.Action) string {
1400		if a.Objdir == "" {
1401			panic("internal error: objdir not set in coverProfTempFile")
1402		}
1403		return a.Objdir + "_cover_.out"
1404	}
1405
1406	if p := a.Package; len(p.TestGoFiles)+len(p.XTestGoFiles) == 0 {
1407		reportNoTestFiles := true
1408		if cfg.BuildCover && cfg.Experiment.CoverageRedesign && p.Internal.Cover.GenMeta {
1409			if err := sh.Mkdir(a.Objdir); err != nil {
1410				return err
1411			}
1412			mf, err := work.BuildActionCoverMetaFile(a)
1413			if err != nil {
1414				return err
1415			} else if mf != "" {
1416				reportNoTestFiles = false
1417				// Write out "percent statements covered".
1418				if err := work.WriteCoveragePercent(b, a, mf, stdout); err != nil {
1419					return err
1420				}
1421				// If -coverprofile is in effect, then generate a
1422				// coverage profile fragment for this package and
1423				// merge it with the final -coverprofile output file.
1424				if coverMerge.f != nil {
1425					cp := coverProfTempFile(a)
1426					if err := work.WriteCoverageProfile(b, a, mf, cp, stdout); err != nil {
1427						return err
1428					}
1429					mergeCoverProfile(stdout, cp)
1430				}
1431			}
1432		}
1433		if reportNoTestFiles {
1434			fmt.Fprintf(stdout, "?   \t%s\t[no test files]\n", p.ImportPath)
1435		}
1436		return nil
1437	}
1438
1439	var buf bytes.Buffer
1440	if len(pkgArgs) == 0 || testBench != "" || testFuzz != "" {
1441		// Stream test output (no buffering) when no package has
1442		// been given on the command line (implicit current directory)
1443		// or when benchmarking or fuzzing.
1444		// No change to stdout.
1445	} else {
1446		// If we're only running a single package under test or if parallelism is
1447		// set to 1, and if we're displaying all output (testShowPass), we can
1448		// hurry the output along, echoing it as soon as it comes in.
1449		// We still have to copy to &buf for caching the result. This special
1450		// case was introduced in Go 1.5 and is intentionally undocumented:
1451		// the exact details of output buffering are up to the go command and
1452		// subject to change. It would be nice to remove this special case
1453		// entirely, but it is surely very helpful to see progress being made
1454		// when tests are run on slow single-CPU ARM systems.
1455		//
1456		// If we're showing JSON output, then display output as soon as
1457		// possible even when multiple tests are being run: the JSON output
1458		// events are attributed to specific package tests, so interlacing them
1459		// is OK.
1460		if testShowPass() && (len(pkgs) == 1 || cfg.BuildP == 1) || testJSON {
1461			// Write both to stdout and buf, for possible saving
1462			// to cache, and for looking for the "no tests to run" message.
1463			stdout = io.MultiWriter(stdout, &buf)
1464		} else {
1465			stdout = &buf
1466		}
1467	}
1468
1469	if r.c.buf == nil {
1470		// We did not find a cached result using the link step action ID,
1471		// so we ran the link step. Try again now with the link output
1472		// content ID. The attempt using the action ID makes sure that
1473		// if the link inputs don't change, we reuse the cached test
1474		// result without even rerunning the linker. The attempt using
1475		// the link output (test binary) content ID makes sure that if
1476		// we have different link inputs but the same final binary,
1477		// we still reuse the cached test result.
1478		// c.saveOutput will store the result under both IDs.
1479		r.c.tryCacheWithID(b, a, a.Deps[0].BuildContentID())
1480	}
1481	if r.c.buf != nil {
1482		if stdout != &buf {
1483			stdout.Write(r.c.buf.Bytes())
1484			r.c.buf.Reset()
1485		}
1486		a.TestOutput = r.c.buf
1487		return nil
1488	}
1489
1490	execCmd := work.FindExecCmd()
1491	testlogArg := []string{}
1492	if !r.c.disableCache && len(execCmd) == 0 {
1493		testlogArg = []string{"-test.testlogfile=" + a.Objdir + "testlog.txt"}
1494	}
1495	panicArg := "-test.paniconexit0"
1496	fuzzArg := []string{}
1497	if testFuzz != "" {
1498		fuzzCacheDir := filepath.Join(cache.Default().FuzzDir(), a.Package.ImportPath)
1499		fuzzArg = []string{"-test.fuzzcachedir=" + fuzzCacheDir}
1500	}
1501	coverdirArg := []string{}
1502	addToEnv := ""
1503	if cfg.BuildCover {
1504		gcd := filepath.Join(a.Objdir, "gocoverdir")
1505		if err := sh.Mkdir(gcd); err != nil {
1506			// If we can't create a temp dir, terminate immediately
1507			// with an error as opposed to returning an error to the
1508			// caller; failed MkDir most likely indicates that we're
1509			// out of disk space or there is some other systemic error
1510			// that will make forward progress unlikely.
1511			base.Fatalf("failed to create temporary dir: %v", err)
1512		}
1513		coverdirArg = append(coverdirArg, "-test.gocoverdir="+gcd)
1514		if r.writeCoverMetaAct != nil {
1515			// Copy the meta-files file over into the test's coverdir
1516			// directory so that the coverage runtime support will be
1517			// able to find it.
1518			src := r.writeCoverMetaAct.Objdir + coverage.MetaFilesFileName
1519			dst := filepath.Join(gcd, coverage.MetaFilesFileName)
1520			if err := sh.CopyFile(dst, src, 0666, false); err != nil {
1521				return err
1522			}
1523		}
1524		// Even though we are passing the -test.gocoverdir option to
1525		// the test binary, also set GOCOVERDIR as well. This is
1526		// intended to help with tests that run "go build" to build
1527		// fresh copies of tools to test as part of the testing.
1528		addToEnv = "GOCOVERDIR=" + gcd
1529	}
1530	args := str.StringList(execCmd, a.Deps[0].BuiltTarget(), testlogArg, panicArg, fuzzArg, coverdirArg, testArgs)
1531
1532	if testCoverProfile != "" {
1533		// Write coverage to temporary profile, for merging later.
1534		for i, arg := range args {
1535			if strings.HasPrefix(arg, "-test.coverprofile=") {
1536				args[i] = "-test.coverprofile=" + coverProfTempFile(a)
1537			}
1538		}
1539	}
1540
1541	if cfg.BuildN || cfg.BuildX {
1542		sh.ShowCmd("", "%s", strings.Join(args, " "))
1543		if cfg.BuildN {
1544			return nil
1545		}
1546	}
1547
1548	// Normally, the test will terminate itself when the timeout expires,
1549	// but add a last-ditch deadline to detect and stop wedged binaries.
1550	ctx, cancel := context.WithTimeout(ctx, testKillTimeout)
1551	defer cancel()
1552
1553	// Now we're ready to actually run the command.
1554	//
1555	// If the -o flag is set, or if at some point we change cmd/go to start
1556	// copying test executables into the build cache, we may run into spurious
1557	// ETXTBSY errors on Unix platforms (see https://go.dev/issue/22315).
1558	//
1559	// Since we know what causes those, and we know that they should resolve
1560	// quickly (the ETXTBSY error will resolve as soon as the subprocess
1561	// holding the descriptor open reaches its 'exec' call), we retry them
1562	// in a loop.
1563
1564	var (
1565		cmd            *exec.Cmd
1566		t0             time.Time
1567		cancelKilled   = false
1568		cancelSignaled = false
1569	)
1570	for {
1571		cmd = exec.CommandContext(ctx, args[0], args[1:]...)
1572		cmd.Dir = a.Package.Dir
1573
1574		env := slices.Clip(cfg.OrigEnv)
1575		env = base.AppendPATH(env)
1576		env = base.AppendPWD(env, cmd.Dir)
1577		cmd.Env = env
1578		if addToEnv != "" {
1579			cmd.Env = append(cmd.Env, addToEnv)
1580		}
1581
1582		cmd.Stdout = stdout
1583		cmd.Stderr = stdout
1584
1585		cmd.Cancel = func() error {
1586			if base.SignalTrace == nil {
1587				err := cmd.Process.Kill()
1588				if err == nil {
1589					cancelKilled = true
1590				}
1591				return err
1592			}
1593
1594			// Send a quit signal in the hope that the program will print
1595			// a stack trace and exit.
1596			err := cmd.Process.Signal(base.SignalTrace)
1597			if err == nil {
1598				cancelSignaled = true
1599			}
1600			return err
1601		}
1602		cmd.WaitDelay = testWaitDelay
1603
1604		base.StartSigHandlers()
1605		t0 = time.Now()
1606		err = cmd.Run()
1607
1608		if !isETXTBSY(err) {
1609			// We didn't hit the race in #22315, so there is no reason to retry the
1610			// command.
1611			break
1612		}
1613	}
1614
1615	out := buf.Bytes()
1616	a.TestOutput = &buf
1617	t := fmt.Sprintf("%.3fs", time.Since(t0).Seconds())
1618
1619	mergeCoverProfile(cmd.Stdout, a.Objdir+"_cover_.out")
1620
1621	if err == nil {
1622		norun := ""
1623		if !testShowPass() && !testJSON {
1624			buf.Reset()
1625		}
1626		if bytes.HasPrefix(out, noTestsToRun[1:]) || bytes.Contains(out, noTestsToRun) {
1627			norun = " [no tests to run]"
1628		}
1629		if bytes.HasPrefix(out, noFuzzTestsToFuzz[1:]) || bytes.Contains(out, noFuzzTestsToFuzz) {
1630			norun = " [no fuzz tests to fuzz]"
1631		}
1632		if bytes.HasPrefix(out, tooManyFuzzTestsToFuzz[1:]) || bytes.Contains(out, tooManyFuzzTestsToFuzz) {
1633			norun = "[-fuzz matches more than one fuzz test, won't fuzz]"
1634		}
1635		if len(out) > 0 && !bytes.HasSuffix(out, []byte("\n")) {
1636			// Ensure that the output ends with a newline before the "ok"
1637			// line we're about to print (https://golang.org/issue/49317).
1638			cmd.Stdout.Write([]byte("\n"))
1639		}
1640		fmt.Fprintf(cmd.Stdout, "ok  \t%s\t%s%s%s\n", a.Package.ImportPath, t, coveragePercentage(out), norun)
1641		r.c.saveOutput(a)
1642	} else {
1643		if testFailFast {
1644			testShouldFailFast.Store(true)
1645		}
1646
1647		base.SetExitStatus(1)
1648		if cancelSignaled {
1649			fmt.Fprintf(cmd.Stdout, "*** Test killed with %v: ran too long (%v).\n", base.SignalTrace, testKillTimeout)
1650		} else if cancelKilled {
1651			fmt.Fprintf(cmd.Stdout, "*** Test killed: ran too long (%v).\n", testKillTimeout)
1652		} else if errors.Is(err, exec.ErrWaitDelay) {
1653			fmt.Fprintf(cmd.Stdout, "*** Test I/O incomplete %v after exiting.\n", cmd.WaitDelay)
1654		}
1655		var ee *exec.ExitError
1656		if len(out) == 0 || !errors.As(err, &ee) || !ee.Exited() {
1657			// If there was no test output, print the exit status so that the reason
1658			// for failure is clear.
1659			fmt.Fprintf(cmd.Stdout, "%s\n", err)
1660		} else if !bytes.HasSuffix(out, []byte("\n")) {
1661			// Otherwise, ensure that the output ends with a newline before the FAIL
1662			// line we're about to print (https://golang.org/issue/49317).
1663			cmd.Stdout.Write([]byte("\n"))
1664		}
1665
1666		// NOTE(golang.org/issue/37555): test2json reports that a test passes
1667		// unless "FAIL" is printed at the beginning of a line. The test may not
1668		// actually print that if it panics, exits, or terminates abnormally,
1669		// so we print it here. We can't always check whether it was printed
1670		// because some tests need stdout to be a terminal (golang.org/issue/34791),
1671		// not a pipe.
1672		// TODO(golang.org/issue/29062): tests that exit with status 0 without
1673		// printing a final result should fail.
1674		prefix := ""
1675		if testJSON || testV.json {
1676			prefix = "\x16"
1677		}
1678		fmt.Fprintf(cmd.Stdout, "%sFAIL\t%s\t%s\n", prefix, a.Package.ImportPath, t)
1679	}
1680
1681	if cmd.Stdout != &buf {
1682		buf.Reset() // cmd.Stdout was going to os.Stdout already
1683	}
1684	return nil
1685}
1686
1687// tryCache is called just before the link attempt,
1688// to see if the test result is cached and therefore the link is unneeded.
1689// It reports whether the result can be satisfied from cache.
1690func (c *runCache) tryCache(b *work.Builder, a *work.Action) bool {
1691	return c.tryCacheWithID(b, a, a.Deps[0].BuildActionID())
1692}
1693
1694func (c *runCache) tryCacheWithID(b *work.Builder, a *work.Action, id string) bool {
1695	if len(pkgArgs) == 0 {
1696		// Caching does not apply to "go test",
1697		// only to "go test foo" (including "go test .").
1698		if cache.DebugTest {
1699			fmt.Fprintf(os.Stderr, "testcache: caching disabled in local directory mode\n")
1700		}
1701		c.disableCache = true
1702		return false
1703	}
1704
1705	if a.Package.Root == "" {
1706		// Caching does not apply to tests outside of any module, GOPATH, or GOROOT.
1707		if cache.DebugTest {
1708			fmt.Fprintf(os.Stderr, "testcache: caching disabled for package outside of module root, GOPATH, or GOROOT: %s\n", a.Package.ImportPath)
1709		}
1710		c.disableCache = true
1711		return false
1712	}
1713
1714	var cacheArgs []string
1715	for _, arg := range testArgs {
1716		i := strings.Index(arg, "=")
1717		if i < 0 || !strings.HasPrefix(arg, "-test.") {
1718			if cache.DebugTest {
1719				fmt.Fprintf(os.Stderr, "testcache: caching disabled for test argument: %s\n", arg)
1720			}
1721			c.disableCache = true
1722			return false
1723		}
1724		switch arg[:i] {
1725		case "-test.benchtime",
1726			"-test.cpu",
1727			"-test.list",
1728			"-test.parallel",
1729			"-test.run",
1730			"-test.short",
1731			"-test.timeout",
1732			"-test.failfast",
1733			"-test.v",
1734			"-test.fullpath":
1735			// These are cacheable.
1736			// Note that this list is documented above,
1737			// so if you add to this list, update the docs too.
1738			cacheArgs = append(cacheArgs, arg)
1739
1740		default:
1741			// nothing else is cacheable
1742			if cache.DebugTest {
1743				fmt.Fprintf(os.Stderr, "testcache: caching disabled for test argument: %s\n", arg)
1744			}
1745			c.disableCache = true
1746			return false
1747		}
1748	}
1749
1750	// The test cache result fetch is a two-level lookup.
1751	//
1752	// First, we use the content hash of the test binary
1753	// and its command-line arguments to find the
1754	// list of environment variables and files consulted
1755	// the last time the test was run with those arguments.
1756	// (To avoid unnecessary links, we store this entry
1757	// under two hashes: id1 uses the linker inputs as a
1758	// proxy for the test binary, and id2 uses the actual
1759	// test binary. If the linker inputs are unchanged,
1760	// this way we avoid the link step, even though we
1761	// do not cache link outputs.)
1762	//
1763	// Second, we compute a hash of the values of the
1764	// environment variables and the content of the files
1765	// listed in the log from the previous run.
1766	// Then we look up test output using a combination of
1767	// the hash from the first part (testID) and the hash of the
1768	// test inputs (testInputsID).
1769	//
1770	// In order to store a new test result, we must redo the
1771	// testInputsID computation using the log from the run
1772	// we want to cache, and then we store that new log and
1773	// the new outputs.
1774
1775	h := cache.NewHash("testResult")
1776	fmt.Fprintf(h, "test binary %s args %q execcmd %q", id, cacheArgs, work.ExecCmd)
1777	testID := h.Sum()
1778	if c.id1 == (cache.ActionID{}) {
1779		c.id1 = testID
1780	} else {
1781		c.id2 = testID
1782	}
1783	if cache.DebugTest {
1784		fmt.Fprintf(os.Stderr, "testcache: %s: test ID %x => %x\n", a.Package.ImportPath, id, testID)
1785	}
1786
1787	// Load list of referenced environment variables and files
1788	// from last run of testID, and compute hash of that content.
1789	data, entry, err := cache.GetBytes(cache.Default(), testID)
1790	if !bytes.HasPrefix(data, testlogMagic) || data[len(data)-1] != '\n' {
1791		if cache.DebugTest {
1792			if err != nil {
1793				fmt.Fprintf(os.Stderr, "testcache: %s: input list not found: %v\n", a.Package.ImportPath, err)
1794			} else {
1795				fmt.Fprintf(os.Stderr, "testcache: %s: input list malformed\n", a.Package.ImportPath)
1796			}
1797		}
1798		return false
1799	}
1800	testInputsID, err := computeTestInputsID(a, data)
1801	if err != nil {
1802		return false
1803	}
1804	if cache.DebugTest {
1805		fmt.Fprintf(os.Stderr, "testcache: %s: test ID %x => input ID %x => %x\n", a.Package.ImportPath, testID, testInputsID, testAndInputKey(testID, testInputsID))
1806	}
1807
1808	// Parse cached result in preparation for changing run time to "(cached)".
1809	// If we can't parse the cached result, don't use it.
1810	data, entry, err = cache.GetBytes(cache.Default(), testAndInputKey(testID, testInputsID))
1811	if len(data) == 0 || data[len(data)-1] != '\n' {
1812		if cache.DebugTest {
1813			if err != nil {
1814				fmt.Fprintf(os.Stderr, "testcache: %s: test output not found: %v\n", a.Package.ImportPath, err)
1815			} else {
1816				fmt.Fprintf(os.Stderr, "testcache: %s: test output malformed\n", a.Package.ImportPath)
1817			}
1818		}
1819		return false
1820	}
1821	if entry.Time.Before(testCacheExpire) {
1822		if cache.DebugTest {
1823			fmt.Fprintf(os.Stderr, "testcache: %s: test output expired due to go clean -testcache\n", a.Package.ImportPath)
1824		}
1825		return false
1826	}
1827	i := bytes.LastIndexByte(data[:len(data)-1], '\n') + 1
1828	if !bytes.HasPrefix(data[i:], []byte("ok  \t")) {
1829		if cache.DebugTest {
1830			fmt.Fprintf(os.Stderr, "testcache: %s: test output malformed\n", a.Package.ImportPath)
1831		}
1832		return false
1833	}
1834	j := bytes.IndexByte(data[i+len("ok  \t"):], '\t')
1835	if j < 0 {
1836		if cache.DebugTest {
1837			fmt.Fprintf(os.Stderr, "testcache: %s: test output malformed\n", a.Package.ImportPath)
1838		}
1839		return false
1840	}
1841	j += i + len("ok  \t") + 1
1842
1843	// Committed to printing.
1844	c.buf = new(bytes.Buffer)
1845	c.buf.Write(data[:j])
1846	c.buf.WriteString("(cached)")
1847	for j < len(data) && ('0' <= data[j] && data[j] <= '9' || data[j] == '.' || data[j] == 's') {
1848		j++
1849	}
1850	c.buf.Write(data[j:])
1851	return true
1852}
1853
1854var errBadTestInputs = errors.New("error parsing test inputs")
1855var testlogMagic = []byte("# test log\n") // known to testing/internal/testdeps/deps.go
1856
1857// computeTestInputsID computes the "test inputs ID"
1858// (see comment in tryCacheWithID above) for the
1859// test log.
1860func computeTestInputsID(a *work.Action, testlog []byte) (cache.ActionID, error) {
1861	testlog = bytes.TrimPrefix(testlog, testlogMagic)
1862	h := cache.NewHash("testInputs")
1863	// The runtime always looks at GODEBUG, without telling us in the testlog.
1864	fmt.Fprintf(h, "env GODEBUG %x\n", hashGetenv("GODEBUG"))
1865	pwd := a.Package.Dir
1866	for _, line := range bytes.Split(testlog, []byte("\n")) {
1867		if len(line) == 0 {
1868			continue
1869		}
1870		s := string(line)
1871		op, name, found := strings.Cut(s, " ")
1872		if !found {
1873			if cache.DebugTest {
1874				fmt.Fprintf(os.Stderr, "testcache: %s: input list malformed (%q)\n", a.Package.ImportPath, line)
1875			}
1876			return cache.ActionID{}, errBadTestInputs
1877		}
1878		switch op {
1879		default:
1880			if cache.DebugTest {
1881				fmt.Fprintf(os.Stderr, "testcache: %s: input list malformed (%q)\n", a.Package.ImportPath, line)
1882			}
1883			return cache.ActionID{}, errBadTestInputs
1884		case "getenv":
1885			fmt.Fprintf(h, "env %s %x\n", name, hashGetenv(name))
1886		case "chdir":
1887			pwd = name // always absolute
1888			fmt.Fprintf(h, "chdir %s %x\n", name, hashStat(name))
1889		case "stat":
1890			if !filepath.IsAbs(name) {
1891				name = filepath.Join(pwd, name)
1892			}
1893			if a.Package.Root == "" || search.InDir(name, a.Package.Root) == "" {
1894				// Do not recheck files outside the module, GOPATH, or GOROOT root.
1895				break
1896			}
1897			fmt.Fprintf(h, "stat %s %x\n", name, hashStat(name))
1898		case "open":
1899			if !filepath.IsAbs(name) {
1900				name = filepath.Join(pwd, name)
1901			}
1902			if a.Package.Root == "" || search.InDir(name, a.Package.Root) == "" {
1903				// Do not recheck files outside the module, GOPATH, or GOROOT root.
1904				break
1905			}
1906			fh, err := hashOpen(name)
1907			if err != nil {
1908				if cache.DebugTest {
1909					fmt.Fprintf(os.Stderr, "testcache: %s: input file %s: %s\n", a.Package.ImportPath, name, err)
1910				}
1911				return cache.ActionID{}, err
1912			}
1913			fmt.Fprintf(h, "open %s %x\n", name, fh)
1914		}
1915	}
1916	sum := h.Sum()
1917	return sum, nil
1918}
1919
1920func hashGetenv(name string) cache.ActionID {
1921	h := cache.NewHash("getenv")
1922	v, ok := os.LookupEnv(name)
1923	if !ok {
1924		h.Write([]byte{0})
1925	} else {
1926		h.Write([]byte{1})
1927		h.Write([]byte(v))
1928	}
1929	return h.Sum()
1930}
1931
1932const modTimeCutoff = 2 * time.Second
1933
1934var errFileTooNew = errors.New("file used as input is too new")
1935
1936func hashOpen(name string) (cache.ActionID, error) {
1937	h := cache.NewHash("open")
1938	info, err := os.Stat(name)
1939	if err != nil {
1940		fmt.Fprintf(h, "err %v\n", err)
1941		return h.Sum(), nil
1942	}
1943	hashWriteStat(h, info)
1944	if info.IsDir() {
1945		files, err := os.ReadDir(name)
1946		if err != nil {
1947			fmt.Fprintf(h, "err %v\n", err)
1948		}
1949		for _, f := range files {
1950			fmt.Fprintf(h, "file %s ", f.Name())
1951			finfo, err := f.Info()
1952			if err != nil {
1953				fmt.Fprintf(h, "err %v\n", err)
1954			} else {
1955				hashWriteStat(h, finfo)
1956			}
1957		}
1958	} else if info.Mode().IsRegular() {
1959		// Because files might be very large, do not attempt
1960		// to hash the entirety of their content. Instead assume
1961		// the mtime and size recorded in hashWriteStat above
1962		// are good enough.
1963		//
1964		// To avoid problems for very recent files where a new
1965		// write might not change the mtime due to file system
1966		// mtime precision, reject caching if a file was read that
1967		// is less than modTimeCutoff old.
1968		if time.Since(info.ModTime()) < modTimeCutoff {
1969			return cache.ActionID{}, errFileTooNew
1970		}
1971	}
1972	return h.Sum(), nil
1973}
1974
1975func hashStat(name string) cache.ActionID {
1976	h := cache.NewHash("stat")
1977	if info, err := os.Stat(name); err != nil {
1978		fmt.Fprintf(h, "err %v\n", err)
1979	} else {
1980		hashWriteStat(h, info)
1981	}
1982	if info, err := os.Lstat(name); err != nil {
1983		fmt.Fprintf(h, "err %v\n", err)
1984	} else {
1985		hashWriteStat(h, info)
1986	}
1987	return h.Sum()
1988}
1989
1990func hashWriteStat(h io.Writer, info fs.FileInfo) {
1991	fmt.Fprintf(h, "stat %d %x %v %v\n", info.Size(), uint64(info.Mode()), info.ModTime(), info.IsDir())
1992}
1993
1994// testAndInputKey returns the actual cache key for the pair (testID, testInputsID).
1995func testAndInputKey(testID, testInputsID cache.ActionID) cache.ActionID {
1996	return cache.Subkey(testID, fmt.Sprintf("inputs:%x", testInputsID))
1997}
1998
1999func (c *runCache) saveOutput(a *work.Action) {
2000	if c.id1 == (cache.ActionID{}) && c.id2 == (cache.ActionID{}) {
2001		return
2002	}
2003
2004	// See comment about two-level lookup in tryCacheWithID above.
2005	testlog, err := os.ReadFile(a.Objdir + "testlog.txt")
2006	if err != nil || !bytes.HasPrefix(testlog, testlogMagic) || testlog[len(testlog)-1] != '\n' {
2007		if cache.DebugTest {
2008			if err != nil {
2009				fmt.Fprintf(os.Stderr, "testcache: %s: reading testlog: %v\n", a.Package.ImportPath, err)
2010			} else {
2011				fmt.Fprintf(os.Stderr, "testcache: %s: reading testlog: malformed\n", a.Package.ImportPath)
2012			}
2013		}
2014		return
2015	}
2016	testInputsID, err := computeTestInputsID(a, testlog)
2017	if err != nil {
2018		return
2019	}
2020	if c.id1 != (cache.ActionID{}) {
2021		if cache.DebugTest {
2022			fmt.Fprintf(os.Stderr, "testcache: %s: save test ID %x => input ID %x => %x\n", a.Package.ImportPath, c.id1, testInputsID, testAndInputKey(c.id1, testInputsID))
2023		}
2024		cache.PutNoVerify(cache.Default(), c.id1, bytes.NewReader(testlog))
2025		cache.PutNoVerify(cache.Default(), testAndInputKey(c.id1, testInputsID), bytes.NewReader(a.TestOutput.Bytes()))
2026	}
2027	if c.id2 != (cache.ActionID{}) {
2028		if cache.DebugTest {
2029			fmt.Fprintf(os.Stderr, "testcache: %s: save test ID %x => input ID %x => %x\n", a.Package.ImportPath, c.id2, testInputsID, testAndInputKey(c.id2, testInputsID))
2030		}
2031		cache.PutNoVerify(cache.Default(), c.id2, bytes.NewReader(testlog))
2032		cache.PutNoVerify(cache.Default(), testAndInputKey(c.id2, testInputsID), bytes.NewReader(a.TestOutput.Bytes()))
2033	}
2034}
2035
2036// coveragePercentage returns the coverage results (if enabled) for the
2037// test. It uncovers the data by scanning the output from the test run.
2038func coveragePercentage(out []byte) string {
2039	if !cfg.BuildCover {
2040		return ""
2041	}
2042	// The string looks like
2043	//	test coverage for encoding/binary: 79.9% of statements
2044	// Extract the piece from the percentage to the end of the line.
2045	re := regexp.MustCompile(`coverage: (.*)\n`)
2046	matches := re.FindSubmatch(out)
2047	if matches == nil {
2048		// Probably running "go test -cover" not "go test -cover fmt".
2049		// The coverage output will appear in the output directly.
2050		return ""
2051	}
2052	return fmt.Sprintf("\tcoverage: %s", matches[1])
2053}
2054
2055// builderCleanTest is the action for cleaning up after a test.
2056func builderCleanTest(b *work.Builder, ctx context.Context, a *work.Action) error {
2057	if cfg.BuildWork {
2058		return nil
2059	}
2060	b.Shell(a).RemoveAll(a.Objdir)
2061	return nil
2062}
2063
2064// builderPrintTest is the action for printing a test result.
2065func builderPrintTest(b *work.Builder, ctx context.Context, a *work.Action) error {
2066	clean := a.Deps[0]
2067	run := clean.Deps[0]
2068	if run.TestOutput != nil {
2069		os.Stdout.Write(run.TestOutput.Bytes())
2070		run.TestOutput = nil
2071	}
2072	return nil
2073}
2074
2075// printExitStatus is the action for printing the final exit status.
2076// If we are running multiple test targets, print a final "FAIL"
2077// in case a failure in an early package has already scrolled
2078// off of the user's terminal.
2079// (See https://golang.org/issue/30507#issuecomment-470593235.)
2080//
2081// In JSON mode, we need to maintain valid JSON output and
2082// we assume that the test output is being parsed by a tool
2083// anyway, so the failure will not be missed and would be
2084// awkward to try to wedge into the JSON stream.
2085//
2086// In fuzz mode, we only allow a single package for now
2087// (see CL 350156 and https://golang.org/issue/46312),
2088// so there is no possibility of scrolling off and no need
2089// to print the final status.
2090func printExitStatus(b *work.Builder, ctx context.Context, a *work.Action) error {
2091	if !testJSON && testFuzz == "" && len(pkgArgs) != 0 {
2092		if base.GetExitStatus() != 0 {
2093			fmt.Println("FAIL")
2094			return nil
2095		}
2096	}
2097	return nil
2098}
2099
2100// testBinaryName can be used to create name for test binary executable.
2101// Use last element of import path, not package name.
2102// They differ when package name is "main".
2103// But if the import path is "command-line-arguments",
2104// like it is during 'go run', use the package name.
2105func testBinaryName(p *load.Package) string {
2106	var elem string
2107	if p.ImportPath == "command-line-arguments" {
2108		elem = p.Name
2109	} else {
2110		elem = p.DefaultExecName()
2111	}
2112
2113	return elem + ".test"
2114}
2115