test: Add WaitNext and key() tests for TaskQueue
Tests cover context cancellation, immediately due tasks, waiting for future tasks, empty queue timeout, and multiple task priority ordering. WaitNext coverage 0%→92.3%, key() 0%→100%. Monitoring package 52.3%→52.9%.
This commit is contained in:
parent
e63c297ca3
commit
fc96ba7b69
1 changed files with 201 additions and 0 deletions
|
|
@ -1,6 +1,7 @@
|
|||
package monitoring
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
|
@ -930,3 +931,203 @@ func verifyHeapInvariant(t *testing.T, queue *TaskQueue) {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TestScheduledTaskEntry_Key tests the key() method on scheduledTaskEntry
|
||||
func TestScheduledTaskEntry_Key(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
instType InstanceType
|
||||
instName string
|
||||
wantKey string
|
||||
}{
|
||||
{
|
||||
name: "PVE instance",
|
||||
instType: InstanceTypePVE,
|
||||
instName: "pve1",
|
||||
wantKey: "pve::pve1",
|
||||
},
|
||||
{
|
||||
name: "PBS instance",
|
||||
instType: InstanceTypePBS,
|
||||
instName: "pbs-cluster",
|
||||
wantKey: "pbs::pbs-cluster",
|
||||
},
|
||||
{
|
||||
name: "PMG instance",
|
||||
instType: InstanceTypePMG,
|
||||
instName: "pmg-01",
|
||||
wantKey: "pmg::pmg-01",
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
entry := &scheduledTaskEntry{
|
||||
task: ScheduledTask{
|
||||
InstanceType: tt.instType,
|
||||
InstanceName: tt.instName,
|
||||
},
|
||||
}
|
||||
|
||||
got := entry.key()
|
||||
if got != tt.wantKey {
|
||||
t.Errorf("key() = %q, want %q", got, tt.wantKey)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// TestWaitNext_ContextCancelled tests WaitNext returns when context is cancelled
|
||||
func TestWaitNext_ContextCancelled(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
queue := NewTaskQueue()
|
||||
|
||||
// Create a context that's already cancelled
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
cancel()
|
||||
|
||||
task, ok := queue.WaitNext(ctx)
|
||||
if ok {
|
||||
t.Error("WaitNext should return false when context is cancelled")
|
||||
}
|
||||
if task.InstanceName != "" {
|
||||
t.Error("WaitNext should return empty task when context is cancelled")
|
||||
}
|
||||
}
|
||||
|
||||
// TestWaitNext_ImmediatelyDue tests WaitNext returns immediately for due tasks
|
||||
func TestWaitNext_ImmediatelyDue(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
queue := NewTaskQueue()
|
||||
|
||||
// Add a task that's already due (NextRun in the past)
|
||||
queue.Upsert(ScheduledTask{
|
||||
InstanceName: "pve1",
|
||||
InstanceType: InstanceTypePVE,
|
||||
NextRun: time.Now().Add(-1 * time.Second),
|
||||
Interval: 30 * time.Second,
|
||||
})
|
||||
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second)
|
||||
defer cancel()
|
||||
|
||||
task, ok := queue.WaitNext(ctx)
|
||||
if !ok {
|
||||
t.Fatal("WaitNext should return true for immediately due task")
|
||||
}
|
||||
if task.InstanceName != "pve1" {
|
||||
t.Errorf("expected task pve1, got %s", task.InstanceName)
|
||||
}
|
||||
|
||||
// Task should be removed from queue
|
||||
if queue.Size() != 0 {
|
||||
t.Errorf("queue size should be 0 after WaitNext, got %d", queue.Size())
|
||||
}
|
||||
}
|
||||
|
||||
// TestWaitNext_WaitsForDue tests WaitNext waits until task is due
|
||||
func TestWaitNext_WaitsForDue(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
queue := NewTaskQueue()
|
||||
|
||||
// Add a task due 200ms in the future
|
||||
dueTime := time.Now().Add(200 * time.Millisecond)
|
||||
queue.Upsert(ScheduledTask{
|
||||
InstanceName: "pve1",
|
||||
InstanceType: InstanceTypePVE,
|
||||
NextRun: dueTime,
|
||||
Interval: 30 * time.Second,
|
||||
})
|
||||
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second)
|
||||
defer cancel()
|
||||
|
||||
start := time.Now()
|
||||
task, ok := queue.WaitNext(ctx)
|
||||
elapsed := time.Since(start)
|
||||
|
||||
if !ok {
|
||||
t.Fatal("WaitNext should return true")
|
||||
}
|
||||
if task.InstanceName != "pve1" {
|
||||
t.Errorf("expected task pve1, got %s", task.InstanceName)
|
||||
}
|
||||
|
||||
// Should have waited at least ~150ms (allowing some tolerance)
|
||||
if elapsed < 150*time.Millisecond {
|
||||
t.Errorf("WaitNext returned too early: elapsed %v, expected >= 150ms", elapsed)
|
||||
}
|
||||
}
|
||||
|
||||
// TestWaitNext_EmptyQueueContextCancel tests WaitNext with empty queue and context cancel
|
||||
func TestWaitNext_EmptyQueueContextCancel(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
queue := NewTaskQueue()
|
||||
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 200*time.Millisecond)
|
||||
defer cancel()
|
||||
|
||||
start := time.Now()
|
||||
task, ok := queue.WaitNext(ctx)
|
||||
elapsed := time.Since(start)
|
||||
|
||||
if ok {
|
||||
t.Error("WaitNext should return false when context times out on empty queue")
|
||||
}
|
||||
if task.InstanceName != "" {
|
||||
t.Error("WaitNext should return empty task")
|
||||
}
|
||||
|
||||
// Should have waited close to the timeout
|
||||
if elapsed < 150*time.Millisecond {
|
||||
t.Errorf("WaitNext returned too early: elapsed %v", elapsed)
|
||||
}
|
||||
}
|
||||
|
||||
// TestWaitNext_MultipleTasks tests WaitNext returns earliest due task
|
||||
func TestWaitNext_MultipleTasks(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
queue := NewTaskQueue()
|
||||
now := time.Now()
|
||||
|
||||
// Add tasks with different due times
|
||||
queue.Upsert(ScheduledTask{
|
||||
InstanceName: "pve3",
|
||||
InstanceType: InstanceTypePVE,
|
||||
NextRun: now.Add(300 * time.Millisecond),
|
||||
})
|
||||
queue.Upsert(ScheduledTask{
|
||||
InstanceName: "pve1",
|
||||
InstanceType: InstanceTypePVE,
|
||||
NextRun: now.Add(-10 * time.Millisecond), // Already due
|
||||
})
|
||||
queue.Upsert(ScheduledTask{
|
||||
InstanceName: "pve2",
|
||||
InstanceType: InstanceTypePVE,
|
||||
NextRun: now.Add(200 * time.Millisecond),
|
||||
})
|
||||
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second)
|
||||
defer cancel()
|
||||
|
||||
// Should return pve1 first (earliest due)
|
||||
task, ok := queue.WaitNext(ctx)
|
||||
if !ok {
|
||||
t.Fatal("WaitNext should return true")
|
||||
}
|
||||
if task.InstanceName != "pve1" {
|
||||
t.Errorf("expected pve1 (earliest), got %s", task.InstanceName)
|
||||
}
|
||||
|
||||
// Queue should still have 2 tasks
|
||||
if queue.Size() != 2 {
|
||||
t.Errorf("queue size should be 2, got %d", queue.Size())
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue