Something went wrong on our end
-
Volker Schukai authoredVolker Schukai authored
topological-sort_test.go 6.48 KiB
// Copyright 2023 schukai GmbH
// SPDX-License-Identifier: AGPL-3.0
package jobqueue
import (
"reflect"
"testing"
)
func TestTopologicalSortJobs(t *testing.T) {
// Create a sample set of jobs with dependencies and priorities
job1 := &Job[string]{id: "1", priority: PriorityDefault}
job2 := &Job[string]{id: "2", priority: PriorityHigh, dependencies: []JobID{"1"}}
job3 := &Job[string]{id: "3", priority: PriorityLow, dependencies: []JobID{"1"}}
job4 := &Job[string]{id: "4", priority: PriorityCritical, dependencies: []JobID{"3"}}
job5 := &Job[string]{id: "5", dependencies: []JobID{"2", "4"}}
jobs := []GenericJob{
job1,
job2,
job3,
job4,
job5,
}
// Call the function to get the sorted job IDs
sortedJobIDs, err := topologicalSortJobs(jobs)
if err != nil {
t.Errorf("Error in sorting jobs: %v", err)
}
// Define the expected order
expectedOrder := []JobID{"1", "2", "3", "4", "5"}
// Check if the result matches the expected order
if !reflect.DeepEqual(sortedJobIDs, expectedOrder) {
t.Errorf("Expected order %v, but got %v", expectedOrder, sortedJobIDs)
}
}
func TestTopologicalSortJobs2(t *testing.T) {
// Create a sample set of jobs with dependencies and priorities
job1 := &Job[string]{id: "1", priority: PriorityHigh}
job2 := &Job[string]{id: "2", priority: PriorityHigh, dependencies: []JobID{"1"}}
job3 := &Job[string]{id: "3", priority: PriorityLow, dependencies: []JobID{"1"}}
job4 := &Job[string]{id: "4", priority: PriorityCritical, dependencies: []JobID{"3"}}
job5 := &Job[string]{id: "5", dependencies: []JobID{"2", "4"}}
jobs := []GenericJob{
job1,
job2,
job3,
job4,
job5,
}
// Call the function to get the sorted job IDs
sortedJobIDs, err := topologicalSortJobs(jobs)
if err != nil {
t.Errorf("Error in sorting jobs: %v", err)
}
// Define the expected order
expectedOrder := []JobID{"1", "2", "3", "4", "5"}
// Check if the result matches the expected order
if !reflect.DeepEqual(sortedJobIDs, expectedOrder) {
t.Errorf("Expected order %v, but got %v", expectedOrder, sortedJobIDs)
}
}
func TestTopologicalSortJobsNodePendencies(t *testing.T) {
// Create a sample set of jobs with no dependencies
job1 := &Job[string]{id: "1"}
job2 := &Job[string]{id: "2"}
job3 := &Job[string]{id: "3"}
jobs := []GenericJob{
job1,
job2,
job3,
}
// Call the function to get the sorted job IDs
sortedJobIDs, err := topologicalSortJobs(jobs)
if err != nil {
t.Errorf("Error in sorting jobs: %v", err)
}
// Define the expected order (in any order because they have no dependencies)
expectedOrder := []JobID{"3", "2", "1"}
// Check if the result contains the same elements as the expected order
if len(sortedJobIDs) != len(expectedOrder) {
t.Errorf("Expected order %v, but got %v", expectedOrder, sortedJobIDs)
}
}
func TestTopologicalSortJobs_EmptyMap(t *testing.T) {
jobs := []GenericJob{}
sortedJobIDs, err := topologicalSortJobs(jobs)
if err != nil {
t.Errorf("Error in sorting jobs: %v", err)
}
if len(sortedJobIDs) != 0 {
t.Errorf("Expected empty slice, got %v", sortedJobIDs)
}
}
func TestTopologicalSortJobs_CycleDetected(t *testing.T) {
// Creating a cycle 1 -> 2 -> 3 -> 1
job1 := &Job[string]{id: "1", dependencies: []JobID{"3"}}
job2 := &Job[string]{id: "2", dependencies: []JobID{"1"}}
job3 := &Job[string]{id: "3", dependencies: []JobID{"2"}}
jobs := []GenericJob{
job1,
job2,
job3,
}
_, err := topologicalSortJobs(jobs)
if err != ErrCycleDetected {
t.Errorf("Expected ErrCycleDetected, got %v", err)
}
}
func TestTopologicalSortJobs_SingleNode(t *testing.T) {
job1 := &Job[string]{id: "1"}
jobs := []GenericJob{
job1,
}
sortedJobIDs, err := topologicalSortJobs(jobs)
if err != nil {
t.Errorf("Error in sorting jobs: %v", err)
}
if !reflect.DeepEqual(sortedJobIDs, []JobID{"1"}) {
t.Errorf("Expected [\"1\"], got %v", sortedJobIDs)
}
}
func TestTopologicalSortJobs_MissingDependency(t *testing.T) {
job1 := &Job[string]{id: "1"}
job2 := &Job[string]{id: "2", dependencies: []JobID{"3"}}
jobs := []GenericJob{
job1,
job2,
}
_, err := topologicalSortJobs(jobs)
if err != nil && err != ErrMissingDependency {
t.Errorf("Expected ErrMissingDependency, got %v", err)
}
}
func TestTopologicalSortJobs_SelfDependency(t *testing.T) {
// job 1 depends on itself
job1 := &Job[string]{id: "1", dependencies: []JobID{"1"}}
jobs := []GenericJob{
job1,
}
_, err := topologicalSortJobs(jobs)
if err != ErrCycleDetected {
t.Errorf("Expected ErrCycleDetected, got %v", err)
}
}
func TestTopologicalSortJobs_MultipleEdges(t *testing.T) {
// job 3 and job 4 both depend on job 2
job1 := &Job[string]{id: "1"}
job2 := &Job[string]{id: "2", dependencies: []JobID{"1"}}
job3 := &Job[string]{id: "3", dependencies: []JobID{"2"}}
job4 := &Job[string]{id: "4", dependencies: []JobID{"2"}}
jobs := []GenericJob{
job1,
job2,
job3,
job4,
}
sortedJobIDs, err := topologicalSortJobs(jobs)
if err != nil {
t.Errorf("Error in sorting jobs: %v", err)
}
if !reflect.DeepEqual(sortedJobIDs, []JobID{"1", "2", "3", "4"}) && !reflect.DeepEqual(sortedJobIDs, []JobID{"1", "2", "4", "3"}) {
t.Errorf("Unexpected order: %v", sortedJobIDs)
}
}
func TestTopologicalSortJobs_Multipledependencies(t *testing.T) {
// job 3 depends on both job 1 and job 2
job1 := &Job[string]{id: "1"}
job2 := &Job[string]{id: "2"}
job3 := &Job[string]{id: "3", dependencies: []JobID{"1", "2"}}
jobs := []GenericJob{
job1,
job2,
job3,
}
sortedJobIDs, err := topologicalSortJobs(jobs)
if err != nil {
t.Errorf("Error in sorting jobs: %v", err)
}
if !reflect.DeepEqual(sortedJobIDs, []JobID{"1", "2", "3"}) && !reflect.DeepEqual(sortedJobIDs, []JobID{"2", "1", "3"}) {
t.Errorf("Unexpected order: %v", sortedJobIDs)
}
}
func TestTopologicalSortJobs_PriorityIgnoredInCycle(t *testing.T) {
// Cycle exists even if one job has high priority
job1 := &Job[string]{id: "1", priority: PriorityHigh, dependencies: []JobID{"2"}}
job2 := &Job[string]{id: "2", dependencies: []JobID{"1"}}
jobs := []GenericJob{
job1,
job2,
}
_, err := topologicalSortJobs(jobs)
if err != ErrCycleDetected {
t.Errorf("Expected ErrCycleDetected, got %v", err)
}
}
func TestTopologicalSortJobs_IsNotAvailable(t *testing.T) {
// Cycle exists even if one job has high priority
job1 := &Job[string]{id: "1", priority: PriorityHigh, dependencies: []JobID{"3"}}
job2 := &Job[string]{id: "2"}
jobs := []GenericJob{
job1,
job2,
}
_, err := topologicalSortJobs(jobs)
if err != ErrMissingDependency {
t.Errorf("Expected ErrMissingDependency, got %v", err)
}
}