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, "") _ = conn.CloseWithError(closeErrCodeProtocolError, "")
} }
_ = pktConn.Close() _ = pktConn.Close()
return &coreErrs.ConnectError{Err: err} return coreErrs.ConnectError{Err: err}
} }
if resp.StatusCode != protocol.StatusAuthOK { if resp.StatusCode != protocol.StatusAuthOK {
_ = conn.CloseWithError(closeErrCodeProtocolError, "") _ = conn.CloseWithError(closeErrCodeProtocolError, "")
_ = pktConn.Close() _ = pktConn.Close()
return &coreErrs.AuthError{StatusCode: resp.StatusCode} return coreErrs.AuthError{StatusCode: resp.StatusCode}
} }
// Auth OK // Auth OK
udpEnabled, serverRx := protocol.AuthResponseDataFromHeader(resp.Header) udpEnabled, serverRx := protocol.AuthResponseDataFromHeader(resp.Header)

View File

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

View File

@ -22,7 +22,7 @@ import (
// TestServerMasquerade is a test to ensure that the server behaves as a normal // 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 // 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) { func TestServerMasquerade(t *testing.T) {
// Create server // Create server
udpConn, udpAddr, err := serverConn() udpConn, udpAddr, err := serverConn()

View File

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

View File

@ -9,9 +9,12 @@ import (
"sync" "sync"
"testing" "testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/mock"
"golang.org/x/time/rate" "golang.org/x/time/rate"
"github.com/apernet/hysteria/core/client" "github.com/apernet/hysteria/core/client"
"github.com/apernet/hysteria/core/internal/integration_tests/mocks"
"github.com/apernet/hysteria/core/server" "github.com/apernet/hysteria/core/server"
) )
@ -26,9 +29,7 @@ func (s *tcpStressor) Run(t *testing.T) {
// Make some random data // Make some random data
sData := make([]byte, s.Size) sData := make([]byte, s.Size)
_, err := rand.Read(sData) _, err := rand.Read(sData)
if err != nil { assert.NoError(t, err)
t.Fatal("error generating random data:", err)
}
// Run iterations // Run iterations
for i := 0; i < s.Iterations; i++ { for i := 0; i < s.Iterations; i++ {
@ -57,9 +58,7 @@ func (s *tcpStressor) Run(t *testing.T) {
} }
wg.Wait() wg.Wait()
if len(errChan) > 0 { assert.Empty(t, errChan)
t.Fatal("error reading from TCP:", <-errChan)
}
} }
} }
@ -76,9 +75,7 @@ func (s *udpStressor) Run(t *testing.T) {
// Make some random data // Make some random data
sData := make([]byte, s.Size) sData := make([]byte, s.Size)
_, err := rand.Read(sData) _, err := rand.Read(sData)
if err != nil { assert.NoError(t, err)
t.Fatal("error generating random data:", err)
}
// Due to UDP's unreliability, we need to limit the rate of sending // 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. // 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() wg.Wait()
if len(errChan) > 0 { assert.Empty(t, errChan)
t.Fatal("error reading from UDP:", <-errChan)
}
} }
} }
func TestClientServerTCPStress(t *testing.T) { func TestClientServerTCPStress(t *testing.T) {
// Create server // Create server
udpAddr := &net.UDPAddr{IP: net.IPv4(127, 0, 0, 1), Port: 14514} udpConn, udpAddr, err := serverConn()
udpConn, err := net.ListenUDP("udp", udpAddr) assert.NoError(t, err)
if err != nil { auth := mocks.NewMockAuthenticator(t)
t.Fatal("error creating server:", err) auth.EXPECT().Authenticate(mock.Anything, mock.Anything, mock.Anything).Return(true, "nobody")
}
s, err := server.NewServer(&server.Config{ s, err := server.NewServer(&server.Config{
TLSConfig: serverTLSConfig(), TLSConfig: serverTLSConfig(),
Conn: udpConn, Conn: udpConn,
Authenticator: &pwAuthenticator{ Authenticator: auth,
Password: "password",
ID: "nobody",
},
}) })
if err != nil { assert.NoError(t, err)
t.Fatal("error creating server:", err)
}
defer s.Close() defer s.Close()
go s.Serve() go s.Serve()
// Create TCP echo server // Create TCP echo server
echoTCPAddr := &net.TCPAddr{IP: net.IPv4(127, 0, 0, 1), Port: 14515} echoAddr := "127.0.0.1:22333"
echoListener, err := net.ListenTCP("tcp", echoTCPAddr) echoListener, err := net.Listen("tcp", echoAddr)
if err != nil { assert.NoError(t, err)
t.Fatal("error creating TCP echo server:", err)
}
echoServer := &tcpEchoServer{Listener: echoListener} echoServer := &tcpEchoServer{Listener: echoListener}
defer echoServer.Close() defer echoServer.Close()
go echoServer.Serve() go echoServer.Serve()
@ -163,16 +150,13 @@ func TestClientServerTCPStress(t *testing.T) {
// Create client // Create client
c, err := client.NewClient(&client.Config{ c, err := client.NewClient(&client.Config{
ServerAddr: udpAddr, ServerAddr: udpAddr,
Auth: "password",
TLSConfig: client.TLSConfig{InsecureSkipVerify: true}, TLSConfig: client.TLSConfig{InsecureSkipVerify: true},
}) })
if err != nil { assert.NoError(t, err)
t.Fatal("error creating client:", err)
}
defer c.Close() defer c.Close()
dialFunc := func() (net.Conn, error) { 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) 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) { func TestClientServerUDPStress(t *testing.T) {
// Create server // Create server
udpAddr := &net.UDPAddr{IP: net.IPv4(127, 0, 0, 1), Port: 14514} udpConn, udpAddr, err := serverConn()
udpConn, err := net.ListenUDP("udp", udpAddr) assert.NoError(t, err)
if err != nil { auth := mocks.NewMockAuthenticator(t)
t.Fatal("error creating server:", err) auth.EXPECT().Authenticate(mock.Anything, mock.Anything, mock.Anything).Return(true, "nobody")
}
s, err := server.NewServer(&server.Config{ s, err := server.NewServer(&server.Config{
TLSConfig: serverTLSConfig(), TLSConfig: serverTLSConfig(),
Conn: udpConn, Conn: udpConn,
Authenticator: &pwAuthenticator{ Authenticator: auth,
Password: "password",
ID: "nobody",
},
}) })
if err != nil { assert.NoError(t, err)
t.Fatal("error creating server:", err)
}
defer s.Close() defer s.Close()
go s.Serve() go s.Serve()
// Create UDP echo server // Create UDP echo server
echoUDPAddr := &net.UDPAddr{IP: net.IPv4(127, 0, 0, 1), Port: 14515} echoAddr := "127.0.0.1:22333"
echoListener, err := net.ListenUDP("udp", echoUDPAddr) echoConn, err := net.ListenPacket("udp", echoAddr)
if err != nil { assert.NoError(t, err)
t.Fatal("error creating UDP echo server:", err) echoServer := &udpEchoServer{Conn: echoConn}
}
echoServer := &udpEchoServer{Conn: echoListener}
defer echoServer.Close() defer echoServer.Close()
go echoServer.Serve() go echoServer.Serve()
// Create client // Create client
c, err := client.NewClient(&client.Config{ c, err := client.NewClient(&client.Config{
ServerAddr: udpAddr, ServerAddr: udpAddr,
Auth: "password",
TLSConfig: client.TLSConfig{InsecureSkipVerify: true}, TLSConfig: client.TLSConfig{InsecureSkipVerify: true},
}) })
if err != nil { assert.NoError(t, err)
t.Fatal("error creating client:", err)
}
defer c.Close() defer c.Close()
t.Run("Single 1000x100b", (&udpStressor{ t.Run("Single 1000x100b", (&udpStressor{
ListenFunc: c.UDP, ListenFunc: c.UDP,
ServerAddr: echoUDPAddr.String(), ServerAddr: echoAddr,
Size: 100, Size: 100,
Count: 1000, Count: 1000,
Parallel: 1, Parallel: 1,
@ -236,7 +209,7 @@ func TestClientServerUDPStress(t *testing.T) {
}).Run) }).Run)
t.Run("Single 1000x3k", (&udpStressor{ t.Run("Single 1000x3k", (&udpStressor{
ListenFunc: c.UDP, ListenFunc: c.UDP,
ServerAddr: echoUDPAddr.String(), ServerAddr: echoAddr,
Size: 3000, Size: 3000,
Count: 1000, Count: 1000,
Parallel: 1, Parallel: 1,
@ -245,7 +218,7 @@ func TestClientServerUDPStress(t *testing.T) {
t.Run("5 Sequential 1000x100b", (&udpStressor{ t.Run("5 Sequential 1000x100b", (&udpStressor{
ListenFunc: c.UDP, ListenFunc: c.UDP,
ServerAddr: echoUDPAddr.String(), ServerAddr: echoAddr,
Size: 100, Size: 100,
Count: 1000, Count: 1000,
Parallel: 1, Parallel: 1,
@ -253,7 +226,7 @@ func TestClientServerUDPStress(t *testing.T) {
}).Run) }).Run)
t.Run("5 Sequential 200x3k", (&udpStressor{ t.Run("5 Sequential 200x3k", (&udpStressor{
ListenFunc: c.UDP, ListenFunc: c.UDP,
ServerAddr: echoUDPAddr.String(), ServerAddr: echoAddr,
Size: 3000, Size: 3000,
Count: 200, Count: 200,
Parallel: 1, Parallel: 1,
@ -262,7 +235,7 @@ func TestClientServerUDPStress(t *testing.T) {
t.Run("2 Sequential 5 Parallel 1000x100b", (&udpStressor{ t.Run("2 Sequential 5 Parallel 1000x100b", (&udpStressor{
ListenFunc: c.UDP, ListenFunc: c.UDP,
ServerAddr: echoUDPAddr.String(), ServerAddr: echoAddr,
Size: 100, Size: 100,
Count: 1000, Count: 1000,
Parallel: 5, Parallel: 5,
@ -271,19 +244,10 @@ func TestClientServerUDPStress(t *testing.T) {
t.Run("2 Sequential 5 Parallel 200x3k", (&udpStressor{ t.Run("2 Sequential 5 Parallel 200x3k", (&udpStressor{
ListenFunc: c.UDP, ListenFunc: c.UDP,
ServerAddr: echoUDPAddr.String(), ServerAddr: echoAddr,
Size: 3000, Size: 3000,
Count: 200, Count: 200,
Parallel: 5, Parallel: 5,
Iterations: 2, Iterations: 2,
}).Run) }).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 package integration_tests
import ( import (
"bytes"
"crypto/tls" "crypto/tls"
"io" "io"
"net" "net"
@ -35,18 +34,6 @@ func serverConn() (net.PacketConn, net.Addr, error) {
return udpConn, udpAddr, nil 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. // tcpEchoServer is a TCP server that echoes what it reads from the connection.
// It will never actively close the connection. // It will never actively close the connection.
type tcpEchoServer struct { type tcpEchoServer struct {
@ -70,92 +57,6 @@ func (s *tcpEchoServer) Close() error {
return s.Listener.Close() 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. // udpEchoServer is a UDP server that echoes what it reads from the connection.
// It will never actively close the connection. // It will never actively close the connection.
type udpEchoServer struct { type udpEchoServer struct {
@ -179,140 +80,3 @@ func (s *udpEchoServer) Serve() error {
func (s *udpEchoServer) Close() error { func (s *udpEchoServer) Close() error {
return s.Conn.Close() 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,
}
}
}