2016-03-01 22:57:46 +00:00
// Copyright 2015 The Go Authors. All rights reserved.
2015-03-02 17:07:11 -08:00
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package main
import (
"bytes"
"flag"
"fmt"
"log"
"os"
"os/exec"
2019-05-21 19:02:00 +00:00
"path"
2015-03-02 17:07:11 -08:00
"path/filepath"
2017-11-29 14:16:25 -05:00
"reflect"
2015-03-02 17:07:11 -08:00
"regexp"
2017-04-25 06:11:09 +00:00
"runtime"
2015-03-02 17:07:11 -08:00
"strconv"
"strings"
2015-12-21 20:42:40 -05:00
"sync"
2015-03-02 17:07:11 -08:00
"time"
)
func cmdtest ( ) {
cmd/go: switch to entirely content-based staleness determination
This CL changes the go command to base all its rebuilding decisions
on the content of the files being processed and not their file system
modification times. It also eliminates the special handling of release
toolchains, which were previously considered always up-to-date
because modification time order could not be trusted when unpacking
a pre-built release.
The go command previously tracked "build IDs" as a backup to
modification times, to catch changes not reflected in modification times.
For example, if you remove one .go file in a package with multiple .go
files, there is no modification time remaining in the system that indicates
that the installed package is out of date. The old build ID was the hash
of a list of file names and a few other factors, expected to change if
those factors changed.
This CL moves to using this kind of build ID as the only way to
detect staleness, making sure that the build ID hash includes all
possible factors that need to influence the rebuild decision.
One such factor is the compiler flags. As of this CL, if you run
go build -gcflags -N cmd/gofmt
you will get a gofmt where every package is built with -N,
regardless of what may or may not be installed already.
Another such factor is the linker flags. As of this CL, if you run
go install myprog
go install -ldflags=-s myprog
the second go install will now correctly build a new myprog with
the updated linker flags. (Previously the installed myprog appeared
up-to-date, because the ldflags were not included in the build ID.)
Because we have more precise information we can also validate whether
the target of a "go test -c" operation is already the right binary and
therefore can avoid a rebuild.
This CL sets us up for having a more general build artifact cache,
maybe even a step toward not having a pkg directory with .a files,
but this CL does not take that step. For now the result of go install
is the same as it ever was; we just do a better job of what needs to
be installed.
This CL does slow down builds a small amount by reading all the
dependent source files in full. (The go command already read the
beginning of every dependent source file to discover build tags
and imports.) On my MacBook Pro, before this CL all.bash takes
3m58s, while after this CL and a few optimizations stacked above it
all.bash takes 4m28s. Given that CL 73850 cut 1m43s off the all.bash
time earlier today, we can afford adding 30s back for now.
More optimizations are planned that should make the go command
more efficient than it was even before this CL.
Fixes #15799.
Fixes #18369.
Fixes #19340.
Fixes #21477.
Change-Id: I10d7ca0e31ca3f58aabb9b1f11e2e3d9d18f0bc9
Reviewed-on: https://go-review.googlesource.com/73212
Run-TryBot: Russ Cox <rsc@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: David Crawshaw <crawshaw@golang.org>
2017-10-11 20:39:28 -04:00
gogcflags = os . Getenv ( "GO_GCFLAGS" )
2022-08-16 18:51:57 +07:00
setNoOpt ( )
cmd/go: switch to entirely content-based staleness determination
This CL changes the go command to base all its rebuilding decisions
on the content of the files being processed and not their file system
modification times. It also eliminates the special handling of release
toolchains, which were previously considered always up-to-date
because modification time order could not be trusted when unpacking
a pre-built release.
The go command previously tracked "build IDs" as a backup to
modification times, to catch changes not reflected in modification times.
For example, if you remove one .go file in a package with multiple .go
files, there is no modification time remaining in the system that indicates
that the installed package is out of date. The old build ID was the hash
of a list of file names and a few other factors, expected to change if
those factors changed.
This CL moves to using this kind of build ID as the only way to
detect staleness, making sure that the build ID hash includes all
possible factors that need to influence the rebuild decision.
One such factor is the compiler flags. As of this CL, if you run
go build -gcflags -N cmd/gofmt
you will get a gofmt where every package is built with -N,
regardless of what may or may not be installed already.
Another such factor is the linker flags. As of this CL, if you run
go install myprog
go install -ldflags=-s myprog
the second go install will now correctly build a new myprog with
the updated linker flags. (Previously the installed myprog appeared
up-to-date, because the ldflags were not included in the build ID.)
Because we have more precise information we can also validate whether
the target of a "go test -c" operation is already the right binary and
therefore can avoid a rebuild.
This CL sets us up for having a more general build artifact cache,
maybe even a step toward not having a pkg directory with .a files,
but this CL does not take that step. For now the result of go install
is the same as it ever was; we just do a better job of what needs to
be installed.
This CL does slow down builds a small amount by reading all the
dependent source files in full. (The go command already read the
beginning of every dependent source file to discover build tags
and imports.) On my MacBook Pro, before this CL all.bash takes
3m58s, while after this CL and a few optimizations stacked above it
all.bash takes 4m28s. Given that CL 73850 cut 1m43s off the all.bash
time earlier today, we can afford adding 30s back for now.
More optimizations are planned that should make the go command
more efficient than it was even before this CL.
Fixes #15799.
Fixes #18369.
Fixes #19340.
Fixes #21477.
Change-Id: I10d7ca0e31ca3f58aabb9b1f11e2e3d9d18f0bc9
Reviewed-on: https://go-review.googlesource.com/73212
Run-TryBot: Russ Cox <rsc@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: David Crawshaw <crawshaw@golang.org>
2017-10-11 20:39:28 -04:00
2015-03-02 17:07:11 -08:00
var t tester
2022-04-29 20:05:26 -04:00
2015-12-20 14:29:20 -05:00
var noRebuild bool
2015-03-02 17:07:11 -08:00
flag . BoolVar ( & t . listMode , "list" , false , "list available tests" )
2015-12-20 14:29:20 -05:00
flag . BoolVar ( & t . rebuild , "rebuild" , false , "rebuild everything first" )
flag . BoolVar ( & noRebuild , "no-rebuild" , false , "overrides -rebuild (historical dreg)" )
2015-05-01 22:23:04 -04:00
flag . BoolVar ( & t . keepGoing , "k" , false , "keep going even when error occurred" )
2015-06-08 17:56:27 -07:00
flag . BoolVar ( & t . race , "race" , false , "run in race builder mode (different set of tests)" )
2016-05-04 09:08:27 -07:00
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." )
2015-03-02 17:07:11 -08:00
flag . StringVar ( & t . banner , "banner" , "##### " , "banner prefix; blank means no section banners" )
2015-05-14 13:03:02 -07:00
flag . StringVar ( & t . runRxStr , "run" , os . Getenv ( "GOTESTONLY" ) ,
"run only those tests matching the regular expression; empty means to run all. " +
"Special exception: if the string begins with '!', the match is inverted." )
2021-12-30 16:46:21 +08:00
flag . BoolVar ( & t . msan , "msan" , false , "run in memory sanitizer builder mode" )
flag . BoolVar ( & t . asan , "asan" , false , "run in address sanitizer builder mode" )
2015-06-03 23:21:30 -07:00
xflagparse ( - 1 ) // any number of args
2015-12-20 14:29:20 -05:00
if noRebuild {
t . rebuild = false
}
cmd/dist,cmd/go: set GOTRACEBACK to "system" for testing
If we're testing through dist, we're testing the implementation of Go,
so we're interested in any package failing with potential runtime
issues. In these cases, we'd like to have as much relevant detail as
possible, but currently runtime stack frames and goroutines are
suppressed due to the default GOTRACEBACK setting.
So, try to set GOTRACEBACK to system if it's unset. Check if it's unset
first so we don't override the user asking for a lower or higher level.
This change was brought up in the context of #45916, since there's an
apparent deadlock (or something!) in the runtime that appears when
running other code, but it's difficult to see exactly where it's
blocked. However, this change is very generally useful.
This change also runs scripted tests with GOTRACEBACK=system, upgrading
from GOTRACEBACK=all. Often, script tests can trigger failures deep in
the runtime in interesting ways because they start many individual Go
processes, so being able to identify points of interest in the runtime
is quite useful.
For #45916.
Change-Id: I3d50658d0d0090fb4c9182b87200d266c7f8f915
Reviewed-on: https://go-review.googlesource.com/c/go/+/316469
Trust: Michael Knyszek <mknyszek@google.com>
Trust: Bryan C. Mills <bcmills@google.com>
Run-TryBot: Michael Knyszek <mknyszek@google.com>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Dmitri Shuralyov <dmitshur@golang.org>
2021-05-03 18:11:55 +00:00
2015-03-02 17:07:11 -08:00
t . run ( )
}
// tester executes cmdtest.
type tester struct {
2015-12-21 16:08:57 -05:00
race bool
2021-12-30 16:46:21 +08:00
msan bool
asan bool
2015-12-21 16:08:57 -05:00
listMode bool
rebuild bool
failed bool
keepGoing bool
2016-05-04 09:08:27 -07:00
compileOnly bool // just try to compile all tests, but no need to run
2015-12-21 16:08:57 -05:00
runRxStr string
runRx * regexp . Regexp
runRxWant bool // want runRx to match (true) or not match (false)
runNames [ ] string // tests to run, exclusive with runRx; empty means all
banner string // prefix, or "" for none
lastHeading string // last dir heading printed
2015-03-02 17:07:11 -08:00
cgoEnabled bool
partial bool
haveTime bool // the 'time' binary is available
tests [ ] distTest
timeoutScale int
2015-12-21 16:08:57 -05:00
worklist [ ] * work
}
type work struct {
dt * distTest
cmd * exec . Cmd
start chan bool
out [ ] byte
err error
end chan bool
2015-03-02 17:07:11 -08:00
}
// A distTest is a test run by dist test.
// Each test has a unique name and belongs to a group (heading)
type distTest struct {
name string // unique test name; may be filtered with -run flag
heading string // group section; this header is printed before the test is run.
2015-12-21 16:08:57 -05:00
fn func ( * distTest ) error
2015-03-02 17:07:11 -08:00
}
func ( t * tester ) run ( ) {
2017-10-27 13:07:38 -04:00
timelog ( "start" , "dist test" )
2022-04-29 20:05:26 -04:00
os . Setenv ( "PATH" , fmt . Sprintf ( "%s%c%s" , gorootBin , os . PathListSeparator , os . Getenv ( "PATH" ) ) )
2017-09-19 18:18:09 +09:00
2022-04-29 20:05:26 -04:00
cmd := exec . Command ( gorootBinGo , "env" , "CGO_ENABLED" )
2020-03-06 14:32:26 -05:00
cmd . Stderr = new ( bytes . Buffer )
slurp , err := cmd . Output ( )
2015-03-02 17:07:11 -08:00
if err != nil {
2020-03-06 14:32:26 -05:00
fatalf ( "Error running go env CGO_ENABLED: %v\n%s" , err , cmd . Stderr )
2015-03-02 17:07:11 -08:00
}
t . cgoEnabled , _ = strconv . ParseBool ( strings . TrimSpace ( string ( slurp ) ) )
2015-06-03 23:21:30 -07:00
if flag . NArg ( ) > 0 && t . runRxStr != "" {
2019-11-15 12:26:09 -05:00
fatalf ( "the -run regular expression flag is mutually exclusive with test name arguments" )
2015-06-03 23:21:30 -07:00
}
2017-09-19 22:13:22 +09:00
2015-06-03 23:21:30 -07:00
t . runNames = flag . Args ( )
2015-03-02 17:07:11 -08:00
if t . hasBash ( ) {
if _ , err := exec . LookPath ( "time" ) ; err == nil {
t . haveTime = true
}
}
cmd/dist,cmd/go: set GOTRACEBACK to "system" for testing
If we're testing through dist, we're testing the implementation of Go,
so we're interested in any package failing with potential runtime
issues. In these cases, we'd like to have as much relevant detail as
possible, but currently runtime stack frames and goroutines are
suppressed due to the default GOTRACEBACK setting.
So, try to set GOTRACEBACK to system if it's unset. Check if it's unset
first so we don't override the user asking for a lower or higher level.
This change was brought up in the context of #45916, since there's an
apparent deadlock (or something!) in the runtime that appears when
running other code, but it's difficult to see exactly where it's
blocked. However, this change is very generally useful.
This change also runs scripted tests with GOTRACEBACK=system, upgrading
from GOTRACEBACK=all. Often, script tests can trigger failures deep in
the runtime in interesting ways because they start many individual Go
processes, so being able to identify points of interest in the runtime
is quite useful.
For #45916.
Change-Id: I3d50658d0d0090fb4c9182b87200d266c7f8f915
Reviewed-on: https://go-review.googlesource.com/c/go/+/316469
Trust: Michael Knyszek <mknyszek@google.com>
Trust: Bryan C. Mills <bcmills@google.com>
Run-TryBot: Michael Knyszek <mknyszek@google.com>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Dmitri Shuralyov <dmitshur@golang.org>
2021-05-03 18:11:55 +00:00
// Set GOTRACEBACK to system if the user didn't set a level explicitly.
// Since we're running tests for Go, we want as much detail as possible
// if something goes wrong.
//
// Set it before running any commands just in case something goes wrong.
if ok := isEnvSet ( "GOTRACEBACK" ) ; ! ok {
if err := os . Setenv ( "GOTRACEBACK" , "system" ) ; err != nil {
if t . keepGoing {
log . Printf ( "Failed to set GOTRACEBACK: %v" , err )
} else {
fatalf ( "Failed to set GOTRACEBACK: %v" , err )
}
}
}
2015-12-20 14:29:20 -05:00
if t . rebuild {
2015-03-02 17:07:11 -08:00
t . out ( "Building packages and commands." )
cmd/go: do not install dependencies during "go install"
This CL makes "go install" behave the way many users expect:
install only the things named on the command line.
Future builds still run as fast, thanks to the new build cache (CL 75473).
To install dependencies as well (the old behavior), use "go install -i".
Actual definitions aside, what most users know and expect of "go install"
is that (1) it installs what you asked, and (2) it's fast, unlike "go build".
It was fast because it installed dependencies, but installing dependencies
confused users repeatedly (see for example #5065, #6424, #10998, #12329,
"go build" and "go test" so that they could be "fast" too, but that only
created new opportunities for confusion. We also had to add -installsuffix
and then -pkgdir, to allow "fast" even when dependencies could not be
installed in the usual place.
The recent introduction of precise content-based staleness logic means that
the go command detects the need for rebuilding packages more often than it
used to, with the consequence that "go install" rebuilds and reinstalls
dependencies more than it used to. This will create more new opportunities
for confusion and will certainly lead to more issues filed like the ones
listed above.
CL 75743 introduced a build cache, separate from the install locations.
That cache makes all operations equally incremental and fast, whether or
not the operation is "install" or "build", and whether or not "-i" is used.
Installing dependencies is no longer necessary for speed, it has confused
users in the past, and the more accurate rebuilds mean that it will confuse
users even more often in the future. This CL aims to end all that confusion
by not installing dependencies by default.
By analogy with "go build -i" and "go test -i", which still install
dependencies, this CL introduces "go install -i", which installs
dependencies in addition to the things named on the command line.
Fixes #5065.
Fixes #6424.
Fixes #10998.
Fixes #12329.
Fixes #18981.
Fixes #22469.
Another step toward #4719.
Change-Id: I3d7bc145c3a680e2f26416e182fa0dcf1e2a15e5
Reviewed-on: https://go-review.googlesource.com/75850
Run-TryBot: Russ Cox <rsc@golang.org>
Reviewed-by: David Crawshaw <crawshaw@golang.org>
2017-11-03 01:24:19 -04:00
// Force rebuild the whole toolchain.
goInstall ( "go" , append ( [ ] string { "-a" , "-i" } , toolchain ... ) ... )
}
2020-03-17 21:29:54 -04:00
if ! t . listMode {
if os . Getenv ( "GO_BUILDER_NAME" ) == "" {
// Complete rebuild bootstrap, even with -no-rebuild.
// If everything is up-to-date, this is a no-op.
// If everything is not up-to-date, the first checkNotStale
// during the test process will kill the tests, so we might
// as well install the world.
// Now that for example "go install cmd/compile" does not
// also install runtime (you need "go install -i cmd/compile"
// for that), it's easy for previous workflows like
// "rebuild the compiler and then run run.bash"
// to break if we don't automatically refresh things here.
// Rebuilding is a shortened bootstrap.
// See cmdbootstrap for a description of the overall process.
goInstall ( "go" , append ( [ ] string { "-i" } , toolchain ... ) ... )
goInstall ( "go" , append ( [ ] string { "-i" } , toolchain ... ) ... )
goInstall ( "go" , "std" , "cmd" )
} else {
// The Go builder infrastructure should always begin running tests from a
// clean, non-stale state, so there is no need to rebuild the world.
// Instead, we can just check that it is not stale, which may be less
// expensive (and is also more likely to catch bugs in the builder
// implementation).
willTest := [ ] string { "std" }
if t . shouldTestCmd ( ) {
willTest = append ( willTest , "cmd" )
}
checkNotStale ( "go" , willTest ... )
}
2015-03-02 17:07:11 -08:00
}
t . timeoutScale = 1
2017-09-19 22:13:22 +09:00
switch goarch {
2016-12-02 23:30:09 +00:00
case "arm" :
2015-03-02 17:07:11 -08:00
t . timeoutScale = 2
2016-12-01 23:27:25 +00:00
case "mips" , "mipsle" , "mips64" , "mips64le" :
t . timeoutScale = 4
2015-03-02 17:07:11 -08:00
}
2015-04-23 02:16:31 -04:00
if s := os . Getenv ( "GO_TEST_TIMEOUT_SCALE" ) ; s != "" {
t . timeoutScale , err = strconv . Atoi ( s )
if err != nil {
2019-11-15 12:26:09 -05:00
fatalf ( "failed to parse $GO_TEST_TIMEOUT_SCALE = %q as integer: %v" , s , err )
2015-04-23 02:16:31 -04:00
}
}
2015-03-02 17:07:11 -08:00
if t . runRxStr != "" {
2015-05-14 13:03:02 -07:00
if t . runRxStr [ 0 ] == '!' {
t . runRxWant = false
t . runRxStr = t . runRxStr [ 1 : ]
} else {
t . runRxWant = true
}
2015-03-02 17:07:11 -08:00
t . runRx = regexp . MustCompile ( t . runRxStr )
}
t . registerTests ( )
if t . listMode {
for _ , tt := range t . tests {
fmt . Println ( tt . name )
}
return
}
2015-06-03 23:21:30 -07:00
for _ , name := range t . runNames {
if ! t . isRegisteredTestName ( name ) {
2019-11-15 12:26:09 -05:00
fatalf ( "unknown test %q" , name )
2015-06-03 23:21:30 -07:00
}
}
2019-02-22 20:16:24 +00:00
// On a few builders, make GOROOT unwritable to catch tests writing to it.
if strings . HasPrefix ( os . Getenv ( "GO_BUILDER_NAME" ) , "linux-" ) {
2019-11-12 10:18:06 -05:00
if os . Getuid ( ) == 0 {
2019-11-13 09:06:25 -05:00
// Don't bother making GOROOT unwritable:
// we're running as root, so permissions would have no effect.
2019-11-12 10:18:06 -05:00
} else {
2019-11-15 12:26:09 -05:00
xatexit ( t . makeGOROOTUnwritable ( ) )
2019-11-12 10:18:06 -05:00
}
2019-02-22 20:16:24 +00:00
}
2021-12-13 17:32:07 -05:00
if err := t . maybeLogMetadata ( ) ; err != nil {
t . failed = true
if t . keepGoing {
log . Printf ( "Failed logging metadata: %v" , err )
} else {
fatalf ( "Failed logging metadata: %v" , err )
}
}
2015-03-02 17:07:11 -08:00
for _ , dt := range t . tests {
2015-06-03 23:21:30 -07:00
if ! t . shouldRunTest ( dt . name ) {
2015-03-02 17:07:11 -08:00
t . partial = true
continue
}
2015-12-21 16:08:57 -05:00
dt := dt // dt used in background after this iteration
if err := dt . fn ( & dt ) ; err != nil {
2015-12-21 20:42:40 -05:00
t . runPending ( & dt ) // in case that hasn't been done yet
2015-12-21 16:08:57 -05:00
t . failed = true
2015-05-01 22:23:04 -04:00
if t . keepGoing {
log . Printf ( "Failed: %v" , err )
} else {
2019-11-15 12:26:09 -05:00
fatalf ( "Failed: %v" , err )
2015-05-01 22:23:04 -04:00
}
2015-03-02 17:07:11 -08:00
}
}
2015-12-21 16:08:57 -05:00
t . runPending ( nil )
2017-10-27 13:07:38 -04:00
timelog ( "end" , "dist test" )
2019-11-12 10:18:06 -05:00
2015-12-21 16:08:57 -05:00
if t . failed {
2015-05-01 22:23:04 -04:00
fmt . Println ( "\nFAILED" )
2019-11-15 12:26:09 -05:00
xexit ( 1 )
2018-12-28 11:46:35 +01:00
} else if incomplete [ goos + "/" + goarch ] {
2020-10-24 20:21:48 +02:00
// The test succeeded, but consider it as failed so we don't
// forget to remove the port from the incomplete map once the
// port is complete.
2018-12-28 11:46:35 +01:00
fmt . Println ( "\nFAILED (incomplete port)" )
2019-11-15 12:26:09 -05:00
xexit ( 1 )
2015-05-01 22:23:04 -04:00
} else if t . partial {
2015-03-02 17:07:11 -08:00
fmt . Println ( "\nALL TESTS PASSED (some were excluded)" )
} else {
fmt . Println ( "\nALL TESTS PASSED" )
}
}
2015-06-03 23:21:30 -07:00
func ( t * tester ) shouldRunTest ( name string ) bool {
if t . runRx != nil {
return t . runRx . MatchString ( name ) == t . runRxWant
}
if len ( t . runNames ) == 0 {
return true
}
for _ , runName := range t . runNames {
if runName == name {
return true
}
}
return false
}
2021-12-13 17:32:07 -05:00
func ( t * tester ) maybeLogMetadata ( ) error {
if t . compileOnly {
// We need to run a subprocess to log metadata. Don't do that
// on compile-only runs.
return nil
}
t . out ( "Test execution environment." )
// Helper binary to print system metadata (CPU model, etc). This is a
// separate binary from dist so it need not build with the bootstrap
// toolchain.
//
// TODO(prattmic): If we split dist bootstrap and dist test then this
// could be simplified to directly use internal/sysinfo here.
2022-06-09 17:30:05 -04:00
return t . dirCmd ( filepath . Join ( goroot , "src/cmd/internal/metadata" ) , "go" , [ ] string { "run" , "main.go" } ) . Run ( )
2021-12-13 17:32:07 -05:00
}
2020-05-13 13:57:36 -04:00
// short returns a -short flag value to use with 'go test'
// or a test binary for tests intended to run in short mode.
// It returns "true", unless the environment variable
2018-05-16 19:29:59 +00:00
// GO_TEST_SHORT is set to a non-empty, false-ish string.
//
// This environment variable is meant to be an internal
2020-05-13 13:57:36 -04:00
// detail between the Go build system and cmd/dist for
// the purpose of longtest builders, and is not intended
// for use by users. See golang.org/issue/12508.
2018-05-16 19:29:59 +00:00
func short ( ) string {
if v := os . Getenv ( "GO_TEST_SHORT" ) ; v != "" {
short , err := strconv . ParseBool ( v )
if err != nil {
2019-11-15 12:26:09 -05:00
fatalf ( "invalid GO_TEST_SHORT %q: %v" , v , err )
2018-05-16 19:29:59 +00:00
}
if ! short {
2020-05-13 13:57:36 -04:00
return "false"
2018-05-16 19:29:59 +00:00
}
}
2020-05-13 13:57:36 -04:00
return "true"
2018-05-16 19:29:59 +00:00
}
2017-11-29 14:16:25 -05:00
// goTest returns the beginning of the go test command line.
// Callers should use goTest and then pass flags overriding these
// defaults as later arguments in the command line.
func ( t * tester ) goTest ( ) [ ] string {
return [ ] string {
2020-05-13 13:57:36 -04:00
"go" , "test" , "-short=" + short ( ) , "-count=1" , t . tags ( ) , t . runFlag ( "" ) ,
2017-11-29 14:16:25 -05:00
}
}
2015-06-04 15:03:38 -04:00
func ( t * tester ) tags ( ) string {
2022-08-16 18:51:57 +07:00
ios := t . iOS ( )
switch {
case ios && noOpt :
return "-tags=lldb,noopt"
case ios :
2015-06-04 15:03:38 -04:00
return "-tags=lldb"
2022-08-16 18:51:57 +07:00
case noOpt :
return "-tags=noopt"
default :
return "-tags="
2015-06-04 15:03:38 -04:00
}
}
2019-05-21 19:02:00 +00:00
// timeoutDuration converts the provided number of seconds into a
// time.Duration, scaled by the t.timeoutScale factor.
func ( t * tester ) timeoutDuration ( sec int ) time . Duration {
return time . Duration ( sec ) * time . Second * time . Duration ( t . timeoutScale )
}
// timeout returns the "-timeout=" string argument to "go test" given
// the number of seconds of timeout. It scales it by the
// t.timeoutScale factor.
2015-03-02 17:07:11 -08:00
func ( t * tester ) timeout ( sec int ) string {
2019-05-21 19:02:00 +00:00
return "-timeout=" + t . timeoutDuration ( sec ) . String ( )
2015-03-02 17:07:11 -08:00
}
2015-05-27 16:33:03 -07:00
// ranGoTest and stdMatches are state closed over by the stdlib
// testing func in registerStdTest below. The tests are run
// sequentially, so there's no need for locks.
2015-06-08 17:56:27 -07:00
//
// ranGoBench and benchMatches are the same, but are only used
// in -race mode.
2015-05-27 16:33:03 -07:00
var (
ranGoTest bool
stdMatches [ ] string
2015-06-08 17:56:27 -07:00
ranGoBench bool
benchMatches [ ] string
2015-05-27 16:33:03 -07:00
)
2022-02-28 14:32:19 -08:00
func ( t * tester ) registerStdTest ( pkg string ) {
2021-01-20 14:08:53 -08:00
heading := "Testing packages."
testPrefix := "go_test:"
gcflags := gogcflags
testName := testPrefix + pkg
2017-02-21 17:00:10 -08:00
if t . runRx == nil || t . runRx . MatchString ( testName ) == t . runRxWant {
2015-05-27 16:33:03 -07:00
stdMatches = append ( stdMatches , pkg )
}
2021-01-20 14:08:53 -08:00
2015-05-27 16:33:03 -07:00
t . tests = append ( t . tests , distTest {
name : testName ,
2021-01-20 14:08:53 -08:00
heading : heading ,
2015-12-21 16:08:57 -05:00
fn : func ( dt * distTest ) error {
2015-05-27 16:33:03 -07:00
if ranGoTest {
return nil
}
2015-12-21 16:08:57 -05:00
t . runPending ( dt )
2017-10-27 13:07:38 -04:00
timelog ( "start" , dt . name )
defer timelog ( "end" , dt . name )
2015-05-27 16:33:03 -07:00
ranGoTest = true
cmd/dist: fix computation of test timeout
When dist test was updated to run "go test" with multiple package
arguments at once, merging the logical test units into one execution,
the hack to give cmd/go twice as much time wasn't updated.
What was happening (even in the all.bash case) was that we were
merging together, say, "cmd/go" and "bytes", and because bar was
lexically earlier, the timeout calculation was based on package "byte",
even though we were actually running, say: "go test bytes cmd/go".
This explains why x/build/cmd/release was often flaky with its
all.bash, since cmd/go can't really finish in 3 minutes reliably
unless it's running by itself. If it has any competition, it runs
over.
Change-Id: I875c8c9e65940ce0ceff48215740dfadfaa89d3f
Reviewed-on: https://go-review.googlesource.com/111395
Run-TryBot: Brad Fitzpatrick <bradfitz@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Andrew Bonventre <andybons@golang.org>
2018-05-04 05:32:01 +00:00
timeoutSec := 180
for _ , pkg := range stdMatches {
if pkg == "cmd/go" {
2018-06-25 20:24:37 +00:00
timeoutSec *= 3
cmd/dist: fix computation of test timeout
When dist test was updated to run "go test" with multiple package
arguments at once, merging the logical test units into one execution,
the hack to give cmd/go twice as much time wasn't updated.
What was happening (even in the all.bash case) was that we were
merging together, say, "cmd/go" and "bytes", and because bar was
lexically earlier, the timeout calculation was based on package "byte",
even though we were actually running, say: "go test bytes cmd/go".
This explains why x/build/cmd/release was often flaky with its
all.bash, since cmd/go can't really finish in 3 minutes reliably
unless it's running by itself. If it has any competition, it runs
over.
Change-Id: I875c8c9e65940ce0ceff48215740dfadfaa89d3f
Reviewed-on: https://go-review.googlesource.com/111395
Run-TryBot: Brad Fitzpatrick <bradfitz@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Andrew Bonventre <andybons@golang.org>
2018-05-04 05:32:01 +00:00
break
}
}
2019-05-21 19:02:00 +00:00
// Special case for our slow cross-compiled
// qemu builders:
if t . shouldUsePrecompiledStdTest ( ) {
return t . runPrecompiledStdTest ( t . timeoutDuration ( timeoutSec ) )
}
2015-06-08 17:56:27 -07:00
args := [ ] string {
2015-05-27 16:33:03 -07:00
"test" ,
2020-05-13 13:57:36 -04:00
"-short=" + short ( ) ,
2015-06-04 15:03:38 -04:00
t . tags ( ) ,
2017-12-15 01:49:04 +00:00
t . timeout ( timeoutSec ) ,
2022-03-08 17:01:12 -05:00
}
if gcflags != "" {
args = append ( args , "-gcflags=all=" + gcflags )
2015-06-08 17:56:27 -07:00
}
if t . race {
args = append ( args , "-race" )
}
2021-12-30 16:46:21 +08:00
if t . msan {
args = append ( args , "-msan" )
}
if t . asan {
args = append ( args , "-asan" )
}
2016-05-04 09:08:27 -07:00
if t . compileOnly {
args = append ( args , "-run=^$" )
}
2015-06-08 17:56:27 -07:00
args = append ( args , stdMatches ... )
2022-04-29 20:05:26 -04:00
cmd := exec . Command ( gorootBinGo , args ... )
2015-06-08 17:56:27 -07:00
cmd . Stdout = os . Stdout
cmd . Stderr = os . Stderr
return cmd . Run ( )
} ,
} )
}
func ( t * tester ) registerRaceBenchTest ( pkg string ) {
testName := "go_test_bench:" + pkg
2017-02-21 17:00:10 -08:00
if t . runRx == nil || t . runRx . MatchString ( testName ) == t . runRxWant {
2015-06-08 17:56:27 -07:00
benchMatches = append ( benchMatches , pkg )
}
t . tests = append ( t . tests , distTest {
name : testName ,
heading : "Running benchmarks briefly." ,
2015-12-21 16:08:57 -05:00
fn : func ( dt * distTest ) error {
2015-06-08 17:56:27 -07:00
if ranGoBench {
return nil
}
2015-12-21 16:08:57 -05:00
t . runPending ( dt )
2017-10-27 13:07:38 -04:00
timelog ( "start" , dt . name )
defer timelog ( "end" , dt . name )
2015-06-08 17:56:27 -07:00
ranGoBench = true
args := [ ] string {
"test" ,
2020-05-13 13:57:36 -04:00
"-short=" + short ( ) ,
2015-06-08 17:56:27 -07:00
"-race" ,
2018-03-29 11:15:18 -04:00
t . timeout ( 1200 ) , // longer timeout for race with benchmarks
"-run=^$" , // nothing. only benchmarks.
2015-06-08 17:56:27 -07:00
"-benchtime=.1s" ,
"-cpu=4" ,
}
2016-05-04 09:08:27 -07:00
if ! t . compileOnly {
args = append ( args , "-bench=.*" )
}
2015-06-08 17:56:27 -07:00
args = append ( args , benchMatches ... )
2022-04-29 20:05:26 -04:00
cmd := exec . Command ( gorootBinGo , args ... )
2015-05-27 16:33:03 -07:00
cmd . Stdout = os . Stdout
cmd . Stderr = os . Stderr
return cmd . Run ( )
} ,
} )
}
2016-12-06 18:22:42 +00:00
// stdOutErrAreTerminals is defined in test_linux.go, to report
// whether stdout & stderr are terminals.
var stdOutErrAreTerminals func ( ) bool
2015-05-27 16:33:03 -07:00
func ( t * tester ) registerTests ( ) {
// Fast path to avoid the ~1 second of `go list std cmd` when
2015-06-03 23:21:30 -07:00
// the caller lists specific tests to run. (as the continuous
2015-05-27 16:33:03 -07:00
// build coordinator does).
2015-06-03 23:21:30 -07:00
if len ( t . runNames ) > 0 {
for _ , name := range t . runNames {
if strings . HasPrefix ( name , "go_test:" ) {
2022-02-28 14:32:19 -08:00
t . registerStdTest ( strings . TrimPrefix ( name , "go_test:" ) )
2015-06-03 23:21:30 -07:00
}
2015-06-08 17:56:27 -07:00
if strings . HasPrefix ( name , "go_test_bench:" ) {
t . registerRaceBenchTest ( strings . TrimPrefix ( name , "go_test_bench:" ) )
}
2015-06-03 23:21:30 -07:00
}
} else {
// Use a format string to only list packages and commands that have tests.
const format = "{{if (or .TestGoFiles .XTestGoFiles)}}{{.ImportPath}}{{end}}"
2022-04-29 20:05:26 -04:00
cmd := exec . Command ( gorootBinGo , "list" , "-f" , format )
2016-01-18 22:42:40 -05:00
if t . race {
2017-11-29 14:16:25 -05:00
cmd . Args = append ( cmd . Args , "-tags=race" )
2016-01-18 22:42:40 -05:00
}
cmd . Args = append ( cmd . Args , "std" )
2019-10-29 17:03:56 +00:00
if t . shouldTestCmd ( ) {
2015-06-08 17:56:27 -07:00
cmd . Args = append ( cmd . Args , "cmd" )
}
2019-03-01 10:12:30 -05:00
cmd . Stderr = new ( bytes . Buffer )
2016-10-25 19:09:36 -07:00
all , err := cmd . Output ( )
2015-06-03 23:21:30 -07:00
if err != nil {
2019-11-15 12:26:09 -05:00
fatalf ( "Error running go list std cmd: %v:\n%s" , err , cmd . Stderr )
2015-06-03 23:21:30 -07:00
}
2015-06-08 17:56:27 -07:00
pkgs := strings . Fields ( string ( all ) )
2021-01-20 14:08:53 -08:00
for _ , pkg := range pkgs {
2022-02-28 14:32:19 -08:00
t . registerStdTest ( pkg )
2015-03-02 17:07:11 -08:00
}
2015-06-08 17:56:27 -07:00
if t . race {
for _ , pkg := range pkgs {
2016-09-14 16:34:27 +00:00
if t . packageHasBenchmarks ( pkg ) {
t . registerRaceBenchTest ( pkg )
}
2015-06-08 17:56:27 -07:00
}
}
}
2018-04-16 17:41:24 +00:00
// Test the os/user package in the pure-Go mode too.
if ! t . compileOnly {
t . tests = append ( t . tests , distTest {
name : "osusergo" ,
heading : "os/user with tag osusergo" ,
fn : func ( dt * distTest ) error {
t . addCmd ( dt , "src" , t . goTest ( ) , t . timeout ( 300 ) , "-tags=osusergo" , "os/user" )
return nil
} ,
2020-04-23 13:58:46 -07:00
} )
}
2020-10-24 22:02:50 -04:00
// Test ios/amd64 for the iOS simulator.
if goos == "darwin" && goarch == "amd64" && t . cgoEnabled {
2020-06-24 12:59:10 -04:00
t . tests = append ( t . tests , distTest {
name : "amd64ios" ,
2020-10-24 22:02:50 -04:00
heading : "GOOS=ios on darwin/amd64" ,
2020-06-24 12:59:10 -04:00
fn : func ( dt * distTest ) error {
2020-10-24 22:02:50 -04:00
cmd := t . addCmd ( dt , "src" , t . goTest ( ) , t . timeout ( 300 ) , "-run=SystemRoots" , "crypto/x509" )
2021-09-30 15:15:45 -04:00
setEnv ( cmd , "GOOS" , "ios" )
setEnv ( cmd , "CGO_ENABLED" , "1" )
2020-06-24 12:59:10 -04:00
return nil
} ,
} )
}
2018-06-25 19:05:25 +00:00
if t . race {
2015-06-08 17:56:27 -07:00
return
2015-03-02 17:07:11 -08:00
}
// Runtime CPU tests.
2018-06-25 19:05:25 +00:00
if ! t . compileOnly && goos != "js" { // js can't handle -cpu != 1
2016-05-04 09:08:27 -07:00
testName := "runtime:cpu124"
t . tests = append ( t . tests , distTest {
name : testName ,
2017-10-27 13:30:09 -04:00
heading : "GOMAXPROCS=2 runtime -cpu=1,2,4 -quick" ,
2016-05-04 09:08:27 -07:00
fn : func ( dt * distTest ) error {
2022-07-16 16:08:35 -07:00
cmd := t . addCmd ( dt , "src" , t . goTest ( ) , "-short=true" , t . timeout ( 300 ) , "runtime" , "-cpu=1,2,4" , "-quick" )
2016-05-04 09:08:27 -07:00
// We set GOMAXPROCS=2 in addition to -cpu=1,2,4 in order to test runtime bootstrap code,
// creation of first goroutines and first garbage collections in the parallel setting.
2021-09-30 15:15:45 -04:00
setEnv ( cmd , "GOMAXPROCS" , "2" )
2016-05-04 09:08:27 -07:00
return nil
} ,
} )
}
2015-03-02 17:07:11 -08:00
2021-11-04 21:06:06 -04:00
// morestack tests. We only run these on in long-test mode
// (with GO_TEST_SHORT=false) because the runtime test is
// already quite long and mayMoreStackMove makes it about
// twice as slow.
if ! t . compileOnly && short ( ) == "false" {
// hooks is the set of maymorestack hooks to test with.
hooks := [ ] string { "mayMoreStackPreempt" , "mayMoreStackMove" }
// pkgs is the set of test packages to run.
pkgs := [ ] string { "runtime" , "reflect" , "sync" }
// hookPkgs is the set of package patterns to apply
// the maymorestack hook to.
hookPkgs := [ ] string { "runtime/..." , "reflect" , "sync" }
// unhookPkgs is the set of package patterns to
// exclude from hookPkgs.
unhookPkgs := [ ] string { "runtime/testdata/..." }
for _ , hook := range hooks {
// Construct the build flags to use the
// maymorestack hook in the compiler and
// assembler. We pass this via the GOFLAGS
// environment variable so that it applies to
// both the test itself and to binaries built
// by the test.
goFlagsList := [ ] string { }
for _ , flag := range [ ] string { "-gcflags" , "-asmflags" } {
for _ , hookPkg := range hookPkgs {
goFlagsList = append ( goFlagsList , flag + "=" + hookPkg + "=-d=maymorestack=runtime." + hook )
}
for _ , unhookPkg := range unhookPkgs {
goFlagsList = append ( goFlagsList , flag + "=" + unhookPkg + "=" )
}
}
goFlags := strings . Join ( goFlagsList , " " )
for _ , pkg := range pkgs {
pkg := pkg
testName := hook + ":" + pkg
t . tests = append ( t . tests , distTest {
name : testName ,
heading : "maymorestack=" + hook ,
fn : func ( dt * distTest ) error {
cmd := t . addCmd ( dt , "src" , t . goTest ( ) , t . timeout ( 600 ) , pkg , "-short" )
setEnv ( cmd , "GOFLAGS" , goFlags )
return nil
} ,
} )
}
}
}
2017-08-18 17:43:33 -07:00
// This test needs its stdout/stderr to be terminals, so we don't run it from cmd/go's tests.
// See issue 18153.
2017-09-19 22:13:22 +09:00
if goos == "linux" {
2017-08-18 17:43:33 -07:00
t . tests = append ( t . tests , distTest {
name : "cmd_go_test_terminal" ,
heading : "cmd/go terminal test" ,
fn : func ( dt * distTest ) error {
t . runPending ( dt )
2017-10-27 13:07:38 -04:00
timelog ( "start" , dt . name )
defer timelog ( "end" , dt . name )
2017-08-18 17:43:33 -07:00
if ! stdOutErrAreTerminals ( ) {
fmt . Println ( "skipping terminal test; stdout/stderr not terminals" )
return nil
}
2022-04-29 20:05:26 -04:00
cmd := exec . Command ( gorootBinGo , "test" )
2021-09-30 15:15:45 -04:00
setDir ( cmd , filepath . Join ( os . Getenv ( "GOROOT" ) , "src/cmd/go/testdata/testterminal18153" ) )
2017-08-18 17:43:33 -07:00
cmd . Stdout = os . Stdout
cmd . Stderr = os . Stderr
return cmd . Run ( )
} ,
} )
}
2017-07-14 08:22:30 -07:00
// On the builders only, test that a moved GOROOT still works.
2017-07-15 06:33:24 -07:00
// Fails on iOS because CC_FOR_TARGET refers to clangwrap.sh
// in the unmoved GOROOT.
2018-06-25 19:05:25 +00:00
// Fails on Android and js/wasm with an exec format error.
2017-07-15 06:33:24 -07:00
// Fails on plan9 with "cannot find GOROOT" (issue #21016).
2018-06-25 19:05:25 +00:00
if os . Getenv ( "GO_BUILDER_NAME" ) != "" && goos != "android" && ! t . iOS ( ) && goos != "plan9" && goos != "js" {
2017-07-14 08:22:30 -07:00
t . tests = append ( t . tests , distTest {
name : "moved_goroot" ,
heading : "moved GOROOT" ,
fn : func ( dt * distTest ) error {
t . runPending ( dt )
2017-10-27 13:07:38 -04:00
timelog ( "start" , dt . name )
defer timelog ( "end" , dt . name )
2017-09-19 22:13:22 +09:00
moved := goroot + "-moved"
if err := os . Rename ( goroot , moved ) ; err != nil {
if goos == "windows" {
2017-07-27 04:33:18 +00:00
// Fails on Windows (with "Access is denied") if a process
// or binary is in this directory. For instance, using all.bat
// when run from c:\workdir\go\src fails here
// if GO_BUILDER_NAME is set. Our builders invoke tests
// a different way which happens to work when sharding
// tests, but we should be tolerant of the non-sharded
// all.bat case.
log . Printf ( "skipping test on Windows" )
return nil
}
2017-07-14 08:22:30 -07:00
return err
}
2021-09-30 15:15:45 -04:00
// Run `go test fmt` in the moved GOROOT, without explicitly setting
// GOROOT in the environment. The 'go' command should find itself.
2017-07-14 08:22:30 -07:00
cmd := exec . Command ( filepath . Join ( moved , "bin" , "go" ) , "test" , "fmt" )
cmd . Stdout = os . Stdout
cmd . Stderr = os . Stderr
2021-09-30 15:15:45 -04:00
unsetEnv ( cmd , "GOROOT" )
unsetEnv ( cmd , "GOCACHE" ) // TODO(bcmills): ...why‽
2017-07-14 08:22:30 -07:00
err := cmd . Run ( )
2017-09-19 22:13:22 +09:00
if rerr := os . Rename ( moved , goroot ) ; rerr != nil {
2019-11-15 12:26:09 -05:00
fatalf ( "failed to restore GOROOT: %v" , rerr )
2017-07-14 08:22:30 -07:00
}
return err
} ,
} )
}
2015-11-16 18:11:35 -08:00
// Test that internal linking of standard packages does not
2016-03-01 23:21:55 +00:00
// require libgcc. This ensures that we can install a Go
2015-11-16 18:11:35 -08:00
// release on a system that does not have a C compiler
// installed and still build Go programs (that don't use cgo).
for _ , pkg := range cgoPackages {
2016-09-16 18:25:52 -04:00
if ! t . internalLink ( ) {
2015-11-16 18:11:35 -08:00
break
}
2015-11-18 09:28:24 -08:00
// ARM libgcc may be Thumb, which internal linking does not support.
2017-09-19 22:13:22 +09:00
if goarch == "arm" {
2015-11-18 09:28:24 -08:00
break
}
2015-11-16 18:11:35 -08:00
pkg := pkg
2015-12-21 13:49:12 -05:00
var run string
if pkg == "net" {
run = "TestTCPStress"
}
2015-11-16 18:11:35 -08:00
t . tests = append ( t . tests , distTest {
name : "nolibgcc:" + pkg ,
heading : "Testing without libgcc." ,
2015-12-21 16:08:57 -05:00
fn : func ( dt * distTest ) error {
2019-05-15 20:49:39 -04:00
// What matters is that the tests build and start up.
// Skip expensive tests, especially x509 TestSystemRoots.
t . addCmd ( dt , "src" , t . goTest ( ) , "-ldflags=-linkmode=internal -libgcc=none" , "-run=^Test[^CS]" , pkg , t . runFlag ( run ) )
2015-12-21 16:08:57 -05:00
return nil
2015-11-16 18:11:35 -08:00
} ,
} )
}
2022-08-09 10:32:59 -04:00
// Stub out following test on alpine until 54354 resolved.
builderName := os . Getenv ( "GO_BUILDER_NAME" )
disablePIE := strings . HasSuffix ( builderName , "-alpine" )
2016-09-06 09:16:48 -04:00
// Test internal linking of PIE binaries where it is supported.
2022-08-09 10:32:59 -04:00
if t . internalLinkPIE ( ) && ! disablePIE {
2016-09-06 09:16:48 -04:00
t . tests = append ( t . tests , distTest {
name : "pie_internal" ,
heading : "internal linking of -buildmode=pie" ,
fn : func ( dt * distTest ) error {
2022-08-31 09:37:22 +07:00
cmd := t . addCmd ( dt , "src" , t . goTest ( ) , "reflect" , "-buildmode=pie" , "-ldflags=-linkmode=internal" , t . timeout ( 60 ) )
setEnv ( cmd , "CGO_ENABLED" , "0" )
2016-09-06 09:16:48 -04:00
return nil
} ,
} )
2019-03-06 17:57:35 -05:00
// Also test a cgo package.
2022-08-09 10:32:59 -04:00
if t . cgoEnabled && t . internalLink ( ) && ! disablePIE {
2019-03-06 17:57:35 -05:00
t . tests = append ( t . tests , distTest {
name : "pie_internal_cgo" ,
heading : "internal linking of -buildmode=pie" ,
fn : func ( dt * distTest ) error {
t . addCmd ( dt , "src" , t . goTest ( ) , "os/user" , "-buildmode=pie" , "-ldflags=-linkmode=internal" , t . timeout ( 60 ) )
return nil
} ,
} )
}
2016-09-06 09:16:48 -04:00
}
2015-03-02 17:07:11 -08:00
// sync tests
2018-06-25 19:05:25 +00:00
if goos != "js" { // js doesn't support -cpu=10
t . tests = append ( t . tests , distTest {
name : "sync_cpu" ,
heading : "sync -cpu=10" ,
fn : func ( dt * distTest ) error {
2020-03-13 20:38:58 +00:00
t . addCmd ( dt , "src" , t . goTest ( ) , "sync" , t . timeout ( 120 ) , "-cpu=10" , t . runFlag ( "" ) )
2018-06-25 19:05:25 +00:00
return nil
} ,
} )
}
2015-03-02 17:07:11 -08:00
2017-08-18 17:43:33 -07:00
if t . raceDetectorSupported ( ) {
t . tests = append ( t . tests , distTest {
name : "race" ,
heading : "Testing race detector" ,
fn : t . raceTest ,
} )
}
2016-06-01 20:58:02 +02:00
if t . cgoEnabled && ! t . iOS ( ) {
// Disabled on iOS. golang.org/issue/15919
2019-02-27 13:02:04 -05:00
t . registerHostTest ( "cgo_stdio" , "../misc/cgo/stdio" , "misc/cgo/stdio" , "." )
t . registerHostTest ( "cgo_life" , "../misc/cgo/life" , "misc/cgo/life" , "." )
2016-02-18 21:19:03 +10:30
fortran := os . Getenv ( "FC" )
if fortran == "" {
fortran , _ = exec . LookPath ( "gfortran" )
}
2019-02-26 19:01:47 +01:00
if t . hasBash ( ) && goos != "android" && fortran != "" {
2016-02-18 21:19:03 +10:30
t . tests = append ( t . tests , distTest {
name : "cgo_fortran" ,
heading : "../misc/cgo/fortran" ,
fn : func ( dt * distTest ) error {
2016-02-25 17:39:45 +10:30
t . addCmd ( dt , "misc/cgo/fortran" , "./test.bash" , fortran )
2016-02-18 21:19:03 +10:30
return nil
} ,
} )
}
2017-12-06 18:09:11 -08:00
if t . hasSwig ( ) && goos != "android" {
2017-11-15 21:14:21 -05:00
t . tests = append ( t . tests , distTest {
name : "swig_stdio" ,
heading : "../misc/swig/stdio" ,
fn : func ( dt * distTest ) error {
2022-06-16 15:45:25 -04:00
t . addCmd ( dt , "misc/swig/stdio" , t . goTest ( ) , "." )
2017-11-15 21:14:21 -05:00
return nil
} ,
} )
2018-07-17 15:55:01 +00:00
if t . hasCxx ( ) {
2021-05-25 16:31:41 -07:00
t . tests = append ( t . tests ,
distTest {
name : "swig_callback" ,
heading : "../misc/swig/callback" ,
fn : func ( dt * distTest ) error {
2022-06-16 15:45:25 -04:00
t . addCmd ( dt , "misc/swig/callback" , t . goTest ( ) , "." )
2021-05-25 16:31:41 -07:00
return nil
} ,
} ,
distTest {
name : "swig_callback_lto" ,
heading : "../misc/swig/callback" ,
fn : func ( dt * distTest ) error {
2022-06-16 15:45:25 -04:00
cmd := t . addCmd ( dt , "misc/swig/callback" , t . goTest ( ) , "." )
2021-09-30 15:15:45 -04:00
setEnv ( cmd , "CGO_CFLAGS" , "-flto -Wno-lto-type-mismatch -Wno-unknown-warning-option" )
setEnv ( cmd , "CGO_CXXFLAGS" , "-flto -Wno-lto-type-mismatch -Wno-unknown-warning-option" )
setEnv ( cmd , "CGO_LDFLAGS" , "-flto -Wno-lto-type-mismatch -Wno-unknown-warning-option" )
2021-05-25 16:31:41 -07:00
return nil
} ,
2017-11-15 21:14:21 -05:00
} ,
2021-05-25 16:31:41 -07:00
)
2017-11-15 21:14:21 -05:00
}
}
2015-03-19 13:15:56 -04:00
}
2016-06-01 22:51:30 +02:00
if t . cgoEnabled {
2015-03-02 17:07:11 -08:00
t . tests = append ( t . tests , distTest {
name : "cgo_test" ,
heading : "../misc/cgo/test" ,
fn : t . cgoTest ,
} )
}
2017-10-30 15:28:11 -04:00
// Don't run these tests with $GO_GCFLAGS because most of them
// assume that they can run "go install" with no -gcflags and not
// recompile the entire standard library. If make.bash ran with
// special -gcflags, that's not true.
if t . cgoEnabled && gogcflags == "" {
2019-11-13 12:25:09 -05:00
t . registerHostTest ( "testgodefs" , "../misc/cgo/testgodefs" , "misc/cgo/testgodefs" , "." )
2019-05-15 14:33:16 -04:00
t . registerTest ( "testso" , "../misc/cgo/testso" , t . goTest ( ) , t . timeout ( 600 ) , "." )
t . registerTest ( "testsovar" , "../misc/cgo/testsovar" , t . goTest ( ) , t . timeout ( 600 ) , "." )
2016-03-24 21:47:02 +01:00
if t . supportedBuildmode ( "c-archive" ) {
2019-02-21 12:34:27 -05:00
t . registerHostTest ( "testcarchive" , "../misc/cgo/testcarchive" , "misc/cgo/testcarchive" , "." )
2015-04-13 11:31:14 -04:00
}
2015-04-29 17:30:56 -07:00
if t . supportedBuildmode ( "c-shared" ) {
2019-02-21 16:18:28 -05:00
t . registerHostTest ( "testcshared" , "../misc/cgo/testcshared" , "misc/cgo/testcshared" , "." )
2015-04-17 14:50:07 -04:00
}
2021-10-29 01:18:24 +00:00
if t . supportedBuildmode ( "shared" ) {
t . registerTest ( "testshared" , "../misc/cgo/testshared" , t . goTest ( ) , t . timeout ( 600 ) , "." )
}
2016-08-26 09:04:27 -04:00
if t . supportedBuildmode ( "plugin" ) {
2019-05-15 14:33:16 -04:00
t . registerTest ( "testplugin" , "../misc/cgo/testplugin" , t . goTest ( ) , t . timeout ( 600 ) , "." )
2016-08-26 09:04:27 -04:00
}
2022-05-26 05:24:38 -05:00
if gohostos == "linux" && ( goarch == "amd64" || goarch == "ppc64le" ) {
2019-11-22 17:14:25 -05:00
t . registerTest ( "testasan" , "../misc/cgo/testasan" , "go" , "run" , "." )
2015-03-03 15:50:32 -08:00
}
2022-08-17 10:04:57 -05:00
if goos == "linux" {
2021-07-02 05:41:10 +00:00
// because syscall.SysProcAttr struct used in misc/cgo/testsanitizers is only built on linux.
2021-03-01 10:34:08 +08:00
t . registerHostTest ( "testsanitizers" , "../misc/cgo/testsanitizers" , "misc/cgo/testsanitizers" , "." )
2015-09-29 21:24:13 -07:00
}
2017-09-19 22:13:22 +09:00
if t . hasBash ( ) && goos != "android" && ! t . iOS ( ) && gohostos != "windows" {
2017-09-12 18:28:02 -04:00
t . registerHostTest ( "cgo_errors" , "../misc/cgo/errors" , "misc/cgo/errors" , "." )
2015-03-03 15:50:32 -08:00
}
2017-09-19 22:13:22 +09:00
if gohostos == "linux" && t . extLink ( ) {
2019-11-22 17:14:25 -05:00
t . registerTest ( "testsigfwd" , "../misc/cgo/testsigfwd" , "go" , "run" , "." )
runtime: signal forwarding
Forward signals to signal handlers installed before Go installs its own,
under certain circumstances. In particular, as iant@ suggests, signals are
forwarded iff:
(1) a non-SIG_DFL signal handler existed before Go, and
(2) signal is synchronous (i.e., one of SIGSEGV, SIGBUS, SIGFPE), and
(3a) signal occured on a non-Go thread, or
(3b) signal occurred on a Go thread but in CGo code.
Supported only on Linux, for now.
Change-Id: I403219ee47b26cf65da819fb86cf1ec04d3e25f5
Reviewed-on: https://go-review.googlesource.com/8712
Reviewed-by: Ian Lance Taylor <iant@golang.org>
2015-04-09 11:12:12 -07:00
}
2015-03-02 17:07:11 -08:00
}
2015-12-21 16:15:36 -05:00
2017-09-19 22:13:22 +09:00
if goos != "android" && ! t . iOS ( ) {
2019-05-15 20:49:39 -04:00
// There are no tests in this directory, only benchmarks.
// Check that the test binary builds but don't bother running it.
// (It has init-time work to set up for the benchmarks that is not worth doing unnecessarily.)
t . registerTest ( "bench_go1" , "../test/bench/go1" , t . goTest ( ) , "-c" , "-o=" + os . DevNull )
2015-03-02 17:07:11 -08:00
}
2017-09-19 22:13:22 +09:00
if goos != "android" && ! t . iOS ( ) {
2017-05-02 05:35:55 -07:00
// Only start multiple test dir shards on builders,
// where they get distributed to multiple machines.
2019-05-05 02:25:42 +00:00
// See issues 20141 and 31834.
2017-05-02 05:35:55 -07:00
nShards := 1
if os . Getenv ( "GO_BUILDER_NAME" ) != "" {
nShards = 10
}
2019-05-05 02:25:42 +00:00
if n , err := strconv . Atoi ( os . Getenv ( "GO_TEST_SHARDS" ) ) ; err == nil {
nShards = n
}
2015-06-03 23:21:30 -07:00
for shard := 0 ; shard < nShards ; shard ++ {
shard := shard
t . tests = append ( t . tests , distTest {
name : fmt . Sprintf ( "test:%d_%d" , shard , nShards ) ,
heading : "../test" ,
2015-12-21 16:08:57 -05:00
fn : func ( dt * distTest ) error { return t . testDirTest ( dt , shard , nShards ) } ,
2015-06-03 23:21:30 -07:00
} )
}
2015-03-02 17:07:11 -08:00
}
2022-08-05 14:37:34 -04:00
// Only run the API check on fast development platforms.
// Every platform checks the API on every GOOS/GOARCH/CGO_ENABLED combination anyway,
// so we really only need to run this check once anywhere to get adequate coverage.
// To help developers avoid trybot-only failures, we try to run on typical developer machines
// which is darwin/linux/windows and amd64/arm64.
if ( goos == "darwin" || goos == "linux" || goos == "windows" ) && ( goarch == "amd64" || goarch == "arm64" ) {
2015-03-02 17:07:11 -08:00
t . tests = append ( t . tests , distTest {
name : "api" ,
heading : "API check" ,
2015-12-21 16:08:57 -05:00
fn : func ( dt * distTest ) error {
2016-05-04 09:08:27 -07:00
if t . compileOnly {
2019-11-15 12:29:04 -05:00
t . addCmd ( dt , "src" , "go" , "build" , "-o" , os . DevNull , filepath . Join ( goroot , "src/cmd/api/run.go" ) )
2016-05-04 09:08:27 -07:00
return nil
}
2017-09-19 22:13:22 +09:00
t . addCmd ( dt , "src" , "go" , "run" , filepath . Join ( goroot , "src/cmd/api/run.go" ) )
2015-12-21 16:08:57 -05:00
return nil
2015-03-02 17:07:11 -08:00
} ,
} )
}
2019-03-13 16:42:18 -04:00
// Ensure that the toolchain can bootstrap itself.
// This test adds another ~45s to all.bash if run sequentially, so run it only on the builders.
if os . Getenv ( "GO_BUILDER_NAME" ) != "" && goos != "android" && ! t . iOS ( ) {
t . registerHostTest ( "reboot" , "../misc/reboot" , "misc/reboot" , "." )
}
2015-05-27 16:33:03 -07:00
}
// isRegisteredTestName reports whether a test named testName has already
// been registered.
func ( t * tester ) isRegisteredTestName ( testName string ) bool {
for _ , tt := range t . tests {
if tt . name == testName {
return true
}
}
return false
2015-03-02 17:07:11 -08:00
}
2017-11-29 14:16:25 -05:00
func ( t * tester ) registerTest1 ( seq bool , name , dirBanner string , cmdline ... interface { } ) {
bin , args := flattenCmdline ( cmdline )
2015-03-02 17:07:11 -08:00
if bin == "time" && ! t . haveTime {
bin , args = args [ 0 ] , args [ 1 : ]
}
2015-06-03 23:21:30 -07:00
if t . isRegisteredTestName ( name ) {
panic ( "duplicate registered test name " + name )
}
2015-03-02 17:07:11 -08:00
t . tests = append ( t . tests , distTest {
name : name ,
heading : dirBanner ,
2015-12-21 16:08:57 -05:00
fn : func ( dt * distTest ) error {
if seq {
t . runPending ( dt )
2017-10-27 13:07:38 -04:00
timelog ( "start" , name )
defer timelog ( "end" , name )
2017-11-29 14:16:25 -05:00
return t . dirCmd ( filepath . Join ( goroot , "src" , dirBanner ) , bin , args ) . Run ( )
2015-12-21 16:08:57 -05:00
}
2017-11-29 14:16:25 -05:00
t . addCmd ( dt , filepath . Join ( goroot , "src" , dirBanner ) , bin , args )
2015-12-21 16:08:57 -05:00
return nil
2015-03-02 17:07:11 -08:00
} ,
} )
}
2017-11-29 14:16:25 -05:00
func ( t * tester ) registerTest ( name , dirBanner string , cmdline ... interface { } ) {
t . registerTest1 ( false , name , dirBanner , cmdline ... )
2015-12-21 16:08:57 -05:00
}
2017-11-29 14:16:25 -05:00
func ( t * tester ) registerSeqTest ( name , dirBanner string , cmdline ... interface { } ) {
t . registerTest1 ( true , name , dirBanner , cmdline ... )
2015-12-21 16:08:57 -05:00
}
func ( t * tester ) bgDirCmd ( dir , bin string , args ... string ) * exec . Cmd {
2015-03-02 17:07:11 -08:00
cmd := exec . Command ( bin , args ... )
if filepath . IsAbs ( dir ) {
2021-09-30 15:15:45 -04:00
setDir ( cmd , dir )
2015-03-02 17:07:11 -08:00
} else {
2021-09-30 15:15:45 -04:00
setDir ( cmd , filepath . Join ( goroot , dir ) )
2015-03-02 17:07:11 -08:00
}
2015-12-21 16:08:57 -05:00
return cmd
}
2017-11-29 14:16:25 -05:00
func ( t * tester ) dirCmd ( dir string , cmdline ... interface { } ) * exec . Cmd {
bin , args := flattenCmdline ( cmdline )
2015-12-21 16:08:57 -05:00
cmd := t . bgDirCmd ( dir , bin , args ... )
2015-03-02 17:07:11 -08:00
cmd . Stdout = os . Stdout
cmd . Stderr = os . Stderr
2015-07-22 09:23:21 +02:00
if vflag > 1 {
errprintf ( "%s\n" , strings . Join ( cmd . Args , " " ) )
}
2015-03-02 17:07:11 -08:00
return cmd
}
2017-11-29 14:16:25 -05:00
// flattenCmdline flattens a mixture of string and []string as single list
// and then interprets it as a command line: first element is binary, then args.
func flattenCmdline ( cmdline [ ] interface { } ) ( bin string , args [ ] string ) {
var list [ ] string
for _ , x := range cmdline {
switch x := x . ( type ) {
case string :
list = append ( list , x )
case [ ] string :
list = append ( list , x ... )
default :
panic ( "invalid addCmd argument type: " + reflect . TypeOf ( x ) . String ( ) )
}
}
// The go command is too picky about duplicated flags.
// Drop all but the last of the allowed duplicated flags.
drop := make ( [ ] bool , len ( list ) )
have := map [ string ] int { }
for i := 1 ; i < len ( list ) ; i ++ {
j := strings . Index ( list [ i ] , "=" )
if j < 0 {
continue
}
flag := list [ i ] [ : j ]
switch flag {
case "-run" , "-tags" :
if have [ flag ] != 0 {
drop [ have [ flag ] ] = true
}
have [ flag ] = i
}
}
out := list [ : 0 ]
for i , x := range list {
if ! drop [ i ] {
out = append ( out , x )
}
}
list = out
2022-04-29 20:05:26 -04:00
bin = list [ 0 ]
if bin == "go" {
bin = gorootBinGo
}
return bin , list [ 1 : ]
2017-11-29 14:16:25 -05:00
}
func ( t * tester ) addCmd ( dt * distTest , dir string , cmdline ... interface { } ) * exec . Cmd {
bin , args := flattenCmdline ( cmdline )
2015-12-21 16:08:57 -05:00
w := & work {
dt : dt ,
cmd : t . bgDirCmd ( dir , bin , args ... ) ,
}
t . worklist = append ( t . worklist , w )
return w . cmd
}
2015-04-30 16:38:10 -04:00
func ( t * tester ) iOS ( ) bool {
2020-09-17 12:39:43 -04:00
return goos == "ios"
2015-04-30 16:38:10 -04:00
}
2015-03-02 17:07:11 -08:00
func ( t * tester ) out ( v string ) {
if t . banner == "" {
return
}
fmt . Println ( "\n" + t . banner + v )
}
func ( t * tester ) extLink ( ) bool {
2017-09-19 22:13:22 +09:00
pair := gohostos + "-" + goarch
2015-03-02 17:07:11 -08:00
switch pair {
2019-02-21 10:56:35 +01:00
case "aix-ppc64" ,
2020-02-26 10:24:39 -05:00
"android-arm" , "android-arm64" ,
2020-04-06 16:16:48 -04:00
"darwin-amd64" , "darwin-arm64" ,
2017-11-23 10:16:02 +01:00
"dragonfly-amd64" ,
2015-03-02 17:07:11 -08:00
"freebsd-386" , "freebsd-amd64" , "freebsd-arm" ,
2021-08-15 15:53:05 +08:00
"linux-386" , "linux-amd64" , "linux-arm" , "linux-arm64" , "linux-loong64" , "linux-ppc64le" , "linux-mips64" , "linux-mips64le" , "linux-mips" , "linux-mipsle" , "linux-riscv64" , "linux-s390x" ,
2015-03-02 17:07:11 -08:00
"netbsd-386" , "netbsd-amd64" ,
2015-03-10 04:11:30 -04:00
"openbsd-386" , "openbsd-amd64" ,
2015-03-13 22:12:09 -04:00
"windows-386" , "windows-amd64" :
2015-03-02 17:07:11 -08:00
return true
}
return false
}
2016-09-16 18:25:52 -04:00
func ( t * tester ) internalLink ( ) bool {
2017-09-19 22:13:22 +09:00
if gohostos == "dragonfly" {
2016-09-16 18:25:52 -04:00
// linkmode=internal fails on dragonfly since errno is a TLS relocation.
return false
}
2017-09-19 22:13:22 +09:00
if goos == "android" {
2016-09-16 18:25:52 -04:00
return false
}
2020-09-16 16:59:58 -04:00
if goos == "ios" {
return false
}
2021-04-14 12:38:20 -04:00
if goos == "windows" && goarch == "arm64" {
return false
}
2016-09-16 18:25:52 -04:00
// Internally linking cgo is incomplete on some architectures.
// https://golang.org/issue/10373
// https://golang.org/issue/14449
2021-08-15 15:53:05 +08:00
if goarch == "loong64" || goarch == "mips64" || goarch == "mips64le" || goarch == "mips" || goarch == "mipsle" || goarch == "riscv64" {
2016-09-16 18:25:52 -04:00
return false
}
2019-02-21 10:56:35 +01:00
if goos == "aix" {
// linkmode=internal isn't supported.
return false
}
2016-09-16 18:25:52 -04:00
return true
}
2020-02-09 17:01:53 -05:00
func ( t * tester ) internalLinkPIE ( ) bool {
2020-02-26 10:24:39 -05:00
switch goos + "-" + goarch {
2020-10-14 21:15:37 -04:00
case "darwin-amd64" , "darwin-arm64" ,
2021-07-14 14:09:27 -05:00
"linux-amd64" , "linux-arm64" , "linux-ppc64le" ,
2020-10-11 15:48:22 -04:00
"android-arm64" ,
"windows-amd64" , "windows-386" , "windows-arm" :
2020-02-25 18:42:24 +11:00
return true
2020-02-26 10:24:39 -05:00
}
return false
2020-02-09 17:01:53 -05:00
}
2015-04-29 17:30:56 -07:00
func ( t * tester ) supportedBuildmode ( mode string ) bool {
2017-09-19 22:13:22 +09:00
pair := goos + "-" + goarch
2015-04-16 10:08:20 -07:00
switch mode {
case "c-archive" :
2015-04-23 17:27:38 -04:00
if ! t . extLink ( ) {
2015-04-16 10:08:20 -07:00
return false
2015-04-23 17:27:38 -04:00
}
switch pair {
2019-03-25 10:34:57 +01:00
case "aix-ppc64" ,
2020-10-04 00:25:17 -04:00
"darwin-amd64" , "darwin-arm64" , "ios-arm64" ,
2021-07-16 03:06:18 +10:00
"linux-amd64" , "linux-386" , "linux-ppc64le" , "linux-riscv64" , "linux-s390x" ,
2018-02-13 19:00:17 -08:00
"freebsd-amd64" ,
2017-05-24 15:01:49 -07:00
"windows-amd64" , "windows-386" :
2015-04-16 10:08:20 -07:00
return true
}
2015-04-23 17:27:38 -04:00
return false
2015-04-17 14:50:07 -04:00
case "c-shared" :
2015-04-23 17:27:38 -04:00
switch pair {
2021-07-16 03:06:18 +10:00
case "linux-386" , "linux-amd64" , "linux-arm" , "linux-arm64" , "linux-ppc64le" , "linux-riscv64" , "linux-s390x" ,
2020-10-03 23:58:29 -04:00
"darwin-amd64" , "darwin-arm64" ,
2018-02-13 19:00:17 -08:00
"freebsd-amd64" ,
2017-10-05 17:36:13 +11:00
"android-arm" , "android-arm64" , "android-386" ,
2021-06-11 17:38:23 +02:00
"windows-amd64" , "windows-386" , "windows-arm64" :
2015-04-23 17:27:38 -04:00
return true
}
return false
2021-10-29 01:18:24 +00:00
case "shared" :
switch pair {
case "linux-386" , "linux-amd64" , "linux-arm" , "linux-arm64" , "linux-ppc64le" , "linux-s390x" :
return true
}
return false
2016-08-26 09:04:27 -04:00
case "plugin" :
switch pair {
2021-12-06 18:41:49 -05:00
case "linux-386" , "linux-amd64" , "linux-arm" , "linux-arm64" , "linux-s390x" , "linux-ppc64le" :
2015-04-27 15:00:48 +12:00
return true
2020-10-03 16:26:37 -04:00
case "darwin-amd64" , "darwin-arm64" :
2017-09-04 21:23:29 +09:00
return true
2019-08-23 11:38:12 -04:00
case "freebsd-amd64" :
return true
2015-04-27 15:00:48 +12:00
}
return false
2017-09-28 10:26:39 -04:00
case "pie" :
switch pair {
2019-03-22 12:54:37 +01:00
case "aix/ppc64" ,
2020-11-04 00:26:15 +11:00
"linux-386" , "linux-amd64" , "linux-arm" , "linux-arm64" , "linux-ppc64le" , "linux-riscv64" , "linux-s390x" ,
2017-09-28 10:26:39 -04:00
"android-amd64" , "android-arm" , "android-arm64" , "android-386" :
return true
2020-10-03 23:36:58 -04:00
case "darwin-amd64" , "darwin-arm64" :
2017-09-28 10:26:39 -04:00
return true
2020-02-25 18:42:24 +11:00
case "windows-amd64" , "windows-386" , "windows-arm" :
return true
2017-09-28 10:26:39 -04:00
}
return false
2015-04-16 10:08:20 -07:00
default :
2019-11-15 12:26:09 -05:00
fatalf ( "internal error: unknown buildmode %s" , mode )
2015-04-16 10:08:20 -07:00
return false
}
}
2016-08-30 18:11:10 -07:00
func ( t * tester ) registerHostTest ( name , heading , dir , pkg string ) {
2016-03-24 21:47:02 +01:00
t . tests = append ( t . tests , distTest {
name : name ,
2016-08-30 18:11:10 -07:00
heading : heading ,
2016-03-24 21:47:02 +01:00
fn : func ( dt * distTest ) error {
2016-03-25 01:27:34 +01:00
t . runPending ( dt )
2017-10-27 13:07:38 -04:00
timelog ( "start" , name )
defer timelog ( "end" , name )
2016-08-30 18:11:10 -07:00
return t . runHostTest ( dir , pkg )
2016-03-24 21:47:02 +01:00
} ,
} )
}
2016-08-30 18:11:10 -07:00
func ( t * tester ) runHostTest ( dir , pkg string ) error {
2022-04-29 20:05:26 -04:00
out , err := exec . Command ( gorootBinGo , "env" , "GOEXE" , "GOTMPDIR" ) . Output ( )
2019-11-11 11:08:20 -05:00
if err != nil {
return err
}
parts := strings . Split ( string ( out ) , "\n" )
if len ( parts ) < 2 {
return fmt . Errorf ( "'go env GOEXE GOTMPDIR' output contains <2 lines" )
}
GOEXE := strings . TrimSpace ( parts [ 0 ] )
GOTMPDIR := strings . TrimSpace ( parts [ 1 ] )
2022-08-28 03:38:00 +08:00
f , err := os . CreateTemp ( GOTMPDIR , "test.test-*" + GOEXE )
2019-11-11 11:08:20 -05:00
if err != nil {
return err
}
f . Close ( )
defer os . Remove ( f . Name ( ) )
cmd := t . dirCmd ( dir , t . goTest ( ) , "-c" , "-o" , f . Name ( ) , pkg )
2021-09-30 15:15:45 -04:00
setEnv ( cmd , "GOARCH" , gohostarch )
setEnv ( cmd , "GOOS" , gohostos )
2016-03-24 21:47:02 +01:00
if err := cmd . Run ( ) ; err != nil {
return err
}
2022-05-19 12:10:38 -07:00
return t . dirCmd ( dir , f . Name ( ) , "-test.short=" + short ( ) , "-test.timeout=" + t . timeoutDuration ( 300 ) . String ( ) ) . Run ( )
2016-03-24 21:47:02 +01:00
}
2015-12-21 16:08:57 -05:00
func ( t * tester ) cgoTest ( dt * distTest ) error {
2022-06-16 15:45:25 -04:00
cmd := t . addCmd ( dt , "misc/cgo/test" , t . goTest ( ) , "." )
2021-09-30 15:15:45 -04:00
setEnv ( cmd , "GOFLAGS" , "-ldflags=-linkmode=auto" )
2015-04-07 16:43:11 +10:00
2022-08-09 10:32:59 -04:00
// Stub out various buildmode=pie tests on alpine until 54354 resolved.
builderName := os . Getenv ( "GO_BUILDER_NAME" )
disablePIE := strings . HasSuffix ( builderName , "-alpine" )
2022-05-05 13:46:15 -04:00
if t . internalLink ( ) {
2022-06-16 15:45:25 -04:00
cmd := t . addCmd ( dt , "misc/cgo/test" , t . goTest ( ) , "-tags=internal" , "." )
2021-09-30 15:15:45 -04:00
setEnv ( cmd , "GOFLAGS" , "-ldflags=-linkmode=internal" )
2015-03-02 17:07:11 -08:00
}
2017-09-19 22:13:22 +09:00
pair := gohostos + "-" + goarch
2015-03-02 17:07:11 -08:00
switch pair {
2020-10-14 21:15:37 -04:00
case "darwin-amd64" , "darwin-arm64" ,
2015-06-29 13:12:10 -04:00
"windows-386" , "windows-amd64" :
2015-03-02 17:07:11 -08:00
// test linkmode=external, but __thread not supported, so skip testtls.
2015-06-29 13:12:10 -04:00
if ! t . extLink ( ) {
break
}
2022-06-16 15:45:25 -04:00
cmd := t . addCmd ( dt , "misc/cgo/test" , t . goTest ( ) , "." )
2021-09-30 15:15:45 -04:00
setEnv ( cmd , "GOFLAGS" , "-ldflags=-linkmode=external" )
2019-03-29 01:26:45 +11:00
2022-06-16 15:45:25 -04:00
t . addCmd ( dt , "misc/cgo/test" , t . goTest ( ) , "-ldflags" , "-linkmode=external -s" , "." )
2019-03-29 01:26:45 +11:00
2022-08-09 10:32:59 -04:00
if t . supportedBuildmode ( "pie" ) && ! disablePIE {
2022-06-16 15:45:25 -04:00
t . addCmd ( dt , "misc/cgo/test" , t . goTest ( ) , "-buildmode=pie" , "." )
2020-10-11 15:48:22 -04:00
if t . internalLink ( ) && t . internalLinkPIE ( ) {
2022-06-16 15:45:25 -04:00
t . addCmd ( dt , "misc/cgo/test" , t . goTest ( ) , "-buildmode=pie" , "-ldflags=-linkmode=internal" , "-tags=internal,internal_pie" , "." )
2020-10-11 15:48:22 -04:00
}
}
2019-02-21 10:56:35 +01:00
case "aix-ppc64" ,
2020-02-26 10:24:39 -05:00
"android-arm" , "android-arm64" ,
2017-11-23 10:16:02 +01:00
"dragonfly-amd64" ,
2015-03-02 17:07:11 -08:00
"freebsd-386" , "freebsd-amd64" , "freebsd-arm" ,
2020-05-19 18:56:01 +10:00
"linux-386" , "linux-amd64" , "linux-arm" , "linux-arm64" , "linux-ppc64le" , "linux-riscv64" , "linux-s390x" ,
2020-11-04 00:29:39 +11:00
"netbsd-386" , "netbsd-amd64" ,
"openbsd-386" , "openbsd-amd64" , "openbsd-arm" , "openbsd-arm64" , "openbsd-mips64" :
2015-03-02 17:07:11 -08:00
2022-06-16 15:45:25 -04:00
cmd := t . addCmd ( dt , "misc/cgo/test" , t . goTest ( ) , "." )
2021-09-30 15:15:45 -04:00
setEnv ( cmd , "GOFLAGS" , "-ldflags=-linkmode=external" )
2020-08-27 16:12:18 -04:00
// cgo should be able to cope with both -g arguments and colored
// diagnostics.
2021-09-30 15:15:45 -04:00
setEnv ( cmd , "CGO_CFLAGS" , "-g0 -fdiagnostics-color" )
2018-12-03 16:02:10 -08:00
2022-06-16 15:45:25 -04:00
t . addCmd ( dt , "misc/cgo/testtls" , t . goTest ( ) , "-ldflags" , "-linkmode=auto" , "." )
t . addCmd ( dt , "misc/cgo/testtls" , t . goTest ( ) , "-ldflags" , "-linkmode=external" , "." )
2015-03-02 17:07:11 -08:00
switch pair {
2019-02-21 10:56:35 +01:00
case "aix-ppc64" , "netbsd-386" , "netbsd-amd64" :
2015-03-02 17:07:11 -08:00
// no static linking
case "freebsd-arm" :
// -fPIC compiled tls code will use __tls_get_addr instead
// of __aeabi_read_tp, however, on FreeBSD/ARM, __tls_get_addr
// is implemented in rtld-elf, so -fPIC isn't compatible with
// static linking on FreeBSD/ARM with clang. (cgo depends on
// -fPIC fundamentally.)
default :
2017-11-14 15:50:38 -05:00
cmd := t . dirCmd ( "misc/cgo/test" ,
compilerEnvLookup ( defaultcc , goos , goarch ) , "-xc" , "-o" , "/dev/null" , "-static" , "-" )
cmd . Stdin = strings . NewReader ( "int main() {}" )
if err := cmd . Run ( ) ; err != nil {
fmt . Println ( "No support for static linking found (lacks libc.a?), skip cgo static linking test." )
} else {
if goos != "android" {
2022-06-16 15:45:25 -04:00
t . addCmd ( dt , "misc/cgo/testtls" , t . goTest ( ) , "-ldflags" , ` -linkmode=external -extldflags "-static -pthread" ` , "." )
2017-11-14 15:50:38 -05:00
}
2022-06-16 15:45:25 -04:00
t . addCmd ( dt , "misc/cgo/nocgo" , t . goTest ( ) , "." )
t . addCmd ( dt , "misc/cgo/nocgo" , t . goTest ( ) , "-ldflags" , ` -linkmode=external ` , "." )
2017-11-14 15:50:38 -05:00
if goos != "android" {
2022-06-16 15:45:25 -04:00
t . addCmd ( dt , "misc/cgo/nocgo" , t . goTest ( ) , "-ldflags" , ` -linkmode=external -extldflags "-static -pthread" ` , "." )
t . addCmd ( dt , "misc/cgo/test" , t . goTest ( ) , "-tags=static" , "-ldflags" , ` -linkmode=external -extldflags "-static -pthread" ` , "." )
2018-01-24 14:45:28 -08:00
// -static in CGO_LDFLAGS triggers a different code path
// than -static in -extldflags, so test both.
// See issue #16651.
2022-06-16 15:45:25 -04:00
cmd := t . addCmd ( dt , "misc/cgo/test" , t . goTest ( ) , "-tags=static" , "." )
2021-09-30 15:15:45 -04:00
setEnv ( cmd , "CGO_LDFLAGS" , "-static -pthread" )
2017-11-14 15:50:38 -05:00
}
}
2022-08-09 10:32:59 -04:00
if t . supportedBuildmode ( "pie" ) && ! disablePIE {
2022-06-16 15:45:25 -04:00
t . addCmd ( dt , "misc/cgo/test" , t . goTest ( ) , "-buildmode=pie" , "." )
2022-05-05 13:46:15 -04:00
if t . internalLink ( ) && t . internalLinkPIE ( ) {
2022-06-16 15:45:25 -04:00
t . addCmd ( dt , "misc/cgo/test" , t . goTest ( ) , "-buildmode=pie" , "-ldflags=-linkmode=internal" , "-tags=internal,internal_pie" , "." )
2020-02-09 17:01:53 -05:00
}
2022-06-16 15:45:25 -04:00
t . addCmd ( dt , "misc/cgo/testtls" , t . goTest ( ) , "-buildmode=pie" , "." )
t . addCmd ( dt , "misc/cgo/nocgo" , t . goTest ( ) , "-buildmode=pie" , "." )
2015-03-02 17:07:11 -08:00
}
}
}
return nil
}
2015-12-21 16:08:57 -05:00
// run pending test commands, in parallel, emitting headers as appropriate.
2015-12-21 20:42:40 -05:00
// When finished, emit header for nextTest, which is going to run after the
2015-12-21 16:08:57 -05:00
// pending commands are done (and runPending returns).
2015-12-21 20:42:40 -05:00
// A test should call runPending if it wants to make sure that it is not
// running in parallel with earlier tests, or if it has some other reason
// for needing the earlier tests to be done.
2015-12-21 16:08:57 -05:00
func ( t * tester ) runPending ( nextTest * distTest ) {
cmd/link: set runtime.GOROOT default during link
Suppose you build the Go toolchain in directory A,
move the whole thing to directory B, and then use
it from B to build a new program hello.exe, and then
run hello.exe, and hello.exe crashes with a stack
trace into the standard library.
Long ago, you'd have seen hello.exe print file names
in the A directory tree, even though the files had moved
to the B directory tree. About two years ago we changed
the compiler to write down these files with the name
"$GOROOT" (that literal string) instead of A, so that the
final link from B could replace "$GOROOT" with B,
so that hello.exe's crash would show the correct source
file paths in the stack trace. (golang.org/cl/18200)
Now suppose that you do the same thing but hello.exe
doesn't crash: it prints fmt.Println(runtime.GOROOT()).
And you run hello.exe after clearing $GOROOT from the
environment.
Long ago, you'd have seen hello.exe print A instead of B.
Before this CL, you'd still see hello.exe print A instead of B.
This case is the one instance where a moved toolchain
still divulges its origin. Not anymore. After this CL, hello.exe
will print B, because the linker sets runtime/internal/sys.DefaultGoroot
with the effective GOROOT from link time.
This makes the default result of runtime.GOROOT once again
match the file names recorded in the binary, after two years
of divergence.
With that cleared up, we can reintroduce GOROOT into the
link action ID and also reenable TestExecutableGOROOT/RelocatedExe.
When $GOROOT_FINAL is set during link, it is used
in preference to $GOROOT, as always, but it was easier
to explain the behavior above without introducing that
complication.
Fixes #22155.
Fixes #20284.
Fixes #22475.
Change-Id: Ifdaeb77fd4678fdb337cf59ee25b2cd873ec1016
Reviewed-on: https://go-review.googlesource.com/86835
Run-TryBot: Russ Cox <rsc@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Ian Lance Taylor <iant@golang.org>
2018-01-08 11:59:29 -05:00
checkNotStale ( "go" , "std" )
2015-12-21 16:08:57 -05:00
worklist := t . worklist
t . worklist = nil
for _ , w := range worklist {
w . start = make ( chan bool )
w . end = make ( chan bool )
go func ( w * work ) {
if ! <- w . start {
2017-10-27 13:07:38 -04:00
timelog ( "skip" , w . dt . name )
2015-12-21 16:08:57 -05:00
w . out = [ ] byte ( fmt . Sprintf ( "skipped due to earlier error\n" ) )
} else {
2017-10-27 13:07:38 -04:00
timelog ( "start" , w . dt . name )
2015-12-21 16:08:57 -05:00
w . out , w . err = w . cmd . CombinedOutput ( )
2019-02-02 10:27:37 +00:00
if w . err != nil {
if isUnsupportedVMASize ( w ) {
timelog ( "skip" , w . dt . name )
w . out = [ ] byte ( fmt . Sprintf ( "skipped due to unsupported VMA\n" ) )
w . err = nil
}
}
2015-12-21 16:08:57 -05:00
}
2017-10-27 13:07:38 -04:00
timelog ( "end" , w . dt . name )
2015-12-21 16:08:57 -05:00
w . end <- true
} ( w )
}
started := 0
ended := 0
var last * distTest
for ended < len ( worklist ) {
for started < len ( worklist ) && started - ended < maxbg {
w := worklist [ started ]
started ++
w . start <- ! t . failed || t . keepGoing
}
w := worklist [ ended ]
dt := w . dt
if dt . heading != "" && t . lastHeading != dt . heading {
t . lastHeading = dt . heading
t . out ( dt . heading )
}
if dt != last {
// Assumes all the entries for a single dt are in one worklist.
last = w . dt
if vflag > 0 {
fmt . Printf ( "# go tool dist test -run=^%s$\n" , dt . name )
}
}
if vflag > 1 {
errprintf ( "%s\n" , strings . Join ( w . cmd . Args , " " ) )
}
ended ++
<- w . end
os . Stdout . Write ( w . out )
if w . err != nil {
log . Printf ( "Failed: %v" , w . err )
t . failed = true
}
cmd/link: set runtime.GOROOT default during link
Suppose you build the Go toolchain in directory A,
move the whole thing to directory B, and then use
it from B to build a new program hello.exe, and then
run hello.exe, and hello.exe crashes with a stack
trace into the standard library.
Long ago, you'd have seen hello.exe print file names
in the A directory tree, even though the files had moved
to the B directory tree. About two years ago we changed
the compiler to write down these files with the name
"$GOROOT" (that literal string) instead of A, so that the
final link from B could replace "$GOROOT" with B,
so that hello.exe's crash would show the correct source
file paths in the stack trace. (golang.org/cl/18200)
Now suppose that you do the same thing but hello.exe
doesn't crash: it prints fmt.Println(runtime.GOROOT()).
And you run hello.exe after clearing $GOROOT from the
environment.
Long ago, you'd have seen hello.exe print A instead of B.
Before this CL, you'd still see hello.exe print A instead of B.
This case is the one instance where a moved toolchain
still divulges its origin. Not anymore. After this CL, hello.exe
will print B, because the linker sets runtime/internal/sys.DefaultGoroot
with the effective GOROOT from link time.
This makes the default result of runtime.GOROOT once again
match the file names recorded in the binary, after two years
of divergence.
With that cleared up, we can reintroduce GOROOT into the
link action ID and also reenable TestExecutableGOROOT/RelocatedExe.
When $GOROOT_FINAL is set during link, it is used
in preference to $GOROOT, as always, but it was easier
to explain the behavior above without introducing that
complication.
Fixes #22155.
Fixes #20284.
Fixes #22475.
Change-Id: Ifdaeb77fd4678fdb337cf59ee25b2cd873ec1016
Reviewed-on: https://go-review.googlesource.com/86835
Run-TryBot: Russ Cox <rsc@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Ian Lance Taylor <iant@golang.org>
2018-01-08 11:59:29 -05:00
checkNotStale ( "go" , "std" )
2015-12-21 16:08:57 -05:00
}
if t . failed && ! t . keepGoing {
2019-11-15 12:26:09 -05:00
fatalf ( "FAILED" )
2015-12-21 16:08:57 -05:00
}
if dt := nextTest ; dt != nil {
if dt . heading != "" && t . lastHeading != dt . heading {
t . lastHeading = dt . heading
t . out ( dt . heading )
}
if vflag > 0 {
fmt . Printf ( "# go tool dist test -run=^%s$\n" , dt . name )
}
}
}
2015-03-02 17:07:11 -08:00
func ( t * tester ) hasBash ( ) bool {
2017-09-19 22:13:22 +09:00
switch gohostos {
2015-03-02 17:07:11 -08:00
case "windows" , "plan9" :
return false
}
return true
}
2018-07-17 15:55:01 +00:00
func ( t * tester ) hasCxx ( ) bool {
cxx , _ := exec . LookPath ( compilerEnvLookup ( defaultcxx , goos , goarch ) )
return cxx != ""
}
2017-12-06 18:09:11 -08:00
func ( t * tester ) hasSwig ( ) bool {
swig , err := exec . LookPath ( "swig" )
if err != nil {
return false
}
2018-01-19 18:26:58 +01:00
// Check that swig was installed with Go support by checking
// that a go directory exists inside the swiglib directory.
// See https://golang.org/issue/23469.
output , err := exec . Command ( swig , "-go" , "-swiglib" ) . Output ( )
if err != nil {
return false
}
swigDir := strings . TrimSpace ( string ( output ) )
_ , err = os . Stat ( filepath . Join ( swigDir , "go" ) )
if err != nil {
return false
}
// Check that swig has a new enough version.
// See https://golang.org/issue/22858.
2017-12-06 18:09:11 -08:00
out , err := exec . Command ( swig , "-version" ) . CombinedOutput ( )
if err != nil {
return false
}
2022-09-27 04:18:15 +00:00
re := regexp . MustCompile ( ` [vV]ersion +(\d+)([.]\d+)?([.]\d+)? ` )
2017-12-06 18:09:11 -08:00
matches := re . FindSubmatch ( out )
if matches == nil {
// Can't find version number; hope for the best.
return true
}
major , err := strconv . Atoi ( string ( matches [ 1 ] ) )
if err != nil {
// Can't find version number; hope for the best.
return true
}
if major < 3 {
return false
}
if major > 3 {
// 4.0 or later
return true
}
// We have SWIG version 3.x.
if len ( matches [ 2 ] ) > 0 {
minor , err := strconv . Atoi ( string ( matches [ 2 ] [ 1 : ] ) )
if err != nil {
return true
}
if minor > 0 {
// 3.1 or later
return true
}
}
// We have SWIG version 3.0.x.
if len ( matches [ 3 ] ) > 0 {
patch , err := strconv . Atoi ( string ( matches [ 3 ] [ 1 : ] ) )
if err != nil {
return true
}
if patch < 6 {
// Before 3.0.6.
return false
}
}
return true
}
2015-03-02 17:07:11 -08:00
func ( t * tester ) raceDetectorSupported ( ) bool {
2018-06-29 21:14:47 -07:00
if gohostos != goos {
return false
2015-03-02 17:07:11 -08:00
}
2018-06-29 21:14:47 -07:00
if ! t . cgoEnabled {
return false
}
if ! raceDetectorSupported ( goos , goarch ) {
return false
}
// The race detector doesn't work on Alpine Linux:
// golang.org/issue/14481
if isAlpineLinux ( ) {
return false
}
2018-08-27 13:16:38 +00:00
// NetBSD support is unfinished.
// golang.org/issue/26403
if goos == "netbsd" {
return false
}
2018-06-29 21:14:47 -07:00
return true
2015-03-02 17:07:11 -08:00
}
2017-04-25 06:11:09 +00:00
func isAlpineLinux ( ) bool {
if runtime . GOOS != "linux" {
return false
}
fi , err := os . Lstat ( "/etc/alpine-release" )
return err == nil && fi . Mode ( ) . IsRegular ( )
}
2016-05-04 09:08:27 -07:00
func ( t * tester ) runFlag ( rx string ) string {
if t . compileOnly {
return "-run=^$"
}
return "-run=" + rx
}
2015-12-21 16:08:57 -05:00
func ( t * tester ) raceTest ( dt * distTest ) error {
2017-11-29 14:16:25 -05:00
t . addCmd ( dt , "src" , t . goTest ( ) , "-race" , t . runFlag ( "Output" ) , "runtime/race" )
2018-07-10 16:44:56 -07:00
t . addCmd ( dt , "src" , t . goTest ( ) , "-race" , t . runFlag ( "TestParse|TestEcho|TestStdinCloseRace|TestClosedPipeRace|TestTypeRace|TestFdRace|TestFdReadRace|TestFileCloseRace" ) , "flag" , "net" , "os" , "os/exec" , "encoding/gob" )
2016-02-16 07:13:10 -08:00
// We don't want the following line, because it
// slows down all.bash (by 10 seconds on my laptop).
// The race builder should catch any error here, but doesn't.
// TODO(iant): Figure out how to catch this.
2017-11-29 14:16:25 -05:00
// t.addCmd(dt, "src", t.goTest(), "-race", "-run=TestParallelTest", "cmd/go")
2016-10-28 17:12:39 +02:00
if t . cgoEnabled {
2019-05-15 20:49:39 -04:00
// Building misc/cgo/test takes a long time.
// There are already cgo-enabled packages being tested with the race detector.
// We shouldn't need to redo all of misc/cgo/test too.
// The race buildler will take care of this.
// cmd := t.addCmd(dt, "misc/cgo/test", t.goTest(), "-race")
2021-09-30 15:15:45 -04:00
// setEnv(cmd, "GOTRACEBACK", "2")
2015-07-22 15:31:54 -04:00
}
2015-03-02 17:07:11 -08:00
if t . extLink ( ) {
// Test with external linking; see issue 9133.
2017-11-29 14:16:25 -05:00
t . addCmd ( dt , "src" , t . goTest ( ) , "-race" , "-ldflags=-linkmode=external" , t . runFlag ( "TestParse|TestEcho|TestStdinCloseRace" ) , "flag" , "os/exec" )
2015-03-02 17:07:11 -08:00
}
return nil
}
2015-12-21 20:42:40 -05:00
var runtest struct {
sync . Once
exe string
err error
}
2015-12-21 16:08:57 -05:00
func ( t * tester ) testDirTest ( dt * distTest , shard , shards int ) error {
2015-12-21 20:42:40 -05:00
runtest . Do ( func ( ) {
2022-08-28 03:38:00 +08:00
f , err := os . CreateTemp ( "" , "runtest-*.exe" ) // named exe for Windows, but harmless elsewhere
2019-11-18 13:58:58 +00:00
if err != nil {
2015-12-21 20:42:40 -05:00
runtest . err = err
return
}
2019-11-18 13:58:58 +00:00
f . Close ( )
runtest . exe = f . Name ( )
2015-12-21 20:42:40 -05:00
xatexit ( func ( ) {
os . Remove ( runtest . exe )
} )
2019-11-18 13:58:58 +00:00
cmd := t . dirCmd ( "test" , "go" , "build" , "-o" , runtest . exe , "run.go" )
2021-09-30 15:15:45 -04:00
setEnv ( cmd , "GOOS" , gohostos )
setEnv ( cmd , "GOARCH" , gohostarch )
2019-11-18 13:58:58 +00:00
runtest . err = cmd . Run ( )
2015-12-21 20:42:40 -05:00
} )
if runtest . err != nil {
return runtest . err
2015-03-02 17:07:11 -08:00
}
2016-05-04 09:08:27 -07:00
if t . compileOnly {
return nil
}
2015-12-21 20:42:40 -05:00
t . addCmd ( dt , "test" , runtest . exe ,
2015-06-03 23:21:30 -07:00
fmt . Sprintf ( "--shard=%d" , shard ) ,
fmt . Sprintf ( "--shards=%d" , shards ) ,
2015-12-21 20:42:40 -05:00
)
return nil
2015-03-02 17:07:11 -08:00
}
2015-11-16 18:11:35 -08:00
// cgoPackages is the standard packages that use cgo.
var cgoPackages = [ ] string {
"net" ,
"os/user" ,
}
2016-09-14 16:34:27 +00:00
var funcBenchmark = [ ] byte ( "\nfunc Benchmark" )
// packageHasBenchmarks reports whether pkg has benchmarks.
// On any error, it conservatively returns true.
//
// This exists just to eliminate work on the builders, since compiling
// a test in race mode just to discover it has no benchmarks costs a
// second or two per package, and this function returns false for
// about 100 packages.
func ( t * tester ) packageHasBenchmarks ( pkg string ) bool {
2017-09-19 22:13:22 +09:00
pkgDir := filepath . Join ( goroot , "src" , pkg )
2016-09-14 16:34:27 +00:00
d , err := os . Open ( pkgDir )
if err != nil {
return true // conservatively
}
defer d . Close ( )
names , err := d . Readdirnames ( - 1 )
if err != nil {
return true // conservatively
}
for _ , name := range names {
if ! strings . HasSuffix ( name , "_test.go" ) {
continue
}
2022-08-28 03:38:00 +08:00
slurp , err := os . ReadFile ( filepath . Join ( pkgDir , name ) )
2016-09-14 16:34:27 +00:00
if err != nil {
return true // conservatively
}
if bytes . Contains ( slurp , funcBenchmark ) {
return true
}
}
return false
}
2018-06-29 21:14:47 -07:00
2019-02-22 20:16:24 +00:00
// makeGOROOTUnwritable makes all $GOROOT files & directories non-writable to
// check that no tests accidentally write to $GOROOT.
2019-11-12 10:18:06 -05:00
func ( t * tester ) makeGOROOTUnwritable ( ) ( undo func ( ) ) {
dir := os . Getenv ( "GOROOT" )
if dir == "" {
2019-02-22 20:16:24 +00:00
panic ( "GOROOT not set" )
}
2019-11-12 10:18:06 -05:00
type pathMode struct {
path string
mode os . FileMode
}
var dirs [ ] pathMode // in lexical order
undo = func ( ) {
for i := range dirs {
os . Chmod ( dirs [ i ] . path , dirs [ i ] . mode ) // best effort
2019-02-22 20:16:24 +00:00
}
2019-11-12 10:18:06 -05:00
}
2019-11-15 16:19:11 -05:00
gocache := os . Getenv ( "GOCACHE" )
if gocache == "" {
panic ( "GOCACHE not set" )
}
gocacheSubdir , _ := filepath . Rel ( dir , gocache )
2020-11-04 18:20:17 -05:00
// Note: Can't use WalkDir here, because this has to compile with Go 1.4.
2019-11-12 10:18:06 -05:00
filepath . Walk ( dir , func ( path string , info os . FileInfo , err error ) error {
2019-11-15 16:19:11 -05:00
if suffix := strings . TrimPrefix ( path , dir + string ( filepath . Separator ) ) ; suffix != "" {
if suffix == gocacheSubdir {
// Leave GOCACHE writable: we may need to write test binaries into it.
return filepath . SkipDir
}
if suffix == ".git" {
// Leave Git metadata in whatever state it was in. It may contain a lot
// of files, and it is highly unlikely that a test will try to modify
// anything within that directory.
return filepath . SkipDir
}
}
2019-11-12 10:18:06 -05:00
if err == nil {
mode := info . Mode ( )
if mode & 0222 != 0 && ( mode . IsDir ( ) || mode . IsRegular ( ) ) {
dirs = append ( dirs , pathMode { path , mode } )
2019-02-22 20:16:24 +00:00
}
}
return nil
} )
2019-11-12 10:18:06 -05:00
// Run over list backward to chmod children before parents.
for i := len ( dirs ) - 1 ; i >= 0 ; i -- {
err := os . Chmod ( dirs [ i ] . path , dirs [ i ] . mode &^ 0222 )
if err != nil {
dirs = dirs [ i : ] // Only undo what we did so far.
undo ( )
2019-11-15 12:26:09 -05:00
fatalf ( "failed to make GOROOT read-only: %v" , err )
2019-11-12 10:18:06 -05:00
}
2019-02-22 20:16:24 +00:00
}
2019-11-12 10:18:06 -05:00
return undo
2019-02-22 20:16:24 +00:00
}
2019-05-21 19:02:00 +00:00
// shouldUsePrecompiledStdTest reports whether "dist test" should use
// a pre-compiled go test binary on disk rather than running "go test"
// and compiling it again. This is used by our slow qemu-based builder
// that do full processor emulation where we cross-compile the
// make.bash step as well as pre-compile each std test binary.
//
// This only reports true if dist is run with an single go_test:foo
// argument (as the build coordinator does with our slow qemu-based
// builders), we're in a builder environment ("GO_BUILDER_NAME" is set),
// and the pre-built test binary exists.
func ( t * tester ) shouldUsePrecompiledStdTest ( ) bool {
bin := t . prebuiltGoPackageTestBinary ( )
if bin == "" {
return false
}
_ , err := os . Stat ( bin )
return err == nil
}
2019-10-29 17:03:56 +00:00
func ( t * tester ) shouldTestCmd ( ) bool {
if goos == "js" && goarch == "wasm" {
// Issues 25911, 35220
return false
}
return true
}
2019-05-21 19:02:00 +00:00
// prebuiltGoPackageTestBinary returns the path where we'd expect
// the pre-built go test binary to be on disk when dist test is run with
// a single argument.
// It returns an empty string if a pre-built binary should not be used.
func ( t * tester ) prebuiltGoPackageTestBinary ( ) string {
if len ( stdMatches ) != 1 || t . race || t . compileOnly || os . Getenv ( "GO_BUILDER_NAME" ) == "" {
return ""
}
pkg := stdMatches [ 0 ]
return filepath . Join ( os . Getenv ( "GOROOT" ) , "src" , pkg , path . Base ( pkg ) + ".test" )
}
// runPrecompiledStdTest runs the pre-compiled standard library package test binary.
// See shouldUsePrecompiledStdTest above; it must return true for this to be called.
func ( t * tester ) runPrecompiledStdTest ( timeout time . Duration ) error {
bin := t . prebuiltGoPackageTestBinary ( )
fmt . Fprintf ( os . Stderr , "# %s: using pre-built %s...\n" , stdMatches [ 0 ] , bin )
2020-05-13 13:57:36 -04:00
cmd := exec . Command ( bin , "-test.short=" + short ( ) , "-test.timeout=" + timeout . String ( ) )
2021-09-30 15:15:45 -04:00
setDir ( cmd , filepath . Dir ( bin ) )
2019-05-21 19:02:00 +00:00
cmd . Stdout = os . Stdout
cmd . Stderr = os . Stderr
if err := cmd . Start ( ) ; err != nil {
return err
}
// And start a timer to kill the process if it doesn't kill
// itself in the prescribed timeout.
const backupKillFactor = 1.05 // add 5%
timer := time . AfterFunc ( time . Duration ( float64 ( timeout ) * backupKillFactor ) , func ( ) {
fmt . Fprintf ( os . Stderr , "# %s: timeout running %s; killing...\n" , stdMatches [ 0 ] , bin )
cmd . Process . Kill ( )
} )
defer timer . Stop ( )
return cmd . Wait ( )
}
2018-06-29 21:14:47 -07:00
// raceDetectorSupported is a copy of the function
// cmd/internal/sys.RaceDetectorSupported, which can't be used here
// because cmd/dist has to be buildable by Go 1.4.
2019-02-02 10:27:37 +00:00
// The race detector only supports 48-bit VMA on arm64. But we don't have
// a good solution to check VMA size(See https://golang.org/issue/29948)
// raceDetectorSupported will always return true for arm64. But race
// detector tests may abort on non 48-bit VMA configuration, the tests
// will be marked as "skipped" in this case.
2018-06-29 21:14:47 -07:00
func raceDetectorSupported ( goos , goarch string ) bool {
switch goos {
2018-09-11 14:27:41 +02:00
case "linux" :
2022-07-21 15:11:13 -04:00
return goarch == "amd64" || goarch == "ppc64le" || goarch == "arm64" || goarch == "s390x"
2020-10-29 11:27:17 -04:00
case "darwin" :
return goarch == "amd64" || goarch == "arm64"
2020-12-08 04:14:34 +11:00
case "freebsd" , "netbsd" , "openbsd" , "windows" :
2018-09-11 14:27:41 +02:00
return goarch == "amd64"
2018-06-29 21:14:47 -07:00
default :
return false
}
}
2019-02-02 10:27:37 +00:00
// isUnsupportedVMASize reports whether the failure is caused by an unsupported
// VMA for the race detector (for example, running the race detector on an
// arm64 machine configured with 39-bit VMA)
func isUnsupportedVMASize ( w * work ) bool {
unsupportedVMA := [ ] byte ( "unsupported VMA range" )
return w . dt . name == "race" && bytes . Contains ( w . out , unsupportedVMA )
}
cmd/dist,cmd/go: set GOTRACEBACK to "system" for testing
If we're testing through dist, we're testing the implementation of Go,
so we're interested in any package failing with potential runtime
issues. In these cases, we'd like to have as much relevant detail as
possible, but currently runtime stack frames and goroutines are
suppressed due to the default GOTRACEBACK setting.
So, try to set GOTRACEBACK to system if it's unset. Check if it's unset
first so we don't override the user asking for a lower or higher level.
This change was brought up in the context of #45916, since there's an
apparent deadlock (or something!) in the runtime that appears when
running other code, but it's difficult to see exactly where it's
blocked. However, this change is very generally useful.
This change also runs scripted tests with GOTRACEBACK=system, upgrading
from GOTRACEBACK=all. Often, script tests can trigger failures deep in
the runtime in interesting ways because they start many individual Go
processes, so being able to identify points of interest in the runtime
is quite useful.
For #45916.
Change-Id: I3d50658d0d0090fb4c9182b87200d266c7f8f915
Reviewed-on: https://go-review.googlesource.com/c/go/+/316469
Trust: Michael Knyszek <mknyszek@google.com>
Trust: Bryan C. Mills <bcmills@google.com>
Run-TryBot: Michael Knyszek <mknyszek@google.com>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Dmitri Shuralyov <dmitshur@golang.org>
2021-05-03 18:11:55 +00:00
// isEnvSet reports whether the environment variable evar is
// set in the environment.
func isEnvSet ( evar string ) bool {
evarEq := evar + "="
for _ , e := range os . Environ ( ) {
if strings . HasPrefix ( e , evarEq ) {
return true
}
}
return false
}