Something went wrong on our end
Select Git revision
monitor-attribute-errors.pcss
-
Volker Schukai authoredVolker Schukai authored
queue_test.go 9.40 KiB
package jobqueue
import (
"errors"
"fmt"
"math/rand"
"testing"
"time"
)
func TestEnqueueJobAlreadyExists(t *testing.T) {
runner := &DummyRunnable{}
job := NewJob[DummyResult](JobID("1"), runner)
q := NewQueue(nil)
_ = q.Enqueue(job)
err := q.Enqueue(job)
if err != ErrJobAlreadyExists {
t.Fatalf("Expected ErrJobAlreadyExists, got %v", err)
}
}
func TestEnqueueAndDequeue(t *testing.T) {
runner := &DummyRunnable{}
q := NewQueue(nil)
job1 := NewJob[DummyResult](JobID("1"), runner)
job1.SetPriority(PriorityHigh)
job2 := NewJob[DummyResult](JobID("2"), runner)
_ = q.Enqueue(job1)
_ = q.Enqueue(job2)
dequeuedJob, err := q.Dequeue()
if err != nil || dequeuedJob.GetID() != JobID("1") {
t.Fatalf("Unexpected dequeue result: jobID %s, err %v", dequeuedJob.GetID(), err)
}
}
func TestEnqueueAndDequeue2(t *testing.T) {
runner := &DummyRunnable{}
q := NewQueue(nil)
job1 := NewJob[DummyResult](JobID("1"), runner)
job2 := NewJob[DummyResult](JobID("2"), runner)
job2.AddDependency(JobID("1"))
_ = q.Enqueue(job1)
_ = q.Enqueue(job2)
dequeuedJob, err := q.Dequeue()
if err != nil {
t.Fatalf("Unexpected error: %v", err)
}
if dequeuedJob.GetID() != JobID("1") {
t.Fatalf("Unexpected dequeue result: jobID %s", dequeuedJob.GetID())
}
}
func TestDependencyResolution(t *testing.T) {
runner := &DummyRunnable{}
q := NewQueue(nil)
job1 := NewJob[DummyResult](JobID("1"), runner)
job2 := NewJob[DummyResult](JobID("2"), runner)
job3 := NewJob[DummyResult](JobID("3"), runner)
_ = q.Enqueue(job3)
_ = q.Enqueue(job2)
_ = q.Enqueue(job1)
contains := func(arr []JobID, id JobID) bool {
for _, v := range arr {
if v == id {
return true
}
}
return false
}
possibleJobIDs := []JobID{"1", "2", "3"}
job, _ := q.Dequeue()
if !contains(possibleJobIDs, job.GetID()) {
t.Fatalf("Expected jobID in %v, got %s", possibleJobIDs, job.GetID())
}
// remove jobID from possibleJobIDs
for i, v := range possibleJobIDs {
if v == job.GetID() {
possibleJobIDs = append(possibleJobIDs[:i], possibleJobIDs[i+1:]...)
}
}
job, _ = q.Dequeue()
if !contains(possibleJobIDs, job.GetID()) {
t.Fatalf("Expected jobID in %v, got %s", possibleJobIDs, job.GetID())
}
// remove jobID from possibleJobIDs
for i, v := range possibleJobIDs {
if v == job.GetID() {
possibleJobIDs = append(possibleJobIDs[:i], possibleJobIDs[i+1:]...)
}
}
job, _ = q.Dequeue()
if !contains(possibleJobIDs, job.GetID()) {
t.Fatalf("Expected jobID in %v, got %s", possibleJobIDs, job.GetID())
}
// remove jobID from possibleJobIDs
for i, v := range possibleJobIDs {
if v == job.GetID() {
possibleJobIDs = append(possibleJobIDs[:i], possibleJobIDs[i+1:]...)
}
}
if len(possibleJobIDs) != 0 {
t.Fatalf("Expected no jobIDs left in %v", possibleJobIDs)
}
}
func TestDequeueEmptyQueue(t *testing.T) {
q := NewQueue(nil)
_, err := q.Dequeue()
if err != ErrQueueEmpty {
t.Fatalf("Expected ErrQueueEmpty, got %v", err)
}
}
func TestProcessedJobs(t *testing.T) {
q := NewQueue(nil)
runner := &DummyRunnable{}
job1 := NewJob[DummyResult](JobID("1"), runner)
job2 := NewJob[DummyResult](JobID("2"), runner)
_ = q.Enqueue(job1)
_, _ = q.Dequeue()
_ = q.Enqueue(job2)
_, err := q.Dequeue()
if err != nil {
t.Fatalf("Dequeue failed: %v", err)
}
if _, exists := q.processedJobs[job1.GetID()]; !exists {
t.Fatalf("Job 1 not marked as processed")
}
}
func TestCyclicDependencies(t *testing.T) {
runner := &DummyRunnable{}
q := NewQueue(nil)
job1 := NewJob[DummyResult](JobID("1"), runner)
job2 := NewJob[DummyResult](JobID("2"), runner)
job3 := NewJob[DummyResult](JobID("3"), runner)
job1.AddDependency(JobID("2"))
job2.AddDependency(JobID("3"))
job3.AddDependency(JobID("1"))
err := q.Enqueue(job1)
if err != nil {
t.Fatalf("Enqueue failed: %v", err)
}
err = q.Enqueue(job2)
if err != nil {
t.Fatalf("Enqueue failed: %v", err)
}
err = q.Enqueue(job3)
if err == nil || err != ErrCycleDetected {
t.Fatalf("Expected ErrCyclicDependency, got %v", err)
}
}
func TestDuplicateDependencies(t *testing.T) {
runner := &DummyRunnable{}
q := NewQueue(nil)
job1 := NewJob[DummyResult](JobID("1"), runner)
job2 := NewJob[DummyResult](JobID("2"), runner)
job2.AddDependency(JobID("1"))
job2.AddDependency(JobID("1"))
_ = q.Enqueue(job1)
err := q.Enqueue(job2)
if err != nil {
t.Fatalf("Enqueue failed: %v", err)
}
_, err = q.Dequeue()
if err != nil {
t.Fatalf("Dequeue failed: %v", err)
}
_, err = q.Dequeue()
if err != nil {
t.Fatalf("Dequeue failed: %v", err)
}
if len(q.processedJobs) != 2 {
t.Fatalf("Expected 2 processed jobs, got %d", len(q.processedJobs))
}
}
func TestJobWithSelfAsDependency(t *testing.T) {
runner := &DummyRunnable{}
q := NewQueue(nil)
job1 := NewJob[DummyResult](JobID("1"), runner)
job1.AddDependency(JobID("1"))
err := q.Enqueue(job1)
if err == nil || err != ErrCycleDetected {
t.Fatalf("Expected ErrCycleDetected, got %v", err)
}
}
func TestEnqueueDequeue(t *testing.T) {
q := NewQueue(nil)
job1 := NewJob[DummyResult]("job1", nil)
job2 := NewJob[DummyResult]("job2", nil)
job3 := NewJob[DummyResult]("job3", nil)
job2.dependencies = []JobID{"job1"}
job3.dependencies = []JobID{"job2"}
// Enqueue a job with dependencies that haven't been enqueued yet
if err := q.Enqueue(job3); err != nil {
t.Fatalf("Failed to enqueue job3: %v", err)
}
// Try to dequeue from an empty readyQueue
if _, err := q.Dequeue(); !errors.Is(err, ErrQueueEmpty) {
t.Fatalf("Expected ErrQueueEmpty, got: %v", err)
}
// Enqueue a job with no dependencies
if err := q.Enqueue(job1); err != nil {
t.Fatalf("Failed to enqueue job1: %v", err)
}
// Enqueue a job that has its dependencies met
if err := q.Enqueue(job2); err != nil {
t.Fatalf("Failed to enqueue job2: %v", err)
}
// Try to dequeue jobs in the expected order
if job, err := q.Dequeue(); err != nil || job.GetID() != "job1" {
t.Fatalf("Expected job1, got: %v, %v", job, err)
}
if job, err := q.Dequeue(); err != nil || job.GetID() != "job2" {
t.Fatalf("Expected job2, got: %v, %v", job, err)
}
if job, err := q.Dequeue(); err != nil || job.GetID() != "job3" {
t.Fatalf("Expected job3, got: %v, %v", job, err)
}
}
func TestDuplicateEnqueue(t *testing.T) {
q := NewQueue(nil)
job1 := NewJob[DummyResult]("job1", nil)
// Enqueue the same job twice
if err := q.Enqueue(job1); err != nil {
t.Fatalf("Failed to enqueue job1: %v", err)
}
if err := q.Enqueue(job1); !errors.Is(err, ErrJobAlreadyExists) {
t.Fatalf("Expected ErrJobAlreadyExists, got: %v", err)
}
}
func TestCircularDependency(t *testing.T) {
q := NewQueue(nil)
job1 := NewJob[DummyResult]("job1", nil)
job2 := NewJob[DummyResult]("job2", nil)
job1.dependencies = []JobID{"job2"}
job2.dependencies = []JobID{"job1"}
if err := q.Enqueue(job1); err != nil {
t.Fatalf("Failed to enqueue job1: %v", err)
}
// This enqueue should fail if you have logic to detect circular dependencies
if err := q.Enqueue(job2); err == nil {
t.Fatalf("Expected an error due to circular dependency, got: %v", err)
}
}
// TestFuzzyEnqueueDequeue tests the queue by generating random jobs and
// you can run it with:
// go test -v -fuzz TestFuzzyEnqueueDequeue
// or with a fuzztime of 10 seconds:
// go test -v -run -fuzz TestFuzzyEnqueueDequeue -fuzztime=10s
func TestFuzzyEnqueueDequeue(t *testing.T) {
rand.Seed(time.Now().UnixNano())
q := NewQueue(nil)
// Generate random jobs
jobCount := 1000
jobs := make([]GenericJob, jobCount)
for i := 0; i < jobCount; i++ {
jobID := JobID(fmt.Sprintf("job%d", i))
jobs[i] = NewJob[DummyResult](jobID, nil)
}
// Randomly set dependencies for each job
for _, job := range jobs {
depCount := rand.Intn(5) // up to 5 dependencies
deps := make([]JobID, depCount)
for i := 0; i < depCount; i++ {
depIndex := rand.Intn(jobCount)
deps[i] = jobs[depIndex].GetID()
}
job.(*Job[DummyResult]).dependencies = deps
}
// Randomly enqueue jobs
for i := 0; i < jobCount; i++ {
index := rand.Intn(len(jobs))
job := jobs[index]
q.Enqueue(job)
jobs = append(jobs[:index], jobs[index+1:]...)
}
// Randomly dequeue jobs, ignoring errors for this fuzzy test
for i := 0; i < jobCount; i++ {
_, _ = q.Dequeue()
}
// Verify that the queue is empty
if _, err := q.Dequeue(); !errors.Is(err, ErrQueueEmpty) {
t.Fatalf("Expected ErrQueueEmpty, got: %v", err)
}
}
func TestEnqueueDequeueOrder(t *testing.T) {
eventBus := NewEventBus() // Ihre EventBus-Initialisierung
q := NewQueue(eventBus)
job1 := NewJob[DummyResult]("job1", nil)
job2 := NewJob[DummyResult]("job2", nil)
job3 := NewJob[DummyResult]("job3", nil)
job2.AddDependency(JobID("job1"))
job3.AddDependency(JobID("job2"))
if err := q.Enqueue(job1); err != nil {
t.Fatalf("Failed to enqueue job1: %s", err)
}
if err := q.Enqueue(job3); err != nil {
t.Fatalf("Failed to enqueue job3: %s", err)
}
if err := q.Enqueue(job2); err != nil {
t.Fatalf("Failed to enqueue job2: %s", err)
}
dequeuedJob, err := q.Dequeue()
if err != nil {
t.Fatalf("Failed to dequeue: %s", err)
}
if dequeuedJob.GetID() != "job1" {
t.Errorf("Expected job1, got %s", dequeuedJob.GetID())
}
dequeuedJob, err = q.Dequeue()
if err != nil {
t.Fatalf("Failed to dequeue: %s", err)
}
if dequeuedJob.GetID() != "job2" {
t.Errorf("Expected job2, got %s", dequeuedJob.GetID())
}
dequeuedJob, err = q.Dequeue()
if err != nil {
t.Fatalf("Failed to dequeue: %s", err)
}
if dequeuedJob.GetID() != "job3" {
t.Errorf("Expected job3, got %s", dequeuedJob.GetID())
}
}