1// Copyright 2015 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.
4
5package main
6
7import (
8	"fmt"
9	"runtime"
10)
11
12func init() {
13	register("Crash", Crash)
14	register("DoublePanic", DoublePanic)
15	register("ErrorPanic", ErrorPanic)
16	register("StringerPanic", StringerPanic)
17	register("DoubleErrorPanic", DoubleErrorPanic)
18	register("DoubleStringerPanic", DoubleStringerPanic)
19	register("StringPanic", StringPanic)
20	register("NilPanic", NilPanic)
21	register("CircularPanic", CircularPanic)
22}
23
24func test(name string) {
25	defer func() {
26		if x := recover(); x != nil {
27			fmt.Printf(" recovered")
28		}
29		fmt.Printf(" done\n")
30	}()
31	fmt.Printf("%s:", name)
32	var s *string
33	_ = *s
34	fmt.Print("SHOULD NOT BE HERE")
35}
36
37func testInNewThread(name string) {
38	c := make(chan bool)
39	go func() {
40		runtime.LockOSThread()
41		test(name)
42		c <- true
43	}()
44	<-c
45}
46
47func Crash() {
48	runtime.LockOSThread()
49	test("main")
50	testInNewThread("new-thread")
51	testInNewThread("second-new-thread")
52	test("main-again")
53}
54
55type P string
56
57func (p P) String() string {
58	// Try to free the "YYY" string header when the "XXX"
59	// panic is stringified.
60	runtime.GC()
61	runtime.GC()
62	runtime.GC()
63	return string(p)
64}
65
66// Test that panic message is not clobbered.
67// See issue 30150.
68func DoublePanic() {
69	defer func() {
70		panic(P("YYY"))
71	}()
72	panic(P("XXX"))
73}
74
75// Test that panic while panicking discards error message
76// See issue 52257
77type exampleError struct{}
78
79func (e exampleError) Error() string {
80	panic("important multi-line\nerror message")
81}
82
83func ErrorPanic() {
84	panic(exampleError{})
85}
86
87type examplePanicError struct{}
88
89func (e examplePanicError) Error() string {
90	panic(exampleError{})
91}
92
93func DoubleErrorPanic() {
94	panic(examplePanicError{})
95}
96
97type exampleStringer struct{}
98
99func (s exampleStringer) String() string {
100	panic("important multi-line\nstringer message")
101}
102
103func StringerPanic() {
104	panic(exampleStringer{})
105}
106
107type examplePanicStringer struct{}
108
109func (s examplePanicStringer) String() string {
110	panic(exampleStringer{})
111}
112
113func DoubleStringerPanic() {
114	panic(examplePanicStringer{})
115}
116
117func StringPanic() {
118	panic("important multi-line\nstring message")
119}
120
121func NilPanic() {
122	panic(nil)
123}
124
125type exampleCircleStartError struct{}
126
127func (e exampleCircleStartError) Error() string {
128	panic(exampleCircleEndError{})
129}
130
131type exampleCircleEndError struct{}
132
133func (e exampleCircleEndError) Error() string {
134	panic(exampleCircleStartError{})
135}
136
137func CircularPanic() {
138	panic(exampleCircleStartError{})
139}
140