mirror of https://github.com/grpc/grpc-go.git
grpctest: use an interface instead of reflection (#6553)
This commit is contained in:
parent
cc705fe472
commit
7d3996fd85
|
@ -62,6 +62,12 @@ func (Tester) Teardown(t *testing.T) {
|
||||||
TLogger.EndTest(t)
|
TLogger.EndTest(t)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Interface defines Tester's methods for use in this package.
|
||||||
|
type Interface interface {
|
||||||
|
Setup(*testing.T)
|
||||||
|
Teardown(*testing.T)
|
||||||
|
}
|
||||||
|
|
||||||
func getTestFunc(t *testing.T, xv reflect.Value, name string) func(*testing.T) {
|
func getTestFunc(t *testing.T, xv reflect.Value, name string) func(*testing.T) {
|
||||||
if m := xv.MethodByName(name); m.IsValid() {
|
if m := xv.MethodByName(name); m.IsValid() {
|
||||||
if f, ok := m.Interface().(func(*testing.T)); ok {
|
if f, ok := m.Interface().(func(*testing.T)); ok {
|
||||||
|
@ -74,9 +80,8 @@ func getTestFunc(t *testing.T, xv reflect.Value, name string) func(*testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// RunSubTests runs all "Test___" functions that are methods of x as subtests
|
// RunSubTests runs all "Test___" functions that are methods of x as subtests
|
||||||
// of the current test. If x contains methods "Setup(*testing.T)" or
|
// of the current test. Setup is run before the test function and Teardown is
|
||||||
// "Teardown(*testing.T)", those are run before or after each of the test
|
// run after.
|
||||||
// functions, respectively.
|
|
||||||
//
|
//
|
||||||
// For example usage, see example_test.go. Run it using:
|
// For example usage, see example_test.go. Run it using:
|
||||||
//
|
//
|
||||||
|
@ -85,13 +90,10 @@ func getTestFunc(t *testing.T, xv reflect.Value, name string) func(*testing.T) {
|
||||||
// To run a specific test/subtest:
|
// To run a specific test/subtest:
|
||||||
//
|
//
|
||||||
// $ go test -v -run 'TestExample/^Something$' .
|
// $ go test -v -run 'TestExample/^Something$' .
|
||||||
func RunSubTests(t *testing.T, x any) {
|
func RunSubTests(t *testing.T, x Interface) {
|
||||||
xt := reflect.TypeOf(x)
|
xt := reflect.TypeOf(x)
|
||||||
xv := reflect.ValueOf(x)
|
xv := reflect.ValueOf(x)
|
||||||
|
|
||||||
setup := getTestFunc(t, xv, "Setup")
|
|
||||||
teardown := getTestFunc(t, xv, "Teardown")
|
|
||||||
|
|
||||||
for i := 0; i < xt.NumMethod(); i++ {
|
for i := 0; i < xt.NumMethod(); i++ {
|
||||||
methodName := xt.Method(i).Name
|
methodName := xt.Method(i).Name
|
||||||
if !strings.HasPrefix(methodName, "Test") {
|
if !strings.HasPrefix(methodName, "Test") {
|
||||||
|
@ -104,8 +106,8 @@ func RunSubTests(t *testing.T, x any) {
|
||||||
//
|
//
|
||||||
// Note that a defer would run before t.Cleanup, so if a goroutine
|
// Note that a defer would run before t.Cleanup, so if a goroutine
|
||||||
// is closed by a test's t.Cleanup, a deferred leakcheck would fail.
|
// is closed by a test's t.Cleanup, a deferred leakcheck would fail.
|
||||||
t.Cleanup(func() { teardown(t) })
|
t.Cleanup(func() { x.Teardown(t) })
|
||||||
setup(t)
|
x.Setup(t)
|
||||||
tfunc(t)
|
tfunc(t)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -44,20 +44,3 @@ func TestRunSubTests(t *testing.T) {
|
||||||
t.Fatalf("x = %v; want all fields true", x)
|
t.Fatalf("x = %v; want all fields true", x)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
type tNoST struct {
|
|
||||||
test bool
|
|
||||||
}
|
|
||||||
|
|
||||||
func (t *tNoST) TestSubTest(*testing.T) {
|
|
||||||
t.test = true
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestNoSetupOrTeardown(t *testing.T) {
|
|
||||||
// Ensures nothing panics or fails if Setup/Teardown are omitted.
|
|
||||||
x := &tNoST{}
|
|
||||||
RunSubTests(t, x)
|
|
||||||
if want := (&tNoST{test: true}); !reflect.DeepEqual(x, want) {
|
|
||||||
t.Fatalf("x = %v; want %v", x, want)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
Loading…
Reference in New Issue