blob: 6b8b95391df16e810e3d99b77253b8616277d17f [file] [log] [blame]
Damien Neil81a74b42019-05-30 09:46:56 -07001// Copyright 2019 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 testing_test
6
7import (
8 "flag"
9 "fmt"
10 "internal/testenv"
11 "os"
12 "os/exec"
13 "regexp"
14 "strings"
15 "testing"
16)
17
18var testPanicTest = flag.String("test_panic_test", "", "TestPanic: indicates which test should panic")
Ian Lance Taylor998cbe22020-01-14 15:28:47 -080019var testPanicParallel = flag.Bool("test_panic_parallel", false, "TestPanic: run subtests in parallel")
20var testPanicCleanup = flag.Bool("test_panic_cleanup", false, "TestPanic: indicates whether test should call Cleanup")
21var testPanicCleanupPanic = flag.String("test_panic_cleanup_panic", "", "TestPanic: indicate whether test should call Cleanup function that panics")
Damien Neil81a74b42019-05-30 09:46:56 -070022
23func 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`,
Ian Lance Taylor998cbe22020-01-14 15:28:47 -080046 }, {
47 desc: "subtest panics with cleanup",
48 flags: []string{"-test_panic_test=TestPanicHelper/1", "-test_panic_cleanup"},
49 want: `
50ran inner cleanup 1
51ran middle cleanup 1
52ran 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: `
62ran inner cleanup 1
63ran middle cleanup 1
64ran 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: `
72ran inner cleanup 1
73ran middle cleanup 1
74ran 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: `
84ran inner cleanup 1
85ran middle cleanup 1
86ran 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: `
96ran inner cleanup 1
97ran middle cleanup 1
98ran 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: `
108ran inner cleanup 1
109ran middle cleanup 1
110ran 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: `
118ran inner cleanup 1
119ran middle cleanup 1
120ran 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: `
130ran inner cleanup 1
131ran middle cleanup 1
132ran 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`,
Damien Neil81a74b42019-05-30 09:46:56 -0700138 }}
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
155func 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
162func 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 }
Ian Lance Taylor998cbe22020-01-14 15:28:47 -0800170 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 })
Damien Neil81a74b42019-05-30 09:46:56 -0700181 for i := 0; i < 3; i++ {
Ian Lance Taylor998cbe22020-01-14 15:28:47 -0800182 i := i
Damien Neil81a74b42019-05-30 09:46:56 -0700183 t.Run(fmt.Sprintf("%v", i), func(t *testing.T) {
Ian Lance Taylor998cbe22020-01-14 15:28:47 -0800184 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 }
Damien Neil81a74b42019-05-30 09:46:56 -0700196 t.Log(t.Name())
Ian Lance Taylor998cbe22020-01-14 15:28:47 -0800197 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 }
Damien Neil81a74b42019-05-30 09:46:56 -0700206 panic("panic")
207 }
208 })
209 }
210}