194 lines
4.4 KiB
Go
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
|
|
} |