check the options passed to transport constructor match

This commit is contained in:
Marten Seemann 2022-11-10 12:42:10 +00:00
parent d0704fdc7e
commit b90b74f3a5
2 changed files with 68 additions and 1 deletions

View File

@ -186,7 +186,7 @@ func TestTransportConstructorTCP(t *testing.T) {
func TestTransportConstructorQUIC(t *testing.T) { func TestTransportConstructorQUIC(t *testing.T) {
h, err := New( h, err := New(
Transport(quic.NewTransport), Transport(quic.NewTransport, quic.DisableReuseport()),
DisableRelay(), DisableRelay(),
) )
require.NoError(t, err) require.NoError(t, err)
@ -197,6 +197,60 @@ func TestTransportConstructorQUIC(t *testing.T) {
require.Contains(t, err.Error(), swarm.ErrNoTransport.Error()) require.Contains(t, err.Error(), swarm.ErrNoTransport.Error())
} }
type mockTransport struct{}
func (m mockTransport) Dial(context.Context, ma.Multiaddr, peer.ID) (transport.CapableConn, error) {
panic("implement me")
}
func (m mockTransport) CanDial(ma.Multiaddr) bool { panic("implement me") }
func (m mockTransport) Listen(ma.Multiaddr) (transport.Listener, error) { panic("implement me") }
func (m mockTransport) Protocols() []int { return []int{1337} }
func (m mockTransport) Proxy() bool { panic("implement me") }
var _ transport.Transport = &mockTransport{}
func TestTransportConstructorWithoutOpts(t *testing.T) {
t.Run("successful", func(t *testing.T) {
var called bool
constructor := func() transport.Transport {
called = true
return &mockTransport{}
}
h, err := New(
Transport(constructor),
DisableRelay(),
)
require.NoError(t, err)
require.True(t, called, "expected constructor to be called")
defer h.Close()
})
t.Run("with options", func(t *testing.T) {
var called bool
constructor := func() transport.Transport {
called = true
return &mockTransport{}
}
_, err := New(
Transport(constructor, tcp.DisableReuseport()),
DisableRelay(),
)
require.EqualError(t, err, "transport constructor doesn't take any options")
require.False(t, called, "didn't expected constructor to be called")
})
}
func TestTransportConstructorWithWrongOpts(t *testing.T) {
_, err := New(
Transport(quic.NewTransport, tcp.DisableReuseport()),
DisableRelay(),
)
require.EqualError(t, err, "transport option of type tcp.Option not assignable to libp2pquic.Option")
}
func TestSecurityConstructor(t *testing.T) { func TestSecurityConstructor(t *testing.T) {
h, err := New( h, err := New(
Transport(tcp.NewTCPTransport), Transport(tcp.NewTCPTransport),

View File

@ -139,6 +139,19 @@ func Transport(constructor interface{}, opts ...interface{}) Option {
typ := reflect.ValueOf(constructor).Type() typ := reflect.ValueOf(constructor).Type()
numParams := typ.NumIn() numParams := typ.NumIn()
isVariadic := typ.IsVariadic() isVariadic := typ.IsVariadic()
if !isVariadic && len(opts) > 0 {
return errors.New("transport constructor doesn't take any options")
}
if isVariadic && numParams >= 1 {
paramType := typ.In(numParams - 1).Elem()
for _, opt := range opts {
if typ := reflect.TypeOf(opt); !typ.AssignableTo(paramType) {
return fmt.Errorf("transport option of type %s not assignable to %s", typ, paramType)
}
}
}
var params []string var params []string
if isVariadic && len(opts) > 0 { if isVariadic && len(opts) > 0 {
// If there are transport options, apply the tag. // If there are transport options, apply the tag.