package database_test import ( "context" "fmt" "testing" "time" "sneak.berlin/go/vaultik/internal/database" "sneak.berlin/go/vaultik/internal/types" ) func TestFileChunkRepository(t *testing.T) { t.Parallel() db, cleanup := setupTestDB(t) defer cleanup() ctx := context.Background() repo := database.NewFileChunkRepository(db) fileRepo := database.NewFileRepository(db) repos := database.NewRepositories(db) // Create test file first testTime := time.Now().Truncate(time.Second) file := &database.File{ Path: testFileTxt, MTime: testTime, Size: 3072, Mode: 0644, UID: 1000, GID: 1000, LinkTarget: "", } mustCreateFile(t, fileRepo, file) mustCreateChunks(t, repos, chunk1Hash, chunk2Hash, chunk3Hash) // Test Create fc1 := &database.FileChunk{ FileID: file.ID, Idx: 0, ChunkHash: types.ChunkHash(chunk1Hash), } err := repo.Create(ctx, nil, fc1) if err != nil { t.Fatalf("failed to create file chunk: %v", err) } // Add more chunks for the same file fc2 := &database.FileChunk{ FileID: file.ID, Idx: 1, ChunkHash: types.ChunkHash(chunk2Hash), } err = repo.Create(ctx, nil, fc2) if err != nil { t.Fatalf("failed to create second file chunk: %v", err) } fc3 := &database.FileChunk{ FileID: file.ID, Idx: 2, ChunkHash: types.ChunkHash(chunk3Hash), } err = repo.Create(ctx, nil, fc3) if err != nil { t.Fatalf("failed to create third file chunk: %v", err) } // Test GetByFile fileChunks, err := repo.GetByFile(ctx, testFileTxt) if err != nil { t.Fatalf("failed to get file chunks: %v", err) } if len(fileChunks) != 3 { t.Errorf("expected 3 chunks, got %d", len(fileChunks)) } // Verify order for i, chunk := range fileChunks { if chunk.Idx != i { t.Errorf("wrong chunk order: expected idx %d, got %d", i, chunk.Idx) } } // Test duplicate insert (should be idempotent) err = repo.Create(ctx, nil, fc1) if err != nil { t.Fatalf("failed to create duplicate file chunk: %v", err) } } func TestFileChunkRepositoryDeleteByFileID(t *testing.T) { t.Parallel() db, cleanup := setupTestDB(t) defer cleanup() ctx := context.Background() repo := database.NewFileChunkRepository(db) fileRepo := database.NewFileRepository(db) repos := database.NewRepositories(db) file := &database.File{ Path: testFileTxt, MTime: time.Now().Truncate(time.Second), Size: 1024, Mode: 0644, UID: 1000, GID: 1000, } mustCreateFile(t, fileRepo, file) mustCreateChunks(t, repos, chunk1Hash) fc := &database.FileChunk{ FileID: file.ID, Idx: 0, ChunkHash: types.ChunkHash(chunk1Hash), } err := repo.Create(ctx, nil, fc) if err != nil { t.Fatalf("failed to create file chunk: %v", err) } // Test DeleteByFileID err = repo.DeleteByFileID(ctx, nil, file.ID) if err != nil { t.Fatalf("failed to delete file chunks: %v", err) } fileChunks, err := repo.GetByFileID(ctx, file.ID) if err != nil { t.Fatalf("failed to get deleted file chunks: %v", err) } if len(fileChunks) != 0 { t.Errorf("expected 0 chunks after delete, got %d", len(fileChunks)) } } func TestFileChunkRepositoryMultipleFiles(t *testing.T) { t.Parallel() db, cleanup := setupTestDB(t) defer cleanup() ctx := context.Background() repo := database.NewFileChunkRepository(db) fileRepo := database.NewFileRepository(db) // Create test files testTime := time.Now().Truncate(time.Second) filePaths := []string{testFilePath1, testFilePath2, "/file3.txt"} files := make([]*database.File, len(filePaths)) for i, path := range filePaths { file := &database.File{ Path: types.FilePath(path), MTime: testTime, Size: 2048, Mode: 0644, UID: 1000, GID: 1000, LinkTarget: "", } mustCreateFile(t, fileRepo, file) files[i] = file } // Create all chunks first chunkRepo := database.NewChunkRepository(db) for i := range files { for j := range 2 { chunkHash := types.ChunkHash(fmt.Sprintf("file%d_chunk%d", i, j)) chunk := &database.Chunk{ ChunkHash: chunkHash, Size: 1024, } err := chunkRepo.Create(ctx, nil, chunk) if err != nil { t.Fatalf("failed to create chunk %s: %v", chunkHash, err) } } } // Create chunks for multiple files for i, file := range files { for j := range 2 { fc := &database.FileChunk{ FileID: file.ID, Idx: j, ChunkHash: types.ChunkHash(fmt.Sprintf("file%d_chunk%d", i, j)), } err := repo.Create(ctx, nil, fc) if err != nil { t.Fatalf("failed to create file chunk: %v", err) } } } // Verify each file has correct chunks for i, file := range files { chunks, err := repo.GetByFileID(ctx, file.ID) if err != nil { t.Fatalf("failed to get chunks for file %d: %v", i, err) } if len(chunks) != 2 { t.Errorf("expected 2 chunks for file %d, got %d", i, len(chunks)) } } }