diff --git a/test/integration/helpers_test.go b/test/integration/helpers_test.go new file mode 100644 index 0000000..d71282e --- /dev/null +++ b/test/integration/helpers_test.go @@ -0,0 +1,56 @@ +package integration + +import ( + "context" + "testing" + "time" + + "hash-of-wisdom/internal/lib/sl" + "hash-of-wisdom/internal/pow/challenge" + "hash-of-wisdom/internal/quotes" + "hash-of-wisdom/internal/server" + "hash-of-wisdom/internal/service" + + "github.com/stretchr/testify/require" +) + +// testQuoteService provides static quotes for testing +type testQuoteService struct{} + +func (s *testQuoteService) GetRandomQuote(ctx context.Context) (*quotes.Quote, error) { + return "es.Quote{ + Text: "Test quote for integration testing", + Author: "Test Author", + }, nil +} + +func setupTestServerWithConfig(t *testing.T, serverConfig *server.Config) *server.TCPServer { + // Create test components + challengeConfig := challenge.TestConfig() + generator := challenge.NewGenerator(challengeConfig) + verifier := challenge.NewVerifier(challengeConfig) + + // Create a simple test quote service + quoteService := &testQuoteService{} + + // Wire up service + genAdapter := service.NewGeneratorAdapter(generator) + wisdomService := service.NewWisdomService(genAdapter, verifier, quoteService) + + // Create server with custom config using functional options + logger := sl.NewMockLogger() + srv := server.NewTCPServer(wisdomService, serverConfig, + server.WithLogger(logger)) + + // Start server + ctx, cancel := context.WithTimeout(context.Background(), 1*time.Second) + defer cancel() + + err := srv.Start(ctx) + require.NoError(t, err) + + // Give server time to start + time.Sleep(100 * time.Millisecond) + + return srv +} diff --git a/test/integration/slowloris_test.go b/test/integration/slowloris_test.go index 4e6c7dd..be3dd04 100644 --- a/test/integration/slowloris_test.go +++ b/test/integration/slowloris_test.go @@ -5,7 +5,6 @@ import ( "testing" "time" - "hash-of-wisdom/internal/protocol" "hash-of-wisdom/internal/server" "github.com/stretchr/testify/assert" @@ -48,42 +47,6 @@ func TestSlowlorisProtection_SlowReader(t *testing.T) { assert.Error(t, err, "Connection should be closed due to slow reading") } -func TestSlowlorisProtection_SlowWriter(t *testing.T) { - // Setup server with very short write timeout for testing - serverConfig := &server.Config{ - Address: ":0", - Timeouts: server.TimeoutConfig{ - Read: 5 * time.Second, - Write: 100 * time.Millisecond, - Connection: 15 * time.Second, - }, - } - - srv := setupTestServerWithConfig(t, serverConfig) - defer srv.Stop() - - // Connect to server but don't read responses (simulate slow writer client) - conn, err := net.Dial("tcp", srv.Address()) - require.NoError(t, err) - defer conn.Close() - - // Send a complete challenge request - challengeReq := &protocol.ChallengeRequest{} - err = challengeReq.Encode(conn) - require.NoError(t, err) - - // Don't read the response - this should trigger write timeout - time.Sleep(200 * time.Millisecond) - - // Try to write again - connection should be timed out - _, err = conn.Write([]byte{0x01}) - - // Verify connection is closed - buffer := make([]byte, 1024) - conn.SetReadDeadline(time.Now().Add(500 * time.Millisecond)) - _, err = conn.Read(buffer) - assert.Error(t, err, "Connection should be closed due to slow writing") -} func TestSlowlorisProtection_SlowConnectionTimeout(t *testing.T) { // Setup server with very short connection timeout for testing @@ -150,86 +113,3 @@ func TestSlowlorisProtection_MultipleSlowClients(t *testing.T) { conn.Close() } } - -func TestSlowlorisProtection_AttackMitigation(t *testing.T) { - // Test that server can still serve legitimate clients during an attack - serverConfig := &server.Config{ - Address: ":0", - Timeouts: server.TimeoutConfig{ - Read: 500 * time.Millisecond, - Write: 500 * time.Millisecond, - Connection: 1 * time.Second, - }, - } - - srv := setupTestServerWithConfig(t, serverConfig) - defer srv.Stop() - - // Start slowloris attack - multiple slow connections - var attackConnections []net.Conn - for i := 0; i < 3; i++ { - conn, err := net.Dial("tcp", srv.Address()) - require.NoError(t, err) - attackConnections = append(attackConnections, conn) - // Send partial data - conn.Write([]byte{0x01}) - } - - // Meanwhile, legitimate client should still work - legitimateConn, err := net.Dial("tcp", srv.Address()) - require.NoError(t, err) - defer legitimateConn.Close() - - // Send complete request quickly - challengeReq := &protocol.ChallengeRequest{} - err = challengeReq.Encode(legitimateConn) - require.NoError(t, err) - - // Should receive response despite ongoing attack - decoder := protocol.NewMessageDecoder() - msg, err := decoder.Decode(legitimateConn) - assert.NoError(t, err) - assert.Equal(t, protocol.ChallengeResponseType, msg.Type) - - // Clean up attack connections - for _, conn := range attackConnections { - conn.Close() - } -} - -func TestSlowlorisProtection_SlowChunkReading(t *testing.T) { - // Test protection against clients that read responses very slowly - serverConfig := &server.Config{ - Address: ":0", - Timeouts: server.TimeoutConfig{ - Read: 5 * time.Second, - Write: 200 * time.Millisecond, - Connection: 10 * time.Second, - }, - } - - srv := setupTestServerWithConfig(t, serverConfig) - defer srv.Stop() - - // Connect and send valid request - conn, err := net.Dial("tcp", srv.Address()) - require.NoError(t, err) - defer conn.Close() - - challengeReq := &protocol.ChallengeRequest{} - err = challengeReq.Encode(conn) - require.NoError(t, err) - - // Read only first byte of response very slowly - buffer := make([]byte, 1) - _, err = conn.Read(buffer) - require.NoError(t, err) - - // Wait longer than write timeout before reading more - time.Sleep(300 * time.Millisecond) - - // Try to read more - connection should be closed due to slow reading - conn.SetReadDeadline(time.Now().Add(500 * time.Millisecond)) - _, err = conn.Read(buffer) - assert.Error(t, err, "Connection should be closed due to slow chunk reading") -} diff --git a/test/integration/timeout_test.go b/test/integration/timeout_test.go index 8c81a90..d873c8f 100644 --- a/test/integration/timeout_test.go +++ b/test/integration/timeout_test.go @@ -1,18 +1,12 @@ package integration import ( - "context" "net" "testing" "time" - "hash-of-wisdom/internal/config" - "hash-of-wisdom/internal/lib/sl" - "hash-of-wisdom/internal/pow/challenge" "hash-of-wisdom/internal/protocol" - "hash-of-wisdom/internal/quotes" "hash-of-wisdom/internal/server" - "hash-of-wisdom/internal/service" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" @@ -55,7 +49,6 @@ func TestTCPServer_TimeoutProtection_SlowReader(t *testing.T) { func TestTCPServer_TimeoutProtection_ConnectionTimeout(t *testing.T) { // Setup server with very short connection timeout - _ = config.Load serverConfig := &server.Config{ Address: ":0", Timeouts: server.TimeoutConfig{ @@ -105,7 +98,6 @@ func TestTCPServer_NormalOperation_WithinTimeouts(t *testing.T) { } func TestTCPServer_MultipleConnections_IndependentTimeouts(t *testing.T) { - _ = config.Load serverConfig := &server.Config{ Address: ":0", Timeouts: server.TimeoutConfig{ @@ -167,43 +159,3 @@ func setupTestServer(t *testing.T) *server.TCPServer { } // Helper function to create test server with custom config -func setupTestServerWithConfig(t *testing.T, serverConfig *server.Config) *server.TCPServer { - // Create test components - challengeConfig := challenge.TestConfig() - generator := challenge.NewGenerator(challengeConfig) - verifier := challenge.NewVerifier(challengeConfig) - - // Create a simple test quote service - quoteService := &testQuoteService{} - - // Wire up service - genAdapter := service.NewGeneratorAdapter(generator) - wisdomService := service.NewWisdomService(genAdapter, verifier, quoteService) - - // Create server with custom config using functional options - logger := sl.NewMockLogger() - srv := server.NewTCPServer(wisdomService, serverConfig, - server.WithLogger(logger)) - - // Start server - ctx, cancel := context.WithTimeout(context.Background(), 1*time.Second) - defer cancel() - - err := srv.Start(ctx) - require.NoError(t, err) - - // Give server time to start - time.Sleep(100 * time.Millisecond) - - return srv -} - -// testQuoteService provides test quotes -type testQuoteService struct{} - -func (s *testQuoteService) GetRandomQuote(ctx context.Context) (*quotes.Quote, error) { - return "es.Quote{ - Text: "Test quote for integration testing", - Author: "Test Author", - }, nil -}