Source file
src/testing/panic_test.go
1
2
3
4
5 package testing_test
6
7 import (
8 "flag"
9 "fmt"
10 "internal/testenv"
11 "os"
12 "os/exec"
13 "regexp"
14 "strings"
15 "testing"
16 )
17
18 var testPanicTest = flag.String("test_panic_test", "", "TestPanic: indicates which test should panic")
19 var testPanicParallel = flag.Bool("test_panic_parallel", false, "TestPanic: run subtests in parallel")
20 var testPanicCleanup = flag.Bool("test_panic_cleanup", false, "TestPanic: indicates whether test should call Cleanup")
21 var testPanicCleanupPanic = flag.String("test_panic_cleanup_panic", "", "TestPanic: indicate whether test should call Cleanup function that panics")
22
23 func TestPanic(t *testing.T) {
24 testenv.MustHaveExec(t)
25
26 testCases := []struct {
27 desc string
28 flags []string
29 want string
30 }{{
31 desc: "root test panics",
32 flags: []string{"-test_panic_test=TestPanicHelper"},
33 want: `
34 --- FAIL: TestPanicHelper (N.NNs)
35 panic_test.go:NNN: TestPanicHelper
36 `,
37 }, {
38 desc: "subtest panics",
39 flags: []string{"-test_panic_test=TestPanicHelper/1"},
40 want: `
41 --- FAIL: TestPanicHelper (N.NNs)
42 panic_test.go:NNN: TestPanicHelper
43 --- FAIL: TestPanicHelper/1 (N.NNs)
44 panic_test.go:NNN: TestPanicHelper/1
45 `,
46 }, {
47 desc: "subtest panics with cleanup",
48 flags: []string{"-test_panic_test=TestPanicHelper/1", "-test_panic_cleanup"},
49 want: `
50 ran inner cleanup 1
51 ran middle cleanup 1
52 ran outer cleanup
53 --- FAIL: TestPanicHelper (N.NNs)
54 panic_test.go:NNN: TestPanicHelper
55 --- FAIL: TestPanicHelper/1 (N.NNs)
56 panic_test.go:NNN: TestPanicHelper/1
57 `,
58 }, {
59 desc: "subtest panics with outer cleanup panic",
60 flags: []string{"-test_panic_test=TestPanicHelper/1", "-test_panic_cleanup", "-test_panic_cleanup_panic=outer"},
61 want: `
62 ran inner cleanup 1
63 ran middle cleanup 1
64 ran outer cleanup
65 --- FAIL: TestPanicHelper (N.NNs)
66 panic_test.go:NNN: TestPanicHelper
67 `,
68 }, {
69 desc: "subtest panics with middle cleanup panic",
70 flags: []string{"-test_panic_test=TestPanicHelper/1", "-test_panic_cleanup", "-test_panic_cleanup_panic=middle"},
71 want: `
72 ran inner cleanup 1
73 ran middle cleanup 1
74 ran outer cleanup
75 --- FAIL: TestPanicHelper (N.NNs)
76 panic_test.go:NNN: TestPanicHelper
77 --- FAIL: TestPanicHelper/1 (N.NNs)
78 panic_test.go:NNN: TestPanicHelper/1
79 `,
80 }, {
81 desc: "subtest panics with inner cleanup panic",
82 flags: []string{"-test_panic_test=TestPanicHelper/1", "-test_panic_cleanup", "-test_panic_cleanup_panic=inner"},
83 want: `
84 ran inner cleanup 1
85 ran middle cleanup 1
86 ran outer cleanup
87 --- FAIL: TestPanicHelper (N.NNs)
88 panic_test.go:NNN: TestPanicHelper
89 --- FAIL: TestPanicHelper/1 (N.NNs)
90 panic_test.go:NNN: TestPanicHelper/1
91 `,
92 }, {
93 desc: "parallel subtest panics with cleanup",
94 flags: []string{"-test_panic_test=TestPanicHelper/1", "-test_panic_cleanup", "-test_panic_parallel"},
95 want: `
96 ran inner cleanup 1
97 ran middle cleanup 1
98 ran outer cleanup
99 --- FAIL: TestPanicHelper (N.NNs)
100 panic_test.go:NNN: TestPanicHelper
101 --- FAIL: TestPanicHelper/1 (N.NNs)
102 panic_test.go:NNN: TestPanicHelper/1
103 `,
104 }, {
105 desc: "parallel subtest panics with outer cleanup panic",
106 flags: []string{"-test_panic_test=TestPanicHelper/1", "-test_panic_cleanup", "-test_panic_cleanup_panic=outer", "-test_panic_parallel"},
107 want: `
108 ran inner cleanup 1
109 ran middle cleanup 1
110 ran outer cleanup
111 --- FAIL: TestPanicHelper (N.NNs)
112 panic_test.go:NNN: TestPanicHelper
113 `,
114 }, {
115 desc: "parallel subtest panics with middle cleanup panic",
116 flags: []string{"-test_panic_test=TestPanicHelper/1", "-test_panic_cleanup", "-test_panic_cleanup_panic=middle", "-test_panic_parallel"},
117 want: `
118 ran inner cleanup 1
119 ran middle cleanup 1
120 ran outer cleanup
121 --- FAIL: TestPanicHelper (N.NNs)
122 panic_test.go:NNN: TestPanicHelper
123 --- FAIL: TestPanicHelper/1 (N.NNs)
124 panic_test.go:NNN: TestPanicHelper/1
125 `,
126 }, {
127 desc: "parallel subtest panics with inner cleanup panic",
128 flags: []string{"-test_panic_test=TestPanicHelper/1", "-test_panic_cleanup", "-test_panic_cleanup_panic=inner", "-test_panic_parallel"},
129 want: `
130 ran inner cleanup 1
131 ran middle cleanup 1
132 ran outer cleanup
133 --- FAIL: TestPanicHelper (N.NNs)
134 panic_test.go:NNN: TestPanicHelper
135 --- FAIL: TestPanicHelper/1 (N.NNs)
136 panic_test.go:NNN: TestPanicHelper/1
137 `,
138 }}
139 for _, tc := range testCases {
140 t.Run(tc.desc, func(t *testing.T) {
141 cmd := exec.Command(os.Args[0], "-test.run=TestPanicHelper")
142 cmd.Args = append(cmd.Args, tc.flags...)
143 cmd.Env = append(os.Environ(), "GO_WANT_HELPER_PROCESS=1")
144 b, _ := cmd.CombinedOutput()
145 got := string(b)
146 want := strings.TrimSpace(tc.want)
147 re := makeRegexp(want)
148 if ok, err := regexp.MatchString(re, got); !ok || err != nil {
149 t.Errorf("output:\ngot:\n%s\nwant:\n%s", got, want)
150 }
151 })
152 }
153 }
154
155 func makeRegexp(s string) string {
156 s = regexp.QuoteMeta(s)
157 s = strings.ReplaceAll(s, ":NNN:", `:\d+:`)
158 s = strings.ReplaceAll(s, "N\\.NNs", `\d*\.\d*s`)
159 return s
160 }
161
162 func TestPanicHelper(t *testing.T) {
163 if os.Getenv("GO_WANT_HELPER_PROCESS") != "1" {
164 return
165 }
166 t.Log(t.Name())
167 if t.Name() == *testPanicTest {
168 panic("panic")
169 }
170 switch *testPanicCleanupPanic {
171 case "", "outer", "middle", "inner":
172 default:
173 t.Fatalf("bad -test_panic_cleanup_panic: %s", *testPanicCleanupPanic)
174 }
175 t.Cleanup(func() {
176 fmt.Println("ran outer cleanup")
177 if *testPanicCleanupPanic == "outer" {
178 panic("outer cleanup")
179 }
180 })
181 for i := 0; i < 3; i++ {
182 i := i
183 t.Run(fmt.Sprintf("%v", i), func(t *testing.T) {
184 chosen := t.Name() == *testPanicTest
185 if chosen && *testPanicCleanup {
186 t.Cleanup(func() {
187 fmt.Printf("ran middle cleanup %d\n", i)
188 if *testPanicCleanupPanic == "middle" {
189 panic("middle cleanup")
190 }
191 })
192 }
193 if chosen && *testPanicParallel {
194 t.Parallel()
195 }
196 t.Log(t.Name())
197 if chosen {
198 if *testPanicCleanup {
199 t.Cleanup(func() {
200 fmt.Printf("ran inner cleanup %d\n", i)
201 if *testPanicCleanupPanic == "inner" {
202 panic("inner cleanup")
203 }
204 })
205 }
206 panic("panic")
207 }
208 })
209 }
210 }
211
View as plain text