From aacf12939364c2b1329b347509d7b8589051e0ad Mon Sep 17 00:00:00 2001 From: Joshua Blum Date: Thu, 2 Dec 2021 16:28:01 -0500 Subject: [PATCH 1/3] Don't error out for variadic functions in Do/DoReturn --- gomock/call.go | 10 +++++----- gomock/call_test.go | 14 ++++++++++++++ 2 files changed, 19 insertions(+), 5 deletions(-) diff --git a/gomock/call.go b/gomock/call.go index 70efdb23..723d0d5f 100644 --- a/gomock/call.go +++ b/gomock/call.go @@ -115,13 +115,13 @@ func (c *Call) DoAndReturn(f interface{}) *Call { c.addAction(func(args []interface{}) []interface{} { c.t.Helper() - vArgs := make([]reflect.Value, len(args)) ft := v.Type() - if c.methodType.NumIn() != ft.NumIn() { + if c.methodType.NumIn() != ft.NumIn() && !ft.IsVariadic() { c.t.Fatalf("wrong number of arguments in DoAndReturn func for %T.%v: got %d, want %d [%s]", c.receiver, c.method, ft.NumIn(), c.methodType.NumIn(), c.origin) return nil } + vArgs := make([]reflect.Value, len(args)) for i := 0; i < len(args); i++ { if args[i] != nil { vArgs[i] = reflect.ValueOf(args[i]) @@ -151,13 +151,13 @@ func (c *Call) Do(f interface{}) *Call { c.addAction(func(args []interface{}) []interface{} { c.t.Helper() - if c.methodType.NumIn() != v.Type().NumIn() { + ft := v.Type() + if c.methodType.NumIn() != ft.NumIn() && !ft.IsVariadic() { c.t.Fatalf("wrong number of arguments in Do func for %T.%v: got %d, want %d [%s]", - c.receiver, c.method, v.Type().NumIn(), c.methodType.NumIn(), c.origin) + c.receiver, c.method, ft.NumIn(), c.methodType.NumIn(), c.origin) return nil } vArgs := make([]reflect.Value, len(args)) - ft := v.Type() for i := 0; i < len(args); i++ { if args[i] != nil { vArgs[i] = reflect.ValueOf(args[i]) diff --git a/gomock/call_test.go b/gomock/call_test.go index 9483c4f5..e19d1423 100644 --- a/gomock/call_test.go +++ b/gomock/call_test.go @@ -510,6 +510,13 @@ func TestCall_Do_NumArgValidation(t *testing.T) { args: []interface{}{"just", "right"}, wantErr: false, }, + { + name: "variadic", + methodType: reflect.TypeOf(func(one, two string) {}), + doFn: func(args ...interface{}) {}, + args: []interface{}{"just", "right"}, + wantErr: false, + }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { @@ -559,6 +566,13 @@ func TestCall_DoAndReturn_NumArgValidation(t *testing.T) { args: []interface{}{"just", "right"}, wantErr: false, }, + { + name: "variadic", + methodType: reflect.TypeOf(func(one, two string) {}), + doFn: func(args ...interface{}) string { return "" }, + args: []interface{}{"just", "right"}, + wantErr: false, + }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { From 72ff7a45dbcd5a922f75b07b65a9cd2bc588cef0 Mon Sep 17 00:00:00 2001 From: Joshua Blum Date: Wed, 5 Jan 2022 18:29:26 -0500 Subject: [PATCH 2/3] Update error message --- gomock/call.go | 26 ++++++++++++++++++-------- gomock/call_test.go | 4 ++-- 2 files changed, 20 insertions(+), 10 deletions(-) diff --git a/gomock/call.go b/gomock/call.go index 723d0d5f..04db8f8e 100644 --- a/gomock/call.go +++ b/gomock/call.go @@ -108,7 +108,7 @@ func (c *Call) MaxTimes(n int) *Call { // DoAndReturn declares the action to run when the call is matched. // The return values from this function are returned by the mocked function. // It takes an interface{} argument to support n-arity functions. -// The anonymous function must have the same number of input and output arguments as the mocked method. +// The anonymous function must match the function signature mocked method. func (c *Call) DoAndReturn(f interface{}) *Call { // TODO: Check arity and types here, rather than dying badly elsewhere. v := reflect.ValueOf(f) @@ -116,9 +116,14 @@ func (c *Call) DoAndReturn(f interface{}) *Call { c.addAction(func(args []interface{}) []interface{} { c.t.Helper() ft := v.Type() - if c.methodType.NumIn() != ft.NumIn() && !ft.IsVariadic() { - c.t.Fatalf("wrong number of arguments in DoAndReturn func for %T.%v: got %d, want %d [%s]", - c.receiver, c.method, ft.NumIn(), c.methodType.NumIn(), c.origin) + if c.methodType.NumIn() != ft.NumIn() { + if ft.IsVariadic() { + c.t.Fatalf("wrong number of arguments in DoAndReturn func for %T.%v The function signature must match the mocked method, a variadic function cannot be used.", + c.receiver, c.method) + } else { + c.t.Fatalf("wrong number of arguments in DoAndReturn func for %T.%v: got %d, want %d [%s]", + c.receiver, c.method, ft.NumIn(), c.methodType.NumIn(), c.origin) + } return nil } vArgs := make([]reflect.Value, len(args)) @@ -144,7 +149,7 @@ func (c *Call) DoAndReturn(f interface{}) *Call { // return values are ignored to retain backward compatibility. To use the // return values call DoAndReturn. // It takes an interface{} argument to support n-arity functions. -// The anonymous function must have the same number of input arguments as the mocked method. +// The anonymous function must match the function signature mocked method. func (c *Call) Do(f interface{}) *Call { // TODO: Check arity and types here, rather than dying badly elsewhere. v := reflect.ValueOf(f) @@ -152,9 +157,14 @@ func (c *Call) Do(f interface{}) *Call { c.addAction(func(args []interface{}) []interface{} { c.t.Helper() ft := v.Type() - if c.methodType.NumIn() != ft.NumIn() && !ft.IsVariadic() { - c.t.Fatalf("wrong number of arguments in Do func for %T.%v: got %d, want %d [%s]", - c.receiver, c.method, ft.NumIn(), c.methodType.NumIn(), c.origin) + if c.methodType.NumIn() != ft.NumIn() { + if ft.IsVariadic() { + c.t.Fatalf("wrong number of arguments in DoAndReturn func for %T.%v The function signature must match the mocked method, a variadic function cannot be used.", + c.receiver, c.method) + } else { + c.t.Fatalf("wrong number of arguments in DoAndReturn func for %T.%v: got %d, want %d [%s]", + c.receiver, c.method, ft.NumIn(), c.methodType.NumIn(), c.origin) + } return nil } vArgs := make([]reflect.Value, len(args)) diff --git a/gomock/call_test.go b/gomock/call_test.go index e19d1423..c7eb39db 100644 --- a/gomock/call_test.go +++ b/gomock/call_test.go @@ -515,7 +515,7 @@ func TestCall_Do_NumArgValidation(t *testing.T) { methodType: reflect.TypeOf(func(one, two string) {}), doFn: func(args ...interface{}) {}, args: []interface{}{"just", "right"}, - wantErr: false, + wantErr: true, }, } for _, tt := range tests { @@ -571,7 +571,7 @@ func TestCall_DoAndReturn_NumArgValidation(t *testing.T) { methodType: reflect.TypeOf(func(one, two string) {}), doFn: func(args ...interface{}) string { return "" }, args: []interface{}{"just", "right"}, - wantErr: false, + wantErr: true, }, } for _, tt := range tests { From 5e009f958b521a36a6023ac2fd35714bdd976149 Mon Sep 17 00:00:00 2001 From: Joshua Blum Date: Fri, 7 Jan 2022 14:34:29 -0500 Subject: [PATCH 3/3] fix typo --- gomock/call.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/gomock/call.go b/gomock/call.go index 04db8f8e..98881596 100644 --- a/gomock/call.go +++ b/gomock/call.go @@ -159,10 +159,10 @@ func (c *Call) Do(f interface{}) *Call { ft := v.Type() if c.methodType.NumIn() != ft.NumIn() { if ft.IsVariadic() { - c.t.Fatalf("wrong number of arguments in DoAndReturn func for %T.%v The function signature must match the mocked method, a variadic function cannot be used.", + c.t.Fatalf("wrong number of arguments in Do func for %T.%v The function signature must match the mocked method, a variadic function cannot be used.", c.receiver, c.method) } else { - c.t.Fatalf("wrong number of arguments in DoAndReturn func for %T.%v: got %d, want %d [%s]", + c.t.Fatalf("wrong number of arguments in Do func for %T.%v: got %d, want %d [%s]", c.receiver, c.method, ft.NumIn(), c.methodType.NumIn(), c.origin) } return nil