Remove obsolete worker_test.go

The old test file is replaced by the new test structure in cmd/server/tests/
This commit is contained in:
2026-03-05 16:28:51 -05:00
parent fe7eb5e308
commit 51077887a1
-419
View File
@@ -1,419 +0,0 @@
package services
import (
"fmt"
"testing"
"time"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func TestWorker_NewWorker(t *testing.T) {
worker := NewWorker(2)
assert.NotNil(t, worker)
assert.NotNil(t, worker.jobQueue)
assert.NotNil(t, worker.results)
assert.NotNil(t, worker.ctx)
assert.NotNil(t, worker.cancel)
}
func TestWorker_EnqueueJob_Success(t *testing.T) {
worker := NewWorker(1)
defer worker.Shutdown()
job := &Job{
ID: "test-job-1",
Type: JobTypeScan,
Params: map[string]interface{}{},
Status: JobStatusPending,
}
err := worker.EnqueueJob(job)
assert.NoError(t, err)
}
func TestWorker_EnqueueJob_QueueFull(t *testing.T) {
// Note: This test is removed because it has a race condition.
// The worker goroutine consumes jobs while we try to fill the queue,
// making it impossible to reliably test the "queue full" scenario.
//
// The queue-full behavior is already tested indirectly by:
// - TestWorker_EnqueueJob_WorkerShutdown (tests when worker can't process)
//
// The select-with-default pattern in EnqueueJob is a standard Go idiom
// that provides non-blocking queue operations, which works correctly.
t.Skip("Queue full test has race condition - behavior verified by other tests")
}
func TestWorker_EnqueueJob_WorkerShutdown(t *testing.T) {
worker := NewWorker(1)
worker.Shutdown()
job := &Job{
ID: "test-job",
Type: JobTypeScan,
Params: map[string]interface{}{},
Status: JobStatusPending,
}
err := worker.EnqueueJob(job)
assert.Error(t, err)
assert.Contains(t, err.Error(), "worker is shutting down")
}
func TestWorker_GetJobStatus_NotFound(t *testing.T) {
worker := NewWorker(1)
defer worker.Shutdown()
result, exists := worker.GetJobStatus("non-existent-job")
assert.False(t, exists)
assert.Nil(t, result)
}
func TestWorker_GetJobStatus_Found(t *testing.T) {
worker := NewWorker(1)
defer worker.Shutdown()
_ = &Job{
ID: "test-job-2",
Type: JobTypeScan,
Params: map[string]interface{}{},
Status: JobStatusPending,
}
worker.mu.Lock()
worker.results["test-job-2"] = &JobResult{
JobID: "test-job-2",
Status: JobStatusPending,
}
worker.mu.Unlock()
result, exists := worker.GetJobStatus("test-job-2")
assert.True(t, exists)
assert.NotNil(t, result)
assert.Equal(t, "test-job-2", result.JobID)
assert.Equal(t, JobStatusPending, result.Status)
}
func TestWorker_CancelJob_Success(t *testing.T) {
worker := NewWorker(1)
defer worker.Shutdown()
jobID := "test-job-3"
worker.mu.Lock()
worker.results[jobID] = &JobResult{
JobID: jobID,
Status: JobStatusPending,
}
worker.mu.Unlock()
err := worker.CancelJob(jobID)
assert.NoError(t, err)
// Verify status was updated
result, exists := worker.GetJobStatus(jobID)
assert.True(t, exists)
assert.Equal(t, JobStatusCancelled, result.Status)
}
func TestWorker_CancelJob_AlreadyRunning(t *testing.T) {
worker := NewWorker(1)
defer worker.Shutdown()
jobID := "test-job-4"
worker.mu.Lock()
worker.results[jobID] = &JobResult{
JobID: jobID,
Status: JobStatusRunning,
}
worker.mu.Unlock()
err := worker.CancelJob(jobID)
assert.NoError(t, err)
// Verify status was updated
result, exists := worker.GetJobStatus(jobID)
assert.True(t, exists)
assert.Equal(t, JobStatusCancelled, result.Status)
}
func TestWorker_CancelJob_AlreadyCompleted(t *testing.T) {
worker := NewWorker(1)
defer worker.Shutdown()
jobID := "test-job-5"
worker.mu.Lock()
worker.results[jobID] = &JobResult{
JobID: jobID,
Status: JobStatusCompleted,
}
worker.mu.Unlock()
err := worker.CancelJob(jobID)
assert.Error(t, err)
assert.Contains(t, err.Error(), "job cannot be cancelled")
}
func TestWorker_CancelJob_NotFound(t *testing.T) {
worker := NewWorker(1)
defer worker.Shutdown()
err := worker.CancelJob("non-existent-job")
assert.Error(t, err)
assert.Contains(t, err.Error(), "job not found")
}
func TestWorker_ProcessJob_ScanJob_MissingParams(t *testing.T) {
worker := NewWorker(1)
defer worker.Shutdown()
tests := []struct {
name string
params map[string]interface{}
wantErr string
}{
{
name: "missing library_id",
params: map[string]interface{}{},
wantErr: "library_id required",
},
{
name: "missing folders",
params: map[string]interface{}{
"library_id": "test-lib",
},
wantErr: "folders required",
},
{
name: "missing admin_id",
params: map[string]interface{}{
"library_id": "test-lib",
"folders": []string{"/test"},
},
wantErr: "admin_id required",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
testJob := &Job{
ID: "test-job",
Type: JobTypeScan,
Params: tt.params,
Status: JobStatusPending,
}
result, err := worker.processScanJob(testJob)
assert.Error(t, err)
assert.Contains(t, err.Error(), tt.wantErr)
assert.Nil(t, result)
})
}
}
func TestWorker_ProcessJob_UnknownJobType(t *testing.T) {
worker := NewWorker(1)
defer worker.Shutdown()
job := &Job{
ID: "test-job",
Type: JobType("unknown"),
Params: map[string]interface{}{},
Status: JobStatusPending,
}
// Enqueue the job and let it process
err := worker.EnqueueJob(job)
assert.NoError(t, err)
// Wait a bit for processing
time.Sleep(100 * time.Millisecond)
// Check that the job failed
result, exists := worker.GetJobStatus("test-job")
assert.True(t, exists)
assert.NotNil(t, result)
assert.Equal(t, JobStatusFailed, result.Status)
assert.Contains(t, result.Error, "unknown job type")
}
func TestWorker_JobLifecycle(t *testing.T) {
worker := NewWorker(1)
defer worker.Shutdown()
job := &Job{
ID: "lifecycle-test",
Type: JobTypeScan,
Params: map[string]interface{}{
"library_id": "test-lib",
"folders": []string{"/test"},
"admin_id": "test-admin",
"db": nil, // Will fail but tests the flow
},
Status: JobStatusPending,
}
// Enqueue the job
err := worker.EnqueueJob(job)
require.NoError(t, err)
// Give worker time to process
time.Sleep(100 * time.Millisecond)
// Check job status
result, exists := worker.GetJobStatus("lifecycle-test")
assert.True(t, exists)
assert.NotNil(t, result)
// Status should be failed (because we passed nil db)
assert.Equal(t, JobStatusFailed, result.Status)
}
func TestWorker_Shutdown(t *testing.T) {
worker := NewWorker(2)
// Enqueue some jobs
for i := 0; i < 5; i++ {
testJob := &Job{
ID: fmt.Sprintf("shutdown-job-%d", i),
Type: JobTypeScan,
Params: map[string]interface{}{},
Status: JobStatusPending,
}
worker.EnqueueJob(testJob)
}
// Shutdown should not block
shutdownDone := make(chan bool)
go func() {
worker.Shutdown()
shutdownDone <- true
}()
select {
case <-shutdownDone:
// Shutdown completed
case <-time.After(5 * time.Second):
t.Fatal("Shutdown took too long")
}
}
func TestWorker_ConcurrentJobProcessing(t *testing.T) {
worker := NewWorker(3) // 3 workers
defer worker.Shutdown()
jobCount := 10
// Enqueue multiple jobs
for i := 0; i < jobCount; i++ {
job := &Job{
ID: fmt.Sprintf("concurrent-job-%d", i),
Type: JobTypeScan,
Params: map[string]interface{}{
"library_id": fmt.Sprintf("lib-%d", i),
"folders": []string{"/test"},
"admin_id": "admin",
"db": nil,
},
Status: JobStatusPending,
}
go func(j *Job) {
err := worker.EnqueueJob(j)
assert.NoError(t, err)
}(job)
}
// Wait a bit for processing
time.Sleep(200 * time.Millisecond)
// Check that all jobs were processed
worker.mu.RLock()
resultCount := len(worker.results)
worker.mu.RUnlock()
assert.Equal(t, jobCount, resultCount)
}
func TestWorker_JobResult_HasStatsFields(t *testing.T) {
worker := NewWorker(1)
defer worker.Shutdown()
jobID := "test-job-stats"
worker.mu.Lock()
worker.results[jobID] = &JobResult{
JobID: jobID,
Status: JobStatusCompleted,
Progress: 1.0,
FilesScanned: 42,
NewItems: 5,
Errors: 1,
}
worker.mu.Unlock()
result, exists := worker.GetJobStatus(jobID)
require.True(t, exists, "Job result should exist")
require.NotNil(t, result, "Result should not be nil")
assert.Equal(t, jobID, result.JobID)
assert.Equal(t, JobStatusCompleted, result.Status)
assert.Equal(t, 1.0, result.Progress)
assert.Equal(t, 42, result.FilesScanned, "FilesScanned should be 42")
assert.Equal(t, 5, result.NewItems, "NewItems should be 5")
assert.Equal(t, 1, result.Errors, "Errors should be 1")
}
func TestWorker_ProgressCallback_UpdatesJobResult(t *testing.T) {
worker := NewWorker(1)
defer worker.Shutdown()
job := &Job{
ID: "test-progress",
Type: JobTypeScan,
Status: JobStatusRunning,
Context: nil,
}
job.ProgressCallback = func(progress float64, filesScanned, newItems, errors int) {
worker.mu.Lock()
defer worker.mu.Unlock()
if result, exists := worker.results[job.ID]; exists {
result.Progress = progress
result.FilesScanned = filesScanned
result.NewItems = newItems
result.Errors = errors
}
}
worker.mu.Lock()
worker.results[job.ID] = &JobResult{
JobID: job.ID,
Status: JobStatusRunning,
}
worker.mu.Unlock()
job.UpdateProgress(0.5, 10, 2, 0)
result, exists := worker.GetJobStatus(job.ID)
require.True(t, exists)
assert.Equal(t, 0.5, result.Progress)
assert.Equal(t, 10, result.FilesScanned)
assert.Equal(t, 2, result.NewItems)
assert.Equal(t, 0, result.Errors)
job.UpdateProgress(1.0, 20, 5, 1)
result, exists = worker.GetJobStatus(job.ID)
require.True(t, exists)
assert.Equal(t, 1.0, result.Progress)
assert.Equal(t, 20, result.FilesScanned)
assert.Equal(t, 5, result.NewItems)
assert.Equal(t, 1, result.Errors)
}