package rate import ( "testing" "time" ) func TestNewLimiter(t *testing.T) { limiter := NewLimiter(10.0, 1.0) if limiter == nil { t.Fatal("NewLimiter() returned nil") } } func TestLimiter_Allow(t *testing.T) { limiter := NewLimiter(10.0, 1.0) if !limiter.Allow() { t.Error("Allow() should return true initially") } for i := 0; i < 10; i++ { limiter.Allow() } if limiter.Allow() { t.Error("Allow() should return false after exceeding rate") } time.Sleep(1100 * time.Millisecond) if !limiter.Allow() { t.Error("Allow() should return true after waiting") } } func TestNewAnnounceRateControl(t *testing.T) { arc := NewAnnounceRateControl(3600.0, 3, 7200.0) if arc == nil { t.Fatal("NewAnnounceRateControl() returned nil") } } func TestAnnounceRateControl_AllowAnnounce(t *testing.T) { arc := NewAnnounceRateControl(1.0, 2, 2.0) hash := "test-dest-hash" if !arc.AllowAnnounce(hash) { t.Error("AllowAnnounce() should return true for first announce") } if !arc.AllowAnnounce(hash) { t.Error("AllowAnnounce() should return true for second announce (within grace)") } if arc.AllowAnnounce(hash) { t.Error("AllowAnnounce() should return false for third announce (exceeds grace)") } time.Sleep(1100 * time.Millisecond) if !arc.AllowAnnounce(hash) { t.Error("AllowAnnounce() should return true after waiting") } } func TestAnnounceRateControl_AllowAnnounce_DifferentHashes(t *testing.T) { arc := NewAnnounceRateControl(1.0, 1, 1.0) hash1 := "hash1" hash2 := "hash2" if !arc.AllowAnnounce(hash1) { t.Error("AllowAnnounce() should return true for hash1") } if !arc.AllowAnnounce(hash2) { t.Error("AllowAnnounce() should return true for hash2 (different hash)") } } func TestNewIngressControl(t *testing.T) { ic := NewIngressControl(true) if ic == nil { t.Fatal("NewIngressControl() returned nil") } } func TestIngressControl_ProcessAnnounce(t *testing.T) { ic := NewIngressControl(true) hash := "test-hash" data := []byte("announce data") ic.mutex.Lock() ic.lastBurst = time.Now().Add(-time.Second) ic.mutex.Unlock() if !ic.ProcessAnnounce(hash, data, false) { t.Error("ProcessAnnounce() should return true for first announce") } time.Sleep(10 * time.Millisecond) for i := 0; i < 200; i++ { ic.ProcessAnnounce(hash, data, false) } result := ic.ProcessAnnounce(hash, data, false) if result { t.Error("ProcessAnnounce() should return false when burst frequency exceeded") } } func TestIngressControl_ProcessAnnounce_Disabled(t *testing.T) { ic := NewIngressControl(false) hash := "test-hash" data := []byte("announce data") if !ic.ProcessAnnounce(hash, data, false) { t.Error("ProcessAnnounce() should return true when disabled") } } func TestIngressControl_ReleaseHeldAnnounce(t *testing.T) { ic := NewIngressControl(true) hash, data, found := ic.ReleaseHeldAnnounce() if found { t.Error("ReleaseHeldAnnounce() should return false when no announces held") } ic.ProcessAnnounce("hash1", []byte("data1"), false) for i := 0; i < 200; i++ { ic.ProcessAnnounce("hash1", []byte("data1"), false) } hash, data, found = ic.ReleaseHeldAnnounce() if !found { t.Error("ReleaseHeldAnnounce() should return true when announces are held") } if hash == "" { t.Error("ReleaseHeldAnnounce() should return non-empty hash") } if len(data) == 0 { t.Error("ReleaseHeldAnnounce() should return non-empty data") } }