Relax to type assignability for values passed to Call.Return.

This commit is contained in:
David Symonds 2012-05-27 12:49:58 +10:00
Родитель 52e3a9f742
Коммит 8132ae8777
4 изменённых файлов: 31 добавлений и 5 удалений

Просмотреть файл

@ -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)
}
}

Просмотреть файл

@ -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 {

Просмотреть файл

@ -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{})

Просмотреть файл

@ -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 := ""