summaryrefslogtreecommitdiff
path: root/libgo/go/runtime/crash_test.go
diff options
context:
space:
mode:
Diffstat (limited to 'libgo/go/runtime/crash_test.go')
-rw-r--r--libgo/go/runtime/crash_test.go112
1 files changed, 51 insertions, 61 deletions
diff --git a/libgo/go/runtime/crash_test.go b/libgo/go/runtime/crash_test.go
index e3633af7ccf..6e794494c1f 100644
--- a/libgo/go/runtime/crash_test.go
+++ b/libgo/go/runtime/crash_test.go
@@ -6,6 +6,7 @@ package runtime_test
import (
"bytes"
+ "errors"
"flag"
"fmt"
"internal/testenv"
@@ -14,11 +15,9 @@ import (
"path/filepath"
"regexp"
"runtime"
- "strconv"
"strings"
"sync"
"testing"
- "time"
)
var toRemove []string
@@ -34,12 +33,13 @@ func TestMain(m *testing.M) {
var testprog struct {
sync.Mutex
dir string
- target map[string]buildexe
+ target map[string]*buildexe
}
type buildexe struct {
- exe string
- err error
+ once sync.Once
+ exe string
+ err error
}
func runTestProg(t *testing.T, binary, name string, env ...string) string {
@@ -69,52 +69,19 @@ func runBuiltTestProg(t *testing.T, exe, name string, env ...string) string {
if testing.Short() {
cmd.Env = append(cmd.Env, "RUNTIME_TEST_SHORT=1")
}
- var b bytes.Buffer
- cmd.Stdout = &b
- cmd.Stderr = &b
- if err := cmd.Start(); err != nil {
- t.Fatalf("starting %s %s: %v", exe, name, err)
- }
-
- // If the process doesn't complete within 1 minute,
- // assume it is hanging and kill it to get a stack trace.
- p := cmd.Process
- done := make(chan bool)
- go func() {
- scale := 1
- // This GOARCH/GOOS test is copied from cmd/dist/test.go.
- // TODO(iant): Have cmd/dist update the environment variable.
- if runtime.GOARCH == "arm" || runtime.GOOS == "windows" {
- scale = 2
- }
- if s := os.Getenv("GO_TEST_TIMEOUT_SCALE"); s != "" {
- if sc, err := strconv.Atoi(s); err == nil {
- scale = sc
- }
- }
-
- select {
- case <-done:
- case <-time.After(time.Duration(scale) * time.Minute):
- p.Signal(sigquit)
- }
- }()
-
- if err := cmd.Wait(); err != nil {
- t.Logf("%s %s exit status: %v", exe, name, err)
- }
- close(done)
-
- return b.String()
+ out, _ := testenv.RunWithTimeout(t, cmd)
+ return string(out)
}
+var serializeBuild = make(chan bool, 2)
+
func buildTestProg(t *testing.T, binary string, flags ...string) (string, error) {
if *flagQuick {
t.Skip("-quick")
}
+ testenv.MustHaveGoBuild(t)
testprog.Lock()
- defer testprog.Unlock()
if testprog.dir == "" {
dir, err := os.MkdirTemp("", "go-build")
if err != nil {
@@ -125,29 +92,48 @@ func buildTestProg(t *testing.T, binary string, flags ...string) (string, error)
}
if testprog.target == nil {
- testprog.target = make(map[string]buildexe)
+ testprog.target = make(map[string]*buildexe)
}
name := binary
if len(flags) > 0 {
name += "_" + strings.Join(flags, "_")
}
target, ok := testprog.target[name]
- if ok {
- return target.exe, target.err
- }
-
- exe := filepath.Join(testprog.dir, name+".exe")
- cmd := exec.Command(testenv.GoToolPath(t), append([]string{"build", "-o", exe}, flags...)...)
- cmd.Dir = "testdata/" + binary
- out, err := testenv.CleanCmdEnv(cmd).CombinedOutput()
- if err != nil {
- target.err = fmt.Errorf("building %s %v: %v\n%s", binary, flags, err, out)
+ if !ok {
+ target = &buildexe{}
testprog.target[name] = target
- return "", target.err
}
- target.exe = exe
- testprog.target[name] = target
- return exe, nil
+
+ dir := testprog.dir
+
+ // Unlock testprog while actually building, so that other
+ // tests can look up executables that were already built.
+ testprog.Unlock()
+
+ target.once.Do(func() {
+ // Only do two "go build"'s at a time,
+ // to keep load from getting too high.
+ serializeBuild <- true
+ defer func() { <-serializeBuild }()
+
+ // Don't get confused if testenv.GoToolPath calls t.Skip.
+ target.err = errors.New("building test called t.Skip")
+
+ exe := filepath.Join(dir, name+".exe")
+
+ t.Logf("running go build -o %s %s", exe, strings.Join(flags, " "))
+ cmd := exec.Command(testenv.GoToolPath(t), append([]string{"build", "-o", exe}, flags...)...)
+ cmd.Dir = "testdata/" + binary
+ out, err := testenv.CleanCmdEnv(cmd).CombinedOutput()
+ if err != nil {
+ target.err = fmt.Errorf("building %s %v: %v\n%s", binary, flags, err, out)
+ } else {
+ target.exe = exe
+ target.err = nil
+ }
+ })
+
+ return target.exe, target.err
}
func TestVDSO(t *testing.T) {
@@ -421,7 +407,7 @@ func TestRuntimePanicWithRuntimeError(t *testing.T) {
}
}
-func panicValue(fn func()) (recovered interface{}) {
+func panicValue(fn func()) (recovered any) {
defer func() {
recovered = recover()
}()
@@ -722,9 +708,13 @@ func TestTimePprof(t *testing.T) {
if runtime.Compiler == "gccgo" {
t.Skip("gccgo may not have the pprof tool")
}
- if runtime.GOOS == "aix" {
- t.Skip("pprof not yet available on AIX (see golang.org/issue/28555)")
+ // This test is unreliable on any system in which nanotime
+ // calls into libc.
+ switch runtime.GOOS {
+ case "aix", "darwin", "illumos", "openbsd", "solaris":
+ t.Skipf("skipping on %s because nanotime calls libc", runtime.GOOS)
}
+
// Pass GOTRACEBACK for issue #41120 to try to get more
// information on timeout.
fn := runTestProg(t, "testprog", "TimeProf", "GOTRACEBACK=crash")