From 47d0fb5a449360979896e1f406e5d1ba1900a312 Mon Sep 17 00:00:00 2001 From: rcourtman Date: Tue, 2 Dec 2025 11:47:24 +0000 Subject: [PATCH] =?UTF-8?q?test:=20Add=20dispatchAlert=20tests=20(55.6%?= =?UTF-8?q?=E2=86=9277.8%)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add TestDispatchAlert with 8 test cases covering: - Returns false when onAlert callback is nil - Returns false when alert is nil - Returns false when activation state is pending - Returns false when activation state is snoozed - Returns false for monitor-only alerts - Dispatches synchronously when async is false - Dispatches asynchronously when async is true - Clones alert before dispatch Alerts package coverage: 83.4%→83.5% --- internal/alerts/alerts_test.go | 225 +++++++++++++++++++++++++++++++++ 1 file changed, 225 insertions(+) diff --git a/internal/alerts/alerts_test.go b/internal/alerts/alerts_test.go index 209f23c..3b3317a 100644 --- a/internal/alerts/alerts_test.go +++ b/internal/alerts/alerts_test.go @@ -14051,3 +14051,228 @@ func TestCheckStorageComprehensive(t *testing.T) { } }) } + +func TestDispatchAlert(t *testing.T) { + t.Parallel() + + t.Run("returns false when onAlert is nil", func(t *testing.T) { + t.Parallel() + m := newTestManager(t) + + alert := &Alert{ + ID: "test-alert", + Type: "cpu", + } + + result := m.dispatchAlert(alert, false) + + if result { + t.Error("expected false when onAlert callback is nil") + } + }) + + t.Run("returns false when alert is nil", func(t *testing.T) { + t.Parallel() + m := newTestManager(t) + + called := false + m.SetAlertCallback(func(a *Alert) { + called = true + }) + + result := m.dispatchAlert(nil, false) + + if result { + t.Error("expected false when alert is nil") + } + if called { + t.Error("callback should not be called for nil alert") + } + }) + + t.Run("returns false when activation state is pending", func(t *testing.T) { + t.Parallel() + m := newTestManager(t) + + called := false + m.SetAlertCallback(func(a *Alert) { + called = true + }) + + m.mu.Lock() + m.config.ActivationState = ActivationPending + m.mu.Unlock() + + alert := &Alert{ + ID: "test-alert", + Type: "cpu", + } + + result := m.dispatchAlert(alert, false) + + if result { + t.Error("expected false when activation is pending") + } + if called { + t.Error("callback should not be called when pending") + } + }) + + t.Run("returns false when activation state is snoozed", func(t *testing.T) { + t.Parallel() + m := newTestManager(t) + + called := false + m.SetAlertCallback(func(a *Alert) { + called = true + }) + + m.mu.Lock() + m.config.ActivationState = ActivationSnoozed + m.mu.Unlock() + + alert := &Alert{ + ID: "test-alert", + Type: "cpu", + } + + result := m.dispatchAlert(alert, false) + + if result { + t.Error("expected false when activation is snoozed") + } + if called { + t.Error("callback should not be called when snoozed") + } + }) + + t.Run("returns false for monitor-only alert", func(t *testing.T) { + t.Parallel() + m := newTestManager(t) + + called := false + m.SetAlertCallback(func(a *Alert) { + called = true + }) + + m.mu.Lock() + m.config.ActivationState = ActivationActive + m.mu.Unlock() + + alert := &Alert{ + ID: "test-alert", + Type: "cpu", + Metadata: map[string]interface{}{"monitorOnly": true}, + } + + result := m.dispatchAlert(alert, false) + + if result { + t.Error("expected false for monitor-only alert") + } + if called { + t.Error("callback should not be called for monitor-only alert") + } + }) + + t.Run("dispatches synchronously when async is false", func(t *testing.T) { + t.Parallel() + m := newTestManager(t) + + var receivedAlert *Alert + m.SetAlertCallback(func(a *Alert) { + receivedAlert = a + }) + + m.mu.Lock() + m.config.ActivationState = ActivationActive + m.mu.Unlock() + + alert := &Alert{ + ID: "test-alert", + Type: "cpu", + ResourceName: "testvm", + } + + result := m.dispatchAlert(alert, false) + + if !result { + t.Error("expected true for successful dispatch") + } + if receivedAlert == nil { + t.Fatal("callback should have been called") + } + if receivedAlert.ID != alert.ID { + t.Error("alert ID should match") + } + }) + + t.Run("dispatches asynchronously when async is true", func(t *testing.T) { + t.Parallel() + m := newTestManager(t) + + var receivedAlert *Alert + done := make(chan struct{}) + m.SetAlertCallback(func(a *Alert) { + receivedAlert = a + close(done) + }) + + m.mu.Lock() + m.config.ActivationState = ActivationActive + m.mu.Unlock() + + alert := &Alert{ + ID: "test-alert", + Type: "cpu", + ResourceName: "testvm", + } + + result := m.dispatchAlert(alert, true) + + if !result { + t.Error("expected true for successful dispatch") + } + + // Wait for async callback + select { + case <-done: + // Success + case <-time.After(time.Second): + t.Fatal("async callback not called within timeout") + } + + if receivedAlert == nil { + t.Fatal("callback should have been called") + } + if receivedAlert.ID != alert.ID { + t.Error("alert ID should match") + } + }) + + t.Run("clones alert before dispatch", func(t *testing.T) { + t.Parallel() + m := newTestManager(t) + + var receivedAlert *Alert + m.SetAlertCallback(func(a *Alert) { + receivedAlert = a + }) + + m.mu.Lock() + m.config.ActivationState = ActivationActive + m.mu.Unlock() + + alert := &Alert{ + ID: "test-alert", + Type: "cpu", + ResourceName: "testvm", + } + + m.dispatchAlert(alert, false) + + if receivedAlert == alert { + t.Error("alert should be cloned, not passed directly") + } + }) +}