debian-forge-composer/internal/jobqueue/fsjobqueue/fsjobqueue_test.go
Brian C. Lane 5cddc4223d dbjobqueue: Add AllRootJobIDs implementation
Related: RHEL-60120
2025-06-05 10:32:56 +02:00

170 lines
4.9 KiB
Go

package fsjobqueue_test
import (
"context"
"os"
"path"
"sort"
"testing"
"github.com/google/uuid"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/osbuild/osbuild-composer/internal/jobqueue/fsjobqueue"
"github.com/osbuild/osbuild-composer/internal/jobqueue/jobqueuetest"
"github.com/osbuild/osbuild-composer/pkg/jobqueue"
)
func TestJobQueueInterface(t *testing.T) {
jobqueuetest.TestJobQueue(t, func() (jobqueue.JobQueue, func(), error) {
dir := t.TempDir()
q, err := fsjobqueue.New(dir)
if err != nil {
return nil, nil, err
}
stop := func() {
}
return q, stop, nil
})
}
func TestNonExistant(t *testing.T) {
q, err := fsjobqueue.New("/non-existant-directory")
require.Error(t, err)
require.Nil(t, q)
}
func TestJobQueueBadJSON(t *testing.T) {
dir := t.TempDir()
// Write a purposfully invalid JSON file into the queue
err := os.WriteFile(path.Join(dir, "/4f1cf5f8-525d-46b7-aef4-33c6a919c038.json"), []byte("{invalid json content"), 0600)
require.Nil(t, err)
q, err := fsjobqueue.New(dir)
require.Nil(t, err)
require.NotNil(t, q)
}
func sortUUIDs(entries []uuid.UUID) {
sort.Slice(entries, func(i, j int) bool {
return entries[i].String() < entries[j].String()
})
}
func TestAllRootJobIDs(t *testing.T) {
dir := t.TempDir()
q, err := fsjobqueue.New(dir)
require.Nil(t, err)
require.NotNil(t, q)
var rootJobs []uuid.UUID
// root with no dependencies
jidRoot1, err := q.Enqueue("oneRoot", nil, nil, "OneRootJob")
require.Nil(t, err)
rootJobs = append(rootJobs, jidRoot1)
// root with 2 dependencies
jid1, err := q.Enqueue("twoDeps", nil, nil, "TwoDepJobs")
require.Nil(t, err)
jid2, err := q.Enqueue("twoDeps", nil, nil, "TwoDepJobs")
require.Nil(t, err)
jidRoot2, err := q.Enqueue("twoDeps", nil, []uuid.UUID{jid1, jid2}, "TwoDepJobs")
require.Nil(t, err)
rootJobs = append(rootJobs, jidRoot2)
// root with 2 dependencies, one shared with the previous root
jid3, err := q.Enqueue("sharedDeps", nil, nil, "SharedDepJobs")
require.Nil(t, err)
jidRoot3, err := q.Enqueue("sharedDeps", nil, []uuid.UUID{jid1, jid3}, "SharedDepJobs")
require.Nil(t, err)
rootJobs = append(rootJobs, jidRoot3)
sortUUIDs(rootJobs)
roots, err := q.AllRootJobIDs(context.TODO())
require.Nil(t, err)
require.Greater(t, len(roots), 0)
sortUUIDs(roots)
require.Equal(t, rootJobs, roots)
}
func TestDeleteJob(t *testing.T) {
dir := t.TempDir()
q, err := fsjobqueue.New(dir)
require.Nil(t, err)
require.NotNil(t, q)
// root with no dependencies
jidRoot1, err := q.Enqueue("oneRoot", nil, nil, "OneRootJob")
require.Nil(t, err)
err = q.DeleteJob(context.TODO(), jidRoot1)
require.Nil(t, err)
jobs, err := q.AllRootJobIDs(context.TODO())
require.Nil(t, err)
require.Equal(t, 0, len(jobs))
// root with 2 dependencies
jid1, err := q.Enqueue("twoDeps", nil, nil, "TwoDepJobs")
require.Nil(t, err)
jid2, err := q.Enqueue("twoDeps", nil, nil, "TwoDepJobs")
require.Nil(t, err)
jidRoot2, err := q.Enqueue("twoDeps", nil, []uuid.UUID{jid1, jid2}, "TwoDepJobs")
require.Nil(t, err)
// root with 2 dependencies, one shared with the previous root
jid3, err := q.Enqueue("sharedDeps", nil, nil, "SharedDepJobs")
require.Nil(t, err)
jidRoot3, err := q.Enqueue("sharedDeps", nil, []uuid.UUID{jid1, jid3}, "SharedDepJobs")
require.Nil(t, err)
// This should only remove jidRoot2 and jid2, leaving jidRoot3, jid1, jid3
err = q.DeleteJob(context.TODO(), jidRoot2)
require.Nil(t, err)
jobs, err = q.AllRootJobIDs(context.TODO())
require.Nil(t, err)
require.Equal(t, 1, len(jobs))
assert.Equal(t, []uuid.UUID{jidRoot3}, jobs)
// This should remove the rest
err = q.DeleteJob(context.TODO(), jidRoot3)
require.Nil(t, err)
jobs, err = q.AllRootJobIDs(context.TODO())
require.Nil(t, err)
require.Equal(t, 0, len(jobs))
// Make sure all the jobs are deleted
allJobs := []uuid.UUID{jidRoot1, jidRoot2, jidRoot3, jid1, jid2, jid3}
for _, jobId := range allJobs {
jobType, _, _, _, err := q.Job(jobId)
assert.Error(t, err, jobType)
}
// root with 2 jobs depending on another (simulates Koji jobs)
kojiOSTree, err := q.Enqueue("ostree", nil, nil, "KojiJob")
require.Nil(t, err)
kojiDepsolve, err := q.Enqueue("depsolve", nil, nil, "KojiJob")
require.Nil(t, err)
kojiManifest, err := q.Enqueue("manifest", nil, []uuid.UUID{kojiOSTree, kojiDepsolve}, "KojiJob")
require.Nil(t, err)
kojiInit, err := q.Enqueue("init", nil, nil, "KojiJob")
require.Nil(t, err)
kojiRoot, err := q.Enqueue("final", nil, []uuid.UUID{kojiInit, kojiManifest, kojiDepsolve}, "KojiJob")
require.Nil(t, err)
// Delete the koji job
err = q.DeleteJob(context.TODO(), kojiRoot)
require.Nil(t, err)
jobs, err = q.AllRootJobIDs(context.TODO())
require.Nil(t, err)
require.Equal(t, 0, len(jobs))
// Make sure all the jobs are deleted
kojiJobs := []uuid.UUID{kojiRoot, kojiInit, kojiOSTree, kojiDepsolve, kojiManifest}
for _, jobId := range kojiJobs {
jobType, _, _, _, err := q.Job(jobId)
assert.Error(t, err, jobType)
}
}