veza/veza-backend-api/internal/services/track_service_batch_delete_test.go.disabled
2025-12-03 20:29:37 +01:00

308 lines
7.9 KiB
Text

package services
import (
"context"
"github.com/google/uuid"
"os"
"path/filepath"
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"go.uber.org/zap"
"gorm.io/driver/sqlite"
"gorm.io/gorm"
"veza-backend-api/internal/models"
)
func setupTestBatchDeleteDB(t *testing.T) (*TrackService, *gorm.DB, string, func()) {
// Setup in-memory SQLite database
db, err := gorm.Open(sqlite.Open(":memory:"), &gorm.Config{})
require.NoError(t, err)
// Auto-migrate
err = db.AutoMigrate(&models.User{}, &models.Track{})
require.NoError(t, err)
// Create test user
user := &models.User{
ID: 1,
Username: "testuser",
Email: "test@example.com",
IsActive: true,
}
err = db.Create(user).Error
require.NoError(t, err)
// Create another user
user2 := &models.User{
ID: 2,
Username: "otheruser",
Email: "other@example.com",
IsActive: true,
}
err = db.Create(user2).Error
require.NoError(t, err)
// Create temporary directory for test files
testDir := filepath.Join(os.TempDir(), "test_batch_delete")
err = os.MkdirAll(testDir, 0755)
require.NoError(t, err)
// Create logger
logger := zap.NewNop()
// Create service
service := NewTrackService(db, logger, testDir)
// Cleanup function
cleanup := func() {
os.RemoveAll(testDir)
}
return service, db, testDir, cleanup
}
func TestTrackService_BatchDeleteTracks_Success(t *testing.T) {
service, db, testDir, cleanup := setupTestBatchDeleteDB(t)
defer cleanup()
ctx := context.Background()
// Create test files
file1 := filepath.Join(testDir, "track1.mp3")
file2 := filepath.Join(testDir, "track2.mp3")
os.WriteFile(file1, []byte("test content 1"), 0644)
os.WriteFile(file2, []byte("test content 2"), 0644)
// Create tracks
track1 := &models.Track{
UserID: 1,
Title: "Track 1",
FilePath: file1,
FileSize: 1024,
Format: "MP3",
Duration: 180,
IsPublic: true,
Status: models.TrackStatusCompleted,
}
track2 := &models.Track{
UserID: 1,
Title: "Track 2",
FilePath: file2,
FileSize: 2048,
Format: "MP3",
Duration: 240,
IsPublic: true,
Status: models.TrackStatusCompleted,
}
err := db.Create(track1).Error
require.NoError(t, err)
err = db.Create(track2).Error
require.NoError(t, err)
// Batch delete
result, err := service.BatchDeleteTracks(ctx, []int64{track1.ID, track2.ID}, 1)
require.NoError(t, err)
require.NotNil(t, result)
// Verify results
assert.Equal(t, 2, len(result.Deleted))
assert.Contains(t, result.Deleted, track1.ID)
assert.Contains(t, result.Deleted, track2.ID)
assert.Equal(t, 0, len(result.Failed))
// Verify tracks are deleted from database
var count int64
db.Model(&models.Track{}).Where("id IN ?", []int64{track1.ID, track2.ID}).Count(&count)
assert.Equal(t, int64(0), count)
// Verify files are deleted
assert.NoFileExists(t, file1)
assert.NoFileExists(t, file2)
}
func TestTrackService_BatchDeleteTracks_EmptyList(t *testing.T) {
service, _, _, cleanup := setupTestBatchDeleteDB(t)
defer cleanup()
ctx := context.Background()
result, err := service.BatchDeleteTracks(ctx, []int64{}, 1)
require.NoError(t, err)
require.NotNil(t, result)
assert.Equal(t, 0, len(result.Deleted))
assert.Equal(t, 0, len(result.Failed))
}
func TestTrackService_BatchDeleteTracks_ExceedsMaxBatchSize(t *testing.T) {
service, _, _, cleanup := setupTestBatchDeleteDB(t)
defer cleanup()
ctx := context.Background()
// Create a list with more than 100 tracks
trackIDs := make([]int64, 101)
for i := range trackIDs {
trackIDs[i] = int64(i + 1)
}
result, err := service.BatchDeleteTracks(ctx, trackIDs, 1)
assert.Error(t, err)
assert.Nil(t, result)
assert.Contains(t, err.Error(), "batch size exceeds maximum")
}
func TestTrackService_BatchDeleteTracks_NotFound(t *testing.T) {
service, _, _, cleanup := setupTestBatchDeleteDB(t)
defer cleanup()
ctx := context.Background()
result, err := service.BatchDeleteTracks(ctx, []int64{999, 1000}, 1)
require.NoError(t, err)
require.NotNil(t, result)
assert.Equal(t, 0, len(result.Deleted))
assert.Equal(t, 2, len(result.Failed))
assert.Equal(t, int64(999), result.Failed[0].TrackID)
assert.Equal(t, "track not found", result.Failed[0].Error)
}
func TestTrackService_BatchDeleteTracks_Forbidden(t *testing.T) {
service, db, testDir, cleanup := setupTestBatchDeleteDB(t)
defer cleanup()
ctx := context.Background()
// Create file
file1 := filepath.Join(testDir, "track1.mp3")
os.WriteFile(file1, []byte("test content"), 0644)
// Create track owned by user 1
track1 := &models.Track{
UserID: 1,
Title: "Track 1",
FilePath: file1,
FileSize: 1024,
Format: "MP3",
Duration: 180,
IsPublic: true,
Status: models.TrackStatusCompleted,
}
err := db.Create(track1).Error
require.NoError(t, err)
// Try to delete as user 2
result, err := service.BatchDeleteTracks(ctx, []int64{track1.ID}, 2)
require.NoError(t, err)
require.NotNil(t, result)
assert.Equal(t, 0, len(result.Deleted))
assert.Equal(t, 1, len(result.Failed))
assert.Equal(t, track1.ID, result.Failed[0].TrackID)
assert.Contains(t, result.Failed[0].Error, "forbidden")
// Verify track still exists
var count int64
db.Model(&models.Track{}).Where("id = ?", track1.ID).Count(&count)
assert.Equal(t, int64(1), count)
}
func TestTrackService_BatchDeleteTracks_PartialSuccess(t *testing.T) {
service, db, testDir, cleanup := setupTestBatchDeleteDB(t)
defer cleanup()
ctx := context.Background()
// Create files
file1 := filepath.Join(testDir, "track1.mp3")
file2 := filepath.Join(testDir, "track2.mp3")
os.WriteFile(file1, []byte("test content 1"), 0644)
os.WriteFile(file2, []byte("test content 2"), 0644)
// Create tracks
track1 := &models.Track{
UserID: 1,
Title: "Track 1",
FilePath: file1,
FileSize: 1024,
Format: "MP3",
Duration: 180,
IsPublic: true,
Status: models.TrackStatusCompleted,
}
track2 := &models.Track{
UserID: 2, // Owned by different user
Title: "Track 2",
FilePath: file2,
FileSize: 2048,
Format: "MP3",
Duration: 240,
IsPublic: true,
Status: models.TrackStatusCompleted,
}
err := db.Create(track1).Error
require.NoError(t, err)
err = db.Create(track2).Error
require.NoError(t, err)
// Try to delete both as user 1
result, err := service.BatchDeleteTracks(ctx, []int64{track1.ID, track2.ID}, 1)
require.NoError(t, err)
require.NotNil(t, result)
// Track1 should be deleted, track2 should fail
assert.Equal(t, 1, len(result.Deleted))
assert.Contains(t, result.Deleted, track1.ID)
assert.Equal(t, 1, len(result.Failed))
assert.Equal(t, track2.ID, result.Failed[0].TrackID)
assert.Contains(t, result.Failed[0].Error, "forbidden")
// Verify track1 is deleted, track2 still exists
var count1, count2 int64
db.Model(&models.Track{}).Where("id = ?", track1.ID).Count(&count1)
db.Model(&models.Track{}).Where("id = ?", track2.ID).Count(&count2)
assert.Equal(t, int64(0), count1)
assert.Equal(t, int64(1), count2)
}
func TestTrackService_deleteTrackFiles(t *testing.T) {
service, db, testDir, cleanup := setupTestBatchDeleteDB(t)
defer cleanup()
ctx := context.Background()
// Create test files
file1 := filepath.Join(testDir, "track1.mp3")
waveform1 := filepath.Join(testDir, "waveform1.png")
cover1 := filepath.Join(testDir, "cover1.jpg")
os.WriteFile(file1, []byte("test content"), 0644)
os.WriteFile(waveform1, []byte("waveform"), 0644)
os.WriteFile(cover1, []byte("cover"), 0644)
// Create track with all file paths
track := &models.Track{
UserID: 1,
Title: "Track with all files",
FilePath: file1,
WaveformPath: waveform1,
CoverArtPath: cover1,
FileSize: 1024,
Format: "MP3",
Duration: 180,
IsPublic: true,
Status: models.TrackStatusCompleted,
}
err := db.Create(track).Error
require.NoError(t, err)
// Delete files
err = service.deleteTrackFiles(ctx, track)
require.NoError(t, err)
// Verify all files are deleted
assert.NoFileExists(t, file1)
assert.NoFileExists(t, waveform1)
assert.NoFileExists(t, cover1)
}