128 lines
2.9 KiB
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)
|
|
}
|
|
}
|