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