Files
pekoe/internal/compatibility/helper_test.go
2026-04-03 00:09:40 +03:00

119 lines
2.5 KiB
Go

package compatibility
import (
"context"
"net"
"sync"
"testing"
"time"
"github.com/eleksir/pekoe/internal/config"
"github.com/eleksir/pekoe/internal/pubsub"
"github.com/eleksir/pekoe/internal/server"
)
// testServer manages a test server instance for compatibility tests
type testServer struct {
cfg *config.Config
server *server.Server
ctx context.Context
cancel context.CancelFunc
wg sync.WaitGroup
addr string
}
// startTestServer starts a pekoe server on a random available port for testing
func startTestServer(t *testing.T) *testServer {
t.Helper()
// Find an available port
port := findAvailablePort(t)
cfg := &config.Config{
Bind: "127.0.0.1",
Port: port,
MaxClients: 100,
ReadTimeout: 0,
WriteTimeout: 0,
MaxMsgBytes: 10 * 1024 * 1024, // 10MB
LogLevel: "error", // Suppress logs in tests
}
cfg.SetDefaults()
hub := pubsub.NewHub()
srv := server.New(cfg, hub)
ctx, cancel := context.WithCancel(context.Background())
ts := &testServer{
cfg: cfg,
server: srv,
ctx: ctx,
cancel: cancel,
addr: cfg.Addr(),
}
// Start server in background
ts.wg.Add(1)
go func() {
defer ts.wg.Done()
_ = srv.Run()
}()
// Wait for server to be ready
ts.waitForReady(t)
return ts
}
// waitForReady blocks until the server accepts connections
func (ts *testServer) waitForReady(t *testing.T) {
t.Helper()
deadline := time.Now().Add(5 * time.Second)
for time.Now().Before(deadline) {
conn, err := net.DialTimeout("tcp", ts.addr, 100*time.Millisecond)
if err == nil {
_ = conn.Close()
return
}
time.Sleep(10 * time.Millisecond)
}
t.Fatalf("Server at %s not ready after 5 seconds", ts.addr)
}
// Addr returns the server address for client connections
func (ts *testServer) Addr() string {
return ts.addr
}
// Close shuts down the test server
func (ts *testServer) Close() {
ts.cancel()
// Give time for graceful shutdown
time.Sleep(100 * time.Millisecond)
}
// findAvailablePort finds an available TCP port for testing
func findAvailablePort(t *testing.T) int {
t.Helper()
listener, err := net.Listen("tcp", "127.0.0.1:0")
if err != nil {
t.Fatalf("Failed to find available port: %v", err)
}
port := listener.Addr().(*net.TCPAddr).Port
_ = listener.Close()
return port
}
// waitForMessage waits for a message on a channel with timeout
func waitForMessage[T any](ch <-chan T, timeout time.Duration) (T, bool) {
select {
case msg := <-ch:
return msg, true
case <-time.After(timeout):
var zero T
return zero, false
}
}