github.com/go-asm/go@v1.21.1-0.20240213172139-40c5ead50c48/cmd/go/test/test.go (about)

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