Skip to content

Commit

Permalink
feat: allow setting args for variadic functions
Browse files Browse the repository at this point in the history
The gomock's Call interface allows for setting a value to a specified
argument, making it convinient to work with functions that return data
through pointer arguments. However, this is not possible for variadic
functions, the error is:

  SetArg(1, ...) called for a method with 1 args...

The root cause is that the variadic argument in a form of
...interface{} is threated as single value instead of being treated as
slice.

This commit changes this situation by making sure that the variadic
arguments that are a slice are treated as slices. As a consequence it is
now possible to set argument value for variadic functions.

See: golang#174
  • Loading branch information
bergotorino committed Oct 15, 2021
1 parent 91dfb59 commit 56a15b3
Showing 1 changed file with 23 additions and 13 deletions.
36 changes: 23 additions & 13 deletions gomock/call.go
Original file line number Diff line number Diff line change
Expand Up @@ -225,15 +225,17 @@ func (c *Call) SetArg(n int, value interface{}) *Call {
c.t.Helper()

mt := c.methodType
// TODO: This will break on variadic methods.
// We will need to check those at invocation time.
if n < 0 || n >= mt.NumIn() {
if (n < 0 || n >= mt.NumIn()) && !mt.IsVariadic() {
c.t.Fatalf("SetArg(%d, ...) called for a method with %d args [%s]",
n, mt.NumIn(), c.origin)
}
// Permit setting argument through an interface.
// In the interface case, we don't (nay, can't) check the type here.
at := mt.In(n)
nn := n
if mt.IsVariadic() {
nn = 0
}
at := mt.In(nn)
switch at.Kind() {
case reflect.Ptr:
dt := at.Elem()
Expand All @@ -250,16 +252,24 @@ func (c *Call) SetArg(n int, value interface{}) *Call {
n, at, c.origin)
}

c.addAction(func(args []interface{}) []interface{} {
v := reflect.ValueOf(value)
switch reflect.TypeOf(args[n]).Kind() {
case reflect.Slice:
setSlice(args[n], v)
default:
if mt.IsVariadic() {
c.addAction(func(args []interface{}) []interface{} {
v := reflect.ValueOf(value)
reflect.ValueOf(args[n]).Elem().Set(v)
}
return nil
})
return nil
})
} else {
c.addAction(func(args []interface{}) []interface{} {
v := reflect.ValueOf(value)
switch reflect.TypeOf(args[n]).Kind() {
case reflect.Slice:
setSlice(args[n], v)
default:
reflect.ValueOf(args[n]).Elem().Set(v)
}
return nil
})
}
return c
}

Expand Down

0 comments on commit 56a15b3

Please sign in to comment.