You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@plc4x.apache.org by sr...@apache.org on 2023/05/08 10:40:16 UTC
[plc4x] branch develop updated: test(plc4go/spi): add test for udp transport
This is an automated email from the ASF dual-hosted git repository.
sruehl pushed a commit to branch develop
in repository https://gitbox.apache.org/repos/asf/plc4x.git
The following commit(s) were added to refs/heads/develop by this push:
new 7ec93b5095 test(plc4go/spi): add test for udp transport
7ec93b5095 is described below
commit 7ec93b50953f683b88b8ae9f5a98dc2526623626
Author: Sebastian Rühl <sr...@apache.org>
AuthorDate: Mon May 8 12:40:07 2023 +0200
test(plc4go/spi): add test for udp transport
---
plc4go/spi/transports/tcp/Transport_test.go | 11 +-
plc4go/spi/transports/udp/Transport.go | 20 +-
plc4go/spi/transports/udp/Transport_test.go | 441 +++++++++++++++++++++++++++-
3 files changed, 440 insertions(+), 32 deletions(-)
diff --git a/plc4go/spi/transports/tcp/Transport_test.go b/plc4go/spi/transports/tcp/Transport_test.go
index 3e819581fa..8eb9ae8093 100644
--- a/plc4go/spi/transports/tcp/Transport_test.go
+++ b/plc4go/spi/transports/tcp/Transport_test.go
@@ -25,6 +25,7 @@ import (
"fmt"
"github.com/apache/plc4x/plc4go/spi/transports"
"github.com/stretchr/testify/assert"
+ "github.com/stretchr/testify/require"
"golang.org/x/net/nettest"
"net"
"net/url"
@@ -109,7 +110,7 @@ func TestTransportInstance_Close(t *testing.T) {
fields: fields{
tcpConn: func() *net.TCPConn {
listener, err := nettest.NewLocalListener("tcp")
- assert.NoError(t, err)
+ require.NoError(t, err)
t.Cleanup(func() {
assert.NoError(t, listener.Close())
})
@@ -117,7 +118,7 @@ func TestTransportInstance_Close(t *testing.T) {
_, _ = listener.Accept()
}()
tcp, err := net.DialTCP("tcp", nil, listener.Addr().(*net.TCPAddr))
- assert.NoError(t, err)
+ require.NoError(t, err)
t.Cleanup(func() {
// As we already closed the connection with the whole method this should error
assert.Error(t, tcp.Close())
@@ -207,7 +208,7 @@ func TestTransportInstance_ConnectWithContext(t *testing.T) {
fields: fields{
RemoteAddress: func() *net.TCPAddr {
listener, err := nettest.NewLocalListener("tcp")
- assert.NoError(t, err)
+ require.NoError(t, err)
t.Cleanup(func() {
assert.NoError(t, listener.Close())
})
@@ -401,7 +402,7 @@ func TestTransportInstance_Write(t *testing.T) {
fields: fields{
tcpConn: func() *net.TCPConn {
listener, err := nettest.NewLocalListener("tcp")
- assert.NoError(t, err)
+ require.NoError(t, err)
t.Cleanup(func() {
assert.NoError(t, listener.Close())
})
@@ -409,7 +410,7 @@ func TestTransportInstance_Write(t *testing.T) {
_, _ = listener.Accept()
}()
tcp, err := net.DialTCP("tcp", nil, listener.Addr().(*net.TCPAddr))
- assert.NoError(t, err)
+ require.NoError(t, err)
t.Cleanup(func() {
assert.NoError(t, tcp.Close())
})
diff --git a/plc4go/spi/transports/udp/Transport.go b/plc4go/spi/transports/udp/Transport.go
index d869ad621c..caefed21ba 100644
--- a/plc4go/spi/transports/udp/Transport.go
+++ b/plc4go/spi/transports/udp/Transport.go
@@ -139,11 +139,11 @@ func (m *TransportInstance) Connect() error {
func (m *TransportInstance) ConnectWithContext(ctx context.Context) error {
// If we haven't provided a local address, have the system figure it out by dialing
// the remote address and then using that connections local address as local address.
- if m.LocalAddress == nil {
+ if m.LocalAddress == nil && m.RemoteAddress != nil {
var d net.Dialer
udpTest, err := d.DialContext(ctx, "udp", m.RemoteAddress.String())
if err != nil {
- return errors.Wrap(err, "error connecting to remote address")
+ return errors.Wrapf(err, "error connecting to remote address '%s'", m.RemoteAddress)
}
m.LocalAddress = udpTest.LocalAddr().(*net.UDPAddr)
err = udpTest.Close()
@@ -156,17 +156,17 @@ func (m *TransportInstance) ConnectWithContext(ctx context.Context) error {
var err error
if m.RemoteAddress != nil {
if m.udpConn, err = net.DialUDP("udp", m.LocalAddress, m.RemoteAddress); err != nil {
- return errors.Wrap(err, "error connecting to remote address")
+ return errors.Wrapf(err, "error connecting to remote address '%s'", m.RemoteAddress)
}
- } else if m.SoReUse {
+ } else if m.SoReUse && m.LocalAddress != nil {
if packetConn, err := reuseport.ListenPacket("udp", m.LocalAddress.String()); err != nil {
- return errors.Wrap(err, "error connecting to local address")
+ return errors.Wrapf(err, "error connecting to local address '%s'", m.LocalAddress)
} else {
m.udpConn = packetConn.(*net.UDPConn)
}
} else {
if m.udpConn, err = net.ListenUDP("udp", m.LocalAddress); err != nil {
- return errors.Wrap(err, "error connecting to local address")
+ return errors.Wrapf(err, "error connecting to local address '%s'", m.LocalAddress)
}
}
@@ -251,19 +251,17 @@ func (m *TransportInstance) Write(data []byte) error {
}
var num int
var err error
- if m.RemoteAddress != nil {
-
+ if m.RemoteAddress == nil {
// TODO: usually this happens on the dial port... is there a better way to catch that?
num, err = m.udpConn.Write(data)
} else {
num, err = m.udpConn.WriteToUDP(data, m.RemoteAddress)
}
-
if err != nil {
- return errors.Wrap(err, "error writing")
+ return errors.Wrapf(err, "error writing (remote address: %s)", m.RemoteAddress)
}
if num != len(data) {
- return errors.New("error writing: not all bytes written")
+ return errors.Errorf("error writing: not all bytes written (Expected %d, Actual %d)", len(data), num)
}
return nil
}
diff --git a/plc4go/spi/transports/udp/Transport_test.go b/plc4go/spi/transports/udp/Transport_test.go
index 10fba75736..24ecb55a1a 100644
--- a/plc4go/spi/transports/udp/Transport_test.go
+++ b/plc4go/spi/transports/udp/Transport_test.go
@@ -21,9 +21,13 @@ package udp
import (
"bufio"
+ "bytes"
"context"
+ "fmt"
"github.com/apache/plc4x/plc4go/spi/transports"
"github.com/stretchr/testify/assert"
+ "github.com/stretchr/testify/require"
+ "golang.org/x/net/nettest"
"net"
"net/url"
"testing"
@@ -61,7 +65,10 @@ func TestNewTransportInstance(t *testing.T) {
args args
want *TransportInstance
}{
- // TODO: Add test cases.
+ {
+ name: "create it",
+ want: &TransportInstance{},
+ },
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
@@ -87,7 +94,29 @@ func TestTransportInstance_Close(t *testing.T) {
fields fields
wantErr bool
}{
- // TODO: Add test cases.
+ {
+ name: "close it",
+ },
+ {
+ name: "close it failing",
+ fields: fields{
+ udpConn: &net.UDPConn{},
+ },
+ wantErr: true,
+ },
+ {
+ name: "close success",
+ fields: fields{
+ udpConn: func() *net.UDPConn {
+ listener, err := nettest.NewLocalPacketListener("udp")
+ require.NoError(t, err)
+ t.Cleanup(func() {
+ assert.Error(t, listener.Close()) // Note: connection should have been closed
+ })
+ return listener.(*net.UDPConn)
+ }(),
+ },
+ },
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
@@ -122,7 +151,9 @@ func TestTransportInstance_Connect(t *testing.T) {
fields fields
wantErr bool
}{
- // TODO: Add test cases.
+ {
+ name: "connect it (error)",
+ },
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
@@ -161,7 +192,104 @@ func TestTransportInstance_ConnectWithContext(t *testing.T) {
args args
wantErr bool
}{
- // TODO: Add test cases.
+ {
+ name: "connect it",
+ args: args{ctx: context.Background()},
+ },
+ {
+ name: "connect",
+ fields: fields{
+ RemoteAddress: func() *net.UDPAddr {
+ listener, err := nettest.NewLocalPacketListener("udp")
+ require.NoError(t, err)
+ t.Logf("remote listener %#q", listener.LocalAddr())
+ t.Cleanup(func() {
+ assert.NoError(t, listener.Close())
+ })
+ return listener.LocalAddr().(*net.UDPAddr)
+ }(),
+ },
+ args: args{ctx: context.Background()},
+ },
+ {
+ name: "connect with wrong address", // TODO: not sure how to tests undialable ips here
+ fields: fields{
+ RemoteAddress: &net.UDPAddr{IP: net.IPv4(255, 255, 255, 255), Port: 12},
+ },
+ args: args{ctx: context.Background()},
+ },
+ {
+ name: "connect with localAddress",
+ fields: fields{
+ LocalAddress: func() *net.UDPAddr {
+ listener, err := nettest.NewLocalPacketListener("udp")
+ require.NoError(t, err)
+ t.Logf("local listener %#q", listener.LocalAddr())
+ t.Cleanup(func() {
+ assert.NoError(t, listener.Close())
+ })
+ return listener.LocalAddr().(*net.UDPAddr)
+ }(),
+ RemoteAddress: func() *net.UDPAddr {
+ listener, err := nettest.NewLocalPacketListener("udp")
+ require.NoError(t, err)
+ t.Logf("remote listener %#q", listener.LocalAddr())
+ t.Cleanup(func() {
+ assert.NoError(t, listener.Close())
+ })
+ return listener.LocalAddr().(*net.UDPAddr)
+ }(),
+ },
+ args: args{ctx: context.Background()},
+ wantErr: true,
+ },
+ {
+ name: "connect reuse",
+ fields: fields{
+ LocalAddress: func() *net.UDPAddr {
+ listener, err := nettest.NewLocalPacketListener("udp")
+ require.NoError(t, err)
+ t.Logf("local listener %#q", listener.LocalAddr())
+ assert.NoError(t, listener.Close()) // We close directly again
+ return listener.LocalAddr().(*net.UDPAddr)
+ }(),
+ SoReUse: true,
+ },
+ args: args{ctx: context.Background()},
+ },
+ {
+ name: "connect reuse (used)",
+ fields: fields{
+ LocalAddress: func() *net.UDPAddr {
+ listener, err := nettest.NewLocalPacketListener("udp")
+ require.NoError(t, err)
+ t.Logf("local listener %#q", listener.LocalAddr())
+ t.Cleanup(func() {
+ assert.NoError(t, listener.Close())
+ })
+ return listener.LocalAddr().(*net.UDPAddr)
+ }(),
+ SoReUse: true,
+ },
+ args: args{ctx: context.Background()},
+ wantErr: true,
+ },
+ {
+ name: "connect reuse (used)",
+ fields: fields{
+ LocalAddress: func() *net.UDPAddr {
+ listener, err := nettest.NewLocalPacketListener("udp")
+ require.NoError(t, err)
+ t.Logf("local listener %#q", listener.LocalAddr())
+ t.Cleanup(func() {
+ assert.NoError(t, listener.Close())
+ })
+ return listener.LocalAddr().(*net.UDPAddr)
+ }(),
+ },
+ args: args{ctx: context.Background()},
+ wantErr: true,
+ },
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
@@ -200,7 +328,21 @@ func TestTransportInstance_FillBuffer(t *testing.T) {
args args
wantErr bool
}{
- // TODO: Add test cases.
+ {
+ name: "do it",
+ wantErr: true,
+ },
+ {
+ name: "do it with reader",
+ fields: fields{
+ reader: bufio.NewReader(bytes.NewReader([]byte{1, 2, 3, 4})),
+ },
+ args: args{
+ until: func(pos uint, currentByte byte, reader *bufio.Reader) bool {
+ return pos < 2
+ },
+ },
+ },
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
@@ -236,7 +378,16 @@ func TestTransportInstance_GetNumBytesAvailableInBuffer(t *testing.T) {
want uint32
wantErr bool
}{
- // TODO: Add test cases.
+ {
+ name: "get em",
+ fields: fields{
+ reader: bufio.NewReader(bytes.NewReader([]byte{1, 2, 3, 4})),
+ },
+ want: 4,
+ },
+ {
+ name: "get em (no reader)",
+ },
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
@@ -276,7 +427,9 @@ func TestTransportInstance_IsConnected(t *testing.T) {
fields fields
want bool
}{
- // TODO: Add test cases.
+ {
+ name: "check it",
+ },
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
@@ -316,7 +469,27 @@ func TestTransportInstance_PeekReadableBytes(t *testing.T) {
want []byte
wantErr bool
}{
- // TODO: Add test cases.
+ {
+ name: "peek it",
+ fields: fields{
+ reader: bufio.NewReader(bytes.NewReader([]byte{1, 2, 3, 4})),
+ },
+ want: []byte{},
+ },
+ {
+ name: "peek it 3",
+ fields: fields{
+ reader: bufio.NewReader(bytes.NewReader([]byte{1, 2, 3, 4})),
+ },
+ args: args{
+ numBytes: 3,
+ },
+ want: []byte{1, 2, 3},
+ },
+ {
+ name: "peek it (no reader)",
+ wantErr: true,
+ },
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
@@ -361,7 +534,37 @@ func TestTransportInstance_Read(t *testing.T) {
want []byte
wantErr bool
}{
- // TODO: Add test cases.
+ {
+ name: "read it",
+ fields: fields{
+ reader: bufio.NewReader(bytes.NewReader([]byte{1, 2, 3, 4})),
+ },
+ want: []byte{},
+ },
+ {
+ name: "read it 3",
+ fields: fields{
+ reader: bufio.NewReader(bytes.NewReader([]byte{1, 2, 3, 4})),
+ },
+ args: args{
+ numBytes: 3,
+ },
+ want: []byte{1, 2, 3},
+ },
+ {
+ name: "read it 5",
+ fields: fields{
+ reader: bufio.NewReader(bytes.NewReader([]byte{1, 2, 3, 4})),
+ },
+ args: args{
+ numBytes: 5,
+ },
+ wantErr: true,
+ },
+ {
+ name: "read it (no reader available)",
+ wantErr: true,
+ },
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
@@ -401,7 +604,18 @@ func TestTransportInstance_String(t *testing.T) {
fields fields
want string
}{
- // TODO: Add test cases.
+ {
+ name: "string it",
+ want: "udp:<nil>-><nil>",
+ },
+ {
+ name: "string it with content",
+ fields: fields{
+ LocalAddress: &net.UDPAddr{IP: net.IPv4(1, 2, 3, 4), Port: 5},
+ RemoteAddress: &net.UDPAddr{IP: net.IPv4(6, 7, 8, 9), Port: 10},
+ },
+ want: "udp:1.2.3.4:5->6.7.8.9:10",
+ },
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
@@ -440,7 +654,45 @@ func TestTransportInstance_Write(t *testing.T) {
args args
wantErr bool
}{
- // TODO: Add test cases.
+ {
+ name: "write it (no con)",
+ wantErr: true,
+ },
+ {
+ name: "write it",
+ fields: fields{
+ udpConn: func() *net.UDPConn {
+ listener, err := nettest.NewLocalPacketListener("udp")
+ require.NoError(t, err)
+ t.Cleanup(func() {
+ assert.NoError(t, listener.Close())
+ })
+ udp, err := net.DialUDP("udp", nil, listener.LocalAddr().(*net.UDPAddr))
+ require.NoError(t, err)
+ return udp
+ }(),
+ },
+ },
+ {
+ name: "write it with remote",
+ fields: func() fields {
+ listener, err := nettest.NewLocalPacketListener("udp")
+ require.NoError(t, err)
+ t.Cleanup(func() {
+ assert.NoError(t, listener.Close())
+ })
+ remoteAddress := listener.LocalAddr().(*net.UDPAddr)
+ return fields{
+ RemoteAddress: remoteAddress,
+ udpConn: func() *net.UDPConn {
+ udp, err := net.ListenUDP("udp", nil)
+ require.NoError(t, err)
+ return udp
+ }(),
+ }
+ }(),
+ args: args{data: []byte{1, 2, 3, 4}},
+ },
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
@@ -471,7 +723,18 @@ func TestTransport_CreateTransportInstance(t *testing.T) {
want transports.TransportInstance
wantErr bool
}{
- // TODO: Add test cases.
+ {
+ name: "create it",
+ want: func() transports.TransportInstance {
+ remoteAddress, err := net.ResolveUDPAddr("udp", ":0")
+ require.NoError(t, err)
+ return &TransportInstance{
+ ConnectTimeout: 1000,
+ RemoteAddress: remoteAddress,
+ transport: NewTransport(),
+ }
+ }(),
+ },
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
@@ -500,7 +763,144 @@ func TestTransport_CreateTransportInstanceForLocalAddress(t *testing.T) {
want transports.TransportInstance
wantErr bool
}{
- // TODO: Add test cases.
+ {
+ name: "Create it",
+ want: &TransportInstance{
+ transport: NewTransport(),
+ RemoteAddress: &net.UDPAddr{},
+ ConnectTimeout: 1000,
+ },
+ },
+ {
+ name: "Create it with transport url",
+ args: args{
+ transportUrl: url.URL{Host: "127.0.0.1:123"},
+ },
+ want: func() transports.TransportInstance {
+ udpAddr, err := net.ResolveUDPAddr("udp", fmt.Sprintf("%s:%d", "127.0.0.1", 123))
+ assert.NoError(t, err)
+ ti := &TransportInstance{
+ transport: NewTransport(),
+ RemoteAddress: udpAddr,
+ ConnectTimeout: 1000,
+ }
+ return ti
+ }(),
+ },
+ {
+ name: "Create it with transport url (named host)",
+ args: args{
+ transportUrl: url.URL{Host: "localhost:123"},
+ },
+ want: func() transports.TransportInstance {
+ udpAddr, err := net.ResolveUDPAddr("udp", fmt.Sprintf("%s:%d", "localhost", 123))
+ assert.NoError(t, err)
+ ti := &TransportInstance{
+ transport: NewTransport(),
+ RemoteAddress: udpAddr,
+ ConnectTimeout: 1000,
+ }
+ return ti
+ }(),
+ },
+ {
+ name: "Create it with transport url (without port)",
+ args: args{
+ transportUrl: url.URL{Host: "127.0.0.1"},
+ },
+ wantErr: true,
+ },
+ {
+ name: "Create it with transport url (with nonsense port)",
+ args: args{
+ transportUrl: url.URL{Host: "127.0.0.1:banana"},
+ },
+ wantErr: true,
+ },
+ {
+ name: "Create it with transport url (with default port)",
+ args: args{
+ transportUrl: url.URL{Host: "127.0.0.1"},
+ options: map[string][]string{
+ "defaultUdpPort": {"123"},
+ },
+ },
+ want: func() transports.TransportInstance {
+ udpAddr, err := net.ResolveUDPAddr("udp", fmt.Sprintf("%s:%d", "127.0.0.1", 123))
+ assert.NoError(t, err)
+ ti := &TransportInstance{
+ transport: NewTransport(),
+ RemoteAddress: udpAddr,
+ ConnectTimeout: 1000,
+ }
+ return ti
+ }(),
+ },
+ {
+ name: "Create it with transport url (with broken default port)",
+ args: args{
+ transportUrl: url.URL{Host: "127.0.0.1"},
+ options: map[string][]string{
+ "defaultTcpPort": {"default"},
+ },
+ },
+ wantErr: true,
+ },
+ {
+ name: "Create it with transport url (with default port and connection timeout and reuse)",
+ args: args{
+ transportUrl: url.URL{Host: "127.0.0.1"},
+ options: map[string][]string{
+ "defaultUdpPort": {"123"},
+ "connect-timeout": {"123"},
+ "so-reuse": {"true"},
+ },
+ },
+ want: func() transports.TransportInstance {
+ udpAddr, err := net.ResolveUDPAddr("udp", fmt.Sprintf("%s:%d", "127.0.0.1", 123))
+ assert.NoError(t, err)
+ ti := &TransportInstance{
+ transport: NewTransport(),
+ RemoteAddress: udpAddr,
+ ConnectTimeout: 123,
+ SoReUse: true,
+ }
+ return ti
+ }(),
+ },
+ {
+ name: "Create it with transport url (with default port and connection timeout and reuse broken)",
+ args: args{
+ transportUrl: url.URL{Host: "127.0.0.1"},
+ options: map[string][]string{
+ "defaultUdpPort": {"123"},
+ "connect-timeout": {"123"},
+ "so-reuse": {"banana"},
+ },
+ },
+ wantErr: true,
+ },
+ {
+ name: "Create it with transport url (with default port and connection timeout broken)",
+ args: args{
+ transportUrl: url.URL{Host: "127.0.0.1"},
+ options: map[string][]string{
+ "defaultUdpPort": {"123"},
+ "connect-timeout": {"banana"},
+ },
+ },
+ wantErr: true,
+ },
+ {
+ name: "Create it with unresolvable host",
+ args: args{
+ transportUrl: url.URL{Host: "plc4xhostnothere"},
+ options: map[string][]string{
+ "defaultUdpPort": {"123"},
+ },
+ },
+ wantErr: true,
+ },
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
@@ -522,7 +922,10 @@ func TestTransport_GetTransportCode(t *testing.T) {
name string
want string
}{
- // TODO: Add test cases.
+ {
+ name: "get it",
+ want: "udp",
+ },
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
@@ -539,7 +942,10 @@ func TestTransport_GetTransportName(t *testing.T) {
name string
want string
}{
- // TODO: Add test cases.
+ {
+ name: "get it",
+ want: "UDP Datagram Transport",
+ },
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
@@ -556,7 +962,10 @@ func TestTransport_String(t *testing.T) {
name string
want string
}{
- // TODO: Add test cases.
+ {
+ name: "string it",
+ want: "udp(UDP Datagram Transport)",
+ },
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {