test: Add recordTaskResult tests
Add 6 tests for polling task result recording: - Nil monitor safety check - Success case resets counters - Failure case increments counters - Consecutive failures tracking - Success resets failure state - Nil internal maps don't panic Coverage: 53.7% → 97.6%
This commit is contained in:
parent
67d322c456
commit
2d09c28129
1 changed files with 173 additions and 0 deletions
|
|
@ -1,6 +1,7 @@
|
|||
package monitoring
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
|
|
@ -85,3 +86,175 @@ func TestRescheduleTaskUsesInstanceIntervalWhenSchedulerDisabled(t *testing.T) {
|
|||
t.Fatalf("expected NextRun about %v from now, got %v", cfg.PVEPollingInterval, remaining)
|
||||
}
|
||||
}
|
||||
|
||||
func TestRecordTaskResult_NilMonitor(t *testing.T) {
|
||||
// Should not panic when called on nil monitor
|
||||
var m *Monitor
|
||||
m.recordTaskResult(InstanceTypePVE, "test-instance", nil)
|
||||
// If we get here without panic, the test passes
|
||||
}
|
||||
|
||||
func TestRecordTaskResult_Success(t *testing.T) {
|
||||
m := &Monitor{
|
||||
pollStatusMap: make(map[string]*pollStatus),
|
||||
failureCounts: make(map[string]int),
|
||||
lastOutcome: make(map[string]taskOutcome),
|
||||
circuitBreakers: make(map[string]*circuitBreaker),
|
||||
}
|
||||
|
||||
// Record a success
|
||||
m.recordTaskResult(InstanceTypePVE, "test-instance", nil)
|
||||
|
||||
key := schedulerKey(InstanceTypePVE, "test-instance")
|
||||
|
||||
// Verify failure count is reset
|
||||
if m.failureCounts[key] != 0 {
|
||||
t.Errorf("expected failureCounts[%s] = 0, got %d", key, m.failureCounts[key])
|
||||
}
|
||||
|
||||
// Verify last outcome is success
|
||||
outcome, ok := m.lastOutcome[key]
|
||||
if !ok {
|
||||
t.Fatalf("expected lastOutcome[%s] to exist", key)
|
||||
}
|
||||
if !outcome.success {
|
||||
t.Error("expected outcome.success = true")
|
||||
}
|
||||
|
||||
// Verify poll status
|
||||
status, ok := m.pollStatusMap[key]
|
||||
if !ok {
|
||||
t.Fatalf("expected pollStatusMap[%s] to exist", key)
|
||||
}
|
||||
if status.ConsecutiveFailures != 0 {
|
||||
t.Errorf("expected ConsecutiveFailures = 0, got %d", status.ConsecutiveFailures)
|
||||
}
|
||||
}
|
||||
|
||||
func TestRecordTaskResult_Failure(t *testing.T) {
|
||||
m := &Monitor{
|
||||
pollStatusMap: make(map[string]*pollStatus),
|
||||
failureCounts: make(map[string]int),
|
||||
lastOutcome: make(map[string]taskOutcome),
|
||||
circuitBreakers: make(map[string]*circuitBreaker),
|
||||
}
|
||||
|
||||
testErr := errors.New("connection refused")
|
||||
|
||||
// Record a failure
|
||||
m.recordTaskResult(InstanceTypePVE, "test-instance", testErr)
|
||||
|
||||
key := schedulerKey(InstanceTypePVE, "test-instance")
|
||||
|
||||
// Verify failure count is incremented
|
||||
if m.failureCounts[key] != 1 {
|
||||
t.Errorf("expected failureCounts[%s] = 1, got %d", key, m.failureCounts[key])
|
||||
}
|
||||
|
||||
// Verify last outcome is failure
|
||||
outcome, ok := m.lastOutcome[key]
|
||||
if !ok {
|
||||
t.Fatalf("expected lastOutcome[%s] to exist", key)
|
||||
}
|
||||
if outcome.success {
|
||||
t.Error("expected outcome.success = false")
|
||||
}
|
||||
if outcome.err != testErr {
|
||||
t.Errorf("expected outcome.err = %v, got %v", testErr, outcome.err)
|
||||
}
|
||||
|
||||
// Verify poll status
|
||||
status, ok := m.pollStatusMap[key]
|
||||
if !ok {
|
||||
t.Fatalf("expected pollStatusMap[%s] to exist", key)
|
||||
}
|
||||
if status.ConsecutiveFailures != 1 {
|
||||
t.Errorf("expected ConsecutiveFailures = 1, got %d", status.ConsecutiveFailures)
|
||||
}
|
||||
if status.LastErrorMessage != "connection refused" {
|
||||
t.Errorf("expected LastErrorMessage = 'connection refused', got %q", status.LastErrorMessage)
|
||||
}
|
||||
}
|
||||
|
||||
func TestRecordTaskResult_ConsecutiveFailures(t *testing.T) {
|
||||
m := &Monitor{
|
||||
pollStatusMap: make(map[string]*pollStatus),
|
||||
failureCounts: make(map[string]int),
|
||||
lastOutcome: make(map[string]taskOutcome),
|
||||
circuitBreakers: make(map[string]*circuitBreaker),
|
||||
}
|
||||
|
||||
testErr := errors.New("timeout")
|
||||
|
||||
// Record multiple failures
|
||||
m.recordTaskResult(InstanceTypePBS, "pbs-server", testErr)
|
||||
m.recordTaskResult(InstanceTypePBS, "pbs-server", testErr)
|
||||
m.recordTaskResult(InstanceTypePBS, "pbs-server", testErr)
|
||||
|
||||
key := schedulerKey(InstanceTypePBS, "pbs-server")
|
||||
|
||||
// Verify consecutive failures count
|
||||
status := m.pollStatusMap[key]
|
||||
if status.ConsecutiveFailures != 3 {
|
||||
t.Errorf("expected ConsecutiveFailures = 3, got %d", status.ConsecutiveFailures)
|
||||
}
|
||||
|
||||
// FirstFailureAt should be set on first failure and not change
|
||||
if status.FirstFailureAt.IsZero() {
|
||||
t.Error("expected FirstFailureAt to be set")
|
||||
}
|
||||
}
|
||||
|
||||
func TestRecordTaskResult_SuccessResetsFailures(t *testing.T) {
|
||||
m := &Monitor{
|
||||
pollStatusMap: make(map[string]*pollStatus),
|
||||
failureCounts: make(map[string]int),
|
||||
lastOutcome: make(map[string]taskOutcome),
|
||||
circuitBreakers: make(map[string]*circuitBreaker),
|
||||
}
|
||||
|
||||
testErr := errors.New("error")
|
||||
key := schedulerKey(InstanceTypePMG, "pmg-server")
|
||||
|
||||
// Record some failures first
|
||||
m.recordTaskResult(InstanceTypePMG, "pmg-server", testErr)
|
||||
m.recordTaskResult(InstanceTypePMG, "pmg-server", testErr)
|
||||
|
||||
if m.pollStatusMap[key].ConsecutiveFailures != 2 {
|
||||
t.Fatalf("expected 2 failures before reset")
|
||||
}
|
||||
|
||||
// Now record a success
|
||||
m.recordTaskResult(InstanceTypePMG, "pmg-server", nil)
|
||||
|
||||
// Verify everything is reset
|
||||
if m.failureCounts[key] != 0 {
|
||||
t.Errorf("expected failureCounts to be reset to 0, got %d", m.failureCounts[key])
|
||||
}
|
||||
if m.pollStatusMap[key].ConsecutiveFailures != 0 {
|
||||
t.Errorf("expected ConsecutiveFailures to be reset to 0, got %d", m.pollStatusMap[key].ConsecutiveFailures)
|
||||
}
|
||||
if !m.pollStatusMap[key].FirstFailureAt.IsZero() {
|
||||
t.Error("expected FirstFailureAt to be reset to zero")
|
||||
}
|
||||
}
|
||||
|
||||
func TestRecordTaskResult_NilMaps(t *testing.T) {
|
||||
// Monitor with nil internal maps - should not panic
|
||||
m := &Monitor{
|
||||
pollStatusMap: make(map[string]*pollStatus),
|
||||
failureCounts: nil, // nil
|
||||
lastOutcome: nil, // nil
|
||||
circuitBreakers: make(map[string]*circuitBreaker),
|
||||
}
|
||||
|
||||
// Should not panic
|
||||
m.recordTaskResult(InstanceTypePVE, "test", nil)
|
||||
m.recordTaskResult(InstanceTypePVE, "test", errors.New("error"))
|
||||
|
||||
// pollStatusMap should still be updated
|
||||
key := schedulerKey(InstanceTypePVE, "test")
|
||||
if _, ok := m.pollStatusMap[key]; !ok {
|
||||
t.Error("expected pollStatusMap to be updated even with nil failureCounts/lastOutcome")
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue