coda/internal/validator/validator_test.go

128 lines
2.9 KiB
Go

package validator
import (
"context"
"os"
"os/exec"
"path/filepath"
"testing"
"coda/internal/config"
)
type mockStore struct {
data map[string]string
}
func (m *mockStore) GetAll(_ context.Context) (map[string]string, error) {
result := make(map[string]string, len(m.data))
for k, v := range m.data {
result[k] = v
}
return result, nil
}
func (m *mockStore) Set(_ context.Context, key, value string) error {
if m.data == nil {
m.data = map[string]string{}
}
m.data[key] = value
return nil
}
func (m *mockStore) Delete(_ context.Context, key string) error {
delete(m.data, key)
return nil
}
func newTestService(t *testing.T, overrides map[string]string) *config.Service {
t.Helper()
svc, err := config.NewService(context.Background(), &mockStore{data: overrides})
if err != nil {
t.Fatalf("NewService: %v", err)
}
return svc
}
func requireFFmpegFFprobe(t *testing.T) (ffmpegPath, ffprobePath string) {
t.Helper()
var err error
ffmpegPath, err = exec.LookPath("ffmpeg")
if err != nil {
t.Skip("ffmpeg not found, skipping integration test")
}
ffprobePath, err = exec.LookPath("ffprobe")
if err != nil {
t.Skip("ffprobe not found, skipping integration test")
}
return ffmpegPath, ffprobePath
}
func generateTestMP3(t *testing.T, dir, name string, ffmpegPath string) string {
t.Helper()
mp3Path := filepath.Join(dir, name)
cmd := exec.Command(ffmpegPath,
"-f", "lavfi", "-i", "sine=frequency=440:duration=1",
"-c:a", "libmp3lame",
"-b:a", "320k",
"-y",
mp3Path,
)
if out, err := cmd.CombinedOutput(); err != nil {
t.Fatalf("failed to generate test MP3: %v\n%s", err, out)
}
return mp3Path
}
func TestValidateValidMP3(t *testing.T) {
ffmpegPath, ffprobePath := requireFFmpegFFprobe(t)
t.Setenv("FFMPEG_BIN", ffmpegPath)
t.Setenv("FFPROBE_BIN", ffprobePath)
dir := t.TempDir()
mp3Path := generateTestMP3(t, dir, "valid.mp3", ffmpegPath)
svc := newTestService(t, nil)
v := New(svc)
if err := v.Validate(context.Background(), []string{mp3Path}); err != nil {
t.Errorf("Validate should pass for valid MP3: %v", err)
}
}
func TestValidateMissingFile(t *testing.T) {
svc := newTestService(t, nil)
v := New(svc)
err := v.Validate(context.Background(), []string{"/nonexistent/path.mp3"})
if err == nil {
t.Error("expected error for missing file")
}
}
func TestValidateEmptyFile(t *testing.T) {
dir := t.TempDir()
emptyPath := filepath.Join(dir, "empty.mp3")
if err := os.WriteFile(emptyPath, []byte{}, 0o644); err != nil {
t.Fatalf("write empty file: %v", err)
}
svc := newTestService(t, nil)
v := New(svc)
err := v.Validate(context.Background(), []string{emptyPath})
if err == nil {
t.Error("expected error for empty file")
}
}
func TestValidateDryRun(t *testing.T) {
svc := newTestService(t, map[string]string{"DRY_RUN": "true"})
v := New(svc)
if err := v.Validate(context.Background(), []string{"/nonexistent/path.mp3"}); err != nil {
t.Errorf("Validate should pass in dry run mode: %v", err)
}
}