summaryrefslogtreecommitdiff
path: root/src/pkg/runtime/crash_test.go
diff options
context:
space:
mode:
Diffstat (limited to 'src/pkg/runtime/crash_test.go')
-rw-r--r--src/pkg/runtime/crash_test.go83
1 files changed, 69 insertions, 14 deletions
diff --git a/src/pkg/runtime/crash_test.go b/src/pkg/runtime/crash_test.go
index 929d4a963..5476924bb 100644
--- a/src/pkg/runtime/crash_test.go
+++ b/src/pkg/runtime/crash_test.go
@@ -14,7 +14,7 @@ import (
"text/template"
)
-// testEnv excludes GOGCTRACE from the environment
+// testEnv excludes GODEBUG from the environment
// to prevent its output from breaking tests that
// are trying to parse other command output.
func testEnv(cmd *exec.Cmd) *exec.Cmd {
@@ -22,7 +22,7 @@ func testEnv(cmd *exec.Cmd) *exec.Cmd {
panic("environment already set")
}
for _, env := range os.Environ() {
- if strings.HasPrefix(env, "GOGCTRACE=") {
+ if strings.HasPrefix(env, "GODEBUG=") {
continue
}
cmd.Env = append(cmd.Env, env)
@@ -44,14 +44,16 @@ func executeTest(t *testing.T, templ string, data interface{}) string {
src := filepath.Join(dir, "main.go")
f, err := os.Create(src)
if err != nil {
- t.Fatalf("failed to create %v: %v", src, err)
+ t.Fatalf("failed to create file: %v", err)
}
err = st.Execute(f, data)
if err != nil {
f.Close()
t.Fatalf("failed to execute template: %v", err)
}
- f.Close()
+ if err := f.Close(); err != nil {
+ t.Fatalf("failed to close file: %v", err)
+ }
got, _ := testEnv(exec.Command("go", "run", src)).CombinedOutput()
return string(got)
@@ -72,10 +74,10 @@ func testCrashHandler(t *testing.T, cgo bool) {
type crashTest struct {
Cgo bool
}
- got := executeTest(t, crashSource, &crashTest{Cgo: cgo})
+ output := executeTest(t, crashSource, &crashTest{Cgo: cgo})
want := "main: recovered done\nnew-thread: recovered done\nsecond-new-thread: recovered done\nmain-again: recovered done\n"
- if got != want {
- t.Fatalf("expected %q, but got %q", want, got)
+ if output != want {
+ t.Fatalf("output:\n%s\n\nwanted:\n%s", output, want)
}
}
@@ -84,10 +86,10 @@ func TestCrashHandler(t *testing.T) {
}
func testDeadlock(t *testing.T, source string) {
- got := executeTest(t, source, nil)
+ output := executeTest(t, source, nil)
want := "fatal error: all goroutines are asleep - deadlock!\n"
- if !strings.HasPrefix(got, want) {
- t.Fatalf("expected %q, but got %q", want, got)
+ if !strings.HasPrefix(output, want) {
+ t.Fatalf("output does not start with %q:\n%s", want, output)
}
}
@@ -108,10 +110,25 @@ func TestLockedDeadlock2(t *testing.T) {
}
func TestGoexitDeadlock(t *testing.T) {
- got := executeTest(t, goexitDeadlockSource, nil)
- want := ""
- if got != want {
- t.Fatalf("expected %q, but got %q", want, got)
+ output := executeTest(t, goexitDeadlockSource, nil)
+ if output != "" {
+ t.Fatalf("expected no output, got:\n%s", output)
+ }
+}
+
+func TestStackOverflow(t *testing.T) {
+ output := executeTest(t, stackOverflowSource, nil)
+ want := "runtime: goroutine stack exceeds 4194304-byte limit\nfatal error: stack overflow"
+ if !strings.HasPrefix(output, want) {
+ t.Fatalf("output does not start with %q:\n%s", want, output)
+ }
+}
+
+func TestThreadExhaustion(t *testing.T) {
+ output := executeTest(t, threadExhaustionSource, nil)
+ want := "runtime: program exceeds 10-thread limit\nfatal error: thread exhaustion"
+ if !strings.HasPrefix(output, want) {
+ t.Fatalf("output does not start with %q:\n%s", want, output)
}
}
@@ -217,3 +234,41 @@ func main() {
runtime.Goexit()
}
`
+
+const stackOverflowSource = `
+package main
+
+import "runtime/debug"
+
+func main() {
+ debug.SetMaxStack(4<<20)
+ f(make([]byte, 10))
+}
+
+func f(x []byte) byte {
+ var buf [64<<10]byte
+ return x[0] + f(buf[:])
+}
+`
+
+const threadExhaustionSource = `
+package main
+
+import (
+ "runtime"
+ "runtime/debug"
+)
+
+func main() {
+ debug.SetMaxThreads(10)
+ c := make(chan int)
+ for i := 0; i < 100; i++ {
+ go func() {
+ runtime.LockOSThread()
+ c <- 0
+ select{}
+ }()
+ <-c
+ }
+}
+`