veza/veza-backend-api/internal/services/track_chunk_service_resume_test.go
senke b103a09a25 chore: consolidate CI, E2E, backend and frontend updates
- CI: workflows updates (cd, ci), remove playwright.yml
- E2E: global-setup, auth/playlists/profile specs
- Remove playwright-report and test-results artifacts from tracking
- Backend: auth, handlers, services, workers, migrations
- Frontend: components, features, vite config
- Add e2e-results.json to gitignore
- Docs: REMEDIATION_PROGRESS, audit archive
- Rust: chat-server, stream-server updates
2026-02-17 16:43:21 +01:00

220 lines
6.3 KiB
Go

package services
import (
"context"
"fmt"
"testing"
"time"
"github.com/google/uuid"
"github.com/stretchr/testify/assert"
"go.uber.org/zap"
)
// MockStore for testing
type MockStore struct {
data map[string]*ChunkUploadInfo
}
func NewMockStore() *MockStore {
return &MockStore{data: make(map[string]*ChunkUploadInfo)}
}
func (m *MockStore) SetState(ctx context.Context, info *ChunkUploadInfo) error {
m.data[info.UploadID] = info
return nil
}
func (m *MockStore) GetState(ctx context.Context, uploadID string) (*ChunkUploadInfo, error) {
info, ok := m.data[uploadID]
if !ok {
return nil, fmt.Errorf("upload not found")
}
return info, nil
}
func (m *MockStore) DeleteState(ctx context.Context, uploadID string) error {
delete(m.data, uploadID)
return nil
}
func setupTestTrackChunkServiceForResume(_ *testing.T) (*TrackChunkService, func()) {
logger := zap.NewNop()
chunksDir := "test_uploads/tracks/chunks"
// Create service with MockStore
service := &TrackChunkService{
chunksDir: chunksDir,
store: NewMockStore(),
logger: logger,
// other fields defaults
}
cleanup := func() {
// Cleanup will be handled by the service
// os.RemoveAll(chunksDir) if needed
}
return service, cleanup
}
func TestTrackChunkService_GetUploadState_Success(t *testing.T) {
service, cleanup := setupTestTrackChunkServiceForResume(t)
defer cleanup()
// Initialiser un upload
userID := uuid.New()
uploadID, err := service.InitiateChunkedUpload(userID, 5, 1024*1024*50, "test.mp3")
assert.NoError(t, err)
assert.NotEmpty(t, uploadID)
// Récupérer l'état initial (aucun chunk reçu)
state, err := service.GetUploadState(uploadID)
assert.NoError(t, err)
assert.NotNil(t, state)
assert.Equal(t, uploadID, state.UploadID)
assert.Equal(t, userID, state.UserID)
assert.Equal(t, 5, state.TotalChunks)
assert.Equal(t, int64(1024*1024*50), state.TotalSize)
assert.Equal(t, "test.mp3", state.Filename)
assert.Empty(t, state.ChunksReceived)
assert.Equal(t, 0, state.LastChunk)
assert.Equal(t, 0, state.ReceivedCount)
assert.Equal(t, 0, state.Progress)
}
func TestTrackChunkService_GetUploadState_NotFound(t *testing.T) {
service, cleanup := setupTestTrackChunkServiceForResume(t)
defer cleanup()
// Essayer de récupérer l'état d'un upload inexistant
state, err := service.GetUploadState("non-existent-upload-id")
assert.Error(t, err)
assert.Nil(t, state)
assert.Contains(t, err.Error(), "upload not found")
}
func TestTrackChunkService_GetUploadState_WithChunks(t *testing.T) {
service, cleanup := setupTestTrackChunkServiceForResume(t)
defer cleanup()
// Initialiser un upload
userID := uuid.New()
uploadID, err := service.InitiateChunkedUpload(userID, 5, 1024*1024*50, "test.mp3")
assert.NoError(t, err)
// Simuler l'ajout de quelques chunks via l'interface
// Note: In real Redis implementation we can't lock keys like this.
// For testing, we update the MockStore directly.
mockStore := service.store.(*MockStore)
uploadInfo := mockStore.data[uploadID]
assert.NotNil(t, uploadInfo)
// Modifying the struct directly for test setup
// SHA256 checksums (64 hex chars) - SEC-007
uploadInfo.Chunks[1] = ChunkInfo{
ChunkNumber: 1,
Size: 1024 * 1024 * 10,
MD5: "a1b2c3d4e5f6789012345678901234567890abcdef1234567890abcdef123456",
FilePath: "test/chunk_1",
Received: true,
}
uploadInfo.Chunks[2] = ChunkInfo{
ChunkNumber: 2,
Size: 1024 * 1024 * 10,
MD5: "b2c3d4e5f6789012345678901234567890abcdef1234567890abcdef12345678",
FilePath: "test/chunk_2",
Received: true,
}
uploadInfo.Chunks[4] = ChunkInfo{
ChunkNumber: 4,
Size: 1024 * 1024 * 10,
MD5: "c3d4e5f6789012345678901234567890abcdef1234567890abcdef1234567890",
FilePath: "test/chunk_4",
Received: true,
}
// Update store manually
mockStore.data[uploadID] = uploadInfo
// Récupérer l'état
state, err := service.GetUploadState(uploadID)
assert.NoError(t, err)
assert.NotNil(t, state)
// Vérifier les chunks reçus
assert.Equal(t, 3, state.ReceivedCount)
assert.Equal(t, 4, state.LastChunk) // Le dernier chunk reçu est le 4
assert.Equal(t, 60, state.Progress) // 3/5 = 60%
assert.Contains(t, state.ChunksReceived, 1)
assert.Contains(t, state.ChunksReceived, 2)
assert.Contains(t, state.ChunksReceived, 4)
assert.NotContains(t, state.ChunksReceived, 3)
assert.NotContains(t, state.ChunksReceived, 5)
}
func TestTrackChunkService_GetUploadState_Complete(t *testing.T) {
service, cleanup := setupTestTrackChunkServiceForResume(t)
defer cleanup()
// Initialiser un upload
userID := uuid.New()
uploadID, err := service.InitiateChunkedUpload(userID, 3, 1024*1024*30, "complete.mp3")
assert.NoError(t, err)
// Simuler tous les chunks reçus
mockStore := service.store.(*MockStore)
uploadInfo := mockStore.data[uploadID]
assert.NotNil(t, uploadInfo)
chunkChecksum := "d4e5f6789012345678901234567890abcdef1234567890abcdef1234567890ab" // SHA256 format
for i := 1; i <= 3; i++ {
uploadInfo.Chunks[i] = ChunkInfo{
ChunkNumber: i,
Size: 1024 * 1024 * 10,
MD5: chunkChecksum,
FilePath: "test/chunk_" + string(rune(i)),
Received: true,
}
}
uploadInfo.UpdatedAt = time.Now()
// Update store manually
mockStore.data[uploadID] = uploadInfo
// Récupérer l'état
state, err := service.GetUploadState(uploadID)
assert.NoError(t, err)
assert.NotNil(t, state)
assert.Equal(t, 3, state.ReceivedCount)
assert.Equal(t, 3, state.LastChunk)
assert.Equal(t, 100, state.Progress)
assert.Equal(t, 3, len(state.ChunksReceived))
}
func TestTrackChunkService_GetUploadState_MultipleUsers(t *testing.T) {
service, cleanup := setupTestTrackChunkServiceForResume(t)
defer cleanup()
// Créer deux uploads pour deux utilisateurs différents
userID1 := uuid.New()
uploadID1, err := service.InitiateChunkedUpload(userID1, 5, 1024*1024*50, "user1.mp3")
assert.NoError(t, err)
userID2 := uuid.New()
uploadID2, err := service.InitiateChunkedUpload(userID2, 3, 1024*1024*30, "user2.mp3")
assert.NoError(t, err)
// Récupérer les états
state1, err := service.GetUploadState(uploadID1)
assert.NoError(t, err)
assert.Equal(t, userID1, state1.UserID)
state2, err := service.GetUploadState(uploadID2)
assert.NoError(t, err)
assert.Equal(t, userID2, state2.UserID)
// Vérifier que les états sont isolés
assert.NotEqual(t, state1.UploadID, state2.UploadID)
}