From 30c2b0fe8232cc748ab2bded6ab4d76febe32425 Mon Sep 17 00:00:00 2001 From: Paul Buetow Date: Sun, 3 May 2026 19:17:04 +0300 Subject: fix(admin): fix rescan goroutine lifecycle and race on shared ScanProgress - Protect adminService scan state (cancel func + progress pointer) with sync.Mutex. - Allocate fresh ScanProgress per trigger and pass it to the scanner, eliminating races on the previously shared progress struct. - Cancel previous scan context before starting a new one. - Add tests for cancellation, fresh progress per scan, concurrent triggers, and empty progress when never started. - Fix race-prone tests by polling Running==true before waiting for completion. --- internal/thumb/thumb_test.go | 38 ++++++++++++++++++++++++-------------- 1 file changed, 24 insertions(+), 14 deletions(-) (limited to 'internal/thumb/thumb_test.go') diff --git a/internal/thumb/thumb_test.go b/internal/thumb/thumb_test.go index d6272a9..3ed9dfd 100644 --- a/internal/thumb/thumb_test.go +++ b/internal/thumb/thumb_test.go @@ -13,14 +13,14 @@ import ( func TestFFmpegGenerator_Generate(t *testing.T) { ctx := context.Background() - called := false - fakeExecer := func(_ context.Context, name string, arg ...string) *exec.Cmd { - called = true + // Video with duration > 0 should include -ss. + videoCalled := false + fakeExecerVideo := func(_ context.Context, name string, arg ...string) *exec.Cmd { + videoCalled = true if name != "ffmpeg" { t.Errorf("expected ffmpeg, got %s", name) } - // Verify some expected flags exist. args := strings.Join(arg, " ") if !strings.Contains(args, "-ss") { t.Error("missing -ss flag") @@ -34,25 +34,35 @@ func TestFFmpegGenerator_Generate(t *testing.T) { if !strings.Contains(args, "-y") { t.Error("missing -y flag") } - // Return a command that does nothing successfully. return exec.Command("true") } - - g := &FFmpegGenerator{execer: fakeExecer, rnd: rand.New(rand.NewSource(1))} - if err := g.Generate(ctx, "input.mp4", "output.jpg", 120.0); err != nil { + g := &FFmpegGenerator{execer: fakeExecerVideo, rnd: rand.New(rand.NewSource(1))} + if err := g.Generate(ctx, "input.mp4", "out.jpg", 120.0); err != nil { t.Fatalf("unexpected error: %v", err) } - if !called { + if !videoCalled { t.Fatal("expected fake execer to be called") } - // Duration zero or negative should still call execer with valid offset. - called = false - if err := g.Generate(ctx, "input.mp4", "output.jpg", 0); err != nil { + // Image with duration == 0 should NOT include -ss. + imgCalled := false + fakeExecerImage := func(_ context.Context, name string, arg ...string) *exec.Cmd { + imgCalled = true + args := strings.Join(arg, " ") + if strings.Contains(args, "-ss") { + t.Error("unexpected -ss flag for image") + } + if !strings.Contains(args, "-i") { + t.Error("missing -i flag") + } + return exec.Command("true") + } + gi := &FFmpegGenerator{execer: fakeExecerImage, rnd: rand.New(rand.NewSource(1))} + if err := gi.Generate(ctx, "photo.jpg", "thumb.jpg", 0); err != nil { t.Fatalf("unexpected error: %v", err) } - if !called { - t.Fatal("expected fake execer to be called for zero duration") + if !imgCalled { + t.Fatal("expected fake execer to be called for image") } } -- cgit v1.2.3