veza/veza-backend-api/internal/services/cloud_service_test.go
senke ec4564fb37 feat(v0.501): Sprint 3 -- Cloud Storage MVP backend
- C1-01: Create CloudService with CRUD folders/files, quota, ownership
- C1-02: Create CloudHandler with 11 REST endpoints
- C1-03: Register cloud routes in Go router
- C1-04: Implement file streaming with HTTP Range support
- C1-05: Add publish cloud file as track endpoint
- C1-06: Add MSW mock handlers for cloud API
- C1-07: Auto-init 5GB storage quota on user registration
- C1-08: Add 12 unit tests for CloudService
2026-02-22 18:23:58 +01:00

205 lines
6.6 KiB
Go

package services
import (
"context"
"testing"
"github.com/google/uuid"
"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 setupTestCloudDB(t *testing.T) *gorm.DB {
db, err := gorm.Open(sqlite.Open(":memory:"), &gorm.Config{})
require.NoError(t, err)
require.NoError(t, db.AutoMigrate(
&models.User{},
&models.UserFolder{},
&models.UserFile{},
&models.StorageQuota{},
))
return db
}
func createCloudTestUser(t *testing.T, db *gorm.DB) uuid.UUID {
userID := uuid.New()
user := models.User{ID: userID, Email: userID.String() + "@test.com", Username: "user_" + userID.String()[:8]}
require.NoError(t, db.Create(&user).Error)
return userID
}
func createCloudTestQuota(t *testing.T, db *gorm.DB, userID uuid.UUID, maxBytes, usedBytes int64) {
quota := models.StorageQuota{UserID: userID, MaxBytes: maxBytes, UsedBytes: usedBytes}
require.NoError(t, db.Create(&quota).Error)
}
func TestCloudService_CreateFolder(t *testing.T) {
db := setupTestCloudDB(t)
svc := NewCloudService(db, zap.NewNop(), nil)
userID := createCloudTestUser(t, db)
folder, err := svc.CreateFolder(context.Background(), userID, "My Music", nil)
require.NoError(t, err)
assert.Equal(t, "My Music", folder.Name)
assert.Equal(t, userID, folder.UserID)
assert.Nil(t, folder.ParentID)
}
func TestCloudService_CreateSubfolder(t *testing.T) {
db := setupTestCloudDB(t)
svc := NewCloudService(db, zap.NewNop(), nil)
userID := createCloudTestUser(t, db)
parent, err := svc.CreateFolder(context.Background(), userID, "Root", nil)
require.NoError(t, err)
child, err := svc.CreateFolder(context.Background(), userID, "Sub", &parent.ID)
require.NoError(t, err)
assert.Equal(t, &parent.ID, child.ParentID)
}
func TestCloudService_CreateFolder_WrongParentOwner(t *testing.T) {
db := setupTestCloudDB(t)
svc := NewCloudService(db, zap.NewNop(), nil)
user1 := createCloudTestUser(t, db)
user2 := createCloudTestUser(t, db)
folder, err := svc.CreateFolder(context.Background(), user1, "Folder", nil)
require.NoError(t, err)
_, err = svc.CreateFolder(context.Background(), user2, "Sub", &folder.ID)
assert.ErrorIs(t, err, ErrFolderNotFound)
}
func TestCloudService_ListFolders(t *testing.T) {
db := setupTestCloudDB(t)
svc := NewCloudService(db, zap.NewNop(), nil)
userID := createCloudTestUser(t, db)
_, _ = svc.CreateFolder(context.Background(), userID, "A", nil)
_, _ = svc.CreateFolder(context.Background(), userID, "B", nil)
folders, err := svc.ListFolders(context.Background(), userID, nil)
require.NoError(t, err)
assert.Len(t, folders, 2)
assert.Equal(t, "A", folders[0].Name)
}
func TestCloudService_RenameFolder(t *testing.T) {
db := setupTestCloudDB(t)
svc := NewCloudService(db, zap.NewNop(), nil)
userID := createCloudTestUser(t, db)
folder, _ := svc.CreateFolder(context.Background(), userID, "Old", nil)
err := svc.RenameFolder(context.Background(), userID, folder.ID, "New")
require.NoError(t, err)
folders, _ := svc.ListFolders(context.Background(), userID, nil)
assert.Equal(t, "New", folders[0].Name)
}
func TestCloudService_DeleteFolder(t *testing.T) {
db := setupTestCloudDB(t)
svc := NewCloudService(db, zap.NewNop(), nil)
userID := createCloudTestUser(t, db)
createCloudTestQuota(t, db, userID, 5*1024*1024*1024, 0)
folder, _ := svc.CreateFolder(context.Background(), userID, "ToDelete", nil)
err := svc.DeleteFolder(context.Background(), userID, folder.ID)
require.NoError(t, err)
folders, _ := svc.ListFolders(context.Background(), userID, nil)
assert.Len(t, folders, 0)
}
func TestCloudService_UploadFile(t *testing.T) {
db := setupTestCloudDB(t)
svc := NewCloudService(db, zap.NewNop(), nil)
userID := createCloudTestUser(t, db)
createCloudTestQuota(t, db, userID, 5*1024*1024*1024, 0)
data := []byte("fake audio data")
file, err := svc.UploadFile(context.Background(), userID, nil, "test.mp3", data, "audio/mpeg")
require.NoError(t, err)
assert.Equal(t, "test.mp3", file.Filename)
assert.Equal(t, "audio/mpeg", file.MimeType)
assert.Equal(t, int64(len(data)), file.SizeBytes)
}
func TestCloudService_UploadFile_QuotaExceeded(t *testing.T) {
db := setupTestCloudDB(t)
svc := NewCloudService(db, zap.NewNop(), nil)
userID := createCloudTestUser(t, db)
createCloudTestQuota(t, db, userID, 100, 90)
data := make([]byte, 50)
_, err := svc.UploadFile(context.Background(), userID, nil, "big.mp3", data, "audio/mpeg")
assert.ErrorIs(t, err, ErrQuotaExceeded)
}
func TestCloudService_UploadFile_InvalidMimeType(t *testing.T) {
db := setupTestCloudDB(t)
svc := NewCloudService(db, zap.NewNop(), nil)
userID := createCloudTestUser(t, db)
createCloudTestQuota(t, db, userID, 5*1024*1024*1024, 0)
_, err := svc.UploadFile(context.Background(), userID, nil, "test.exe", []byte("data"), "application/x-executable")
assert.ErrorIs(t, err, ErrInvalidMimeType)
}
func TestCloudService_DeleteFile(t *testing.T) {
db := setupTestCloudDB(t)
svc := NewCloudService(db, zap.NewNop(), nil)
userID := createCloudTestUser(t, db)
createCloudTestQuota(t, db, userID, 5*1024*1024*1024, 0)
file, _ := svc.UploadFile(context.Background(), userID, nil, "test.mp3", []byte("data"), "audio/mpeg")
err := svc.DeleteFile(context.Background(), userID, file.ID)
require.NoError(t, err)
_, err = svc.GetFileByID(context.Background(), userID, file.ID)
assert.ErrorIs(t, err, ErrFileNotFound)
}
func TestCloudService_GetQuota(t *testing.T) {
db := setupTestCloudDB(t)
svc := NewCloudService(db, zap.NewNop(), nil)
userID := createCloudTestUser(t, db)
createCloudTestQuota(t, db, userID, 5*1024*1024*1024, 1000)
quota, err := svc.GetQuota(context.Background(), userID)
require.NoError(t, err)
assert.Equal(t, int64(5*1024*1024*1024), quota.MaxBytes)
assert.Equal(t, int64(1000), quota.UsedBytes)
}
func TestCloudService_InitQuota(t *testing.T) {
db := setupTestCloudDB(t)
svc := NewCloudService(db, zap.NewNop(), nil)
userID := createCloudTestUser(t, db)
err := svc.InitQuota(context.Background(), userID)
require.NoError(t, err)
quota, err := svc.GetQuota(context.Background(), userID)
require.NoError(t, err)
assert.Equal(t, int64(5*1024*1024*1024), quota.MaxBytes)
assert.Equal(t, int64(0), quota.UsedBytes)
}
func TestCloudService_Ownership(t *testing.T) {
db := setupTestCloudDB(t)
svc := NewCloudService(db, zap.NewNop(), nil)
user1 := createCloudTestUser(t, db)
user2 := createCloudTestUser(t, db)
createCloudTestQuota(t, db, user1, 5*1024*1024*1024, 0)
file, _ := svc.UploadFile(context.Background(), user1, nil, "secret.mp3", []byte("data"), "audio/mpeg")
_, err := svc.GetFileByID(context.Background(), user2, file.ID)
assert.ErrorIs(t, err, ErrFileNotFound)
}