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 }