test: Add comprehensive tests for HandleDockerHostOffline
HandleDockerHostOffline (0%→100%): - Empty host ID is no-op - Disabled alerts is no-op - DisableAllDockerHostsOffline clears tracking and alert - Override DisableConnectivity clears tracking and alert - Existing alert updates LastSeen - Requires 3 confirmations before alert - Alert has correct metadata (resourceType, hostId, agentId) Coverage: 55.6% → 56.9%
This commit is contained in:
parent
7bac96d60b
commit
5c584b9eee
1 changed files with 213 additions and 0 deletions
|
|
@ -5478,3 +5478,216 @@ func TestReevaluateGuestAlert(t *testing.T) {
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestHandleDockerHostOffline(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
t.Run("empty host ID is no-op", func(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
m := NewManager()
|
||||||
|
m.mu.Lock()
|
||||||
|
m.config.Enabled = true
|
||||||
|
initialCount := len(m.activeAlerts)
|
||||||
|
m.mu.Unlock()
|
||||||
|
|
||||||
|
m.HandleDockerHostOffline(models.DockerHost{ID: ""})
|
||||||
|
|
||||||
|
m.mu.RLock()
|
||||||
|
finalCount := len(m.activeAlerts)
|
||||||
|
m.mu.RUnlock()
|
||||||
|
if finalCount != initialCount {
|
||||||
|
t.Error("expected no change when empty host ID passed")
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("disabled alerts is no-op", func(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
m := NewManager()
|
||||||
|
m.mu.Lock()
|
||||||
|
m.config.Enabled = false
|
||||||
|
m.mu.Unlock()
|
||||||
|
|
||||||
|
m.HandleDockerHostOffline(models.DockerHost{ID: "docker1", DisplayName: "Docker Host 1"})
|
||||||
|
|
||||||
|
m.mu.RLock()
|
||||||
|
_, exists := m.activeAlerts["docker-host-offline-docker1"]
|
||||||
|
m.mu.RUnlock()
|
||||||
|
if exists {
|
||||||
|
t.Error("expected no alert when alerts are disabled")
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("DisableAllDockerHostsOffline clears tracking and alert", func(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
m := NewManager()
|
||||||
|
m.mu.Lock()
|
||||||
|
m.config.Enabled = true
|
||||||
|
m.config.DisableAllDockerHostsOffline = true
|
||||||
|
m.dockerOfflineCount["docker1"] = 5
|
||||||
|
m.activeAlerts["docker-host-offline-docker1"] = &Alert{ID: "docker-host-offline-docker1"}
|
||||||
|
m.mu.Unlock()
|
||||||
|
|
||||||
|
m.HandleDockerHostOffline(models.DockerHost{ID: "docker1", DisplayName: "Docker Host 1"})
|
||||||
|
|
||||||
|
m.mu.RLock()
|
||||||
|
_, alertExists := m.activeAlerts["docker-host-offline-docker1"]
|
||||||
|
_, countExists := m.dockerOfflineCount["docker1"]
|
||||||
|
m.mu.RUnlock()
|
||||||
|
if alertExists {
|
||||||
|
t.Error("expected alert to be cleared")
|
||||||
|
}
|
||||||
|
if countExists {
|
||||||
|
t.Error("expected offline count to be cleared")
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("override DisableConnectivity clears tracking and alert", func(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
m := NewManager()
|
||||||
|
m.mu.Lock()
|
||||||
|
m.config.Enabled = true
|
||||||
|
m.config.Overrides = map[string]ThresholdConfig{
|
||||||
|
"docker1": {DisableConnectivity: true},
|
||||||
|
}
|
||||||
|
m.dockerOfflineCount["docker1"] = 3
|
||||||
|
m.activeAlerts["docker-host-offline-docker1"] = &Alert{ID: "docker-host-offline-docker1"}
|
||||||
|
m.mu.Unlock()
|
||||||
|
|
||||||
|
m.HandleDockerHostOffline(models.DockerHost{ID: "docker1", DisplayName: "Docker Host 1"})
|
||||||
|
|
||||||
|
m.mu.RLock()
|
||||||
|
_, alertExists := m.activeAlerts["docker-host-offline-docker1"]
|
||||||
|
_, countExists := m.dockerOfflineCount["docker1"]
|
||||||
|
m.mu.RUnlock()
|
||||||
|
if alertExists {
|
||||||
|
t.Error("expected alert to be cleared with override")
|
||||||
|
}
|
||||||
|
if countExists {
|
||||||
|
t.Error("expected offline count to be cleared with override")
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("existing alert updates LastSeen", func(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
m := NewManager()
|
||||||
|
oldTime := time.Now().Add(-1 * time.Hour)
|
||||||
|
m.mu.Lock()
|
||||||
|
m.config.Enabled = true
|
||||||
|
m.activeAlerts["docker-host-offline-docker1"] = &Alert{
|
||||||
|
ID: "docker-host-offline-docker1",
|
||||||
|
LastSeen: oldTime,
|
||||||
|
}
|
||||||
|
m.mu.Unlock()
|
||||||
|
|
||||||
|
m.HandleDockerHostOffline(models.DockerHost{ID: "docker1", DisplayName: "Docker Host 1"})
|
||||||
|
|
||||||
|
m.mu.RLock()
|
||||||
|
alert := m.activeAlerts["docker-host-offline-docker1"]
|
||||||
|
m.mu.RUnlock()
|
||||||
|
if alert == nil {
|
||||||
|
t.Fatal("expected alert to exist")
|
||||||
|
}
|
||||||
|
if !alert.LastSeen.After(oldTime) {
|
||||||
|
t.Error("expected LastSeen to be updated")
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("requires 3 confirmations before alert", func(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
m := NewManager()
|
||||||
|
m.mu.Lock()
|
||||||
|
m.config.Enabled = true
|
||||||
|
m.mu.Unlock()
|
||||||
|
|
||||||
|
host := models.DockerHost{ID: "docker1", DisplayName: "Docker Host 1", Hostname: "docker-server"}
|
||||||
|
|
||||||
|
// First call - confirmation 1
|
||||||
|
m.HandleDockerHostOffline(host)
|
||||||
|
m.mu.RLock()
|
||||||
|
count1 := m.dockerOfflineCount["docker1"]
|
||||||
|
alert1 := m.activeAlerts["docker-host-offline-docker1"]
|
||||||
|
m.mu.RUnlock()
|
||||||
|
if count1 != 1 {
|
||||||
|
t.Errorf("expected count 1, got %d", count1)
|
||||||
|
}
|
||||||
|
if alert1 != nil {
|
||||||
|
t.Error("expected no alert after 1 confirmation")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Second call - confirmation 2
|
||||||
|
m.HandleDockerHostOffline(host)
|
||||||
|
m.mu.RLock()
|
||||||
|
count2 := m.dockerOfflineCount["docker1"]
|
||||||
|
alert2 := m.activeAlerts["docker-host-offline-docker1"]
|
||||||
|
m.mu.RUnlock()
|
||||||
|
if count2 != 2 {
|
||||||
|
t.Errorf("expected count 2, got %d", count2)
|
||||||
|
}
|
||||||
|
if alert2 != nil {
|
||||||
|
t.Error("expected no alert after 2 confirmations")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Third call - confirmation 3 - should create alert
|
||||||
|
m.HandleDockerHostOffline(host)
|
||||||
|
m.mu.RLock()
|
||||||
|
count3 := m.dockerOfflineCount["docker1"]
|
||||||
|
alert3 := m.activeAlerts["docker-host-offline-docker1"]
|
||||||
|
m.mu.RUnlock()
|
||||||
|
if count3 != 3 {
|
||||||
|
t.Errorf("expected count 3, got %d", count3)
|
||||||
|
}
|
||||||
|
if alert3 == nil {
|
||||||
|
t.Fatal("expected alert after 3 confirmations")
|
||||||
|
}
|
||||||
|
if alert3.Type != "docker-host-offline" {
|
||||||
|
t.Errorf("expected type docker-host-offline, got %s", alert3.Type)
|
||||||
|
}
|
||||||
|
if alert3.Level != AlertLevelCritical {
|
||||||
|
t.Errorf("expected critical level, got %s", alert3.Level)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("alert has correct metadata", func(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
m := NewManager()
|
||||||
|
m.mu.Lock()
|
||||||
|
m.config.Enabled = true
|
||||||
|
m.dockerOfflineCount["docker1"] = 2 // Pre-set to trigger on next call
|
||||||
|
m.mu.Unlock()
|
||||||
|
|
||||||
|
host := models.DockerHost{
|
||||||
|
ID: "docker1",
|
||||||
|
DisplayName: "My Docker Host",
|
||||||
|
Hostname: "docker-server.local",
|
||||||
|
AgentID: "agent-123",
|
||||||
|
}
|
||||||
|
|
||||||
|
m.HandleDockerHostOffline(host)
|
||||||
|
|
||||||
|
m.mu.RLock()
|
||||||
|
alert := m.activeAlerts["docker-host-offline-docker1"]
|
||||||
|
m.mu.RUnlock()
|
||||||
|
|
||||||
|
if alert == nil {
|
||||||
|
t.Fatal("expected alert to be created")
|
||||||
|
}
|
||||||
|
if alert.ResourceID != "docker:docker1" {
|
||||||
|
t.Errorf("expected resourceID docker:docker1, got %s", alert.ResourceID)
|
||||||
|
}
|
||||||
|
if alert.ResourceName != "My Docker Host" {
|
||||||
|
t.Errorf("expected resourceName 'My Docker Host', got %s", alert.ResourceName)
|
||||||
|
}
|
||||||
|
if alert.Node != "docker-server.local" {
|
||||||
|
t.Errorf("expected node docker-server.local, got %s", alert.Node)
|
||||||
|
}
|
||||||
|
if alert.Metadata["resourceType"] != "DockerHost" {
|
||||||
|
t.Errorf("expected metadata resourceType DockerHost, got %v", alert.Metadata["resourceType"])
|
||||||
|
}
|
||||||
|
if alert.Metadata["hostId"] != "docker1" {
|
||||||
|
t.Errorf("expected metadata hostId docker1, got %v", alert.Metadata["hostId"])
|
||||||
|
}
|
||||||
|
if alert.Metadata["agentId"] != "agent-123" {
|
||||||
|
t.Errorf("expected metadata agentId agent-123, got %v", alert.Metadata["agentId"])
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue