From 8132ae877779b2a52c92f4be4bbb395709e6dd47 Mon Sep 17 00:00:00 2001 From: David Symonds Date: Sun, 27 May 2012 12:49:58 +1000 Subject: [PATCH] Relax to type assignability for values passed to Call.Return. --- gomock/call.go | 14 ++++++++++---- sample/mock_user/mock_user.go | 10 ++++++++++ sample/user.go | 2 ++ sample/user_test.go | 10 +++++++++- 4 files changed, 31 insertions(+), 5 deletions(-) diff --git a/gomock/call.go b/gomock/call.go index eb08cfc..8bff2ac 100644 --- a/gomock/call.go +++ b/gomock/call.go @@ -61,10 +61,16 @@ func (c *Call) Return(rets ...interface{}) *Call { c.receiver, c.method, len(rets), mt.NumOut()) } for i, ret := range rets { - // TODO: Relax this to permit assignable types. That will require changes to the - // generated code, too, because the type assertions there enforce type identity. - if got, want := reflect.TypeOf(ret), mt.Out(i); got != want { - c.t.Fatalf("wrong type of argument %d to Return for %T.%v: got %v, want %v", + if got, want := reflect.TypeOf(ret), mt.Out(i); got == want { + // Identical types; nothing to do. + } else if got.AssignableTo(want) { + // Assignable type relation. Make the assignment now so that the generated code + // can return the values with a type assertion. + v := reflect.New(want).Elem() + v.Set(reflect.ValueOf(ret)) + rets[i] = v.Interface() + } else { + c.t.Fatalf("wrong type of argument %d to Return for %T.%v: %v is not assignable to %v", i, c.receiver, c.method, got, want) } } diff --git a/sample/mock_user/mock_user.go b/sample/mock_user/mock_user.go index 88a7b9c..841f809 100644 --- a/sample/mock_user/mock_user.go +++ b/sample/mock_user/mock_user.go @@ -134,6 +134,16 @@ func (_mr *_MockIndexRecorder) NillableRet() *gomock.Call { return _mr.mock.ctrl.RecordCall(_mr.mock, "NillableRet") } +func (_m *MockIndex) ConcreteRet() chan<- bool { + ret := _m.ctrl.Call(_m, "ConcreteRet") + ret0, _ := ret[0].(chan<- bool) + return ret0 +} + +func (_mr *_MockIndexRecorder) ConcreteRet() *gomock.Call { + return _mr.mock.ctrl.RecordCall(_mr.mock, "ConcreteRet") +} + func (_m *MockIndex) Ellip(fmt string, args ...interface{}) { _s := []interface{}{fmt} for _, _x := range args { diff --git a/sample/user.go b/sample/user.go index ed5187c..f4c93b9 100644 --- a/sample/user.go +++ b/sample/user.go @@ -42,6 +42,8 @@ type Index interface { // A method that returns a nillable type. NillableRet() error + // A method that returns a non-interface type. + ConcreteRet() chan<- bool // Methods with an ellipsis argument. Ellip(fmt string, args ...interface{}) diff --git a/sample/user_test.go b/sample/user_test.go index 3873d81..577ab77 100644 --- a/sample/user_test.go +++ b/sample/user_test.go @@ -5,9 +5,9 @@ import ( "testing" "github.com/dsymonds/gomock/gomock" + "github.com/dsymonds/gomock/sample" "github.com/dsymonds/gomock/sample/imp1" "github.com/dsymonds/gomock/sample/mock_user" - "github.com/dsymonds/gomock/sample" ) func TestRemember(t *testing.T) { @@ -20,6 +20,10 @@ func TestRemember(t *testing.T) { // NillableRet returns error. Not declaring it should result in a nil return. mockIndex.EXPECT().NillableRet() + // A call that returns something assignable to the return type. + // In this case, "chan bool" is assignable to "chan<- bool". + boolc := make(chan bool) + mockIndex.EXPECT().ConcreteRet().Return(boolc) // Should be able to place expectations on variadic methods. mockIndex.EXPECT().Ellip("%d", 0, 1, 1, 2, 3) // direct args @@ -28,6 +32,10 @@ func TestRemember(t *testing.T) { mockIndex.EXPECT().EllipOnly(gomock.Eq("arg")) user.Remember(mockIndex, []string{"a", "b"}, []interface{}{1, 2}) + // Force checking of the second NillableRet. + if c := mockIndex.ConcreteRet(); c != boolc { + t.Errorf("ConcreteRet: got %v, want %v", c, boolc) + } // Try one with an action. calledString := ""