1 // Copyright 2012 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
17 // testEnv excludes GODEBUG from the environment
18 // to prevent its output from breaking tests that
19 // are trying to parse other command output.
20 func testEnv(cmd
*exec
.Cmd
) *exec
.Cmd
{
22 panic("environment already set")
24 for _
, env
:= range os
.Environ() {
25 if strings
.HasPrefix(env
, "GODEBUG=") {
28 cmd
.Env
= append(cmd
.Env
, env
)
33 func executeTest(t
*testing
.T
, templ
string, data
interface{}) string {
34 t
.Skip("gccgo does not have a go command")
37 st
:= template
.Must(template
.New("crashSource").Parse(templ
))
39 dir
, err
:= ioutil
.TempDir("", "go-build")
41 t
.Fatalf("failed to create temp directory: %v", err
)
43 defer os
.RemoveAll(dir
)
45 src
:= filepath
.Join(dir
, "main.go")
46 f
, err
:= os
.Create(src
)
48 t
.Fatalf("failed to create file: %v", err
)
50 err
= st
.Execute(f
, data
)
53 t
.Fatalf("failed to execute template: %v", err
)
55 if err
:= f
.Close(); err
!= nil {
56 t
.Fatalf("failed to close file: %v", err
)
59 got
, _
:= testEnv(exec
.Command("go", "run", src
)).CombinedOutput()
63 func checkStaleRuntime(t
*testing
.T
) {
64 // 'go run' uses the installed copy of runtime.a, which may be out of date.
65 out
, err
:= testEnv(exec
.Command("go", "list", "-f", "{{.Stale}}", "runtime")).CombinedOutput()
67 t
.Fatalf("failed to execute 'go list': %v\n%v", err
, string(out
))
69 if string(out
) != "false\n" {
70 t
.Fatalf("Stale runtime.a. Run 'go install runtime'.")
74 func testCrashHandler(t
*testing
.T
, cgo
bool) {
75 type crashTest
struct {
78 output
:= executeTest(t
, crashSource
, &crashTest
{Cgo
: cgo
})
79 want
:= "main: recovered done\nnew-thread: recovered done\nsecond-new-thread: recovered done\nmain-again: recovered done\n"
81 t
.Fatalf("output:\n%s\n\nwanted:\n%s", output
, want
)
85 func TestCrashHandler(t
*testing
.T
) {
86 testCrashHandler(t
, false)
89 func testDeadlock(t
*testing
.T
, source
string) {
90 output
:= executeTest(t
, source
, nil)
91 want
:= "fatal error: all goroutines are asleep - deadlock!\n"
92 if !strings
.HasPrefix(output
, want
) {
93 t
.Fatalf("output does not start with %q:\n%s", want
, output
)
97 func TestSimpleDeadlock(t
*testing
.T
) {
98 testDeadlock(t
, simpleDeadlockSource
)
101 func TestInitDeadlock(t
*testing
.T
) {
102 testDeadlock(t
, initDeadlockSource
)
105 func TestLockedDeadlock(t
*testing
.T
) {
106 testDeadlock(t
, lockedDeadlockSource
)
109 func TestLockedDeadlock2(t
*testing
.T
) {
110 testDeadlock(t
, lockedDeadlockSource2
)
113 func TestGoexitDeadlock(t
*testing
.T
) {
114 output
:= executeTest(t
, goexitDeadlockSource
, nil)
116 t
.Fatalf("expected no output, got:\n%s", output
)
120 func TestStackOverflow(t
*testing
.T
) {
121 output
:= executeTest(t
, stackOverflowSource
, nil)
122 want
:= "runtime: goroutine stack exceeds 4194304-byte limit\nfatal error: stack overflow"
123 if !strings
.HasPrefix(output
, want
) {
124 t
.Fatalf("output does not start with %q:\n%s", want
, output
)
128 func TestThreadExhaustion(t
*testing
.T
) {
129 output
:= executeTest(t
, threadExhaustionSource
, nil)
130 want
:= "runtime: program exceeds 10-thread limit\nfatal error: thread exhaustion"
131 if !strings
.HasPrefix(output
, want
) {
132 t
.Fatalf("output does not start with %q:\n%s", want
, output
)
136 const crashSource
= `
148 func test(name string) {
150 if x := recover(); x != nil {
151 fmt.Printf(" recovered")
153 fmt.Printf(" done\n")
155 fmt.Printf("%s:", name)
158 fmt.Print("SHOULD NOT BE HERE")
161 func testInNewThread(name string) {
164 runtime.LockOSThread()
172 runtime.LockOSThread()
174 testInNewThread("new-thread")
175 testInNewThread("second-new-thread")
180 const simpleDeadlockSource
= `
187 const initDeadlockSource
= `
196 const lockedDeadlockSource
= `
200 runtime.LockOSThread()
205 const lockedDeadlockSource2
= `
213 runtime.LockOSThread()
216 time.Sleep(time.Millisecond)
221 const goexitDeadlockSource
= `
228 for i := 0; i < 10; i++ {
239 const stackOverflowSource
= `
242 import "runtime/debug"
245 debug.SetMaxStack(4<<20)
249 func f(x []byte) byte {
251 return x[0] + f(buf[:])
255 const threadExhaustionSource
= `
264 debug.SetMaxThreads(10)
266 for i := 0; i < 100; i++ {
268 runtime.LockOSThread()