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  	"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.
    43  func init() {
    44  	CmdTest.Run = runTest
    45  }
    46  
    47  const testUsage = "go test [build/test flags] [packages] [build/test flags & test binary flags]"
    48  
    49  var 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.
    55  It 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  
    62  followed by detailed output for each failed package.
    63  
    64  'Go test' recompiles each package along with any files with names matching
    65  the file pattern "*_test.go".
    66  These additional files can contain test functions, benchmark functions, fuzz
    67  tests and example functions. See 'go help testfunc' for more.
    68  Each listed package causes the execution of a separate test binary.
    69  Files whose names begin with "_" (including "_test.go") or "." are ignored.
    70  
    71  Test files that declare a package with the suffix "_test" will be compiled as a
    72  separate package, and then linked and run with the main test binary.
    73  
    74  The go tool will ignore a directory named "testdata", making it available
    75  to hold ancillary data needed by the tests.
    76  
    77  As part of building a test binary, go test runs go vet on the package
    78  and its test source files to identify significant problems. If go vet
    79  finds any problems, go test reports those and does not run the test
    80  binary. Only a high-confidence subset of the default go vet checks are
    81  used. That subset is: atomic, bool, buildtags, directive, errorsas,
    82  ifaceassert, nilfunc, printf, and stringintconv. You can see
    83  the documentation for these and other vet tests via "go doc cmd/vet".
    84  To disable the running of go vet, use the -vet=off flag. To run all
    85  checks, use the -vet=all flag.
    86  
    87  All test output and summary lines are printed to the go command's
    88  standard output, even if the test printed them to its own standard
    89  error. (The go command's standard error is reserved for printing
    90  errors building the tests.)
    91  
    92  The go command places $GOROOT/bin at the beginning of $PATH
    93  in the test's environment, so that tests that execute
    94  'go' commands use the same 'go' as the parent 'go test' command.
    95  
    96  Go test runs in two different modes:
    97  
    98  The first, called local directory mode, occurs when go test is
    99  invoked with no package arguments (for example, 'go test' or 'go
   100  test -v'). In this mode, go test compiles the package sources and
   101  tests found in the current directory and then runs the resulting
   102  test binary. In this mode, caching (discussed below) is disabled.
   103  After the package test finishes, go test prints a summary line
   104  showing the test status ('ok' or 'FAIL'), package name, and elapsed
   105  time.
   106  
   107  The second, called package list mode, occurs when go test is invoked
   108  with explicit package arguments (for example 'go test math', 'go
   109  test ./...', and even 'go test .'). In this mode, go test compiles
   110  and tests each of the packages listed on the command line. If a
   111  package test passes, go test prints only the final 'ok' summary
   112  line. If a package test fails, go test prints the full test output.
   113  If invoked with the -bench or -v flag, go test prints the full
   114  output even for passing package tests, in order to display the
   115  requested benchmark results or verbose logging. After the package
   116  tests for all of the listed packages finish, and their output is
   117  printed, go test prints a final 'FAIL' status if any package test
   118  has failed.
   119  
   120  In package list mode only, go test caches successful package test
   121  results to avoid unnecessary repeated running of tests. When the
   122  result of a test can be recovered from the cache, go test will
   123  redisplay the previous output instead of running the test binary
   124  again. When this happens, go test prints '(cached)' in place of the
   125  elapsed time in the summary line.
   126  
   127  The rule for a match in the cache is that the run involves the same
   128  test binary and the flags on the command line come entirely from a
   129  restricted set of 'cacheable' test flags, defined as -benchtime, -cpu,
   130  -list, -parallel, -run, -short, -timeout, -failfast, -fullpath and -v.
   131  If a run of go test has any test or non-test flags outside this set,
   132  the result is not cached. To disable test caching, use any test flag
   133  or argument other than the cacheable flags. The idiomatic way to disable
   134  test caching explicitly is to use -count=1. Tests that open files within
   135  the package's source root (usually $GOPATH) or that consult environment
   136  variables only match future runs in which the files and environment
   137  variables are unchanged. A cached test result is treated as executing
   138  in no time at all, so a successful package test result will be cached and
   139  reused regardless of -timeout setting.
   140  
   141  In 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  
   168  The test binary also accepts flags that control execution of the test; these
   169  flags are also accessible by 'go test'. See 'go help testflag' for details.
   170  
   171  For more about build flags, see 'go help build'.
   172  For more about specifying packages, see 'go help packages'.
   173  
   174  See also: go build, go vet.
   175  `,
   176  }
   177  
   178  var HelpTestflag = &base.Command{
   179  	UsageLine: "testflag",
   180  	Short:     "testing flags",
   181  	Long: `
   182  The 'go test' command takes both flags that apply to 'go test' itself
   183  and flags that apply to the resulting test binary.
   184  
   185  Several of the flags control profiling and write an execution profile
   186  suitable for "go tool pprof"; run "go tool pprof -h" for more
   187  information. The --alloc_space, --alloc_objects, and --show_bytes
   188  options of pprof control how the information is presented.
   189  
   190  The following flags are recognized by the 'go test' command and
   191  control 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  
   351  The following flags are also recognized by 'go test' and can be used to
   352  profile 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  
   405  Each of these flags is also recognized with an optional 'test.' prefix,
   406  as in -test.v. When invoking the generated test binary (the result of
   407  'go test -c') directly, however, the prefix is mandatory.
   408  
   409  The 'go test' command rewrites or removes recognized flags,
   410  as appropriate, both before and after the optional package list,
   411  before invoking the test binary.
   412  
   413  For instance, the command
   414  
   415  	go test -v -myflag testdata -cpuprofile=prof.out -x
   416  
   417  will 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
   422  execution, not to the test itself.)
   423  
   424  The test flags that generate profiles (other than for coverage) also
   425  leave the test binary in pkg.test for use when analyzing the profiles.
   426  
   427  When 'go test' runs a test binary, it does so from within the
   428  corresponding package's source code directory. Depending on the test,
   429  it may be necessary to do the same when invoking a generated test
   430  binary directly. Because that directory may be located within the
   431  module cache, which may be read-only and is verified by checksums, the
   432  test must not write to it or any other directory within the module
   433  unless explicitly requested by the user (such as with the -fuzz flag,
   434  which writes failures to testdata/fuzz).
   435  
   436  The command-line package list, if present, must appear before any
   437  flag not known to the go test command. Continuing the example above,
   438  the package list would have to appear before -myflag, but could appear
   439  on either side of -v.
   440  
   441  When 'go test' runs in package list mode, 'go test' caches successful
   442  package test results to avoid unnecessary repeated running of tests. To
   443  disable test caching, use any test flag or argument other than the
   444  cacheable flags. The idiomatic way to disable test caching explicitly
   445  is to use -count=1.
   446  
   447  To keep an argument for a test binary from being interpreted as a
   448  known flag or a package name, use -args (see 'go help test') which
   449  passes the remainder of the command line through to the test binary
   450  uninterpreted and unaltered.
   451  
   452  For instance, the command
   453  
   454  	go test -v -args -x -v
   455  
   456  will compile the test binary and then run it as
   457  
   458  	pkg.test -test.v -x -v
   459  
   460  Similarly,
   461  
   462  	go test -args math
   463  
   464  will compile the test binary and then run it as
   465  
   466  	pkg.test math
   467  
   468  In the first example, the -x and the second -v are passed through to the
   469  test binary unchanged and with no effect on the go command itself.
   470  In the second example, the argument math is passed through to the test
   471  binary, instead of being interpreted as the package list.
   472  `,
   473  }
   474  
   475  var HelpTestfunc = &base.Command{
   476  	UsageLine: "testfunc",
   477  	Short:     "testing functions",
   478  	Long: `
   479  The 'go test' command expects to find test, benchmark, and example functions
   480  in the "*_test.go" files corresponding to the package under test.
   481  
   482  A test function is one named TestXxx (where Xxx does not start with a
   483  lower case letter) and should have the signature,
   484  
   485  	func TestXxx(t *testing.T) { ... }
   486  
   487  A benchmark function is one named BenchmarkXxx and should have the signature,
   488  
   489  	func BenchmarkXxx(b *testing.B) { ... }
   490  
   491  A fuzz test is one named FuzzXxx and should have the signature,
   492  
   493  	func FuzzXxx(f *testing.F) { ... }
   494  
   495  An 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.
   497  If the last comment in the function starts with "Output:" then the output
   498  is compared exactly against the comment (see examples below). If the last
   499  comment begins with "Unordered output:" then the output is compared to the
   500  comment, however the order of the lines is ignored. An example with no such
   501  comment is compiled but not executed. An example with no text after
   502  "Output:" is compiled, executed, and expected to produce no output.
   503  
   504  Godoc displays the body of ExampleXxx to demonstrate the use
   505  of the function, constant, or variable Xxx. An example of a method M with
   506  receiver type T or *T is named ExampleT_M. There may be multiple examples
   507  for a given function, constant, or variable, distinguished by a trailing _xxx,
   508  where xxx is a suffix not beginning with an upper case letter.
   509  
   510  Here 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  
   518  Here 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  
   532  The entire test file is presented as the example when it contains a single
   533  example function, at least one other function, type, variable, or constant
   534  declaration, and no tests, benchmarks, or fuzz tests.
   535  
   536  See the documentation of the testing package for more information.
   537  `,
   538  }
   539  
   540  var (
   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  
   557  type 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  
   562  func (*testVFlag) IsBoolFlag() bool { return true }
   563  
   564  func (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  
   578  func (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  
   588  var (
   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.
   607  func 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.
   625  func 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.
   643  func testShowPass() bool {
   644  	return testV.on || testList != "" || testHelp
   645  }
   646  
   647  var 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  
   677  func 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  
  1047  var windowsBadWords = []string{
  1048  	"install",
  1049  	"patch",
  1050  	"setup",
  1051  	"update",
  1052  }
  1053  
  1054  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) {
  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 {
  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  
  1297  func 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  
  1313  var noTestsToRun = []byte("\ntesting: warning: no tests to run\n")
  1314  var noFuzzTestsToFuzz = []byte("\ntesting: warning: no fuzz tests to fuzz\n")
  1315  var 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.
  1318  type 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.
  1333  type 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.
  1346  var stdoutMu sync.Mutex
  1347  
  1348  type lockedStdout struct{}
  1349  
  1350  func (lockedStdout) Write(b []byte) (int, error) {
  1351  	stdoutMu.Lock()
  1352  	defer stdoutMu.Unlock()
  1353  	return os.Stdout.Write(b)
  1354  }
  1355  
  1356  func (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.
  1690  func (c *runCache) tryCache(b *work.Builder, a *work.Action) bool {
  1691  	return c.tryCacheWithID(b, a, a.Deps[0].BuildActionID())
  1692  }
  1693  
  1694  func (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  
  1854  var errBadTestInputs = errors.New("error parsing test inputs")
  1855  var 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.
  1860  func 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  
  1920  func 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  
  1932  const modTimeCutoff = 2 * time.Second
  1933  
  1934  var errFileTooNew = errors.New("file used as input is too new")
  1935  
  1936  func 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  
  1975  func 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  
  1990  func 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).
  1995  func testAndInputKey(testID, testInputsID cache.ActionID) cache.ActionID {
  1996  	return cache.Subkey(testID, fmt.Sprintf("inputs:%x", testInputsID))
  1997  }
  1998  
  1999  func (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.
  2038  func 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.
  2056  func 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.
  2065  func 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.
  2090  func 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.
  2105  func 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  

View as plain text