github.com/code-reading/golang@v0.0.0-20220303082512-ba5bc0e589a3/go/src/testing/panic_test.go (about) 1 // 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 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 }