...

Source file src/testing/panic_test.go

Documentation: testing

		 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  }
	 211  

View as plain text