1// Copyright 2017 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	"sync"
9	"testing"
10)
11
12// The line numbering of this file is important for TestTBHelper.
13
14func notHelper(t *testing.T, msg string) {
15	t.Error(msg)
16}
17
18func helper(t *testing.T, msg string) {
19	t.Helper()
20	t.Error(msg)
21}
22
23func notHelperCallingHelper(t *testing.T, msg string) {
24	helper(t, msg)
25}
26
27func helperCallingHelper(t *testing.T, msg string) {
28	t.Helper()
29	helper(t, msg)
30}
31
32func genericHelper[G any](t *testing.T, msg string) {
33	t.Helper()
34	t.Error(msg)
35}
36
37var genericIntHelper = genericHelper[int]
38
39func testTestHelper(t *testing.T) {
40	testHelper(t)
41}
42
43func testHelper(t *testing.T) {
44	// Check combinations of directly and indirectly
45	// calling helper functions.
46	notHelper(t, "0")
47	helper(t, "1")
48	notHelperCallingHelper(t, "2")
49	helperCallingHelper(t, "3")
50
51	// Check a function literal closing over t that uses Helper.
52	fn := func(msg string) {
53		t.Helper()
54		t.Error(msg)
55	}
56	fn("4")
57
58	t.Run("sub", func(t *testing.T) {
59		helper(t, "5")
60		notHelperCallingHelper(t, "6")
61		// Check that calling Helper from inside a subtest entry function
62		// works as if it were in an ordinary function call.
63		t.Helper()
64		t.Error("7")
65	})
66
67	// Check that right caller is reported for func passed to Cleanup when
68	// multiple cleanup functions have been registered.
69	t.Cleanup(func() {
70		t.Helper()
71		t.Error("10")
72	})
73	t.Cleanup(func() {
74		t.Helper()
75		t.Error("9")
76	})
77
78	// Check that helper-ness propagates up through subtests
79	// to helpers above. See https://golang.org/issue/44887.
80	helperSubCallingHelper(t, "11")
81
82	// Check that helper-ness propagates up through panic/recover.
83	// See https://golang.org/issue/31154.
84	recoverHelper(t, "12")
85
86	genericHelper[float64](t, "GenericFloat64")
87	genericIntHelper(t, "GenericInt")
88}
89
90func parallelTestHelper(t *testing.T) {
91	var wg sync.WaitGroup
92	for i := 0; i < 5; i++ {
93		wg.Add(1)
94		go func() {
95			notHelperCallingHelper(t, "parallel")
96			wg.Done()
97		}()
98	}
99	wg.Wait()
100}
101
102func helperSubCallingHelper(t *testing.T, msg string) {
103	t.Helper()
104	t.Run("sub2", func(t *testing.T) {
105		t.Helper()
106		t.Fatal(msg)
107	})
108}
109
110func recoverHelper(t *testing.T, msg string) {
111	t.Helper()
112	defer func() {
113		t.Helper()
114		if err := recover(); err != nil {
115			t.Errorf("recover %s", err)
116		}
117	}()
118	doPanic(t, msg)
119}
120
121func doPanic(t *testing.T, msg string) {
122	t.Helper()
123	panic(msg)
124}
125