diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-16 19:23:18 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-16 19:23:18 +0000 |
commit | 43a123c1ae6613b3efeed291fa552ecd909d3acf (patch) | |
tree | fd92518b7024bc74031f78a1cf9e454b65e73665 /src/testing/panic_test.go | |
parent | Initial commit. (diff) | |
download | golang-1.20-upstream.tar.xz golang-1.20-upstream.zip |
Adding upstream version 1.20.14.upstream/1.20.14upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to '')
-rw-r--r-- | src/testing/panic_test.go | 267 |
1 files changed, 267 insertions, 0 deletions
diff --git a/src/testing/panic_test.go b/src/testing/panic_test.go new file mode 100644 index 0000000..8733bc3 --- /dev/null +++ b/src/testing/panic_test.go @@ -0,0 +1,267 @@ +// Copyright 2019 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package testing_test + +import ( + "flag" + "fmt" + "internal/testenv" + "os" + "os/exec" + "regexp" + "runtime" + "strings" + "testing" +) + +var testPanicTest = flag.String("test_panic_test", "", "TestPanic: indicates which test should panic") +var testPanicParallel = flag.Bool("test_panic_parallel", false, "TestPanic: run subtests in parallel") +var testPanicCleanup = flag.Bool("test_panic_cleanup", false, "TestPanic: indicates whether test should call Cleanup") +var testPanicCleanupPanic = flag.String("test_panic_cleanup_panic", "", "TestPanic: indicate whether test should call Cleanup function that panics") + +func TestPanic(t *testing.T) { + testenv.MustHaveExec(t) + + testCases := []struct { + desc string + flags []string + want string + }{{ + desc: "root test panics", + flags: []string{"-test_panic_test=TestPanicHelper"}, + want: ` +--- FAIL: TestPanicHelper (N.NNs) + panic_test.go:NNN: TestPanicHelper +`, + }, { + desc: "subtest panics", + flags: []string{"-test_panic_test=TestPanicHelper/1"}, + want: ` +--- FAIL: TestPanicHelper (N.NNs) + panic_test.go:NNN: TestPanicHelper + --- FAIL: TestPanicHelper/1 (N.NNs) + panic_test.go:NNN: TestPanicHelper/1 +`, + }, { + desc: "subtest panics with cleanup", + flags: []string{"-test_panic_test=TestPanicHelper/1", "-test_panic_cleanup"}, + want: ` +ran inner cleanup 1 +ran middle cleanup 1 +ran outer cleanup +--- FAIL: TestPanicHelper (N.NNs) + panic_test.go:NNN: TestPanicHelper + --- FAIL: TestPanicHelper/1 (N.NNs) + panic_test.go:NNN: TestPanicHelper/1 +`, + }, { + desc: "subtest panics with outer cleanup panic", + flags: []string{"-test_panic_test=TestPanicHelper/1", "-test_panic_cleanup", "-test_panic_cleanup_panic=outer"}, + want: ` +ran inner cleanup 1 +ran middle cleanup 1 +ran outer cleanup +--- FAIL: TestPanicHelper (N.NNs) + panic_test.go:NNN: TestPanicHelper +`, + }, { + desc: "subtest panics with middle cleanup panic", + flags: []string{"-test_panic_test=TestPanicHelper/1", "-test_panic_cleanup", "-test_panic_cleanup_panic=middle"}, + want: ` +ran inner cleanup 1 +ran middle cleanup 1 +ran outer cleanup +--- FAIL: TestPanicHelper (N.NNs) + panic_test.go:NNN: TestPanicHelper + --- FAIL: TestPanicHelper/1 (N.NNs) + panic_test.go:NNN: TestPanicHelper/1 +`, + }, { + desc: "subtest panics with inner cleanup panic", + flags: []string{"-test_panic_test=TestPanicHelper/1", "-test_panic_cleanup", "-test_panic_cleanup_panic=inner"}, + want: ` +ran inner cleanup 1 +ran middle cleanup 1 +ran outer cleanup +--- FAIL: TestPanicHelper (N.NNs) + panic_test.go:NNN: TestPanicHelper + --- FAIL: TestPanicHelper/1 (N.NNs) + panic_test.go:NNN: TestPanicHelper/1 +`, + }, { + desc: "parallel subtest panics with cleanup", + flags: []string{"-test_panic_test=TestPanicHelper/1", "-test_panic_cleanup", "-test_panic_parallel"}, + want: ` +ran inner cleanup 1 +ran middle cleanup 1 +ran outer cleanup +--- FAIL: TestPanicHelper (N.NNs) + panic_test.go:NNN: TestPanicHelper + --- FAIL: TestPanicHelper/1 (N.NNs) + panic_test.go:NNN: TestPanicHelper/1 +`, + }, { + desc: "parallel subtest panics with outer cleanup panic", + flags: []string{"-test_panic_test=TestPanicHelper/1", "-test_panic_cleanup", "-test_panic_cleanup_panic=outer", "-test_panic_parallel"}, + want: ` +ran inner cleanup 1 +ran middle cleanup 1 +ran outer cleanup +--- FAIL: TestPanicHelper (N.NNs) + panic_test.go:NNN: TestPanicHelper +`, + }, { + desc: "parallel subtest panics with middle cleanup panic", + flags: []string{"-test_panic_test=TestPanicHelper/1", "-test_panic_cleanup", "-test_panic_cleanup_panic=middle", "-test_panic_parallel"}, + want: ` +ran inner cleanup 1 +ran middle cleanup 1 +ran outer cleanup +--- FAIL: TestPanicHelper (N.NNs) + panic_test.go:NNN: TestPanicHelper + --- FAIL: TestPanicHelper/1 (N.NNs) + panic_test.go:NNN: TestPanicHelper/1 +`, + }, { + desc: "parallel subtest panics with inner cleanup panic", + flags: []string{"-test_panic_test=TestPanicHelper/1", "-test_panic_cleanup", "-test_panic_cleanup_panic=inner", "-test_panic_parallel"}, + want: ` +ran inner cleanup 1 +ran middle cleanup 1 +ran outer cleanup +--- FAIL: TestPanicHelper (N.NNs) + panic_test.go:NNN: TestPanicHelper + --- FAIL: TestPanicHelper/1 (N.NNs) + panic_test.go:NNN: TestPanicHelper/1 +`, + }} + for _, tc := range testCases { + t.Run(tc.desc, func(t *testing.T) { + cmd := exec.Command(os.Args[0], "-test.run=TestPanicHelper") + cmd.Args = append(cmd.Args, tc.flags...) + cmd.Env = append(os.Environ(), "GO_WANT_HELPER_PROCESS=1") + b, _ := cmd.CombinedOutput() + got := string(b) + want := strings.TrimSpace(tc.want) + re := makeRegexp(want) + if ok, err := regexp.MatchString(re, got); !ok || err != nil { + t.Errorf("output:\ngot:\n%s\nwant:\n%s", got, want) + } + }) + } +} + +func makeRegexp(s string) string { + s = regexp.QuoteMeta(s) + s = strings.ReplaceAll(s, ":NNN:", `:\d+:`) + s = strings.ReplaceAll(s, "N\\.NNs", `\d*\.\d*s`) + return s +} + +func TestPanicHelper(t *testing.T) { + if os.Getenv("GO_WANT_HELPER_PROCESS") != "1" { + return + } + t.Log(t.Name()) + if t.Name() == *testPanicTest { + panic("panic") + } + switch *testPanicCleanupPanic { + case "", "outer", "middle", "inner": + default: + t.Fatalf("bad -test_panic_cleanup_panic: %s", *testPanicCleanupPanic) + } + t.Cleanup(func() { + fmt.Println("ran outer cleanup") + if *testPanicCleanupPanic == "outer" { + panic("outer cleanup") + } + }) + for i := 0; i < 3; i++ { + i := i + t.Run(fmt.Sprintf("%v", i), func(t *testing.T) { + chosen := t.Name() == *testPanicTest + if chosen && *testPanicCleanup { + t.Cleanup(func() { + fmt.Printf("ran middle cleanup %d\n", i) + if *testPanicCleanupPanic == "middle" { + panic("middle cleanup") + } + }) + } + if chosen && *testPanicParallel { + t.Parallel() + } + t.Log(t.Name()) + if chosen { + if *testPanicCleanup { + t.Cleanup(func() { + fmt.Printf("ran inner cleanup %d\n", i) + if *testPanicCleanupPanic == "inner" { + panic("inner cleanup") + } + }) + } + panic("panic") + } + }) + } +} + +func TestMorePanic(t *testing.T) { + testenv.MustHaveExec(t) + + testCases := []struct { + desc string + flags []string + want string + }{ + { + desc: "Issue 48502: call runtime.Goexit in t.Cleanup after panic", + flags: []string{"-test.run=TestGoexitInCleanupAfterPanicHelper"}, + want: `panic: die + panic: test executed panic(nil) or runtime.Goexit`, + }, + { + desc: "Issue 48515: call t.Run in t.Cleanup should trigger panic", + flags: []string{"-test.run=TestCallRunInCleanupHelper"}, + want: `panic: testing: t.Run called during t.Cleanup`, + }, + } + + for _, tc := range testCases { + cmd := exec.Command(os.Args[0], tc.flags...) + cmd.Env = append(os.Environ(), "GO_WANT_HELPER_PROCESS=1") + b, _ := cmd.CombinedOutput() + got := string(b) + want := tc.want + re := makeRegexp(want) + if ok, err := regexp.MatchString(re, got); !ok || err != nil { + t.Errorf("output:\ngot:\n%s\nwant:\n%s", got, want) + } + } +} + +func TestCallRunInCleanupHelper(t *testing.T) { + if os.Getenv("GO_WANT_HELPER_PROCESS") != "1" { + return + } + + t.Cleanup(func() { + t.Run("in-cleanup", func(t *testing.T) { + t.Log("must not be executed") + }) + }) +} + +func TestGoexitInCleanupAfterPanicHelper(t *testing.T) { + if os.Getenv("GO_WANT_HELPER_PROCESS") != "1" { + return + } + + t.Cleanup(func() { runtime.Goexit() }) + t.Parallel() + panic("die") +} |