1
0
Protocol/stream_test.go
2025-09-01 13:56:01 -05:00

194 lines
4.4 KiB
Go

package eq2net
import (
"net"
"testing"
"time"
)
func TestStreamCreation(t *testing.T) {
config := DefaultStreamConfig()
stream := NewEQStream(config)
if stream == nil {
t.Fatal("Failed to create stream")
}
if stream.GetState() != StreamStateDisconnected {
t.Errorf("Expected disconnected state, got %v", stream.GetState())
}
// Test state transitions
if !stream.compareAndSwapState(StreamStateDisconnected, StreamStateConnecting) {
t.Error("Failed to transition to connecting state")
}
if stream.GetState() != StreamStateConnecting {
t.Errorf("Expected connecting state, got %v", stream.GetState())
}
// Clean up
stream.Close()
}
func TestStreamConfig(t *testing.T) {
config := DefaultStreamConfig()
if config.MaxPacketSize != 512 {
t.Errorf("Expected max packet size 512, got %d", config.MaxPacketSize)
}
if config.WindowSize != 2048 {
t.Errorf("Expected window size 2048, got %d", config.WindowSize)
}
if config.RetransmitTimeMs != 500 {
t.Errorf("Expected retransmit time 500ms, got %d", config.RetransmitTimeMs)
}
}
func TestRTTCalculation(t *testing.T) {
stream := NewEQStream(nil)
// Test first RTT sample
stream.updateRTT(100000) // 100ms in microseconds
if stream.rtt.Load() != 100000 {
t.Errorf("Expected RTT 100000, got %d", stream.rtt.Load())
}
// Test subsequent samples
stream.updateRTT(120000) // 120ms
stream.updateRTT(80000) // 80ms
// RTT should be smoothed
rtt := stream.rtt.Load()
if rtt < 80000 || rtt > 120000 {
t.Errorf("RTT outside expected range: %d", rtt)
}
// RTO should be set
rto := stream.rto.Load()
if rto < 200000 { // Minimum 200ms
t.Errorf("RTO below minimum: %d", rto)
}
}
func TestPacketSequencing(t *testing.T) {
stream := NewEQStream(nil)
// Test sequence number generation
seq1 := stream.nextSeqOut.Add(1)
seq2 := stream.nextSeqOut.Add(1)
seq3 := stream.nextSeqOut.Add(1)
if seq1 != 1 || seq2 != 2 || seq3 != 3 {
t.Errorf("Sequence numbers not incrementing correctly: %d, %d, %d", seq1, seq2, seq3)
}
}
func TestSendWindow(t *testing.T) {
stream := NewEQStream(nil)
// Add packet to send window
packet := NewEQProtocolPacket(OPPacket, []byte("test"))
packet.Sequence = 1
stream.sendWindowMu.Lock()
stream.sendWindow[1] = &sendPacket{
packet: packet,
sentTime: time.Now(),
attempts: 1,
nextRetry: time.Now().Add(500 * time.Millisecond),
}
stream.sendWindowMu.Unlock()
// Process ACK
stream.processAck(1)
// Verify packet removed from window
stream.sendWindowMu.RLock()
_, exists := stream.sendWindow[1]
stream.sendWindowMu.RUnlock()
if exists {
t.Error("Packet not removed from send window after ACK")
}
}
func TestFragmentation(t *testing.T) {
stream := NewEQStream(nil)
// Create large data that needs fragmentation
largeData := make([]byte, 1000)
for i := range largeData {
largeData[i] = byte(i % 256)
}
// Fragment the data
fragments := stream.FragmentPacket(largeData, 100)
if len(fragments) == 0 {
t.Fatal("No fragments created")
}
// Verify fragments
expectedFragments := (len(largeData) + 93) / 94 // 100 - 6 header bytes
if len(fragments) != expectedFragments {
t.Errorf("Expected %d fragments, got %d", expectedFragments, len(fragments))
}
// Verify each fragment has correct opcode
for _, frag := range fragments {
if frag.Opcode != OPFragment {
t.Errorf("Fragment has wrong opcode: %04x", frag.Opcode)
}
}
}
// TestMockConnection tests basic packet flow without real network
func TestMockConnection(t *testing.T) {
// Create mock packet conn
clientConn, serverConn := net.Pipe()
defer clientConn.Close()
defer serverConn.Close()
// Note: net.Pipe creates a stream connection, not packet-based
// For a real test, we'd need to use actual UDP sockets
// This is just to verify compilation
config := DefaultStreamConfig()
stream := NewEQStream(config)
// Verify stream creation
if stream == nil {
t.Fatal("Failed to create stream")
}
stream.Close()
}
func TestServerCreation(t *testing.T) {
config := DefaultServerConfig()
server := NewEQ2Server(config)
if server == nil {
t.Fatal("Failed to create server")
}
// Set callbacks
connectCount := 0
disconnectCount := 0
server.SetCallbacks(
func(s *EQStream) {
connectCount++
},
func(s *EQStream, reason string) {
disconnectCount++
},
)
// Note: We don't actually start the server in unit tests
// as it would require binding to a real port
}