Files
kandev/apps/backend/internal/orchestrator/queue/queue_test.go
T
2026-02-17 12:32:02 +00:00

221 lines
5.0 KiB
Go

package queue
import (
"testing"
"testing/synctest"
"time"
v1 "github.com/kandev/kandev/pkg/api/v1"
)
// createTestTask creates a task for testing with the given parameters
func createTestTask(id string, priority int) *v1.Task {
return &v1.Task{
ID: id,
WorkflowID: "test-wf",
Title: "Test Task " + id,
Priority: priority,
State: v1.TaskStateTODO,
CreatedAt: time.Now(),
UpdatedAt: time.Now(),
}
}
func TestNewTaskQueue(t *testing.T) {
q := NewTaskQueue(100)
if q == nil {
t.Fatal("NewTaskQueue returned nil")
}
if q.Len() != 0 {
t.Errorf("expected empty queue, got Len() = %d", q.Len())
}
if q.maxSize != 100 {
t.Errorf("expected maxSize = 100, got %d", q.maxSize)
}
}
func TestEnqueue(t *testing.T) {
q := NewTaskQueue(10)
task := createTestTask("task-1", 5)
err := q.Enqueue(task)
if err != nil {
t.Fatalf("Enqueue failed: %v", err)
}
if q.Len() != 1 {
t.Errorf("expected Len() = 1, got %d", q.Len())
}
}
func TestEnqueueDuplicate(t *testing.T) {
q := NewTaskQueue(10)
task := createTestTask("task-1", 5)
_ = q.Enqueue(task)
err := q.Enqueue(task)
if err != ErrTaskExists {
t.Errorf("expected ErrTaskExists, got %v", err)
}
}
func TestEnqueueQueueFull(t *testing.T) {
q := NewTaskQueue(2)
_ = q.Enqueue(createTestTask("task-1", 5))
_ = q.Enqueue(createTestTask("task-2", 5))
err := q.Enqueue(createTestTask("task-3", 5))
if err != ErrQueueFull {
t.Errorf("expected ErrQueueFull, got %v", err)
}
}
func TestDequeue(t *testing.T) {
q := NewTaskQueue(10)
task := createTestTask("task-1", 5)
_ = q.Enqueue(task)
dequeued := q.Dequeue()
if dequeued == nil {
t.Fatal("Dequeue returned nil")
} else if dequeued.TaskID != task.ID {
t.Errorf("expected TaskID = %s, got %s", task.ID, dequeued.TaskID)
}
if q.Len() != 0 {
t.Errorf("expected Len() = 0 after dequeue, got %d", q.Len())
}
}
func TestDequeueEmptyQueue(t *testing.T) {
q := NewTaskQueue(10)
dequeued := q.Dequeue()
if dequeued != nil {
t.Errorf("expected nil from empty queue, got %v", dequeued)
}
}
func TestPriorityOrdering(t *testing.T) {
q := NewTaskQueue(10)
// Enqueue tasks with different priorities
_ = q.Enqueue(createTestTask("low", 1))
_ = q.Enqueue(createTestTask("high", 10))
_ = q.Enqueue(createTestTask("medium", 5))
// Dequeue should return highest priority first
first := q.Dequeue()
if first.TaskID != "high" {
t.Errorf("expected first dequeue = 'high', got %s", first.TaskID)
}
second := q.Dequeue()
if second.TaskID != "medium" {
t.Errorf("expected second dequeue = 'medium', got %s", second.TaskID)
}
third := q.Dequeue()
if third.TaskID != "low" {
t.Errorf("expected third dequeue = 'low', got %s", third.TaskID)
}
}
func TestRemove(t *testing.T) {
q := NewTaskQueue(10)
_ = q.Enqueue(createTestTask("task-1", 5))
_ = q.Enqueue(createTestTask("task-2", 3))
removed := q.Remove("task-1")
if !removed {
t.Error("Remove should return true for existing task")
}
if q.Len() != 1 {
t.Errorf("expected Len() = 1 after remove, got %d", q.Len())
}
// Verify task was removed by trying to remove again
if q.Remove("task-1") {
t.Error("queue should not contain removed task")
}
}
func TestRemoveNonExistent(t *testing.T) {
q := NewTaskQueue(10)
removed := q.Remove("non-existent")
if removed {
t.Error("Remove should return false for non-existent task")
}
}
func TestIsFull(t *testing.T) {
q := NewTaskQueue(2)
if q.IsFull() {
t.Error("empty queue should not be full")
}
_ = q.Enqueue(createTestTask("task-1", 5))
if q.IsFull() {
t.Error("queue with 1 item (capacity 2) should not be full")
}
_ = q.Enqueue(createTestTask("task-2", 5))
if !q.IsFull() {
t.Error("queue at capacity should be full")
}
}
func TestList(t *testing.T) {
q := NewTaskQueue(10)
_ = q.Enqueue(createTestTask("task-1", 5))
_ = q.Enqueue(createTestTask("task-2", 3))
_ = q.Enqueue(createTestTask("task-3", 7))
list := q.List()
if len(list) != 3 {
t.Errorf("expected List() to return 3 items, got %d", len(list))
}
}
func TestUnlimitedQueue(t *testing.T) {
// maxSize of 0 means unlimited
q := NewTaskQueue(0)
for i := 0; i < 100; i++ {
err := q.Enqueue(createTestTask(string(rune('a'+i)), 5))
if err != nil {
t.Fatalf("Enqueue failed on unlimited queue: %v", err)
}
}
if q.IsFull() {
t.Error("unlimited queue should never be full")
}
}
func TestFIFOWithSamePriority(t *testing.T) {
synctest.Test(t, func(t *testing.T) {
q := NewTaskQueue(10)
// All tasks have same priority - should be FIFO
// Using 1s sleeps with synctest fake clock ensures distinct timestamps instantly
_ = q.Enqueue(createTestTask("first", 5))
time.Sleep(1 * time.Second)
_ = q.Enqueue(createTestTask("second", 5))
time.Sleep(1 * time.Second)
_ = q.Enqueue(createTestTask("third", 5))
first := q.Dequeue()
if first.TaskID != "first" {
t.Errorf("expected 'first' with FIFO ordering, got %s", first.TaskID)
}
second := q.Dequeue()
if second.TaskID != "second" {
t.Errorf("expected 'second' with FIFO ordering, got %s", second.TaskID)
}
})
}