re PR target/61662 (Incorrect value calculated for _lrotl on LLP64 systems)
[official-gcc.git] / libgo / go / runtime / crash_test.go
blobd8bfdbdad6dcfb5fe040a521da92070a0baaf798
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.
5 package runtime_test
7 import (
8 "io/ioutil"
9 "os"
10 "os/exec"
11 "path/filepath"
12 "strings"
13 "testing"
14 "text/template"
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 {
21 if cmd.Env != nil {
22 panic("environment already set")
24 for _, env := range os.Environ() {
25 if strings.HasPrefix(env, "GODEBUG=") {
26 continue
28 cmd.Env = append(cmd.Env, env)
30 return cmd
33 func executeTest(t *testing.T, templ string, data interface{}) string {
34 t.Skip("gccgo does not have a go command")
35 checkStaleRuntime(t)
37 st := template.Must(template.New("crashSource").Parse(templ))
39 dir, err := ioutil.TempDir("", "go-build")
40 if err != nil {
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)
47 if err != nil {
48 t.Fatalf("failed to create file: %v", err)
50 err = st.Execute(f, data)
51 if err != nil {
52 f.Close()
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()
60 return string(got)
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()
66 if err != nil {
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 {
76 Cgo bool
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"
80 if output != want {
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)
115 if output != "" {
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 = `
137 package main
139 import (
140 "fmt"
141 "runtime"
144 {{if .Cgo}}
145 import "C"
146 {{end}}
148 func test(name string) {
149 defer func() {
150 if x := recover(); x != nil {
151 fmt.Printf(" recovered")
153 fmt.Printf(" done\n")
155 fmt.Printf("%s:", name)
156 var s *string
157 _ = *s
158 fmt.Print("SHOULD NOT BE HERE")
161 func testInNewThread(name string) {
162 c := make(chan bool)
163 go func() {
164 runtime.LockOSThread()
165 test(name)
166 c <- true
171 func main() {
172 runtime.LockOSThread()
173 test("main")
174 testInNewThread("new-thread")
175 testInNewThread("second-new-thread")
176 test("main-again")
180 const simpleDeadlockSource = `
181 package main
182 func main() {
183 select {}
187 const initDeadlockSource = `
188 package main
189 func init() {
190 select {}
192 func main() {
196 const lockedDeadlockSource = `
197 package main
198 import "runtime"
199 func main() {
200 runtime.LockOSThread()
201 select {}
205 const lockedDeadlockSource2 = `
206 package main
207 import (
208 "runtime"
209 "time"
211 func main() {
212 go func() {
213 runtime.LockOSThread()
214 select {}
216 time.Sleep(time.Millisecond)
217 select {}
221 const goexitDeadlockSource = `
222 package main
223 import (
224 "runtime"
227 func F() {
228 for i := 0; i < 10; i++ {
232 func main() {
233 go F()
234 go F()
235 runtime.Goexit()
239 const stackOverflowSource = `
240 package main
242 import "runtime/debug"
244 func main() {
245 debug.SetMaxStack(4<<20)
246 f(make([]byte, 10))
249 func f(x []byte) byte {
250 var buf [64<<10]byte
251 return x[0] + f(buf[:])
255 const threadExhaustionSource = `
256 package main
258 import (
259 "runtime"
260 "runtime/debug"
263 func main() {
264 debug.SetMaxThreads(10)
265 c := make(chan int)
266 for i := 0; i < 100; i++ {
267 go func() {
268 runtime.LockOSThread()
269 c <- 0
270 select{}