package services import ( "bytes" "mime/multipart" "net/http" "testing" "github.com/stretchr/testify/assert" ) // createTestAudioFileHeader crée un FileHeader pour les tests func createTestAudioFileHeader(filename string, data []byte) *multipart.FileHeader { body := new(bytes.Buffer) writer := multipart.NewWriter(body) part, err := writer.CreateFormFile("file", filename) if err != nil { return nil } if _, err := part.Write(data); err != nil { return nil } writer.Close() req, err := http.NewRequest("POST", "/test", body) if err != nil { return nil } req.Header.Set("Content-Type", writer.FormDataContentType()) // Parse multipart form if err := req.ParseMultipartForm(10 << 20); err != nil { return nil } formFile := req.MultipartForm.File["file"] if len(formFile) == 0 { return nil } return formFile[0] } func TestTrackValidationService_ValidateFormat_MP3(t *testing.T) { service := NewTrackValidationService() // MP3 avec ID3v2 mp3Data := []byte{'I', 'D', '3', 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} fileHeader := createTestAudioFileHeader("test.mp3", mp3Data) assert.NotNil(t, fileHeader) err := service.ValidateFormat(fileHeader) assert.NoError(t, err) } func TestTrackValidationService_ValidateFormat_MP3_MPEG(t *testing.T) { service := NewTrackValidationService() // MP3 avec MPEG frame sync mp3Data := []byte{0xFF, 0xFB, 0x90, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} fileHeader := createTestAudioFileHeader("test.mp3", mp3Data) assert.NotNil(t, fileHeader) err := service.ValidateFormat(fileHeader) assert.NoError(t, err) } func TestTrackValidationService_ValidateFormat_FLAC(t *testing.T) { service := NewTrackValidationService() // FLAC flacData := []byte{'f', 'L', 'a', 'C', 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00, 0x00} fileHeader := createTestAudioFileHeader("test.flac", flacData) assert.NotNil(t, fileHeader) err := service.ValidateFormat(fileHeader) assert.NoError(t, err) } func TestTrackValidationService_ValidateFormat_WAV(t *testing.T) { service := NewTrackValidationService() // WAV wavData := []byte{'R', 'I', 'F', 'F', 0x00, 0x00, 0x00, 0x00, 'W', 'A', 'V', 'E'} fileHeader := createTestAudioFileHeader("test.wav", wavData) assert.NotNil(t, fileHeader) err := service.ValidateFormat(fileHeader) assert.NoError(t, err) } func TestTrackValidationService_ValidateFormat_OGG(t *testing.T) { service := NewTrackValidationService() // OGG oggData := []byte{'O', 'g', 'g', 'S', 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} fileHeader := createTestAudioFileHeader("test.ogg", oggData) assert.NotNil(t, fileHeader) err := service.ValidateFormat(fileHeader) assert.NoError(t, err) } func TestTrackValidationService_ValidateFormat_Invalid(t *testing.T) { service := NewTrackValidationService() // Fichier invalide invalidData := []byte("not an audio file") fileHeader := createTestAudioFileHeader("test.txt", invalidData) assert.NotNil(t, fileHeader) err := service.ValidateFormat(fileHeader) assert.Error(t, err) assert.Contains(t, err.Error(), "invalid audio file format") } func TestTrackValidationService_ValidateFileSize_Valid(t *testing.T) { service := NewTrackValidationService() data := make([]byte, 10*1024*1024) // 10MB fileHeader := createTestAudioFileHeader("test.mp3", data) assert.NotNil(t, fileHeader) err := service.ValidateFileSize(fileHeader) assert.NoError(t, err) } func TestTrackValidationService_ValidateFileSize_TooLarge(t *testing.T) { service := NewTrackValidationService() data := make([]byte, 101*1024*1024) // 101MB fileHeader := createTestAudioFileHeader("test.mp3", data) assert.NotNil(t, fileHeader) err := service.ValidateFileSize(fileHeader) assert.Error(t, err) assert.Contains(t, err.Error(), "file size exceeds maximum") } func TestTrackValidationService_ValidateFileSize_Empty(t *testing.T) { service := NewTrackValidationService() data := []byte{} fileHeader := createTestAudioFileHeader("test.mp3", data) assert.NotNil(t, fileHeader) err := service.ValidateFileSize(fileHeader) assert.Error(t, err) assert.Contains(t, err.Error(), "file is empty") } func TestTrackValidationService_ValidateDuration_Valid(t *testing.T) { service := NewTrackValidationService() // Durée valide (30 secondes) err := service.ValidateDuration(30) assert.NoError(t, err) // Durée valide (1 seconde - minimum) err = service.ValidateDuration(1) assert.NoError(t, err) // Durée valide (3 heures - maximum) err = service.ValidateDuration(MaxTrackDuration) assert.NoError(t, err) } func TestTrackValidationService_ValidateDuration_TooShort(t *testing.T) { service := NewTrackValidationService() // Durée trop courte err := service.ValidateDuration(0) assert.Error(t, err) assert.Contains(t, err.Error(), "too short") } func TestTrackValidationService_ValidateDuration_TooLong(t *testing.T) { service := NewTrackValidationService() // Durée trop longue err := service.ValidateDuration(MaxTrackDuration + 1) assert.Error(t, err) assert.Contains(t, err.Error(), "too long") } func TestTrackValidationService_ValidateCodec_Valid(t *testing.T) { service := NewTrackValidationService() validCodecs := []string{"mp3", "MP3", "flac", "FLAC", "pcm", "vorbis", "aac", "AAC"} for _, codec := range validCodecs { err := service.ValidateCodec(codec) assert.NoError(t, err, "codec %s should be valid", codec) } } func TestTrackValidationService_ValidateCodec_Invalid(t *testing.T) { service := NewTrackValidationService() // Codec invalide err := service.ValidateCodec("invalid_codec") assert.Error(t, err) assert.Contains(t, err.Error(), "unsupported codec") } func TestTrackValidationService_ValidateCodec_Empty(t *testing.T) { service := NewTrackValidationService() // Codec vide err := service.ValidateCodec("") assert.Error(t, err) assert.Contains(t, err.Error(), "codec is required") } func TestTrackValidationService_ValidateTrackFile_Success(t *testing.T) { service := NewTrackValidationService() // Créer un fichier MP3 valide mp3Data := []byte{'I', 'D', '3', 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} fileHeader := createTestAudioFileHeader("test.mp3", mp3Data) assert.NotNil(t, fileHeader) result, err := service.ValidateTrackFile(fileHeader, 180, "mp3") assert.NoError(t, err) assert.NotNil(t, result) assert.True(t, result.Valid) assert.Equal(t, "mp3", result.Codec) assert.Equal(t, 180, result.Duration) } func TestTrackValidationService_ValidateTrackFile_InvalidFormat(t *testing.T) { service := NewTrackValidationService() // Fichier invalide invalidData := []byte("not an audio file") fileHeader := createTestAudioFileHeader("test.txt", invalidData) assert.NotNil(t, fileHeader) result, err := service.ValidateTrackFile(fileHeader, 180, "mp3") assert.Error(t, err) assert.NotNil(t, result) assert.False(t, result.Valid) assert.NotEmpty(t, result.Errors) } func TestTrackValidationService_ValidateTrackFile_InvalidSize(t *testing.T) { service := NewTrackValidationService() // Fichier trop grand largeData := make([]byte, 101*1024*1024) // 101MB fileHeader := createTestAudioFileHeader("test.mp3", largeData) assert.NotNil(t, fileHeader) result, err := service.ValidateTrackFile(fileHeader, 180, "mp3") assert.Error(t, err) assert.NotNil(t, result) assert.False(t, result.Valid) } func TestTrackValidationService_ValidateTrackFile_InvalidDuration(t *testing.T) { service := NewTrackValidationService() // Fichier valide mais durée invalide mp3Data := []byte{'I', 'D', '3', 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} fileHeader := createTestAudioFileHeader("test.mp3", mp3Data) assert.NotNil(t, fileHeader) // Durée trop longue result, err := service.ValidateTrackFile(fileHeader, MaxTrackDuration+1, "mp3") assert.Error(t, err) assert.NotNil(t, result) assert.False(t, result.Valid) // Durée trop courte (0) est ignorée par ValidateTrackFile (considérée comme non fournie) // Donc on ne teste pas le cas 0 ici qui retourne valide par design (optionalité) } func TestTrackValidationService_ValidateTrackFile_InvalidCodec(t *testing.T) { service := NewTrackValidationService() // Fichier valide mais codec invalide mp3Data := []byte{'I', 'D', '3', 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} fileHeader := createTestAudioFileHeader("test.mp3", mp3Data) assert.NotNil(t, fileHeader) result, err := service.ValidateTrackFile(fileHeader, 180, "invalid_codec") assert.Error(t, err) assert.NotNil(t, result) assert.False(t, result.Valid) } func TestTrackValidationService_DetectFormat(t *testing.T) { service := NewTrackValidationService() tests := []struct { name string data []byte expected string }{ { name: "MP3 ID3v2", data: []byte{'I', 'D', '3', 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, expected: "audio/mpeg", }, { name: "FLAC", data: []byte{'f', 'L', 'a', 'C', 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00, 0x00}, expected: "audio/flac", }, { name: "WAV", data: []byte{'R', 'I', 'F', 'F', 0x00, 0x00, 0x00, 0x00, 'W', 'A', 'V', 'E'}, expected: "audio/wav", }, { name: "OGG", data: []byte{'O', 'g', 'g', 'S', 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, expected: "audio/ogg", }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { fileHeader := createTestAudioFileHeader("test."+tt.name, tt.data) assert.NotNil(t, fileHeader) format := service.detectFormat(fileHeader) assert.Equal(t, tt.expected, format) }) } }