github.com/megatontech/mynoteforgo@v0.0.0-20200507084910-5d0c6ea6e890/源码/cmd/dist/test.go (about) 1 // Copyright 2015 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 main 6 7 import ( 8 "bytes" 9 "errors" 10 "flag" 11 "fmt" 12 "io/ioutil" 13 "log" 14 "os" 15 "os/exec" 16 "path/filepath" 17 "reflect" 18 "regexp" 19 "runtime" 20 "strconv" 21 "strings" 22 "sync" 23 "time" 24 ) 25 26 func cmdtest() { 27 gogcflags = os.Getenv("GO_GCFLAGS") 28 29 var t tester 30 var noRebuild bool 31 flag.BoolVar(&t.listMode, "list", false, "list available tests") 32 flag.BoolVar(&t.rebuild, "rebuild", false, "rebuild everything first") 33 flag.BoolVar(&noRebuild, "no-rebuild", false, "overrides -rebuild (historical dreg)") 34 flag.BoolVar(&t.keepGoing, "k", false, "keep going even when error occurred") 35 flag.BoolVar(&t.race, "race", false, "run in race builder mode (different set of tests)") 36 flag.BoolVar(&t.compileOnly, "compile-only", false, "compile tests, but don't run them. This is for some builders. Not all dist tests respect this flag, but most do.") 37 flag.StringVar(&t.banner, "banner", "##### ", "banner prefix; blank means no section banners") 38 flag.StringVar(&t.runRxStr, "run", os.Getenv("GOTESTONLY"), 39 "run only those tests matching the regular expression; empty means to run all. "+ 40 "Special exception: if the string begins with '!', the match is inverted.") 41 xflagparse(-1) // any number of args 42 if noRebuild { 43 t.rebuild = false 44 } 45 t.run() 46 } 47 48 // tester executes cmdtest. 49 type tester struct { 50 race bool 51 listMode bool 52 rebuild bool 53 failed bool 54 keepGoing bool 55 compileOnly bool // just try to compile all tests, but no need to run 56 runRxStr string 57 runRx *regexp.Regexp 58 runRxWant bool // want runRx to match (true) or not match (false) 59 runNames []string // tests to run, exclusive with runRx; empty means all 60 banner string // prefix, or "" for none 61 lastHeading string // last dir heading printed 62 63 cgoEnabled bool 64 partial bool 65 haveTime bool // the 'time' binary is available 66 67 tests []distTest 68 timeoutScale int 69 70 worklist []*work 71 } 72 73 type work struct { 74 dt *distTest 75 cmd *exec.Cmd 76 start chan bool 77 out []byte 78 err error 79 end chan bool 80 } 81 82 // A distTest is a test run by dist test. 83 // Each test has a unique name and belongs to a group (heading) 84 type distTest struct { 85 name string // unique test name; may be filtered with -run flag 86 heading string // group section; this header is printed before the test is run. 87 fn func(*distTest) error 88 } 89 90 func (t *tester) run() { 91 timelog("start", "dist test") 92 93 var exeSuffix string 94 if goos == "windows" { 95 exeSuffix = ".exe" 96 } 97 if _, err := os.Stat(filepath.Join(gobin, "go"+exeSuffix)); err == nil { 98 os.Setenv("PATH", fmt.Sprintf("%s%c%s", gobin, os.PathListSeparator, os.Getenv("PATH"))) 99 } 100 101 slurp, err := exec.Command("go", "env", "CGO_ENABLED").Output() 102 if err != nil { 103 log.Fatalf("Error running go env CGO_ENABLED: %v", err) 104 } 105 t.cgoEnabled, _ = strconv.ParseBool(strings.TrimSpace(string(slurp))) 106 if flag.NArg() > 0 && t.runRxStr != "" { 107 log.Fatalf("the -run regular expression flag is mutually exclusive with test name arguments") 108 } 109 110 t.runNames = flag.Args() 111 112 if t.hasBash() { 113 if _, err := exec.LookPath("time"); err == nil { 114 t.haveTime = true 115 } 116 } 117 118 if t.rebuild { 119 t.out("Building packages and commands.") 120 // Force rebuild the whole toolchain. 121 goInstall("go", append([]string{"-a", "-i"}, toolchain...)...) 122 } 123 124 // Complete rebuild bootstrap, even with -no-rebuild. 125 // If everything is up-to-date, this is a no-op. 126 // If everything is not up-to-date, the first checkNotStale 127 // during the test process will kill the tests, so we might 128 // as well install the world. 129 // Now that for example "go install cmd/compile" does not 130 // also install runtime (you need "go install -i cmd/compile" 131 // for that), it's easy for previous workflows like 132 // "rebuild the compiler and then run run.bash" 133 // to break if we don't automatically refresh things here. 134 // Rebuilding is a shortened bootstrap. 135 // See cmdbootstrap for a description of the overall process. 136 // 137 // But don't do this if we're running in the Go build system, 138 // where cmd/dist is invoked many times. This just slows that 139 // down (Issue 24300). 140 if !t.listMode && os.Getenv("GO_BUILDER_NAME") == "" { 141 goInstall("go", append([]string{"-i"}, toolchain...)...) 142 goInstall("go", append([]string{"-i"}, toolchain...)...) 143 goInstall("go", "std", "cmd") 144 checkNotStale("go", "std", "cmd") 145 } 146 147 t.timeoutScale = 1 148 switch goarch { 149 case "arm": 150 t.timeoutScale = 2 151 case "mips", "mipsle", "mips64", "mips64le": 152 t.timeoutScale = 4 153 } 154 if s := os.Getenv("GO_TEST_TIMEOUT_SCALE"); s != "" { 155 t.timeoutScale, err = strconv.Atoi(s) 156 if err != nil { 157 log.Fatalf("failed to parse $GO_TEST_TIMEOUT_SCALE = %q as integer: %v", s, err) 158 } 159 } 160 161 if t.runRxStr != "" { 162 if t.runRxStr[0] == '!' { 163 t.runRxWant = false 164 t.runRxStr = t.runRxStr[1:] 165 } else { 166 t.runRxWant = true 167 } 168 t.runRx = regexp.MustCompile(t.runRxStr) 169 } 170 171 t.registerTests() 172 if t.listMode { 173 for _, tt := range t.tests { 174 fmt.Println(tt.name) 175 } 176 return 177 } 178 179 // We must unset GOROOT_FINAL before tests, because runtime/debug requires 180 // correct access to source code, so if we have GOROOT_FINAL in effect, 181 // at least runtime/debug test will fail. 182 // If GOROOT_FINAL was set before, then now all the commands will appear stale. 183 // Nothing we can do about that other than not checking them below. 184 // (We call checkNotStale but only with "std" not "cmd".) 185 os.Setenv("GOROOT_FINAL_OLD", os.Getenv("GOROOT_FINAL")) // for cmd/link test 186 os.Unsetenv("GOROOT_FINAL") 187 188 for _, name := range t.runNames { 189 if !t.isRegisteredTestName(name) { 190 log.Fatalf("unknown test %q", name) 191 } 192 } 193 194 for _, dt := range t.tests { 195 if !t.shouldRunTest(dt.name) { 196 t.partial = true 197 continue 198 } 199 dt := dt // dt used in background after this iteration 200 if err := dt.fn(&dt); err != nil { 201 t.runPending(&dt) // in case that hasn't been done yet 202 t.failed = true 203 if t.keepGoing { 204 log.Printf("Failed: %v", err) 205 } else { 206 log.Fatalf("Failed: %v", err) 207 } 208 } 209 } 210 t.runPending(nil) 211 timelog("end", "dist test") 212 if t.failed { 213 fmt.Println("\nFAILED") 214 os.Exit(1) 215 } else if incomplete[goos+"/"+goarch] { 216 fmt.Println("\nFAILED (incomplete port)") 217 os.Exit(1) 218 } else if t.partial { 219 fmt.Println("\nALL TESTS PASSED (some were excluded)") 220 } else { 221 fmt.Println("\nALL TESTS PASSED") 222 } 223 } 224 225 func (t *tester) shouldRunTest(name string) bool { 226 if t.runRx != nil { 227 return t.runRx.MatchString(name) == t.runRxWant 228 } 229 if len(t.runNames) == 0 { 230 return true 231 } 232 for _, runName := range t.runNames { 233 if runName == name { 234 return true 235 } 236 } 237 return false 238 } 239 240 // short returns a -short flag to pass to 'go test'. 241 // It returns "-short", unless the environment variable 242 // GO_TEST_SHORT is set to a non-empty, false-ish string. 243 // 244 // This environment variable is meant to be an internal 245 // detail between the Go build system and cmd/dist 246 // and is not intended for use by users. 247 func short() string { 248 if v := os.Getenv("GO_TEST_SHORT"); v != "" { 249 short, err := strconv.ParseBool(v) 250 if err != nil { 251 log.Fatalf("invalid GO_TEST_SHORT %q: %v", v, err) 252 } 253 if !short { 254 return "-short=false" 255 } 256 } 257 return "-short" 258 } 259 260 // goTest returns the beginning of the go test command line. 261 // Callers should use goTest and then pass flags overriding these 262 // defaults as later arguments in the command line. 263 func (t *tester) goTest() []string { 264 return []string{ 265 "go", "test", short(), "-count=1", t.tags(), t.runFlag(""), 266 } 267 } 268 269 func (t *tester) tags() string { 270 if t.iOS() { 271 return "-tags=lldb" 272 } 273 return "-tags=" 274 } 275 276 func (t *tester) timeout(sec int) string { 277 return "-timeout=" + fmt.Sprint(time.Duration(sec)*time.Second*time.Duration(t.timeoutScale)) 278 } 279 280 // ranGoTest and stdMatches are state closed over by the stdlib 281 // testing func in registerStdTest below. The tests are run 282 // sequentially, so there's no need for locks. 283 // 284 // ranGoBench and benchMatches are the same, but are only used 285 // in -race mode. 286 var ( 287 ranGoTest bool 288 stdMatches []string 289 290 ranGoBench bool 291 benchMatches []string 292 ) 293 294 func (t *tester) registerStdTest(pkg string) { 295 testName := "go_test:" + pkg 296 if t.runRx == nil || t.runRx.MatchString(testName) == t.runRxWant { 297 stdMatches = append(stdMatches, pkg) 298 } 299 t.tests = append(t.tests, distTest{ 300 name: testName, 301 heading: "Testing packages.", 302 fn: func(dt *distTest) error { 303 if ranGoTest { 304 return nil 305 } 306 t.runPending(dt) 307 timelog("start", dt.name) 308 defer timelog("end", dt.name) 309 ranGoTest = true 310 311 timeoutSec := 180 312 for _, pkg := range stdMatches { 313 if pkg == "cmd/go" { 314 timeoutSec *= 3 315 break 316 } 317 } 318 args := []string{ 319 "test", 320 short(), 321 t.tags(), 322 t.timeout(timeoutSec), 323 "-gcflags=all=" + gogcflags, 324 } 325 if t.race { 326 args = append(args, "-race") 327 } 328 if t.compileOnly { 329 args = append(args, "-run=^$") 330 } else if goos == "js" && goarch == "wasm" { 331 args = append(args, "-run=^Test") // exclude examples; Issue 25913 332 } 333 args = append(args, stdMatches...) 334 cmd := exec.Command("go", args...) 335 cmd.Stdout = os.Stdout 336 cmd.Stderr = os.Stderr 337 return cmd.Run() 338 }, 339 }) 340 } 341 342 func (t *tester) registerRaceBenchTest(pkg string) { 343 testName := "go_test_bench:" + pkg 344 if t.runRx == nil || t.runRx.MatchString(testName) == t.runRxWant { 345 benchMatches = append(benchMatches, pkg) 346 } 347 t.tests = append(t.tests, distTest{ 348 name: testName, 349 heading: "Running benchmarks briefly.", 350 fn: func(dt *distTest) error { 351 if ranGoBench { 352 return nil 353 } 354 t.runPending(dt) 355 timelog("start", dt.name) 356 defer timelog("end", dt.name) 357 ranGoBench = true 358 args := []string{ 359 "test", 360 short(), 361 "-race", 362 t.timeout(1200), // longer timeout for race with benchmarks 363 "-run=^$", // nothing. only benchmarks. 364 "-benchtime=.1s", 365 "-cpu=4", 366 } 367 if !t.compileOnly { 368 args = append(args, "-bench=.*") 369 } 370 args = append(args, benchMatches...) 371 cmd := exec.Command("go", args...) 372 cmd.Stdout = os.Stdout 373 cmd.Stderr = os.Stderr 374 return cmd.Run() 375 }, 376 }) 377 } 378 379 // stdOutErrAreTerminals is defined in test_linux.go, to report 380 // whether stdout & stderr are terminals. 381 var stdOutErrAreTerminals func() bool 382 383 func (t *tester) registerTests() { 384 if strings.HasSuffix(os.Getenv("GO_BUILDER_NAME"), "-vetall") { 385 // Run vet over std and cmd and call it quits. 386 for k := range cgoEnabled { 387 osarch := k 388 t.tests = append(t.tests, distTest{ 389 name: "vet/" + osarch, 390 heading: "cmd/vet/all", 391 fn: func(dt *distTest) error { 392 t.addCmd(dt, "src/cmd/vet/all", "go", "run", "main.go", "-p="+osarch) 393 return nil 394 }, 395 }) 396 } 397 return 398 } 399 400 // Fast path to avoid the ~1 second of `go list std cmd` when 401 // the caller lists specific tests to run. (as the continuous 402 // build coordinator does). 403 if len(t.runNames) > 0 { 404 for _, name := range t.runNames { 405 if strings.HasPrefix(name, "go_test:") { 406 t.registerStdTest(strings.TrimPrefix(name, "go_test:")) 407 } 408 if strings.HasPrefix(name, "go_test_bench:") { 409 t.registerRaceBenchTest(strings.TrimPrefix(name, "go_test_bench:")) 410 } 411 } 412 } else { 413 // Use a format string to only list packages and commands that have tests. 414 const format = "{{if (or .TestGoFiles .XTestGoFiles)}}{{.ImportPath}}{{end}}" 415 cmd := exec.Command("go", "list", "-f", format) 416 if t.race { 417 cmd.Args = append(cmd.Args, "-tags=race") 418 } 419 cmd.Args = append(cmd.Args, "std") 420 if !t.race { 421 cmd.Args = append(cmd.Args, "cmd") 422 } 423 all, err := cmd.Output() 424 if err != nil { 425 log.Fatalf("Error running go list std cmd: %v, %s", err, all) 426 } 427 pkgs := strings.Fields(string(all)) 428 for _, pkg := range pkgs { 429 t.registerStdTest(pkg) 430 } 431 if t.race { 432 for _, pkg := range pkgs { 433 if t.packageHasBenchmarks(pkg) { 434 t.registerRaceBenchTest(pkg) 435 } 436 } 437 } 438 } 439 440 // Test the os/user package in the pure-Go mode too. 441 if !t.compileOnly { 442 t.tests = append(t.tests, distTest{ 443 name: "osusergo", 444 heading: "os/user with tag osusergo", 445 fn: func(dt *distTest) error { 446 t.addCmd(dt, "src", t.goTest(), t.timeout(300), "-tags=osusergo", "os/user") 447 return nil 448 }, 449 }) 450 } 451 452 if t.race { 453 return 454 } 455 456 // Runtime CPU tests. 457 if !t.compileOnly && goos != "js" { // js can't handle -cpu != 1 458 testName := "runtime:cpu124" 459 t.tests = append(t.tests, distTest{ 460 name: testName, 461 heading: "GOMAXPROCS=2 runtime -cpu=1,2,4 -quick", 462 fn: func(dt *distTest) error { 463 cmd := t.addCmd(dt, "src", t.goTest(), t.timeout(300), "runtime", "-cpu=1,2,4", "-quick") 464 // We set GOMAXPROCS=2 in addition to -cpu=1,2,4 in order to test runtime bootstrap code, 465 // creation of first goroutines and first garbage collections in the parallel setting. 466 cmd.Env = append(os.Environ(), "GOMAXPROCS=2") 467 return nil 468 }, 469 }) 470 } 471 472 // This test needs its stdout/stderr to be terminals, so we don't run it from cmd/go's tests. 473 // See issue 18153. 474 if goos == "linux" { 475 t.tests = append(t.tests, distTest{ 476 name: "cmd_go_test_terminal", 477 heading: "cmd/go terminal test", 478 fn: func(dt *distTest) error { 479 t.runPending(dt) 480 timelog("start", dt.name) 481 defer timelog("end", dt.name) 482 if !stdOutErrAreTerminals() { 483 fmt.Println("skipping terminal test; stdout/stderr not terminals") 484 return nil 485 } 486 cmd := exec.Command("go", "test") 487 cmd.Dir = filepath.Join(os.Getenv("GOROOT"), "src/cmd/go/testdata/testterminal18153") 488 cmd.Stdout = os.Stdout 489 cmd.Stderr = os.Stderr 490 return cmd.Run() 491 }, 492 }) 493 } 494 495 // On the builders only, test that a moved GOROOT still works. 496 // Fails on iOS because CC_FOR_TARGET refers to clangwrap.sh 497 // in the unmoved GOROOT. 498 // Fails on Android and js/wasm with an exec format error. 499 // Fails on plan9 with "cannot find GOROOT" (issue #21016). 500 if os.Getenv("GO_BUILDER_NAME") != "" && goos != "android" && !t.iOS() && goos != "plan9" && goos != "js" { 501 t.tests = append(t.tests, distTest{ 502 name: "moved_goroot", 503 heading: "moved GOROOT", 504 fn: func(dt *distTest) error { 505 t.runPending(dt) 506 timelog("start", dt.name) 507 defer timelog("end", dt.name) 508 moved := goroot + "-moved" 509 if err := os.Rename(goroot, moved); err != nil { 510 if goos == "windows" { 511 // Fails on Windows (with "Access is denied") if a process 512 // or binary is in this directory. For instance, using all.bat 513 // when run from c:\workdir\go\src fails here 514 // if GO_BUILDER_NAME is set. Our builders invoke tests 515 // a different way which happens to work when sharding 516 // tests, but we should be tolerant of the non-sharded 517 // all.bat case. 518 log.Printf("skipping test on Windows") 519 return nil 520 } 521 return err 522 } 523 524 // Run `go test fmt` in the moved GOROOT. 525 cmd := exec.Command(filepath.Join(moved, "bin", "go"), "test", "fmt") 526 cmd.Stdout = os.Stdout 527 cmd.Stderr = os.Stderr 528 // Don't set GOROOT in the environment. 529 for _, e := range os.Environ() { 530 if !strings.HasPrefix(e, "GOROOT=") && !strings.HasPrefix(e, "GOCACHE=") { 531 cmd.Env = append(cmd.Env, e) 532 } 533 } 534 err := cmd.Run() 535 536 if rerr := os.Rename(moved, goroot); rerr != nil { 537 log.Fatalf("failed to restore GOROOT: %v", rerr) 538 } 539 return err 540 }, 541 }) 542 } 543 544 // Test that internal linking of standard packages does not 545 // require libgcc. This ensures that we can install a Go 546 // release on a system that does not have a C compiler 547 // installed and still build Go programs (that don't use cgo). 548 for _, pkg := range cgoPackages { 549 if !t.internalLink() { 550 break 551 } 552 553 // ARM libgcc may be Thumb, which internal linking does not support. 554 if goarch == "arm" { 555 break 556 } 557 558 pkg := pkg 559 var run string 560 if pkg == "net" { 561 run = "TestTCPStress" 562 } 563 t.tests = append(t.tests, distTest{ 564 name: "nolibgcc:" + pkg, 565 heading: "Testing without libgcc.", 566 fn: func(dt *distTest) error { 567 t.addCmd(dt, "src", t.goTest(), "-ldflags=-linkmode=internal -libgcc=none", pkg, t.runFlag(run)) 568 return nil 569 }, 570 }) 571 } 572 573 // Test internal linking of PIE binaries where it is supported. 574 if goos == "linux" && goarch == "amd64" && !isAlpineLinux() { 575 // Issue 18243: We don't have a way to set the default 576 // dynamic linker used in internal linking mode. So 577 // this test is skipped on Alpine. 578 t.tests = append(t.tests, distTest{ 579 name: "pie_internal", 580 heading: "internal linking of -buildmode=pie", 581 fn: func(dt *distTest) error { 582 t.addCmd(dt, "src", t.goTest(), "reflect", "-buildmode=pie", "-ldflags=-linkmode=internal", t.timeout(60)) 583 return nil 584 }, 585 }) 586 } 587 588 // sync tests 589 if goos != "js" { // js doesn't support -cpu=10 590 t.tests = append(t.tests, distTest{ 591 name: "sync_cpu", 592 heading: "sync -cpu=10", 593 fn: func(dt *distTest) error { 594 t.addCmd(dt, "src", t.goTest(), "sync", t.timeout(120), "-cpu=10", t.runFlag("")) 595 return nil 596 }, 597 }) 598 } 599 600 if t.raceDetectorSupported() { 601 t.tests = append(t.tests, distTest{ 602 name: "race", 603 heading: "Testing race detector", 604 fn: t.raceTest, 605 }) 606 } 607 608 if t.cgoEnabled && !t.iOS() { 609 // Disabled on iOS. golang.org/issue/15919 610 t.tests = append(t.tests, distTest{ 611 name: "cgo_stdio", 612 heading: "../misc/cgo/stdio", 613 fn: func(dt *distTest) error { 614 t.addCmd(dt, "misc/cgo/stdio", "go", "run", filepath.Join(os.Getenv("GOROOT"), "test/run.go"), "-", ".") 615 return nil 616 }, 617 }) 618 t.tests = append(t.tests, distTest{ 619 name: "cgo_life", 620 heading: "../misc/cgo/life", 621 fn: func(dt *distTest) error { 622 t.addCmd(dt, "misc/cgo/life", "go", "run", filepath.Join(os.Getenv("GOROOT"), "test/run.go"), "-", ".") 623 return nil 624 }, 625 }) 626 fortran := os.Getenv("FC") 627 if fortran == "" { 628 fortran, _ = exec.LookPath("gfortran") 629 } 630 if t.hasBash() && fortran != "" { 631 t.tests = append(t.tests, distTest{ 632 name: "cgo_fortran", 633 heading: "../misc/cgo/fortran", 634 fn: func(dt *distTest) error { 635 t.addCmd(dt, "misc/cgo/fortran", "./test.bash", fortran) 636 return nil 637 }, 638 }) 639 } 640 if t.hasSwig() && goos != "android" { 641 t.tests = append(t.tests, distTest{ 642 name: "swig_stdio", 643 heading: "../misc/swig/stdio", 644 fn: func(dt *distTest) error { 645 t.addCmd(dt, "misc/swig/stdio", t.goTest()) 646 return nil 647 }, 648 }) 649 if t.hasCxx() { 650 t.tests = append(t.tests, distTest{ 651 name: "swig_callback", 652 heading: "../misc/swig/callback", 653 fn: func(dt *distTest) error { 654 t.addCmd(dt, "misc/swig/callback", t.goTest()) 655 return nil 656 }, 657 }) 658 } 659 } 660 } 661 if t.cgoEnabled { 662 t.tests = append(t.tests, distTest{ 663 name: "cgo_test", 664 heading: "../misc/cgo/test", 665 fn: t.cgoTest, 666 }) 667 } 668 669 if t.hasBash() && t.cgoEnabled && goos != "android" && goos != "darwin" { 670 t.registerTest("testgodefs", "../misc/cgo/testgodefs", "./test.bash") 671 } 672 673 // Don't run these tests with $GO_GCFLAGS because most of them 674 // assume that they can run "go install" with no -gcflags and not 675 // recompile the entire standard library. If make.bash ran with 676 // special -gcflags, that's not true. 677 if t.cgoEnabled && gogcflags == "" { 678 if t.cgoTestSOSupported() { 679 t.tests = append(t.tests, distTest{ 680 name: "testso", 681 heading: "../misc/cgo/testso", 682 fn: func(dt *distTest) error { 683 return t.cgoTestSO(dt, "misc/cgo/testso") 684 }, 685 }) 686 t.tests = append(t.tests, distTest{ 687 name: "testsovar", 688 heading: "../misc/cgo/testsovar", 689 fn: func(dt *distTest) error { 690 return t.cgoTestSO(dt, "misc/cgo/testsovar") 691 }, 692 }) 693 } 694 if t.supportedBuildmode("c-archive") { 695 t.registerHostTest("testcarchive", "../misc/cgo/testcarchive", "misc/cgo/testcarchive", "carchive_test.go") 696 } 697 if t.supportedBuildmode("c-shared") { 698 t.registerHostTest("testcshared", "../misc/cgo/testcshared", "misc/cgo/testcshared", "cshared_test.go") 699 } 700 if t.supportedBuildmode("shared") { 701 t.registerTest("testshared", "../misc/cgo/testshared", t.goTest(), t.timeout(600)) 702 } 703 if t.supportedBuildmode("plugin") { 704 t.registerTest("testplugin", "../misc/cgo/testplugin", "./test.bash") 705 } 706 if gohostos == "linux" && goarch == "amd64" { 707 t.registerTest("testasan", "../misc/cgo/testasan", "go", "run", "main.go") 708 } 709 if mSanSupported(goos, goarch) { 710 t.registerHostTest("testsanitizers/msan", "../misc/cgo/testsanitizers", "misc/cgo/testsanitizers", ".") 711 } 712 if t.hasBash() && goos != "android" && !t.iOS() && gohostos != "windows" { 713 t.registerHostTest("cgo_errors", "../misc/cgo/errors", "misc/cgo/errors", ".") 714 } 715 if gohostos == "linux" && t.extLink() { 716 t.registerTest("testsigfwd", "../misc/cgo/testsigfwd", "go", "run", "main.go") 717 } 718 } 719 720 // Doc tests only run on builders. 721 // They find problems approximately never. 722 if t.hasBash() && goos != "nacl" && goos != "js" && goos != "android" && !t.iOS() && os.Getenv("GO_BUILDER_NAME") != "" { 723 t.registerTest("doc_progs", "../doc/progs", "time", "go", "run", "run.go") 724 t.registerTest("wiki", "../doc/articles/wiki", "./test.bash") 725 t.registerTest("codewalk", "../doc/codewalk", "time", "./run") 726 } 727 728 if goos != "android" && !t.iOS() { 729 t.registerTest("bench_go1", "../test/bench/go1", t.goTest(), t.timeout(600)) 730 } 731 if goos != "android" && !t.iOS() { 732 // Only start multiple test dir shards on builders, 733 // where they get distributed to multiple machines. 734 // See issue 20141. 735 nShards := 1 736 if os.Getenv("GO_BUILDER_NAME") != "" { 737 nShards = 10 738 } 739 for shard := 0; shard < nShards; shard++ { 740 shard := shard 741 t.tests = append(t.tests, distTest{ 742 name: fmt.Sprintf("test:%d_%d", shard, nShards), 743 heading: "../test", 744 fn: func(dt *distTest) error { return t.testDirTest(dt, shard, nShards) }, 745 }) 746 } 747 } 748 if goos != "nacl" && goos != "android" && !t.iOS() && goos != "js" { 749 t.tests = append(t.tests, distTest{ 750 name: "api", 751 heading: "API check", 752 fn: func(dt *distTest) error { 753 if t.compileOnly { 754 t.addCmd(dt, "src", "go", "build", filepath.Join(goroot, "src/cmd/api/run.go")) 755 return nil 756 } 757 t.addCmd(dt, "src", "go", "run", filepath.Join(goroot, "src/cmd/api/run.go")) 758 return nil 759 }, 760 }) 761 } 762 } 763 764 // isRegisteredTestName reports whether a test named testName has already 765 // been registered. 766 func (t *tester) isRegisteredTestName(testName string) bool { 767 for _, tt := range t.tests { 768 if tt.name == testName { 769 return true 770 } 771 } 772 return false 773 } 774 775 func (t *tester) registerTest1(seq bool, name, dirBanner string, cmdline ...interface{}) { 776 bin, args := flattenCmdline(cmdline) 777 if bin == "time" && !t.haveTime { 778 bin, args = args[0], args[1:] 779 } 780 if t.isRegisteredTestName(name) { 781 panic("duplicate registered test name " + name) 782 } 783 t.tests = append(t.tests, distTest{ 784 name: name, 785 heading: dirBanner, 786 fn: func(dt *distTest) error { 787 if seq { 788 t.runPending(dt) 789 timelog("start", name) 790 defer timelog("end", name) 791 return t.dirCmd(filepath.Join(goroot, "src", dirBanner), bin, args).Run() 792 } 793 t.addCmd(dt, filepath.Join(goroot, "src", dirBanner), bin, args) 794 return nil 795 }, 796 }) 797 } 798 799 func (t *tester) registerTest(name, dirBanner string, cmdline ...interface{}) { 800 t.registerTest1(false, name, dirBanner, cmdline...) 801 } 802 803 func (t *tester) registerSeqTest(name, dirBanner string, cmdline ...interface{}) { 804 t.registerTest1(true, name, dirBanner, cmdline...) 805 } 806 807 func (t *tester) bgDirCmd(dir, bin string, args ...string) *exec.Cmd { 808 cmd := exec.Command(bin, args...) 809 if filepath.IsAbs(dir) { 810 cmd.Dir = dir 811 } else { 812 cmd.Dir = filepath.Join(goroot, dir) 813 } 814 return cmd 815 } 816 817 func (t *tester) dirCmd(dir string, cmdline ...interface{}) *exec.Cmd { 818 bin, args := flattenCmdline(cmdline) 819 cmd := t.bgDirCmd(dir, bin, args...) 820 cmd.Stdout = os.Stdout 821 cmd.Stderr = os.Stderr 822 if vflag > 1 { 823 errprintf("%s\n", strings.Join(cmd.Args, " ")) 824 } 825 return cmd 826 } 827 828 // flattenCmdline flattens a mixture of string and []string as single list 829 // and then interprets it as a command line: first element is binary, then args. 830 func flattenCmdline(cmdline []interface{}) (bin string, args []string) { 831 var list []string 832 for _, x := range cmdline { 833 switch x := x.(type) { 834 case string: 835 list = append(list, x) 836 case []string: 837 list = append(list, x...) 838 default: 839 panic("invalid addCmd argument type: " + reflect.TypeOf(x).String()) 840 } 841 } 842 843 // The go command is too picky about duplicated flags. 844 // Drop all but the last of the allowed duplicated flags. 845 drop := make([]bool, len(list)) 846 have := map[string]int{} 847 for i := 1; i < len(list); i++ { 848 j := strings.Index(list[i], "=") 849 if j < 0 { 850 continue 851 } 852 flag := list[i][:j] 853 switch flag { 854 case "-run", "-tags": 855 if have[flag] != 0 { 856 drop[have[flag]] = true 857 } 858 have[flag] = i 859 } 860 } 861 out := list[:0] 862 for i, x := range list { 863 if !drop[i] { 864 out = append(out, x) 865 } 866 } 867 list = out 868 869 return list[0], list[1:] 870 } 871 872 func (t *tester) addCmd(dt *distTest, dir string, cmdline ...interface{}) *exec.Cmd { 873 bin, args := flattenCmdline(cmdline) 874 w := &work{ 875 dt: dt, 876 cmd: t.bgDirCmd(dir, bin, args...), 877 } 878 t.worklist = append(t.worklist, w) 879 return w.cmd 880 } 881 882 func (t *tester) iOS() bool { 883 return goos == "darwin" && (goarch == "arm" || goarch == "arm64") 884 } 885 886 func (t *tester) out(v string) { 887 if t.banner == "" { 888 return 889 } 890 fmt.Println("\n" + t.banner + v) 891 } 892 893 func (t *tester) extLink() bool { 894 pair := gohostos + "-" + goarch 895 switch pair { 896 case "android-arm", 897 "darwin-386", "darwin-amd64", "darwin-arm", "darwin-arm64", 898 "dragonfly-amd64", 899 "freebsd-386", "freebsd-amd64", "freebsd-arm", 900 "linux-386", "linux-amd64", "linux-arm", "linux-arm64", "linux-ppc64le", "linux-mips64", "linux-mips64le", "linux-mips", "linux-mipsle", "linux-s390x", 901 "netbsd-386", "netbsd-amd64", 902 "openbsd-386", "openbsd-amd64", 903 "windows-386", "windows-amd64": 904 return true 905 } 906 return false 907 } 908 909 func (t *tester) internalLink() bool { 910 if gohostos == "dragonfly" { 911 // linkmode=internal fails on dragonfly since errno is a TLS relocation. 912 return false 913 } 914 if gohostarch == "ppc64le" { 915 // linkmode=internal fails on ppc64le because cmd/link doesn't 916 // handle the TOC correctly (issue 15409). 917 return false 918 } 919 if goos == "android" { 920 return false 921 } 922 if goos == "darwin" && (goarch == "arm" || goarch == "arm64") { 923 return false 924 } 925 // Internally linking cgo is incomplete on some architectures. 926 // https://golang.org/issue/10373 927 // https://golang.org/issue/14449 928 if goarch == "arm64" || goarch == "mips64" || goarch == "mips64le" || goarch == "mips" || goarch == "mipsle" { 929 return false 930 } 931 if isAlpineLinux() { 932 // Issue 18243. 933 return false 934 } 935 return true 936 } 937 938 func (t *tester) supportedBuildmode(mode string) bool { 939 pair := goos + "-" + goarch 940 switch mode { 941 case "c-archive": 942 if !t.extLink() { 943 return false 944 } 945 switch pair { 946 case "darwin-386", "darwin-amd64", "darwin-arm", "darwin-arm64", 947 "linux-amd64", "linux-386", "linux-ppc64le", "linux-s390x", 948 "freebsd-amd64", 949 "windows-amd64", "windows-386": 950 return true 951 } 952 return false 953 case "c-shared": 954 switch pair { 955 case "linux-386", "linux-amd64", "linux-arm", "linux-arm64", "linux-ppc64le", "linux-s390x", 956 "darwin-amd64", "darwin-386", 957 "freebsd-amd64", 958 "android-arm", "android-arm64", "android-386", 959 "windows-amd64", "windows-386": 960 return true 961 } 962 return false 963 case "shared": 964 switch pair { 965 case "linux-386", "linux-amd64", "linux-arm", "linux-arm64", "linux-ppc64le", "linux-s390x": 966 return true 967 } 968 return false 969 case "plugin": 970 // linux-arm64 is missing because it causes the external linker 971 // to crash, see https://golang.org/issue/17138 972 switch pair { 973 case "linux-386", "linux-amd64", "linux-arm", "linux-s390x", "linux-ppc64le": 974 return true 975 case "darwin-amd64": 976 return true 977 } 978 return false 979 case "pie": 980 switch pair { 981 case "linux-386", "linux-amd64", "linux-arm", "linux-arm64", "linux-ppc64le", "linux-s390x", 982 "android-amd64", "android-arm", "android-arm64", "android-386": 983 return true 984 case "darwin-amd64": 985 return true 986 } 987 return false 988 989 default: 990 log.Fatalf("internal error: unknown buildmode %s", mode) 991 return false 992 } 993 } 994 995 func (t *tester) registerHostTest(name, heading, dir, pkg string) { 996 t.tests = append(t.tests, distTest{ 997 name: name, 998 heading: heading, 999 fn: func(dt *distTest) error { 1000 t.runPending(dt) 1001 timelog("start", name) 1002 defer timelog("end", name) 1003 return t.runHostTest(dir, pkg) 1004 }, 1005 }) 1006 } 1007 1008 func (t *tester) runHostTest(dir, pkg string) error { 1009 defer os.Remove(filepath.Join(goroot, dir, "test.test")) 1010 cmd := t.dirCmd(dir, t.goTest(), "-c", "-o", "test.test", pkg) 1011 cmd.Env = append(os.Environ(), "GOARCH="+gohostarch, "GOOS="+gohostos) 1012 if err := cmd.Run(); err != nil { 1013 return err 1014 } 1015 return t.dirCmd(dir, "./test.test").Run() 1016 } 1017 1018 func (t *tester) cgoTest(dt *distTest) error { 1019 t.addCmd(dt, "misc/cgo/test", t.goTest(), "-ldflags", "-linkmode=auto") 1020 1021 if t.internalLink() { 1022 t.addCmd(dt, "misc/cgo/test", t.goTest(), "-tags=internal", "-ldflags", "-linkmode=internal") 1023 } 1024 1025 pair := gohostos + "-" + goarch 1026 switch pair { 1027 case "darwin-386", "darwin-amd64", 1028 "openbsd-386", "openbsd-amd64", 1029 "windows-386", "windows-amd64": 1030 // test linkmode=external, but __thread not supported, so skip testtls. 1031 if !t.extLink() { 1032 break 1033 } 1034 t.addCmd(dt, "misc/cgo/test", t.goTest(), "-ldflags", "-linkmode=external") 1035 t.addCmd(dt, "misc/cgo/test", t.goTest(), "-ldflags", "-linkmode=external -s") 1036 case "android-arm", 1037 "dragonfly-amd64", 1038 "freebsd-386", "freebsd-amd64", "freebsd-arm", 1039 "linux-386", "linux-amd64", "linux-arm", "linux-ppc64le", "linux-s390x", 1040 "netbsd-386", "netbsd-amd64": 1041 1042 cmd := t.addCmd(dt, "misc/cgo/test", t.goTest(), "-ldflags", "-linkmode=external") 1043 // A -g argument in CGO_CFLAGS should not affect how the test runs. 1044 cmd.Env = append(os.Environ(), "CGO_CFLAGS=-g0") 1045 1046 t.addCmd(dt, "misc/cgo/testtls", t.goTest(), "-ldflags", "-linkmode=auto") 1047 t.addCmd(dt, "misc/cgo/testtls", t.goTest(), "-ldflags", "-linkmode=external") 1048 1049 switch pair { 1050 case "netbsd-386", "netbsd-amd64": 1051 // no static linking 1052 case "freebsd-arm": 1053 // -fPIC compiled tls code will use __tls_get_addr instead 1054 // of __aeabi_read_tp, however, on FreeBSD/ARM, __tls_get_addr 1055 // is implemented in rtld-elf, so -fPIC isn't compatible with 1056 // static linking on FreeBSD/ARM with clang. (cgo depends on 1057 // -fPIC fundamentally.) 1058 default: 1059 cmd := t.dirCmd("misc/cgo/test", 1060 compilerEnvLookup(defaultcc, goos, goarch), "-xc", "-o", "/dev/null", "-static", "-") 1061 cmd.Stdin = strings.NewReader("int main() {}") 1062 if err := cmd.Run(); err != nil { 1063 fmt.Println("No support for static linking found (lacks libc.a?), skip cgo static linking test.") 1064 } else { 1065 if goos != "android" { 1066 t.addCmd(dt, "misc/cgo/testtls", t.goTest(), "-ldflags", `-linkmode=external -extldflags "-static -pthread"`) 1067 } 1068 t.addCmd(dt, "misc/cgo/nocgo", t.goTest()) 1069 t.addCmd(dt, "misc/cgo/nocgo", t.goTest(), "-ldflags", `-linkmode=external`) 1070 if goos != "android" { 1071 t.addCmd(dt, "misc/cgo/nocgo", t.goTest(), "-ldflags", `-linkmode=external -extldflags "-static -pthread"`) 1072 t.addCmd(dt, "misc/cgo/test", t.goTest(), "-tags=static", "-ldflags", `-linkmode=external -extldflags "-static -pthread"`) 1073 // -static in CGO_LDFLAGS triggers a different code path 1074 // than -static in -extldflags, so test both. 1075 // See issue #16651. 1076 cmd := t.addCmd(dt, "misc/cgo/test", t.goTest(), "-tags=static") 1077 cmd.Env = append(os.Environ(), "CGO_LDFLAGS=-static -pthread") 1078 } 1079 } 1080 1081 if t.supportedBuildmode("pie") { 1082 t.addCmd(dt, "misc/cgo/test", t.goTest(), "-buildmode=pie") 1083 t.addCmd(dt, "misc/cgo/testtls", t.goTest(), "-buildmode=pie") 1084 t.addCmd(dt, "misc/cgo/nocgo", t.goTest(), "-buildmode=pie") 1085 } 1086 } 1087 } 1088 1089 return nil 1090 } 1091 1092 // run pending test commands, in parallel, emitting headers as appropriate. 1093 // When finished, emit header for nextTest, which is going to run after the 1094 // pending commands are done (and runPending returns). 1095 // A test should call runPending if it wants to make sure that it is not 1096 // running in parallel with earlier tests, or if it has some other reason 1097 // for needing the earlier tests to be done. 1098 func (t *tester) runPending(nextTest *distTest) { 1099 checkNotStale("go", "std") 1100 worklist := t.worklist 1101 t.worklist = nil 1102 for _, w := range worklist { 1103 w.start = make(chan bool) 1104 w.end = make(chan bool) 1105 go func(w *work) { 1106 if !<-w.start { 1107 timelog("skip", w.dt.name) 1108 w.out = []byte(fmt.Sprintf("skipped due to earlier error\n")) 1109 } else { 1110 timelog("start", w.dt.name) 1111 w.out, w.err = w.cmd.CombinedOutput() 1112 } 1113 timelog("end", w.dt.name) 1114 w.end <- true 1115 }(w) 1116 } 1117 1118 started := 0 1119 ended := 0 1120 var last *distTest 1121 for ended < len(worklist) { 1122 for started < len(worklist) && started-ended < maxbg { 1123 //println("start", started) 1124 w := worklist[started] 1125 started++ 1126 w.start <- !t.failed || t.keepGoing 1127 } 1128 w := worklist[ended] 1129 dt := w.dt 1130 if dt.heading != "" && t.lastHeading != dt.heading { 1131 t.lastHeading = dt.heading 1132 t.out(dt.heading) 1133 } 1134 if dt != last { 1135 // Assumes all the entries for a single dt are in one worklist. 1136 last = w.dt 1137 if vflag > 0 { 1138 fmt.Printf("# go tool dist test -run=^%s$\n", dt.name) 1139 } 1140 } 1141 if vflag > 1 { 1142 errprintf("%s\n", strings.Join(w.cmd.Args, " ")) 1143 } 1144 //println("wait", ended) 1145 ended++ 1146 <-w.end 1147 os.Stdout.Write(w.out) 1148 if w.err != nil { 1149 log.Printf("Failed: %v", w.err) 1150 t.failed = true 1151 } 1152 checkNotStale("go", "std") 1153 } 1154 if t.failed && !t.keepGoing { 1155 log.Fatal("FAILED") 1156 } 1157 1158 if dt := nextTest; dt != nil { 1159 if dt.heading != "" && t.lastHeading != dt.heading { 1160 t.lastHeading = dt.heading 1161 t.out(dt.heading) 1162 } 1163 if vflag > 0 { 1164 fmt.Printf("# go tool dist test -run=^%s$\n", dt.name) 1165 } 1166 } 1167 } 1168 1169 func (t *tester) cgoTestSOSupported() bool { 1170 if goos == "android" || t.iOS() { 1171 // No exec facility on Android or iOS. 1172 return false 1173 } 1174 if goarch == "ppc64" { 1175 // External linking not implemented on ppc64 (issue #8912). 1176 return false 1177 } 1178 if goarch == "mips64le" || goarch == "mips64" { 1179 // External linking not implemented on mips64. 1180 return false 1181 } 1182 return true 1183 } 1184 1185 func (t *tester) cgoTestSO(dt *distTest, testpath string) error { 1186 t.runPending(dt) 1187 1188 timelog("start", dt.name) 1189 defer timelog("end", dt.name) 1190 1191 dir := filepath.Join(goroot, testpath) 1192 1193 // build shared object 1194 output, err := exec.Command("go", "env", "CC").Output() 1195 if err != nil { 1196 return fmt.Errorf("Error running go env CC: %v", err) 1197 } 1198 cc := strings.TrimSuffix(string(output), "\n") 1199 if cc == "" { 1200 return errors.New("CC environment variable (go env CC) cannot be empty") 1201 } 1202 output, err = exec.Command("go", "env", "GOGCCFLAGS").Output() 1203 if err != nil { 1204 return fmt.Errorf("Error running go env GOGCCFLAGS: %v", err) 1205 } 1206 gogccflags := strings.Split(strings.TrimSuffix(string(output), "\n"), " ") 1207 1208 ext := "so" 1209 args := append(gogccflags, "-shared") 1210 switch goos { 1211 case "darwin": 1212 ext = "dylib" 1213 args = append(args, "-undefined", "suppress", "-flat_namespace") 1214 case "windows": 1215 ext = "dll" 1216 args = append(args, "-DEXPORT_DLL") 1217 } 1218 sofname := "libcgosotest." + ext 1219 args = append(args, "-o", sofname, "cgoso_c.c") 1220 1221 if err := t.dirCmd(dir, cc, args).Run(); err != nil { 1222 return err 1223 } 1224 defer os.Remove(filepath.Join(dir, sofname)) 1225 1226 if err := t.dirCmd(dir, "go", "build", "-o", "main.exe", "main.go").Run(); err != nil { 1227 return err 1228 } 1229 defer os.Remove(filepath.Join(dir, "main.exe")) 1230 1231 cmd := t.dirCmd(dir, "./main.exe") 1232 if goos != "windows" { 1233 s := "LD_LIBRARY_PATH" 1234 if goos == "darwin" { 1235 s = "DYLD_LIBRARY_PATH" 1236 } 1237 cmd.Env = append(os.Environ(), s+"=.") 1238 1239 // On FreeBSD 64-bit architectures, the 32-bit linker looks for 1240 // different environment variables. 1241 if goos == "freebsd" && gohostarch == "386" { 1242 cmd.Env = append(cmd.Env, "LD_32_LIBRARY_PATH=.") 1243 } 1244 } 1245 return cmd.Run() 1246 } 1247 1248 func (t *tester) hasBash() bool { 1249 switch gohostos { 1250 case "windows", "plan9": 1251 return false 1252 } 1253 return true 1254 } 1255 1256 func (t *tester) hasCxx() bool { 1257 cxx, _ := exec.LookPath(compilerEnvLookup(defaultcxx, goos, goarch)) 1258 return cxx != "" 1259 } 1260 1261 func (t *tester) hasSwig() bool { 1262 swig, err := exec.LookPath("swig") 1263 if err != nil { 1264 return false 1265 } 1266 1267 // Check that swig was installed with Go support by checking 1268 // that a go directory exists inside the swiglib directory. 1269 // See https://golang.org/issue/23469. 1270 output, err := exec.Command(swig, "-go", "-swiglib").Output() 1271 if err != nil { 1272 return false 1273 } 1274 swigDir := strings.TrimSpace(string(output)) 1275 1276 _, err = os.Stat(filepath.Join(swigDir, "go")) 1277 if err != nil { 1278 return false 1279 } 1280 1281 // Check that swig has a new enough version. 1282 // See https://golang.org/issue/22858. 1283 out, err := exec.Command(swig, "-version").CombinedOutput() 1284 if err != nil { 1285 return false 1286 } 1287 1288 re := regexp.MustCompile(`[vV]ersion +([\d]+)([.][\d]+)?([.][\d]+)?`) 1289 matches := re.FindSubmatch(out) 1290 if matches == nil { 1291 // Can't find version number; hope for the best. 1292 return true 1293 } 1294 1295 major, err := strconv.Atoi(string(matches[1])) 1296 if err != nil { 1297 // Can't find version number; hope for the best. 1298 return true 1299 } 1300 if major < 3 { 1301 return false 1302 } 1303 if major > 3 { 1304 // 4.0 or later 1305 return true 1306 } 1307 1308 // We have SWIG version 3.x. 1309 if len(matches[2]) > 0 { 1310 minor, err := strconv.Atoi(string(matches[2][1:])) 1311 if err != nil { 1312 return true 1313 } 1314 if minor > 0 { 1315 // 3.1 or later 1316 return true 1317 } 1318 } 1319 1320 // We have SWIG version 3.0.x. 1321 if len(matches[3]) > 0 { 1322 patch, err := strconv.Atoi(string(matches[3][1:])) 1323 if err != nil { 1324 return true 1325 } 1326 if patch < 6 { 1327 // Before 3.0.6. 1328 return false 1329 } 1330 } 1331 1332 return true 1333 } 1334 1335 func (t *tester) raceDetectorSupported() bool { 1336 if gohostos != goos { 1337 return false 1338 } 1339 if !t.cgoEnabled { 1340 return false 1341 } 1342 if !raceDetectorSupported(goos, goarch) { 1343 return false 1344 } 1345 // The race detector doesn't work on Alpine Linux: 1346 // golang.org/issue/14481 1347 if isAlpineLinux() { 1348 return false 1349 } 1350 // NetBSD support is unfinished. 1351 // golang.org/issue/26403 1352 if goos == "netbsd" { 1353 return false 1354 } 1355 return true 1356 } 1357 1358 func isAlpineLinux() bool { 1359 if runtime.GOOS != "linux" { 1360 return false 1361 } 1362 fi, err := os.Lstat("/etc/alpine-release") 1363 return err == nil && fi.Mode().IsRegular() 1364 } 1365 1366 func (t *tester) runFlag(rx string) string { 1367 if t.compileOnly { 1368 return "-run=^$" 1369 } 1370 if rx == "" && goos == "js" && goarch == "wasm" { 1371 return "-run=^Test" // exclude examples; Issue 25913 1372 } 1373 return "-run=" + rx 1374 } 1375 1376 func (t *tester) raceTest(dt *distTest) error { 1377 t.addCmd(dt, "src", t.goTest(), "-race", "-i", "runtime/race", "flag", "os", "os/exec") 1378 t.addCmd(dt, "src", t.goTest(), "-race", t.runFlag("Output"), "runtime/race") 1379 t.addCmd(dt, "src", t.goTest(), "-race", t.runFlag("TestParse|TestEcho|TestStdinCloseRace|TestClosedPipeRace|TestTypeRace|TestFdRace|TestFdReadRace|TestFileCloseRace"), "flag", "net", "os", "os/exec", "encoding/gob") 1380 // We don't want the following line, because it 1381 // slows down all.bash (by 10 seconds on my laptop). 1382 // The race builder should catch any error here, but doesn't. 1383 // TODO(iant): Figure out how to catch this. 1384 // t.addCmd(dt, "src", t.goTest(), "-race", "-run=TestParallelTest", "cmd/go") 1385 if t.cgoEnabled { 1386 cmd := t.addCmd(dt, "misc/cgo/test", t.goTest(), "-race") 1387 cmd.Env = append(os.Environ(), "GOTRACEBACK=2") 1388 } 1389 if t.extLink() { 1390 // Test with external linking; see issue 9133. 1391 t.addCmd(dt, "src", t.goTest(), "-race", "-ldflags=-linkmode=external", t.runFlag("TestParse|TestEcho|TestStdinCloseRace"), "flag", "os/exec") 1392 } 1393 return nil 1394 } 1395 1396 var runtest struct { 1397 sync.Once 1398 exe string 1399 err error 1400 } 1401 1402 func (t *tester) testDirTest(dt *distTest, shard, shards int) error { 1403 runtest.Do(func() { 1404 const exe = "runtest.exe" // named exe for Windows, but harmless elsewhere 1405 cmd := t.dirCmd("test", "go", "build", "-o", exe, "run.go") 1406 cmd.Env = append(os.Environ(), "GOOS="+gohostos, "GOARCH="+gohostarch) 1407 runtest.exe = filepath.Join(cmd.Dir, exe) 1408 if err := cmd.Run(); err != nil { 1409 runtest.err = err 1410 return 1411 } 1412 xatexit(func() { 1413 os.Remove(runtest.exe) 1414 }) 1415 }) 1416 if runtest.err != nil { 1417 return runtest.err 1418 } 1419 if t.compileOnly { 1420 return nil 1421 } 1422 t.addCmd(dt, "test", runtest.exe, 1423 fmt.Sprintf("--shard=%d", shard), 1424 fmt.Sprintf("--shards=%d", shards), 1425 ) 1426 return nil 1427 } 1428 1429 // cgoPackages is the standard packages that use cgo. 1430 var cgoPackages = []string{ 1431 "crypto/x509", 1432 "net", 1433 "os/user", 1434 } 1435 1436 var funcBenchmark = []byte("\nfunc Benchmark") 1437 1438 // packageHasBenchmarks reports whether pkg has benchmarks. 1439 // On any error, it conservatively returns true. 1440 // 1441 // This exists just to eliminate work on the builders, since compiling 1442 // a test in race mode just to discover it has no benchmarks costs a 1443 // second or two per package, and this function returns false for 1444 // about 100 packages. 1445 func (t *tester) packageHasBenchmarks(pkg string) bool { 1446 pkgDir := filepath.Join(goroot, "src", pkg) 1447 d, err := os.Open(pkgDir) 1448 if err != nil { 1449 return true // conservatively 1450 } 1451 defer d.Close() 1452 names, err := d.Readdirnames(-1) 1453 if err != nil { 1454 return true // conservatively 1455 } 1456 for _, name := range names { 1457 if !strings.HasSuffix(name, "_test.go") { 1458 continue 1459 } 1460 slurp, err := ioutil.ReadFile(filepath.Join(pkgDir, name)) 1461 if err != nil { 1462 return true // conservatively 1463 } 1464 if bytes.Contains(slurp, funcBenchmark) { 1465 return true 1466 } 1467 } 1468 return false 1469 } 1470 1471 // raceDetectorSupported is a copy of the function 1472 // cmd/internal/sys.RaceDetectorSupported, which can't be used here 1473 // because cmd/dist has to be buildable by Go 1.4. 1474 func raceDetectorSupported(goos, goarch string) bool { 1475 switch goos { 1476 case "linux": 1477 return goarch == "amd64" || goarch == "ppc64le" || goarch == "arm64" 1478 case "darwin", "freebsd", "netbsd", "windows": 1479 return goarch == "amd64" 1480 default: 1481 return false 1482 } 1483 } 1484 1485 // mSanSupported is a copy of the function cmd/internal/sys.MSanSupported, 1486 // which can't be used here because cmd/dist has to be buildable by Go 1.4. 1487 func mSanSupported(goos, goarch string) bool { 1488 switch goos { 1489 case "linux": 1490 return goarch == "amd64" || goarch == "arm64" 1491 default: 1492 return false 1493 } 1494 }