233 lines
5.7 KiB
Go
233 lines
5.7 KiB
Go
package monitoring
|
|
|
|
import (
|
|
"testing"
|
|
"time"
|
|
)
|
|
|
|
func TestTaskQueue_Snapshot(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
tasks []ScheduledTask
|
|
wantDepth int
|
|
wantDueWithinSeconds int
|
|
wantPerType map[string]int
|
|
}{
|
|
{
|
|
name: "empty queue",
|
|
tasks: []ScheduledTask{},
|
|
wantDepth: 0,
|
|
wantDueWithinSeconds: 0,
|
|
wantPerType: map[string]int{},
|
|
},
|
|
{
|
|
name: "single task due soon (within 12 seconds)",
|
|
tasks: []ScheduledTask{
|
|
{
|
|
InstanceName: "pve-1",
|
|
InstanceType: InstanceTypePVE,
|
|
NextRun: time.Now().Add(5 * time.Second),
|
|
Interval: 30 * time.Second,
|
|
Priority: 1.0,
|
|
},
|
|
},
|
|
wantDepth: 1,
|
|
wantDueWithinSeconds: 1,
|
|
wantPerType: map[string]int{
|
|
"pve": 1,
|
|
},
|
|
},
|
|
{
|
|
name: "single task NOT due soon (>12 seconds away)",
|
|
tasks: []ScheduledTask{
|
|
{
|
|
InstanceName: "pbs-1",
|
|
InstanceType: InstanceTypePBS,
|
|
NextRun: time.Now().Add(20 * time.Second),
|
|
Interval: 60 * time.Second,
|
|
Priority: 1.0,
|
|
},
|
|
},
|
|
wantDepth: 1,
|
|
wantDueWithinSeconds: 0,
|
|
wantPerType: map[string]int{
|
|
"pbs": 1,
|
|
},
|
|
},
|
|
{
|
|
name: "multiple tasks of same type",
|
|
tasks: []ScheduledTask{
|
|
{
|
|
InstanceName: "pve-1",
|
|
InstanceType: InstanceTypePVE,
|
|
NextRun: time.Now().Add(5 * time.Second),
|
|
Interval: 30 * time.Second,
|
|
Priority: 1.0,
|
|
},
|
|
{
|
|
InstanceName: "pve-2",
|
|
InstanceType: InstanceTypePVE,
|
|
NextRun: time.Now().Add(15 * time.Second),
|
|
Interval: 30 * time.Second,
|
|
Priority: 1.0,
|
|
},
|
|
{
|
|
InstanceName: "pve-3",
|
|
InstanceType: InstanceTypePVE,
|
|
NextRun: time.Now().Add(10 * time.Second),
|
|
Interval: 30 * time.Second,
|
|
Priority: 1.0,
|
|
},
|
|
},
|
|
wantDepth: 3,
|
|
wantDueWithinSeconds: 2, // pve-1 and pve-3 are within 12 seconds
|
|
wantPerType: map[string]int{
|
|
"pve": 3,
|
|
},
|
|
},
|
|
{
|
|
name: "multiple tasks of different types",
|
|
tasks: []ScheduledTask{
|
|
{
|
|
InstanceName: "pve-1",
|
|
InstanceType: InstanceTypePVE,
|
|
NextRun: time.Now().Add(5 * time.Second),
|
|
Interval: 30 * time.Second,
|
|
Priority: 1.0,
|
|
},
|
|
{
|
|
InstanceName: "pbs-1",
|
|
InstanceType: InstanceTypePBS,
|
|
NextRun: time.Now().Add(8 * time.Second),
|
|
Interval: 60 * time.Second,
|
|
Priority: 1.0,
|
|
},
|
|
{
|
|
InstanceName: "pmg-1",
|
|
InstanceType: InstanceTypePMG,
|
|
NextRun: time.Now().Add(25 * time.Second),
|
|
Interval: 45 * time.Second,
|
|
Priority: 1.0,
|
|
},
|
|
},
|
|
wantDepth: 3,
|
|
wantDueWithinSeconds: 2, // pve-1 and pbs-1 are within 12 seconds
|
|
wantPerType: map[string]int{
|
|
"pve": 1,
|
|
"pbs": 1,
|
|
"pmg": 1,
|
|
},
|
|
},
|
|
{
|
|
name: "boundary case: task exactly 12 seconds away",
|
|
tasks: []ScheduledTask{
|
|
{
|
|
InstanceName: "pve-1",
|
|
InstanceType: InstanceTypePVE,
|
|
NextRun: time.Now().Add(12 * time.Second),
|
|
Interval: 30 * time.Second,
|
|
Priority: 1.0,
|
|
},
|
|
},
|
|
wantDepth: 1,
|
|
wantDueWithinSeconds: 1, // <= 12 seconds should be included
|
|
wantPerType: map[string]int{
|
|
"pve": 1,
|
|
},
|
|
},
|
|
{
|
|
name: "mix of due-soon and not-due-soon tasks",
|
|
tasks: []ScheduledTask{
|
|
{
|
|
InstanceName: "pve-1",
|
|
InstanceType: InstanceTypePVE,
|
|
NextRun: time.Now().Add(1 * time.Second),
|
|
Interval: 30 * time.Second,
|
|
Priority: 1.0,
|
|
},
|
|
{
|
|
InstanceName: "pve-2",
|
|
InstanceType: InstanceTypePVE,
|
|
NextRun: time.Now().Add(50 * time.Second),
|
|
Interval: 30 * time.Second,
|
|
Priority: 1.0,
|
|
},
|
|
{
|
|
InstanceName: "pbs-1",
|
|
InstanceType: InstanceTypePBS,
|
|
NextRun: time.Now().Add(11 * time.Second),
|
|
Interval: 60 * time.Second,
|
|
Priority: 1.0,
|
|
},
|
|
{
|
|
InstanceName: "pbs-2",
|
|
InstanceType: InstanceTypePBS,
|
|
NextRun: time.Now().Add(100 * time.Second),
|
|
Interval: 60 * time.Second,
|
|
Priority: 1.0,
|
|
},
|
|
{
|
|
InstanceName: "pmg-1",
|
|
InstanceType: InstanceTypePMG,
|
|
NextRun: time.Now().Add(30 * time.Second),
|
|
Interval: 45 * time.Second,
|
|
Priority: 1.0,
|
|
},
|
|
},
|
|
wantDepth: 5,
|
|
wantDueWithinSeconds: 2, // pve-1 and pbs-1 are within 12 seconds
|
|
wantPerType: map[string]int{
|
|
"pve": 2,
|
|
"pbs": 2,
|
|
"pmg": 1,
|
|
},
|
|
},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
queue := NewTaskQueue()
|
|
|
|
// Add all tasks to the queue
|
|
for _, task := range tt.tasks {
|
|
queue.Upsert(task)
|
|
}
|
|
|
|
// Get snapshot
|
|
snapshot := queue.Snapshot()
|
|
|
|
// Verify depth
|
|
if snapshot.Depth != tt.wantDepth {
|
|
t.Errorf("Depth = %d, want %d", snapshot.Depth, tt.wantDepth)
|
|
}
|
|
|
|
// Verify DueWithinSeconds
|
|
if snapshot.DueWithinSeconds != tt.wantDueWithinSeconds {
|
|
t.Errorf("DueWithinSeconds = %d, want %d", snapshot.DueWithinSeconds, tt.wantDueWithinSeconds)
|
|
}
|
|
|
|
// Verify PerType map
|
|
if len(snapshot.PerType) != len(tt.wantPerType) {
|
|
t.Errorf("PerType has %d entries, want %d", len(snapshot.PerType), len(tt.wantPerType))
|
|
}
|
|
|
|
for typeStr, wantCount := range tt.wantPerType {
|
|
gotCount, ok := snapshot.PerType[typeStr]
|
|
if !ok {
|
|
t.Errorf("PerType missing entry for %s", typeStr)
|
|
continue
|
|
}
|
|
if gotCount != wantCount {
|
|
t.Errorf("PerType[%s] = %d, want %d", typeStr, gotCount, wantCount)
|
|
}
|
|
}
|
|
|
|
// Verify no extra keys in PerType
|
|
for typeStr := range snapshot.PerType {
|
|
if _, ok := tt.wantPerType[typeStr]; !ok {
|
|
t.Errorf("PerType has unexpected entry for %s", typeStr)
|
|
}
|
|
}
|
|
})
|
|
}
|
|
}
|