Source file src/cmd/go/internal/test/test.go

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

View as plain text