package monitoring import ( "testing" "time" "github.com/rcourtman/pulse-go-rewrite/internal/alerts" "github.com/rcourtman/pulse-go-rewrite/internal/models" ) func TestEvaluateHostAgentsTriggersOfflineAlert(t *testing.T) { t.Helper() monitor := &Monitor{ state: models.NewState(), alertManager: alerts.NewManager(), } t.Cleanup(func() { monitor.alertManager.Stop() }) hostID := "host-offline" monitor.state.UpsertHost(models.Host{ ID: hostID, Hostname: "offline.local", DisplayName: "Offline Host", Status: "online", IntervalSeconds: 30, LastSeen: time.Now().Add(-10 * time.Minute), }) now := time.Now() for i := 0; i < 3; i++ { monitor.evaluateHostAgents(now.Add(time.Duration(i) * time.Second)) } snapshot := monitor.state.GetSnapshot() statusUpdated := false for _, host := range snapshot.Hosts { if host.ID == hostID { statusUpdated = true if got := host.Status; got != "offline" { t.Fatalf("expected host status offline, got %q", got) } } } if !statusUpdated { t.Fatalf("host %q not found in state snapshot", hostID) } connKey := hostConnectionPrefix + hostID if healthy, ok := snapshot.ConnectionHealth[connKey]; !ok || healthy { t.Fatalf("expected connection health false, got %v (exists=%v)", healthy, ok) } alerts := monitor.alertManager.GetActiveAlerts() found := false for _, alert := range alerts { if alert.ID == "host-offline-"+hostID { found = true break } } if !found { t.Fatalf("expected host offline alert to remain active") } } func TestEvaluateHostAgentsClearsAlertWhenHostReturns(t *testing.T) { t.Helper() monitor := &Monitor{ state: models.NewState(), alertManager: alerts.NewManager(), } t.Cleanup(func() { monitor.alertManager.Stop() }) hostID := "host-recover" monitor.state.UpsertHost(models.Host{ ID: hostID, Hostname: "recover.local", DisplayName: "Recover Host", Status: "online", IntervalSeconds: 30, LastSeen: time.Now().Add(-10 * time.Minute), }) for i := 0; i < 3; i++ { monitor.evaluateHostAgents(time.Now().Add(time.Duration(i) * time.Second)) } monitor.state.UpsertHost(models.Host{ ID: hostID, Hostname: "recover.local", DisplayName: "Recover Host", Status: "online", IntervalSeconds: 30, LastSeen: time.Now(), }) monitor.evaluateHostAgents(time.Now()) snapshot := monitor.state.GetSnapshot() connKey := hostConnectionPrefix + hostID if healthy, ok := snapshot.ConnectionHealth[connKey]; !ok || !healthy { t.Fatalf("expected connection health true after recovery, got %v (exists=%v)", healthy, ok) } for _, alert := range monitor.alertManager.GetActiveAlerts() { if alert.ID == "host-offline-"+hostID { t.Fatalf("offline alert still active after recovery") } } }