--- /dev/null
+// Copyright 2017 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package gc
+
+import (
+ "bytes"
+ "internal/testenv"
+ "os/exec"
+ "testing"
+)
+
+// TestIntendedInlining tests that specific runtime functions are inlined.
+// This allows refactoring for code clarity and re-use without fear that
+// changes to the compiler will cause silent performance regressions.
+func TestIntendedInlining(t *testing.T) {
+ if testing.Short() && testenv.Builder() == "" {
+ t.Skip("skipping in short mode")
+ }
+ testenv.MustHaveGoRun(t)
+ t.Parallel()
+
+ // want is the list of function names that should be inlined.
+ want := []string{"tophash", "add", "(*bmap).keys", "bucketShift", "bucketMask"}
+
+ m := make(map[string]bool, len(want))
+ for _, s := range want {
+ m[s] = true
+ }
+
+ cmd := testenv.CleanCmdEnv(exec.Command(testenv.GoToolPath(t), "build", "-a", "-gcflags=-m", "runtime"))
+ out, err := cmd.CombinedOutput()
+ if err != nil {
+ t.Logf("%s", out)
+ t.Fatal(err)
+ }
+ lines := bytes.Split(out, []byte{'\n'})
+ for _, x := range lines {
+ f := bytes.Split(x, []byte(": can inline "))
+ if len(f) < 2 {
+ continue
+ }
+ fn := bytes.TrimSpace(f[1])
+ delete(m, string(fn))
+ }
+
+ for s := range m {
+ t.Errorf("function %s not inlined", s)
+ }
+}
t.Skip("skipping test on builder known to have frequent network failures")
}
}
+
+// CleanCmdEnv will fill cmd.Env with the environment, excluding certain
+// variables that could modify the behavior of the Go tools such as
+// GODEBUG and GOTRACEBACK.
+func CleanCmdEnv(cmd *exec.Cmd) *exec.Cmd {
+ if cmd.Env != nil {
+ panic("environment already set")
+ }
+ for _, env := range os.Environ() {
+ // Exclude GODEBUG from the environment to prevent its output
+ // from breaking tests that are trying to parse other command output.
+ if strings.HasPrefix(env, "GODEBUG=") {
+ continue
+ }
+ // Exclude GOTRACEBACK for the same reason.
+ if strings.HasPrefix(env, "GOTRACEBACK=") {
+ continue
+ }
+ cmd.Env = append(cmd.Env, env)
+ }
+ return cmd
+}
t.Fatal(err)
}
- got, err := testEnv(exec.Command(exe, "CgoExternalThreadSIGPROF")).CombinedOutput()
+ got, err := testenv.CleanCmdEnv(exec.Command(exe, "CgoExternalThreadSIGPROF")).CombinedOutput()
if err != nil {
t.Fatalf("exit status: %v\n%s", err, got)
}
t.Fatal(err)
}
- got, err := testEnv(exec.Command(exe, "CgoExternalThreadSIGPROF")).CombinedOutput()
+ got, err := testenv.CleanCmdEnv(exec.Command(exe, "CgoExternalThreadSIGPROF")).CombinedOutput()
if err != nil {
t.Fatalf("exit status: %v\n%s", err, got)
}
const tries = 10
var tot1, tot2 time.Duration
for i := 0; i < tries; i++ {
- cmd := testEnv(exec.Command(exe, "CgoCheckBytes"))
+ cmd := testenv.CleanCmdEnv(exec.Command(exe, "CgoCheckBytes"))
cmd.Env = append(cmd.Env, "GODEBUG=cgocheck=0", fmt.Sprintf("GO_CGOCHECKBYTES_TRY=%d", i))
start := time.Now()
cmd.Run()
d1 := time.Since(start)
- cmd = testEnv(exec.Command(exe, "CgoCheckBytes"))
+ cmd = testenv.CleanCmdEnv(exec.Command(exe, "CgoCheckBytes"))
cmd.Env = append(cmd.Env, fmt.Sprintf("GO_CGOCHECKBYTES_TRY=%d", i))
start = time.Now()
t.Fatal(err)
}
- got, err := testEnv(exec.Command(exe, runArg)).CombinedOutput()
+ got, err := testenv.CleanCmdEnv(exec.Command(exe, runArg)).CombinedOutput()
if err != nil {
if testenv.Builder() == "linux-amd64-alpine" {
// See Issue 18243 and Issue 19938.
defer os.Remove(fn)
for try := 0; try < 2; try++ {
- cmd := testEnv(exec.Command(testenv.GoToolPath(t), "tool", "pprof", "-top", "-nodecount=1"))
+ cmd := testenv.CleanCmdEnv(exec.Command(testenv.GoToolPath(t), "tool", "pprof", "-top", "-nodecount=1"))
// Check that pprof works both with and without explicit executable on command line.
if try == 0 {
cmd.Args = append(cmd.Args, exe, fn)
t.Fatal(err)
}
- got, err := testEnv(exec.Command(exe, "CgoRaceprof")).CombinedOutput()
+ got, err := testenv.CleanCmdEnv(exec.Command(exe, "CgoRaceprof")).CombinedOutput()
if err != nil {
t.Fatal(err)
}
t.Fatal(err)
}
- got, err := testEnv(exec.Command(exe, "CgoRaceSignal")).CombinedOutput()
+ got, err := testenv.CleanCmdEnv(exec.Command(exe, "CgoRaceSignal")).CombinedOutput()
if err != nil {
t.Logf("%s\n", got)
t.Fatal(err)
}
for _, early := range []bool{true, false} {
- cmd := testEnv(exec.Command(exe, "CgoCatchPanic"))
+ cmd := testenv.CleanCmdEnv(exec.Command(exe, "CgoCatchPanic"))
// Make sure a panic results in a crash.
cmd.Env = append(cmd.Env, "GOTRACEBACK=crash")
if early {
os.Exit(status)
}
-func testEnv(cmd *exec.Cmd) *exec.Cmd {
- if cmd.Env != nil {
- panic("environment already set")
- }
- for _, env := range os.Environ() {
- // Exclude GODEBUG from the environment to prevent its output
- // from breaking tests that are trying to parse other command output.
- if strings.HasPrefix(env, "GODEBUG=") {
- continue
- }
- // Exclude GOTRACEBACK for the same reason.
- if strings.HasPrefix(env, "GOTRACEBACK=") {
- continue
- }
- cmd.Env = append(cmd.Env, env)
- }
- return cmd
-}
-
var testprog struct {
sync.Mutex
dir string
t.Fatal(err)
}
- cmd := testEnv(exec.Command(exe, name))
+ cmd := testenv.CleanCmdEnv(exec.Command(exe, name))
var b bytes.Buffer
cmd.Stdout = &b
cmd.Stderr = &b
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(cmd).CombinedOutput()
+ out, err := testenv.CleanCmdEnv(cmd).CombinedOutput()
if err != nil {
target.err = fmt.Errorf("building %s %v: %v\n%s", binary, flags, err, out)
testprog.target[name] = target
func checkStaleRuntime(t *testing.T) {
staleRuntimeOnce.Do(func() {
// 'go run' uses the installed copy of runtime.a, which may be out of date.
- out, err := testEnv(exec.Command(testenv.GoToolPath(t), "list", "-f", "{{.Stale}}", "runtime")).CombinedOutput()
+ out, err := testenv.CleanCmdEnv(exec.Command(testenv.GoToolPath(t), "list", "-f", "{{.Stale}}", "runtime")).CombinedOutput()
if err != nil {
staleRuntimeErr = fmt.Errorf("failed to execute 'go list': %v\n%v", err, string(out))
return
}
if string(out) != "false\n" {
t.Logf("go list -f {{.Stale}} runtime:\n%s", out)
- out, err := testEnv(exec.Command(testenv.GoToolPath(t), "list", "-f", "{{.StaleReason}}", "runtime")).CombinedOutput()
+ out, err := testenv.CleanCmdEnv(exec.Command(testenv.GoToolPath(t), "list", "-f", "{{.StaleReason}}", "runtime")).CombinedOutput()
if err != nil {
t.Logf("go list -f {{.StaleReason}} failed: %v", err)
}
t.Fatal(err)
}
- got, err := testEnv(exec.Command(exe, "MemProf")).CombinedOutput()
+ got, err := testenv.CleanCmdEnv(exec.Command(exe, "MemProf")).CombinedOutput()
if err != nil {
t.Fatal(err)
}
defer os.Remove(fn)
for try := 0; try < 2; try++ {
- cmd := testEnv(exec.Command(testenv.GoToolPath(t), "tool", "pprof", "-alloc_space", "-top"))
+ cmd := testenv.CleanCmdEnv(exec.Command(testenv.GoToolPath(t), "tool", "pprof", "-alloc_space", "-top"))
// Check that pprof works both with and without explicit executable on command line.
if try == 0 {
cmd.Args = append(cmd.Args, exe, fn)
const tries = 10
retry:
for i := 0; i < tries; i++ {
- got, err := testEnv(exec.Command(exe, "PanicRace")).CombinedOutput()
+ got, err := testenv.CleanCmdEnv(exec.Command(exe, "PanicRace")).CombinedOutput()
if err == nil {
t.Logf("try %d: program exited successfully, should have failed", i+1)
continue
cmd := exec.Command(testenv.GoToolPath(t), "build", "-o", "a.exe")
cmd.Dir = dir
- out, err := testEnv(cmd).CombinedOutput()
+ out, err := testenv.CleanCmdEnv(cmd).CombinedOutput()
if err != nil {
t.Fatalf("building source: %v\n%s", err, out)
}
cmd = exec.Command(filepath.Join(dir, "a.exe"))
- cmd = testEnv(cmd)
+ cmd = testenv.CleanCmdEnv(cmd)
cmd.Env = append(cmd.Env, "GOTRACEBACK=crash")
// Set GOGC=off. Because of golang.org/issue/10958, the tight
t.Parallel()
cmd := exec.Command(os.Args[0], "testPanicSystemstackInternal")
- cmd = testEnv(cmd)
+ cmd = testenv.CleanCmdEnv(cmd)
cmd.Env = append(cmd.Env, "GOTRACEBACK=crash")
pr, pw, err := os.Pipe()
if err != nil {
if err != nil {
t.Fatal(err)
}
- err = testEnv(exec.Command(exe, "SignalExitStatus")).Run()
+ err = testenv.CleanCmdEnv(exec.Command(exe, "SignalExitStatus")).Run()
if err == nil {
t.Error("test program succeeded unexpectedly")
} else if ee, ok := err.(*exec.ExitError); !ok {
cmd := exec.Command(testenv.GoToolPath(t), "build", "-o", "a.exe")
cmd.Dir = dir
- out, err := testEnv(cmd).CombinedOutput()
+ out, err := testenv.CleanCmdEnv(cmd).CombinedOutput()
if err != nil {
t.Fatalf("building source %v\n%s", err, out)
}
}
cmd := exec.Command(testenv.GoToolPath(t), "build", "-o", "a.exe")
cmd.Dir = dir
- out, err := testEnv(cmd).CombinedOutput()
+ out, err := testenv.CleanCmdEnv(cmd).CombinedOutput()
if err != nil {
t.Fatalf("building source %v\n%s", err, out)
}
}
cmd := exec.Command(testenv.GoToolPath(t), "build", "-gcflags=-N -l", "-o", "a.exe")
cmd.Dir = dir
- out, err := testEnv(cmd).CombinedOutput()
+ out, err := testenv.CleanCmdEnv(cmd).CombinedOutput()
if err != nil {
t.Fatalf("building source %v\n%s", err, out)
}
package runtime_test
import (
- "bytes"
- "internal/testenv"
"io"
- "os/exec"
. "runtime"
"runtime/debug"
"strings"
t.Fatalf("cr/nl in version: %q", vers)
}
}
-
-// TestIntendedInlining tests that specific runtime functions are inlined.
-// This allows refactoring for code clarity and re-use without fear that
-// changes to the compiler will cause silent performance regressions.
-func TestIntendedInlining(t *testing.T) {
- if testing.Short() && testenv.Builder() == "" {
- t.Skip("skipping in short mode")
- }
- testenv.MustHaveGoRun(t)
- t.Parallel()
-
- // want is the list of function names that should be inlined.
- want := []string{"tophash", "add", "(*bmap).keys", "bucketShift", "bucketMask"}
-
- m := make(map[string]bool, len(want))
- for _, s := range want {
- m[s] = true
- }
-
- cmd := testEnv(exec.Command(testenv.GoToolPath(t), "build", "-a", "-gcflags=-m", "runtime"))
- out, err := cmd.CombinedOutput()
- if err != nil {
- t.Logf("%s", out)
- t.Fatal(err)
- }
- lines := bytes.Split(out, []byte{'\n'})
- for _, x := range lines {
- f := bytes.Split(x, []byte(": can inline "))
- if len(f) < 2 {
- continue
- }
- fn := bytes.TrimSpace(f[1])
- delete(m, string(fn))
- }
-
- for s := range m {
- t.Errorf("function %s not inlined", s)
- }
-}