feat(wip): test reworks (need to add back traffic logger tests)

This commit is contained in:
Toby 2023-07-26 15:51:48 -07:00
parent dd836b4496
commit 6172f2ac53
7 changed files with 131 additions and 618 deletions

View file

@ -109,12 +109,12 @@ func (c *clientImpl) connect() error {
_ = conn.CloseWithError(closeErrCodeProtocolError, "")
}
_ = pktConn.Close()
return &coreErrs.ConnectError{Err: err}
return coreErrs.ConnectError{Err: err}
}
if resp.StatusCode != protocol.StatusAuthOK {
_ = conn.CloseWithError(closeErrCodeProtocolError, "")
_ = pktConn.Close()
return &coreErrs.AuthError{StatusCode: resp.StatusCode}
return coreErrs.AuthError{StatusCode: resp.StatusCode}
}
// Auth OK
udpEnabled, serverRx := protocol.AuthResponseDataFromHeader(resp.Header)

View file

@ -92,8 +92,8 @@ func TestClientServerTCPClose(t *testing.T) {
_ = conn.Close()
}
// TestServerUDPIdleTimeout tests whether the server's UDP idle timeout works correctly.
func TestServerUDPIdleTimeout(t *testing.T) {
// TestClientServerUDPIdleTimeout tests whether the server's UDP idle timeout works correctly.
func TestClientServerUDPIdleTimeout(t *testing.T) {
// Create server
udpConn, udpAddr, err := serverConn()
assert.NoError(t, err)

View file

@ -22,7 +22,7 @@ import (
// TestServerMasquerade is a test to ensure that the server behaves as a normal
// HTTP/3 server when dealing with an unauthenticated client. This is mainly to
// confirm that the server does not expose itself to active probers.
// confirm that the server does not expose itself to active probing.
func TestServerMasquerade(t *testing.T) {
// Create server
udpConn, udpAddr, err := serverConn()

View file

@ -1,43 +1,30 @@
package integration_tests
import (
"errors"
"io"
"net"
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/mock"
"github.com/apernet/hysteria/core/client"
coreErrs "github.com/apernet/hysteria/core/errors"
"github.com/apernet/hysteria/core/internal/integration_tests/mocks"
"github.com/apernet/hysteria/core/server"
)
// Smoke tests that act as a sanity check for client & server to ensure they can talk to each other correctly.
// TestClientNoServer tests how the client handles a server that doesn't exist.
// The client should still be able to be created, but TCP & UDP requests should fail.
// TestClientNoServer tests how the client handles a server address it cannot connect to.
// NewClient should return a ConnectError.
func TestClientNoServer(t *testing.T) {
// Create client
c, err := client.NewClient(&client.Config{
ServerAddr: &net.UDPAddr{IP: net.IPv4(127, 0, 0, 1), Port: 14514},
ServerAddr: &net.UDPAddr{IP: net.IPv4(127, 0, 0, 1), Port: 55666},
})
if err != nil {
t.Fatal("error creating client:", err)
}
defer c.Close()
var cErr *coreErrs.ConnectError
// Try TCP
_, err = c.TCP("google.com:443")
if !errors.As(err, &cErr) {
t.Fatal("expected connect error from TCP")
}
// Try UDP
_, err = c.UDP()
if !errors.As(err, &cErr) {
t.Fatal("expected connect error from DialUDP")
}
assert.Nil(t, c)
_, ok := err.(coreErrs.ConnectError)
assert.True(t, ok)
}
// TestClientServerBadAuth tests two things:
@ -45,79 +32,82 @@ func TestClientNoServer(t *testing.T) {
// - How the client handles failed authentication.
func TestClientServerBadAuth(t *testing.T) {
// Create server
udpAddr := &net.UDPAddr{IP: net.IPv4(127, 0, 0, 1), Port: 14514}
udpConn, err := net.ListenUDP("udp", udpAddr)
if err != nil {
t.Fatal("error creating server:", err)
}
udpConn, udpAddr, err := serverConn()
assert.NoError(t, err)
auth := mocks.NewMockAuthenticator(t)
auth.EXPECT().Authenticate(mock.Anything, "badpassword", uint64(0)).Return(false, "").Once()
s, err := server.NewServer(&server.Config{
TLSConfig: serverTLSConfig(),
Conn: udpConn,
Authenticator: &pwAuthenticator{
Password: "correct password",
ID: "nobody",
},
TLSConfig: serverTLSConfig(),
Conn: udpConn,
Authenticator: auth,
})
if err != nil {
t.Fatal("error creating server:", err)
}
assert.NoError(t, err)
defer s.Close()
go s.Serve()
// Create client
c, err := client.NewClient(&client.Config{
ServerAddr: udpAddr,
Auth: "wrong password",
Auth: "badpassword",
TLSConfig: client.TLSConfig{InsecureSkipVerify: true},
})
if err != nil {
t.Fatal("error creating client:", err)
}
assert.Nil(t, c)
_, ok := err.(coreErrs.AuthError)
assert.True(t, ok)
}
// TestClientServerUDPDisabled tests how the client handles a server that does not support UDP.
// UDP should return a DialError.
func TestClientServerUDPDisabled(t *testing.T) {
// Create server
udpConn, udpAddr, err := serverConn()
assert.NoError(t, err)
auth := mocks.NewMockAuthenticator(t)
auth.EXPECT().Authenticate(mock.Anything, mock.Anything, mock.Anything).Return(true, "nobody")
s, err := server.NewServer(&server.Config{
TLSConfig: serverTLSConfig(),
Conn: udpConn,
DisableUDP: true,
Authenticator: auth,
})
assert.NoError(t, err)
defer s.Close()
go s.Serve()
// Create client
c, err := client.NewClient(&client.Config{
ServerAddr: udpAddr,
TLSConfig: client.TLSConfig{InsecureSkipVerify: true},
})
assert.NoError(t, err)
defer c.Close()
var aErr *coreErrs.AuthError
// Try TCP
_, err = c.TCP("google.com:443")
if !errors.As(err, &aErr) {
t.Fatal("expected auth error from TCP")
}
// Try UDP
_, err = c.UDP()
if !errors.As(err, &aErr) {
t.Fatal("expected auth error from DialUDP")
}
conn, err := c.UDP()
assert.Nil(t, conn)
_, ok := err.(coreErrs.DialError)
assert.True(t, ok)
}
// TestClientServerTCPEcho tests TCP forwarding using a TCP echo server.
func TestClientServerTCPEcho(t *testing.T) {
// Create server
udpAddr := &net.UDPAddr{IP: net.IPv4(127, 0, 0, 1), Port: 14514}
udpConn, err := net.ListenUDP("udp", udpAddr)
if err != nil {
t.Fatal("error creating server:", err)
}
udpConn, udpAddr, err := serverConn()
assert.NoError(t, err)
auth := mocks.NewMockAuthenticator(t)
auth.EXPECT().Authenticate(mock.Anything, mock.Anything, mock.Anything).Return(true, "nobody")
s, err := server.NewServer(&server.Config{
TLSConfig: serverTLSConfig(),
Conn: udpConn,
Authenticator: &pwAuthenticator{
Password: "password",
ID: "nobody",
},
TLSConfig: serverTLSConfig(),
Conn: udpConn,
Authenticator: auth,
})
if err != nil {
t.Fatal("error creating server:", err)
}
assert.NoError(t, err)
defer s.Close()
go s.Serve()
// Create TCP echo server
echoTCPAddr := &net.TCPAddr{IP: net.IPv4(127, 0, 0, 1), Port: 14515}
echoListener, err := net.ListenTCP("tcp", echoTCPAddr)
if err != nil {
t.Fatal("error creating TCP echo server:", err)
}
echoAddr := "127.0.0.1:22333"
echoListener, err := net.Listen("tcp", echoAddr)
assert.NoError(t, err)
echoServer := &tcpEchoServer{Listener: echoListener}
defer echoServer.Close()
go echoServer.Serve()
@ -125,65 +115,46 @@ func TestClientServerTCPEcho(t *testing.T) {
// Create client
c, err := client.NewClient(&client.Config{
ServerAddr: udpAddr,
Auth: "password",
TLSConfig: client.TLSConfig{InsecureSkipVerify: true},
})
if err != nil {
t.Fatal("error creating client:", err)
}
assert.NoError(t, err)
defer c.Close()
// Dial TCP
conn, err := c.TCP(echoTCPAddr.String())
if err != nil {
t.Fatal("error dialing TCP:", err)
}
conn, err := c.TCP(echoAddr)
assert.NoError(t, err)
defer conn.Close()
// Send and receive data
sData := []byte("hello world")
_, err = conn.Write(sData)
if err != nil {
t.Fatal("error writing to TCP:", err)
}
assert.NoError(t, err)
rData := make([]byte, len(sData))
_, err = io.ReadFull(conn, rData)
if err != nil {
t.Fatal("error reading from TCP:", err)
}
if string(rData) != string(sData) {
t.Fatalf("expected %q, got %q", sData, rData)
}
assert.NoError(t, err)
assert.Equal(t, sData, rData)
}
// TestClientServerUDPEcho tests UDP forwarding using a UDP echo server.
func TestClientServerUDPEcho(t *testing.T) {
// Create server
udpAddr := &net.UDPAddr{IP: net.IPv4(127, 0, 0, 1), Port: 14514}
udpConn, err := net.ListenUDP("udp", udpAddr)
if err != nil {
t.Fatal("error creating server:", err)
}
udpConn, udpAddr, err := serverConn()
assert.NoError(t, err)
auth := mocks.NewMockAuthenticator(t)
auth.EXPECT().Authenticate(mock.Anything, mock.Anything, mock.Anything).Return(true, "nobody")
s, err := server.NewServer(&server.Config{
TLSConfig: serverTLSConfig(),
Conn: udpConn,
Authenticator: &pwAuthenticator{
Password: "password",
ID: "nobody",
},
TLSConfig: serverTLSConfig(),
Conn: udpConn,
Authenticator: auth,
})
if err != nil {
t.Fatal("error creating server:", err)
}
assert.NoError(t, err)
defer s.Close()
go s.Serve()
// Create UDP echo server
echoUDPAddr := &net.UDPAddr{IP: net.IPv4(127, 0, 0, 1), Port: 55555}
echoConn, err := net.ListenUDP("udp", echoUDPAddr)
if err != nil {
t.Fatal("error creating UDP echo server:", err)
}
echoAddr := "127.0.0.1:22333"
echoConn, err := net.ListenPacket("udp", echoAddr)
assert.NoError(t, err)
echoServer := &udpEchoServer{Conn: echoConn}
defer echoServer.Close()
go echoServer.Serve()
@ -191,35 +162,22 @@ func TestClientServerUDPEcho(t *testing.T) {
// Create client
c, err := client.NewClient(&client.Config{
ServerAddr: udpAddr,
Auth: "password",
TLSConfig: client.TLSConfig{InsecureSkipVerify: true},
})
if err != nil {
t.Fatal("error creating client:", err)
}
assert.NoError(t, err)
defer c.Close()
// Listen UDP
conn, err := c.UDP()
if err != nil {
t.Fatal("error listening UDP:", err)
}
assert.NoError(t, err)
defer conn.Close()
// Send and receive data
sData := []byte("hello world")
err = conn.Send(sData, echoUDPAddr.String())
if err != nil {
t.Fatal("error sending UDP:", err)
}
err = conn.Send(sData, echoAddr)
assert.NoError(t, err)
rData, rAddr, err := conn.Receive()
if err != nil {
t.Fatal("error receiving UDP:", err)
}
if string(rData) != string(sData) {
t.Fatalf("expected %q, got %q", sData, rData)
}
if rAddr != echoUDPAddr.String() {
t.Fatalf("expected %q, got %q", echoUDPAddr.String(), rAddr)
}
assert.NoError(t, err)
assert.Equal(t, sData, rData)
assert.Equal(t, echoAddr, rAddr)
}

View file

@ -9,9 +9,12 @@ import (
"sync"
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/mock"
"golang.org/x/time/rate"
"github.com/apernet/hysteria/core/client"
"github.com/apernet/hysteria/core/internal/integration_tests/mocks"
"github.com/apernet/hysteria/core/server"
)
@ -26,9 +29,7 @@ func (s *tcpStressor) Run(t *testing.T) {
// Make some random data
sData := make([]byte, s.Size)
_, err := rand.Read(sData)
if err != nil {
t.Fatal("error generating random data:", err)
}
assert.NoError(t, err)
// Run iterations
for i := 0; i < s.Iterations; i++ {
@ -57,9 +58,7 @@ func (s *tcpStressor) Run(t *testing.T) {
}
wg.Wait()
if len(errChan) > 0 {
t.Fatal("error reading from TCP:", <-errChan)
}
assert.Empty(t, errChan)
}
}
@ -76,9 +75,7 @@ func (s *udpStressor) Run(t *testing.T) {
// Make some random data
sData := make([]byte, s.Size)
_, err := rand.Read(sData)
if err != nil {
t.Fatal("error generating random data:", err)
}
assert.NoError(t, err)
// Due to UDP's unreliability, we need to limit the rate of sending
// to reduce packet loss. This is hardcoded to 1 MiB/s for now.
@ -123,39 +120,29 @@ func (s *udpStressor) Run(t *testing.T) {
}
wg.Wait()
if len(errChan) > 0 {
t.Fatal("error reading from UDP:", <-errChan)
}
assert.Empty(t, errChan)
}
}
func TestClientServerTCPStress(t *testing.T) {
// Create server
udpAddr := &net.UDPAddr{IP: net.IPv4(127, 0, 0, 1), Port: 14514}
udpConn, err := net.ListenUDP("udp", udpAddr)
if err != nil {
t.Fatal("error creating server:", err)
}
udpConn, udpAddr, err := serverConn()
assert.NoError(t, err)
auth := mocks.NewMockAuthenticator(t)
auth.EXPECT().Authenticate(mock.Anything, mock.Anything, mock.Anything).Return(true, "nobody")
s, err := server.NewServer(&server.Config{
TLSConfig: serverTLSConfig(),
Conn: udpConn,
Authenticator: &pwAuthenticator{
Password: "password",
ID: "nobody",
},
TLSConfig: serverTLSConfig(),
Conn: udpConn,
Authenticator: auth,
})
if err != nil {
t.Fatal("error creating server:", err)
}
assert.NoError(t, err)
defer s.Close()
go s.Serve()
// Create TCP echo server
echoTCPAddr := &net.TCPAddr{IP: net.IPv4(127, 0, 0, 1), Port: 14515}
echoListener, err := net.ListenTCP("tcp", echoTCPAddr)
if err != nil {
t.Fatal("error creating TCP echo server:", err)
}
echoAddr := "127.0.0.1:22333"
echoListener, err := net.Listen("tcp", echoAddr)
assert.NoError(t, err)
echoServer := &tcpEchoServer{Listener: echoListener}
defer echoServer.Close()
go echoServer.Serve()
@ -163,16 +150,13 @@ func TestClientServerTCPStress(t *testing.T) {
// Create client
c, err := client.NewClient(&client.Config{
ServerAddr: udpAddr,
Auth: "password",
TLSConfig: client.TLSConfig{InsecureSkipVerify: true},
})
if err != nil {
t.Fatal("error creating client:", err)
}
assert.NoError(t, err)
defer c.Close()
dialFunc := func() (net.Conn, error) {
return c.TCP(echoTCPAddr.String())
return c.TCP(echoAddr)
}
t.Run("Single 500m", (&tcpStressor{DialFunc: dialFunc, Size: 524288000, Parallel: 1, Iterations: 1}).Run)
@ -186,49 +170,38 @@ func TestClientServerTCPStress(t *testing.T) {
func TestClientServerUDPStress(t *testing.T) {
// Create server
udpAddr := &net.UDPAddr{IP: net.IPv4(127, 0, 0, 1), Port: 14514}
udpConn, err := net.ListenUDP("udp", udpAddr)
if err != nil {
t.Fatal("error creating server:", err)
}
udpConn, udpAddr, err := serverConn()
assert.NoError(t, err)
auth := mocks.NewMockAuthenticator(t)
auth.EXPECT().Authenticate(mock.Anything, mock.Anything, mock.Anything).Return(true, "nobody")
s, err := server.NewServer(&server.Config{
TLSConfig: serverTLSConfig(),
Conn: udpConn,
Authenticator: &pwAuthenticator{
Password: "password",
ID: "nobody",
},
TLSConfig: serverTLSConfig(),
Conn: udpConn,
Authenticator: auth,
})
if err != nil {
t.Fatal("error creating server:", err)
}
assert.NoError(t, err)
defer s.Close()
go s.Serve()
// Create UDP echo server
echoUDPAddr := &net.UDPAddr{IP: net.IPv4(127, 0, 0, 1), Port: 14515}
echoListener, err := net.ListenUDP("udp", echoUDPAddr)
if err != nil {
t.Fatal("error creating UDP echo server:", err)
}
echoServer := &udpEchoServer{Conn: echoListener}
echoAddr := "127.0.0.1:22333"
echoConn, err := net.ListenPacket("udp", echoAddr)
assert.NoError(t, err)
echoServer := &udpEchoServer{Conn: echoConn}
defer echoServer.Close()
go echoServer.Serve()
// Create client
c, err := client.NewClient(&client.Config{
ServerAddr: udpAddr,
Auth: "password",
TLSConfig: client.TLSConfig{InsecureSkipVerify: true},
})
if err != nil {
t.Fatal("error creating client:", err)
}
assert.NoError(t, err)
defer c.Close()
t.Run("Single 1000x100b", (&udpStressor{
ListenFunc: c.UDP,
ServerAddr: echoUDPAddr.String(),
ServerAddr: echoAddr,
Size: 100,
Count: 1000,
Parallel: 1,
@ -236,7 +209,7 @@ func TestClientServerUDPStress(t *testing.T) {
}).Run)
t.Run("Single 1000x3k", (&udpStressor{
ListenFunc: c.UDP,
ServerAddr: echoUDPAddr.String(),
ServerAddr: echoAddr,
Size: 3000,
Count: 1000,
Parallel: 1,
@ -245,7 +218,7 @@ func TestClientServerUDPStress(t *testing.T) {
t.Run("5 Sequential 1000x100b", (&udpStressor{
ListenFunc: c.UDP,
ServerAddr: echoUDPAddr.String(),
ServerAddr: echoAddr,
Size: 100,
Count: 1000,
Parallel: 1,
@ -253,7 +226,7 @@ func TestClientServerUDPStress(t *testing.T) {
}).Run)
t.Run("5 Sequential 200x3k", (&udpStressor{
ListenFunc: c.UDP,
ServerAddr: echoUDPAddr.String(),
ServerAddr: echoAddr,
Size: 3000,
Count: 200,
Parallel: 1,
@ -262,7 +235,7 @@ func TestClientServerUDPStress(t *testing.T) {
t.Run("2 Sequential 5 Parallel 1000x100b", (&udpStressor{
ListenFunc: c.UDP,
ServerAddr: echoUDPAddr.String(),
ServerAddr: echoAddr,
Size: 100,
Count: 1000,
Parallel: 5,
@ -271,19 +244,10 @@ func TestClientServerUDPStress(t *testing.T) {
t.Run("2 Sequential 5 Parallel 200x3k", (&udpStressor{
ListenFunc: c.UDP,
ServerAddr: echoUDPAddr.String(),
ServerAddr: echoAddr,
Size: 3000,
Count: 200,
Parallel: 5,
Iterations: 2,
}).Run)
t.Run("10 Sequential 5 Parallel 200x3k", (&udpStressor{
ListenFunc: c.UDP,
ServerAddr: echoUDPAddr.String(),
Size: 3000,
Count: 200,
Parallel: 5,
Iterations: 10,
}).Run)
}

View file

@ -1,173 +0,0 @@
package integration_tests
import (
"io"
"net"
"sync/atomic"
"testing"
"github.com/apernet/hysteria/core/client"
"github.com/apernet/hysteria/core/server"
)
type testTrafficLogger struct {
Tx, Rx uint64
Block atomic.Bool
}
func (l *testTrafficLogger) Log(id string, tx, rx uint64) bool {
atomic.AddUint64(&l.Tx, tx)
atomic.AddUint64(&l.Rx, rx)
return !l.Block.Load()
}
func (l *testTrafficLogger) Get() (tx, rx uint64) {
return atomic.LoadUint64(&l.Tx), atomic.LoadUint64(&l.Rx)
}
func (l *testTrafficLogger) SetBlock(block bool) {
l.Block.Store(block)
}
func (l *testTrafficLogger) Reset() {
atomic.StoreUint64(&l.Tx, 0)
atomic.StoreUint64(&l.Rx, 0)
}
// TestServerTrafficLogger tests that the server's TrafficLogger interface is working correctly.
// More specifically, it tests that the server is correctly logging traffic in both directions,
// and that it is correctly disconnecting clients when the traffic logger returns false.
func TestServerTrafficLogger(t *testing.T) {
tl := &testTrafficLogger{}
// Create server
udpAddr := &net.UDPAddr{IP: net.IPv4(127, 0, 0, 1), Port: 14514}
udpConn, err := net.ListenUDP("udp", udpAddr)
if err != nil {
t.Fatal("error creating server:", err)
}
s, err := server.NewServer(&server.Config{
TLSConfig: serverTLSConfig(),
Conn: udpConn,
Authenticator: &pwAuthenticator{
Password: "password",
ID: "nobody",
},
TrafficLogger: tl,
})
if err != nil {
t.Fatal("error creating server:", err)
}
defer s.Close()
go s.Serve()
// Create TCP double echo server
// We use double echo to test that the traffic logger is correctly logging both directions.
echoTCPAddr := &net.TCPAddr{IP: net.IPv4(127, 0, 0, 1), Port: 14515}
echoListener, err := net.ListenTCP("tcp", echoTCPAddr)
if err != nil {
t.Fatal("error creating TCP echo server:", err)
}
tEchoServer := &tcpDoubleEchoServer{Listener: echoListener}
defer tEchoServer.Close()
go tEchoServer.Serve()
// Create client
c, err := client.NewClient(&client.Config{
ServerAddr: udpAddr,
Auth: "password",
TLSConfig: client.TLSConfig{InsecureSkipVerify: true},
})
if err != nil {
t.Fatal("error creating client:", err)
}
defer c.Close()
// Dial TCP
tConn, err := c.TCP(echoTCPAddr.String())
if err != nil {
t.Fatal("error dialing TCP:", err)
}
defer tConn.Close()
// Send and receive TCP data
sData := []byte("1234")
_, err = tConn.Write(sData)
if err != nil {
t.Fatal("error writing to TCP:", err)
}
rData := make([]byte, len(sData)*2)
_, err = io.ReadFull(tConn, rData)
if err != nil {
t.Fatal("error reading from TCP:", err)
}
expected := string(sData) + string(sData)
if string(rData) != expected {
t.Fatalf("expected %q, got %q", expected, string(rData))
}
// Check traffic logger
tx, rx := tl.Get()
if tx != uint64(len(sData)) || rx != uint64(len(rData)) {
t.Fatalf("expected TrafficLogger Tx=%d, Rx=%d, got Tx=%d, Rx=%d", len(sData), len(rData), tx, rx)
}
tl.Reset()
// Create UDP double echo server
echoUDPAddr := &net.UDPAddr{IP: net.IPv4(127, 0, 0, 1), Port: 55555}
echoConn, err := net.ListenUDP("udp", echoUDPAddr)
if err != nil {
t.Fatal("error creating UDP echo server:", err)
}
uEchoServer := &udpDoubleEchoServer{Conn: echoConn}
defer uEchoServer.Close()
go uEchoServer.Serve()
// Listen UDP
uConn, err := c.UDP()
if err != nil {
t.Fatal("error listening UDP:", err)
}
defer uConn.Close()
// Send and receive UDP data
sData = []byte("gucci gang")
err = uConn.Send(sData, echoUDPAddr.String())
if err != nil {
t.Fatal("error sending UDP:", err)
}
for i := 0; i < 2; i++ {
rData, rAddr, err := uConn.Receive()
if err != nil {
t.Fatal("error receiving UDP:", err)
}
if string(rData) != string(sData) {
t.Fatalf("expected %q, got %q", string(sData), string(rData))
}
if rAddr != echoUDPAddr.String() {
t.Fatalf("expected %q, got %q", echoUDPAddr.String(), rAddr)
}
}
// Check traffic logger
tx, rx = tl.Get()
if tx != uint64(len(sData)) || rx != uint64(len(sData)*2) {
t.Fatalf("expected TrafficLogger Tx=%d, Rx=%d, got Tx=%d, Rx=%d", len(sData), len(sData)*2, tx, rx)
}
// Check the disconnect client functionality
tl.SetBlock(true)
// Send and receive TCP data again
sData = []byte("1234")
_, err = tConn.Write(sData)
if err != nil {
t.Fatal("error writing to TCP:", err)
}
// This should fail instantly without reading any data
// io.Copy should return nil as EOF is treated as a non-error though
n, err := io.Copy(io.Discard, tConn)
if n != 0 || err != nil {
t.Fatal("expected 0 bytes read and nil error, got", n, err)
}
}

View file

@ -1,7 +1,6 @@
package integration_tests
import (
"bytes"
"crypto/tls"
"io"
"net"
@ -35,18 +34,6 @@ func serverConn() (net.PacketConn, net.Addr, error) {
return udpConn, udpAddr, nil
}
type pwAuthenticator struct {
Password string
ID string
}
func (a *pwAuthenticator) Authenticate(addr net.Addr, auth string, tx uint64) (ok bool, id string) {
if auth != a.Password {
return false, ""
}
return true, a.ID
}
// tcpEchoServer is a TCP server that echoes what it reads from the connection.
// It will never actively close the connection.
type tcpEchoServer struct {
@ -70,92 +57,6 @@ func (s *tcpEchoServer) Close() error {
return s.Listener.Close()
}
// tcpDoubleEchoServer is a TCP server that echoes twice what it reads from the connection.
// It will never actively close the connection.
type tcpDoubleEchoServer struct {
Listener net.Listener
}
func (s *tcpDoubleEchoServer) Serve() error {
for {
conn, err := s.Listener.Accept()
if err != nil {
return err
}
go func() {
buf := make([]byte, 1024)
for {
n, err := conn.Read(buf)
if err != nil {
_ = conn.Close()
return
}
_, _ = conn.Write(buf[:n])
_, _ = conn.Write(buf[:n])
}
}()
}
}
func (s *tcpDoubleEchoServer) Close() error {
return s.Listener.Close()
}
type sinkEvent struct {
Data []byte
Err error
}
// tcpSinkServer is a TCP server that reads data from the connection,
// and sends what it read to the channel when the connection is closed.
type tcpSinkServer struct {
Listener net.Listener
Ch chan<- sinkEvent
}
func (s *tcpSinkServer) Serve() error {
for {
conn, err := s.Listener.Accept()
if err != nil {
return err
}
go func() {
var buf bytes.Buffer
_, err := io.Copy(&buf, conn)
_ = conn.Close()
s.Ch <- sinkEvent{Data: buf.Bytes(), Err: err}
}()
}
}
func (s *tcpSinkServer) Close() error {
return s.Listener.Close()
}
// tcpSenderServer is a TCP server that sends data to the connection,
// and closes the connection when all data has been sent.
type tcpSenderServer struct {
Listener net.Listener
Data []byte
}
func (s *tcpSenderServer) Serve() error {
for {
conn, err := s.Listener.Accept()
if err != nil {
return err
}
go func() {
_, _ = conn.Write(s.Data)
_ = conn.Close()
}()
}
}
func (s *tcpSenderServer) Close() error {
return s.Listener.Close()
}
// udpEchoServer is a UDP server that echoes what it reads from the connection.
// It will never actively close the connection.
type udpEchoServer struct {
@ -179,140 +80,3 @@ func (s *udpEchoServer) Serve() error {
func (s *udpEchoServer) Close() error {
return s.Conn.Close()
}
// udpDoubleEchoServer is a UDP server that echoes twice what it reads from the connection.
// It will never actively close the connection.
type udpDoubleEchoServer struct {
Conn net.PacketConn
}
func (s *udpDoubleEchoServer) Serve() error {
buf := make([]byte, 65536)
for {
n, addr, err := s.Conn.ReadFrom(buf)
if err != nil {
return err
}
_, err = s.Conn.WriteTo(buf[:n], addr)
if err != nil {
return err
}
_, err = s.Conn.WriteTo(buf[:n], addr)
if err != nil {
return err
}
}
}
func (s *udpDoubleEchoServer) Close() error {
return s.Conn.Close()
}
type connectEvent struct {
Addr net.Addr
ID string
TX uint64
}
type disconnectEvent struct {
Addr net.Addr
ID string
Err error
}
type tcpRequestEvent struct {
Addr net.Addr
ID string
ReqAddr string
}
type tcpErrorEvent struct {
Addr net.Addr
ID string
ReqAddr string
Err error
}
type udpRequestEvent struct {
Addr net.Addr
ID string
SessionID uint32
}
type udpErrorEvent struct {
Addr net.Addr
ID string
SessionID uint32
Err error
}
type channelEventLogger struct {
ConnectEventCh chan connectEvent
DisconnectEventCh chan disconnectEvent
TCPRequestEventCh chan tcpRequestEvent
TCPErrorEventCh chan tcpErrorEvent
UDPRequestEventCh chan udpRequestEvent
UDPErrorEventCh chan udpErrorEvent
}
func (l *channelEventLogger) Connect(addr net.Addr, id string, tx uint64) {
if l.ConnectEventCh != nil {
l.ConnectEventCh <- connectEvent{
Addr: addr,
ID: id,
TX: tx,
}
}
}
func (l *channelEventLogger) Disconnect(addr net.Addr, id string, err error) {
if l.DisconnectEventCh != nil {
l.DisconnectEventCh <- disconnectEvent{
Addr: addr,
ID: id,
Err: err,
}
}
}
func (l *channelEventLogger) TCPRequest(addr net.Addr, id, reqAddr string) {
if l.TCPRequestEventCh != nil {
l.TCPRequestEventCh <- tcpRequestEvent{
Addr: addr,
ID: id,
ReqAddr: reqAddr,
}
}
}
func (l *channelEventLogger) TCPError(addr net.Addr, id, reqAddr string, err error) {
if l.TCPErrorEventCh != nil {
l.TCPErrorEventCh <- tcpErrorEvent{
Addr: addr,
ID: id,
ReqAddr: reqAddr,
Err: err,
}
}
}
func (l *channelEventLogger) UDPRequest(addr net.Addr, id string, sessionID uint32, reqAddr string) {
if l.UDPRequestEventCh != nil {
l.UDPRequestEventCh <- udpRequestEvent{
Addr: addr,
ID: id,
SessionID: sessionID,
}
}
}
func (l *channelEventLogger) UDPError(addr net.Addr, id string, sessionID uint32, err error) {
if l.UDPErrorEventCh != nil {
l.UDPErrorEventCh <- udpErrorEvent{
Addr: addr,
ID: id,
SessionID: sessionID,
Err: err,
}
}
}