test: Add comprehensive tests for checkRateLimit function
Cover all branches: disabled rate limit (zero/negative MaxAlertsHour), under limit, at limit blocking, separate limits per alertID, old entry cleanup, and mixed old/recent entries. Coverage improved from 71.4% to 100%.
This commit is contained in:
parent
c488956001
commit
10498a0d54
1 changed files with 155 additions and 0 deletions
|
|
@ -2513,3 +2513,158 @@ func TestGetMetricTimeThreshold(t *testing.T) {
|
|||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestCheckRateLimit(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
t.Run("no rate limit when MaxAlertsHour is zero", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
m := NewManager()
|
||||
m.mu.Lock()
|
||||
m.config.Schedule.MaxAlertsHour = 0
|
||||
m.mu.Unlock()
|
||||
|
||||
m.mu.Lock()
|
||||
result := m.checkRateLimit("test-alert")
|
||||
m.mu.Unlock()
|
||||
|
||||
if !result {
|
||||
t.Errorf("checkRateLimit() = false, want true when MaxAlertsHour is 0")
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("no rate limit when MaxAlertsHour is negative", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
m := NewManager()
|
||||
m.mu.Lock()
|
||||
m.config.Schedule.MaxAlertsHour = -1
|
||||
m.mu.Unlock()
|
||||
|
||||
m.mu.Lock()
|
||||
result := m.checkRateLimit("test-alert")
|
||||
m.mu.Unlock()
|
||||
|
||||
if !result {
|
||||
t.Errorf("checkRateLimit() = false, want true when MaxAlertsHour is negative")
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("allows alerts under rate limit", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
m := NewManager()
|
||||
m.mu.Lock()
|
||||
m.config.Schedule.MaxAlertsHour = 5
|
||||
m.mu.Unlock()
|
||||
|
||||
// First 5 alerts should be allowed
|
||||
for i := 0; i < 5; i++ {
|
||||
m.mu.Lock()
|
||||
result := m.checkRateLimit("test-alert")
|
||||
m.mu.Unlock()
|
||||
|
||||
if !result {
|
||||
t.Errorf("checkRateLimit() call %d = false, want true (under limit)", i+1)
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("blocks alerts at rate limit", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
m := NewManager()
|
||||
m.mu.Lock()
|
||||
m.config.Schedule.MaxAlertsHour = 3
|
||||
m.mu.Unlock()
|
||||
|
||||
// Use up the rate limit
|
||||
for i := 0; i < 3; i++ {
|
||||
m.mu.Lock()
|
||||
_ = m.checkRateLimit("test-alert")
|
||||
m.mu.Unlock()
|
||||
}
|
||||
|
||||
// Fourth alert should be blocked
|
||||
m.mu.Lock()
|
||||
result := m.checkRateLimit("test-alert")
|
||||
m.mu.Unlock()
|
||||
|
||||
if result {
|
||||
t.Errorf("checkRateLimit() = true, want false (at rate limit)")
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("different alert IDs have separate limits", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
m := NewManager()
|
||||
m.mu.Lock()
|
||||
m.config.Schedule.MaxAlertsHour = 2
|
||||
m.mu.Unlock()
|
||||
|
||||
// Use up limit for alert-1
|
||||
for i := 0; i < 2; i++ {
|
||||
m.mu.Lock()
|
||||
_ = m.checkRateLimit("alert-1")
|
||||
m.mu.Unlock()
|
||||
}
|
||||
|
||||
// alert-2 should still be allowed
|
||||
m.mu.Lock()
|
||||
result := m.checkRateLimit("alert-2")
|
||||
m.mu.Unlock()
|
||||
|
||||
if !result {
|
||||
t.Errorf("checkRateLimit(alert-2) = false, want true (separate limit)")
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("old entries are cleaned up", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
m := NewManager()
|
||||
m.mu.Lock()
|
||||
m.config.Schedule.MaxAlertsHour = 2
|
||||
|
||||
// Pre-populate with old entries (more than 1 hour ago)
|
||||
oldTime := time.Now().Add(-2 * time.Hour)
|
||||
m.alertRateLimit["test-alert"] = []time.Time{oldTime, oldTime}
|
||||
m.mu.Unlock()
|
||||
|
||||
// Should be allowed because old entries are cleaned up
|
||||
m.mu.Lock()
|
||||
result := m.checkRateLimit("test-alert")
|
||||
m.mu.Unlock()
|
||||
|
||||
if !result {
|
||||
t.Errorf("checkRateLimit() = false, want true (old entries should be cleaned)")
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("mixed old and recent entries", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
m := NewManager()
|
||||
m.mu.Lock()
|
||||
m.config.Schedule.MaxAlertsHour = 2
|
||||
|
||||
// Pre-populate with 1 old and 1 recent entry
|
||||
oldTime := time.Now().Add(-2 * time.Hour)
|
||||
recentTime := time.Now().Add(-30 * time.Minute)
|
||||
m.alertRateLimit["test-alert"] = []time.Time{oldTime, recentTime}
|
||||
m.mu.Unlock()
|
||||
|
||||
// First call should be allowed (1 recent + 1 new = 2)
|
||||
m.mu.Lock()
|
||||
result1 := m.checkRateLimit("test-alert")
|
||||
m.mu.Unlock()
|
||||
|
||||
if !result1 {
|
||||
t.Errorf("checkRateLimit() call 1 = false, want true")
|
||||
}
|
||||
|
||||
// Second call should be blocked (2 recent + 1 new would exceed 2)
|
||||
m.mu.Lock()
|
||||
result2 := m.checkRateLimit("test-alert")
|
||||
m.mu.Unlock()
|
||||
|
||||
if result2 {
|
||||
t.Errorf("checkRateLimit() call 2 = true, want false (at limit)")
|
||||
}
|
||||
})
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue