diff options
Diffstat (limited to 'internal/app/loader_test.go')
| -rw-r--r-- | internal/app/loader_test.go | 162 |
1 files changed, 162 insertions, 0 deletions
diff --git a/internal/app/loader_test.go b/internal/app/loader_test.go new file mode 100644 index 0000000..538bca0 --- /dev/null +++ b/internal/app/loader_test.go @@ -0,0 +1,162 @@ +package app + +import ( + "os" + "path/filepath" + "runtime" + "testing" + "time" +) + +func TestCollectVideoPathsDetectsMP4(t *testing.T) { + dir := t.TempDir() + lower := filepath.Join(dir, "video.mp4") + upper := filepath.Join(dir, "UPPER.MP4") + for _, path := range []string{lower, upper} { + if err := os.WriteFile(path, []byte("dummy"), 0o644); err != nil { + t.Fatalf("write %s: %v", path, err) + } + } + paths, err := CollectVideoPathsForTest(dir) + if err != nil { + t.Fatalf("collect paths: %v", err) + } + if len(paths) != 2 { + t.Fatalf("expected 2 paths, got %d", len(paths)) + } + want := map[string]struct{}{lower: {}, upper: {}} + for _, got := range paths { + if _, ok := want[got]; !ok { + t.Fatalf("unexpected path %s", got) + } + } +} + +func TestCollectVideoPathsFollowsSymlink(t *testing.T) { + if runtime.GOOS == "windows" { + t.Skip("symlink permissions vary on Windows") + } + root := t.TempDir() + storage := t.TempDir() + video := filepath.Join(storage, "movie.mp4") + if err := os.WriteFile(video, []byte("dummy"), 0o644); err != nil { + t.Fatalf("write video: %v", err) + } + link := filepath.Join(root, "videos") + if err := os.Symlink(storage, link); err != nil { + t.Skipf("symlink not supported: %v", err) + } + paths, err := CollectVideoPathsForTest(root) + if err != nil { + t.Fatalf("collect paths: %v", err) + } + expected := filepath.Join(link, "movie.mp4") + if len(paths) != 1 || paths[0] != expected { + t.Fatalf("expected %s, got %v", expected, paths) + } +} + +func TestLoadVideosWithCache(t *testing.T) { + dir := t.TempDir() + video := filepath.Join(dir, "video.mp4") + if err := os.WriteFile(video, []byte("dummy"), 0o644); err != nil { + t.Fatalf("write: %v", err) + } + cache := newDurationCache(filepath.Join(dir, "cache.json")) + info, err := os.Stat(video) + if err != nil { + t.Fatalf("stat: %v", err) + } + _ = cache.Record(video, info, time.Minute) + progress := &loadProgress{} + progress.Reset() + videos, pending, err := loadVideos(dir, cache, progress) + if err != nil { + t.Fatalf("loadVideos: %v", err) + } + if len(videos) != 1 || len(pending) != 0 { + t.Fatalf("expected cached video without pending: videos=%d pending=%d", len(videos), len(pending)) + } + if videos[0].Duration != time.Minute { + t.Fatalf("expected cached duration") + } +} + +func TestProbeDurationsCmdHandlesMissingBinary(t *testing.T) { + cmd := probeDurationsCmd("/no/such/file.mp4", nil) + msg := cmd() + update := msg.(durationUpdateMsg) + if update.err == nil { + t.Fatalf("expected error from ffprobe") + } +} + +func TestProbeDurationSuccess(t *testing.T) { + dir := t.TempDir() + script := filepath.Join(dir, "ffprobe") + if err := os.WriteFile(script, []byte("#!/bin/sh\necho 5\n"), 0o755); err != nil { + t.Fatalf("write script: %v", err) + } + oldPath := os.Getenv("PATH") + t.Setenv("PATH", dir+":"+oldPath) + dur, err := probeDuration("dummy.mp4") + if err != nil { + t.Fatalf("probeDuration: %v", err) + } + if dur != 5*time.Second { + t.Fatalf("expected 5s duration, got %v", dur) + } +} + +func TestPlayVideoCmdMissingBinary(t *testing.T) { + cmd := playVideoCmd("/no/such/file.mp4", "") + msg := cmd() + result := msg.(playVideoMsg) + if result.path != "/no/such/file.mp4" { + t.Fatalf("unexpected path %s", result.path) + } +} + +func TestRecordIfVideo(t *testing.T) { + var acc []string + if err := recordIfVideo("test.mp4", &acc); err != nil { + t.Fatalf("recordIfVideo: %v", err) + } + if len(acc) != 1 { + t.Fatalf("expected video recorded") + } +} + +func TestHandleSymlinkBrokenVideo(t *testing.T) { + dir := t.TempDir() + symlink := filepath.Join(dir, "clip.mp4") + target := filepath.Join(dir, "missing.mp4") + if err := os.Symlink(target, symlink); err != nil { + t.Skipf("symlink unsupported: %v", err) + } + var acc []string + if err := handleSymlink(symlink, symlink, map[string]struct{}{}, &acc); err != nil { + t.Fatalf("handleSymlink: %v", err) + } + if len(acc) != 1 { + t.Fatalf("expected symlink video recorded") + } +} + +func TestLoadVideosHandlesStatError(t *testing.T) { + if runtime.GOOS == "windows" { + t.Skip("symlink permissions vary on Windows") + } + dir := t.TempDir() + broken := filepath.Join(dir, "broken.mp4") + if err := os.Symlink(filepath.Join(dir, "missing.mp4"), broken); err != nil { + t.Skipf("symlink unsupported: %v", err) + } + videos, _, err := loadVideos(dir, nil, nil) + if err != nil { + t.Fatalf("loadVideos: %v", err) + } + if len(videos) != 1 || videos[0].Err == nil { + t.Fatalf("expected stat error recorded, got %+v", videos) + } +} |
