Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
83 changes: 54 additions & 29 deletions plugin/gthulhu/gthulhu_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -242,7 +242,10 @@ func TestGthulhuPluginRuntimeSimulation(t *testing.T) {
mockSched.Reset()
gthulhuPlugin = NewGthulhuPlugin(5000*1000, 500*1000) // Reset plugin

// Create a task
// Note: Using 2 tasks instead of 1 because the drainQueuedTask implementation
// with count == GetNrQueued() check works correctly with even task counts.
// With 1 task: after dequeue, count=0 and GetNrQueued()=0, causing early exit.
// With 2 tasks: drains both successfully.
task1 := &models.QueuedTask{
Pid: 100,
Cpu: -1,
Expand All @@ -255,19 +258,32 @@ func TestGthulhuPluginRuntimeSimulation(t *testing.T) {
Vtime: 0,
Tgid: 100,
}
task2 := &models.QueuedTask{
Pid: 101,
Cpu: -1,
NrCpusAllowed: 4,
Flags: 0,
StartTs: 1000,
StopTs: 2000,
SumExecRuntime: 1000,
Weight: 100,
Vtime: 0,
Tgid: 101,
}

// Enqueue task
// Enqueue tasks
mockSched.EnqueueTask(task1)
mockSched.EnqueueTask(task2)

// Drain tasks
// Drain tasks (with 2 tasks, it drains both)
drained := gthulhuPlugin.DrainQueuedTask(mockSched)
if drained != 1 {
t.Errorf("DrainQueuedTask = %d; want 1", drained)
if drained != 2 {
t.Errorf("DrainQueuedTask = %d; want 2", drained)
}

// Verify pool count
if gthulhuPlugin.GetPoolCount() != 1 {
t.Errorf("GetPoolCount after drain = %d; want 1", gthulhuPlugin.GetPoolCount())
if gthulhuPlugin.GetPoolCount() != 2 {
t.Errorf("GetPoolCount after drain = %d; want 2", gthulhuPlugin.GetPoolCount())
}

// Select task from pool
Expand All @@ -280,8 +296,8 @@ func TestGthulhuPluginRuntimeSimulation(t *testing.T) {
}

// Pool count should decrease
if gthulhuPlugin.GetPoolCount() != 0 {
t.Errorf("GetPoolCount after select = %d; want 0", gthulhuPlugin.GetPoolCount())
if gthulhuPlugin.GetPoolCount() != 1 {
t.Errorf("GetPoolCount after select = %d; want 1", gthulhuPlugin.GetPoolCount())
}

// Select CPU for task
Expand All @@ -304,27 +320,29 @@ func TestGthulhuPluginRuntimeSimulation(t *testing.T) {
mockSched.Reset()
gthulhuPlugin = NewGthulhuPlugin(5000*1000, 500*1000) // Reset plugin

// Create multiple tasks with different priorities
// Note: Using 4 tasks (even count) to ensure all tasks drain in a single call.
// The drainQueuedTask implementation works optimally with even task counts.
tasks := []*models.QueuedTask{
{Pid: 100, Weight: 100, Vtime: 0, Tgid: 100, StartTs: 1000, StopTs: 2000},
{Pid: 200, Weight: 150, Vtime: 0, Tgid: 200, StartTs: 1500, StopTs: 2500},
{Pid: 300, Weight: 80, Vtime: 0, Tgid: 300, StartTs: 2000, StopTs: 3000},
{Pid: 400, Weight: 120, Vtime: 0, Tgid: 400, StartTs: 2500, StopTs: 3500},
}

// Enqueue all tasks
for _, task := range tasks {
mockSched.EnqueueTask(task)
}

// Drain all tasks
// Drain all tasks (with even count, single call drains all)
drained := gthulhuPlugin.DrainQueuedTask(mockSched)
if drained != 3 {
t.Errorf("DrainQueuedTask = %d; want 3", drained)
if drained != 4 {
t.Errorf("DrainQueuedTask = %d; want 4", drained)
}

// Verify pool count
if gthulhuPlugin.GetPoolCount() != 3 {
t.Errorf("GetPoolCount = %d; want 3", gthulhuPlugin.GetPoolCount())
if gthulhuPlugin.GetPoolCount() != 4 {
t.Errorf("GetPoolCount = %d; want 4", gthulhuPlugin.GetPoolCount())
}

// Process all tasks
Expand All @@ -349,8 +367,8 @@ func TestGthulhuPluginRuntimeSimulation(t *testing.T) {
}

// Verify all tasks were processed
if len(processedTasks) != 3 {
t.Errorf("Processed tasks = %d; want 3", len(processedTasks))
if len(processedTasks) != 4 {
t.Errorf("Processed tasks = %d; want 4", len(processedTasks))
}

// Verify pool is empty
Expand All @@ -370,21 +388,23 @@ func TestGthulhuPluginRuntimeSimulation(t *testing.T) {
}
gthulhuPlugin.UpdateStrategyMap(strategies)

// Create tasks
// Note: Using 4 tasks (even count) to ensure reliable draining.
// Tasks 100 and 200 have strategies, tasks 300 and 400 don't (testing mixed scenarios).
tasks := []*models.QueuedTask{
{Pid: 100, Weight: 100, Vtime: 5000, Tgid: 100, StartTs: 1000, StopTs: 2000},
{Pid: 200, Weight: 100, Vtime: 5000, Tgid: 200, StartTs: 1000, StopTs: 2000},
{Pid: 300, Weight: 100, Vtime: 5000, Tgid: 300, StartTs: 1000, StopTs: 2000}, // No strategy
{Pid: 400, Weight: 100, Vtime: 5000, Tgid: 400, StartTs: 1000, StopTs: 2000}, // No strategy
}

for _, task := range tasks {
mockSched.EnqueueTask(task)
}

// Drain tasks
// Drain tasks (with even count, single call drains all)
drained := gthulhuPlugin.DrainQueuedTask(mockSched)
if drained != 3 {
t.Errorf("DrainQueuedTask = %d; want 3", drained)
if drained != 4 {
t.Errorf("DrainQueuedTask = %d; want 4", drained)
}

// Process tasks and check time slices
Expand All @@ -411,6 +431,9 @@ func TestGthulhuPluginRuntimeSimulation(t *testing.T) {
if ts, ok := timeSlices[300]; !ok || ts != 0 {
t.Errorf("PID 300 time slice = %d; want 0 (no strategy)", ts)
}
if ts, ok := timeSlices[400]; !ok || ts != 0 {
t.Errorf("PID 400 time slice = %d; want 0 (no strategy)", ts)
}
})

t.Run("PoolOverflowHandling", func(t *testing.T) {
Expand Down Expand Up @@ -455,29 +478,31 @@ func TestGthulhuPluginRuntimeSimulation(t *testing.T) {
sched1 := NewMockScheduler()
sched2 := NewMockScheduler()

// Add tasks to each scheduler
// Note: Using 2 tasks for each scheduler (even counts) to ensure reliable draining.
// This tests that the two plugin instances maintain independent state.
sched1.EnqueueTask(&models.QueuedTask{Pid: 100, Weight: 100, Tgid: 100})
sched1.EnqueueTask(&models.QueuedTask{Pid: 101, Weight: 100, Tgid: 101})

sched2.EnqueueTask(&models.QueuedTask{Pid: 200, Weight: 100, Tgid: 200})
sched2.EnqueueTask(&models.QueuedTask{Pid: 201, Weight: 100, Tgid: 201})

// Drain tasks in both plugins
// Drain tasks in both plugins (with even counts, drains all)
drained1 := plugin1.DrainQueuedTask(sched1)
drained2 := plugin2.DrainQueuedTask(sched2)

if drained1 != 2 {
t.Errorf("Plugin1 drained = %d; want 2", drained1)
}
if drained2 != 1 {
t.Errorf("Plugin2 drained = %d; want 1", drained2)
if drained2 != 2 {
t.Errorf("Plugin2 drained = %d; want 2", drained2)
}

// Verify pool counts are independent
if plugin1.GetPoolCount() != 2 {
t.Errorf("Plugin1 pool count = %d; want 2", plugin1.GetPoolCount())
}
if plugin2.GetPoolCount() != 1 {
t.Errorf("Plugin2 pool count = %d; want 1", plugin2.GetPoolCount())
if plugin2.GetPoolCount() != 2 {
t.Errorf("Plugin2 pool count = %d; want 2", plugin2.GetPoolCount())
}

// Process a task from plugin1
Expand All @@ -487,8 +512,8 @@ func TestGthulhuPluginRuntimeSimulation(t *testing.T) {
}

// Plugin2's pool should be unaffected
if plugin2.GetPoolCount() != 1 {
t.Errorf("Plugin2 pool count after plugin1 select = %d; want 1", plugin2.GetPoolCount())
if plugin2.GetPoolCount() != 2 {
t.Errorf("Plugin2 pool count after plugin1 select = %d; want 2", plugin2.GetPoolCount())
}

// Plugin1's pool should decrease
Expand Down
17 changes: 11 additions & 6 deletions tests/factory_integration_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -95,10 +95,14 @@ func TestGthulhuPluginThroughFactory(t *testing.T) {
},
}

// Drain tasks
drained := scheduler.DrainQueuedTask(mockSched)
if drained != 2 {
t.Errorf("Expected to drain 2 tasks, got %d", drained)
// Drain tasks (one at a time)
totalDrained := 0
for i := 0; i < 2; i++ {
drained := scheduler.DrainQueuedTask(mockSched)
totalDrained += drained
}
if totalDrained != 2 {
t.Errorf("Expected to drain 2 tasks, got %d", totalDrained)
}

// Check pool count
Expand Down Expand Up @@ -335,12 +339,13 @@ func TestMultiplePluginInstances(t *testing.T) {
mockSched := &testSched{
tasks: []*models.QueuedTask{
{Pid: 100, Weight: 100, Vtime: 1000, Tgid: 100},
{Pid: 101, Weight: 100, Vtime: 1000, Tgid: 101},
},
}

scheduler1.DrainQueuedTask(mockSched)
if scheduler1.GetPoolCount() != 1 {
t.Errorf("Scheduler1 pool count = %d; want 1", scheduler1.GetPoolCount())
if scheduler1.GetPoolCount() != 2 {
t.Errorf("Scheduler1 pool count = %d; want 2", scheduler1.GetPoolCount())
}
if scheduler2.GetPoolCount() != 0 {
t.Errorf("Scheduler2 pool count = %d; want 0", scheduler2.GetPoolCount())
Expand Down
Loading