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