Skip to content

Commit

Permalink
check presence and type of transport constructor options
Browse files Browse the repository at this point in the history
  • Loading branch information
marten-seemann committed Sep 29, 2021
1 parent efb3b27 commit 605f189
Show file tree
Hide file tree
Showing 2 changed files with 46 additions and 8 deletions.
38 changes: 31 additions & 7 deletions config/reflection_magic.go
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,32 @@ func makeArgumentConstructors(fnType reflect.Type, argTypes map[reflect.Type]con
return out, nil
}

func getConstructorOpts(t reflect.Type, opts ...interface{}) ([]reflect.Value, error) {
if !t.IsVariadic() {
if len(opts) > 0 {
return nil, errors.New("constructor doesn't accept any options")
}
return nil, nil
}
if len(opts) == 0 {
return nil, nil
}
// variadic parameters always go last
wantType := t.In(t.NumIn() - 1).Elem()
values := make([]reflect.Value, 0, len(opts))
for _, opt := range opts {
val := reflect.ValueOf(opt)
if opt == nil {
return nil, errors.New("expected a transport option, got nil")
}
if val.Type() != wantType {
return nil, fmt.Errorf("expected option of type %s, got %s", wantType, reflect.TypeOf(opt))
}
values = append(values, val.Convert(wantType))
}
return values, nil
}

// makes a transport constructor.
func makeConstructor(
tpt interface{},
Expand All @@ -123,6 +149,10 @@ func makeConstructor(
if err != nil {
return nil, err
}
optValues, err := getConstructorOpts(t, opts...)
if err != nil {
return nil, err
}

return func(h host.Host, u *tptu.Upgrader, cg connmgr.ConnectionGater) (interface{}, error) {
arguments := make([]reflect.Value, 0, len(argConstructors)+len(opts))
Expand All @@ -136,13 +166,7 @@ func makeConstructor(
arguments = append(arguments, reflect.Zero(t.In(i)))
}
}
for _, opt := range opts {
// don't panic on nil options
if opt == nil {
return nil, errors.New("expected a transport option, got nil")
}
arguments = append(arguments, reflect.ValueOf(opt))
}
arguments = append(arguments, optValues...)
return callConstructor(v, arguments)
}, nil
}
16 changes: 15 additions & 1 deletion config/transport_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,20 @@ func TestTransportVariadicOptions(t *testing.T) {
require.NoError(t, err)
}

func TestConstructorWithoutOptsCalledWithOpts(t *testing.T) {
_, err := TransportConstructor(func(_ *tptu.Upgrader) transport.Transport {
return nil
}, 42)
require.EqualError(t, err, "constructor doesn't accept any options")
}

func TestConstructorWithOptsTypeMismatch(t *testing.T) {
_, err := TransportConstructor(func(_ *tptu.Upgrader, opts ...int) transport.Transport {
return nil
}, 42, "foo")
require.EqualError(t, err, "expected option of type int, got string")
}

func TestConstructorWithOpts(t *testing.T) {
var options []int
c, err := TransportConstructor(func(_ *tptu.Upgrader, opts ...int) transport.Transport {
Expand All @@ -25,5 +39,5 @@ func TestConstructorWithOpts(t *testing.T) {
require.NoError(t, err)
_, err = c(nil, nil, nil)
require.NoError(t, err)
require.Equal(t, options, []int{42, 1337})
require.Equal(t, []int{42, 1337}, options)
}

0 comments on commit 605f189

Please sign in to comment.