Agate/manager_test.go
Alexander Lazarenko 047e8d2df0
Add comprehensive test coverage for core functionalities
This commit introduces test cases for the API, archive, store, and filesystem functionalities, as well as a functional test for a full workflow. It ensures robust testing for snapshot operations, archiving, and blob management, significantly improving reliability.
2025-05-10 20:13:29 +03:00

410 lines
12 KiB
Go

package agate
import (
"context"
"io"
"os"
"path/filepath"
"testing"
"gitea.unprism.ru/KRBL/Agate/store"
"gitea.unprism.ru/KRBL/Agate/store/filesystem"
"gitea.unprism.ru/KRBL/Agate/store/sqlite"
)
// setupTestEnvironment creates a temporary directory and initializes the stores
func setupTestEnvironment(t *testing.T) (string, store.MetadataStore, store.BlobStore, func()) {
// Create a temporary directory for tests
tempDir, err := os.MkdirTemp("", "agate-test-*")
if err != nil {
t.Fatalf("Failed to create temp directory: %v", err)
}
// Create directories for metadata and blobs
metadataDir := filepath.Join(tempDir, "metadata")
blobsDir := filepath.Join(tempDir, "blobs")
if err := os.MkdirAll(metadataDir, 0755); err != nil {
os.RemoveAll(tempDir)
t.Fatalf("Failed to create metadata directory: %v", err)
}
if err := os.MkdirAll(blobsDir, 0755); err != nil {
os.RemoveAll(tempDir)
t.Fatalf("Failed to create blobs directory: %v", err)
}
// Initialize the stores
dbPath := filepath.Join(metadataDir, "snapshots.db")
metadataStore, err := sqlite.NewSQLiteStore(dbPath)
if err != nil {
os.RemoveAll(tempDir)
t.Fatalf("Failed to create metadata store: %v", err)
}
blobStore, err := filesystem.NewFileSystemStore(blobsDir)
if err != nil {
metadataStore.Close()
os.RemoveAll(tempDir)
t.Fatalf("Failed to create blob store: %v", err)
}
// Return a cleanup function
cleanup := func() {
metadataStore.Close()
os.RemoveAll(tempDir)
}
return tempDir, metadataStore, blobStore, cleanup
}
// createTestFiles creates test files in the specified directory
func createTestFiles(t *testing.T, dir string) {
// Create a subdirectory
subDir := filepath.Join(dir, "subdir")
if err := os.MkdirAll(subDir, 0755); err != nil {
t.Fatalf("Failed to create subdirectory: %v", err)
}
// Create some test files
testFiles := map[string]string{
filepath.Join(dir, "file1.txt"): "This is file 1",
filepath.Join(dir, "file2.txt"): "This is file 2",
filepath.Join(subDir, "subfile1.txt"): "This is subfile 1",
filepath.Join(subDir, "subfile2.txt"): "This is subfile 2",
}
for path, content := range testFiles {
if err := os.WriteFile(path, []byte(content), 0644); err != nil {
t.Fatalf("Failed to create test file %s: %v", path, err)
}
}
}
func TestCreateAndGetSnapshot(t *testing.T) {
tempDir, metadataStore, blobStore, cleanup := setupTestEnvironment(t)
defer cleanup()
// Create a source directory with test files
sourceDir := filepath.Join(tempDir, "source")
if err := os.MkdirAll(sourceDir, 0755); err != nil {
t.Fatalf("Failed to create source directory: %v", err)
}
createTestFiles(t, sourceDir)
// Create a snapshot manager
manager, err := CreateSnapshotManager(metadataStore, blobStore)
if err != nil {
t.Fatalf("Failed to create snapshot manager: %v", err)
}
// Create a snapshot
ctx := context.Background()
snapshot, err := manager.CreateSnapshot(ctx, sourceDir, "Test Snapshot", "")
if err != nil {
t.Fatalf("Failed to create snapshot: %v", err)
}
// Check that the snapshot was created with the correct name
if snapshot.Name != "Test Snapshot" {
t.Errorf("Snapshot has wrong name: got %s, want %s", snapshot.Name, "Test Snapshot")
}
// Check that the snapshot has the correct number of files
if len(snapshot.Files) != 5 { // 4 files + 1 directory
t.Errorf("Snapshot has wrong number of files: got %d, want %d", len(snapshot.Files), 5)
}
// Get the snapshot details
retrievedSnapshot, err := manager.GetSnapshotDetails(ctx, snapshot.ID)
if err != nil {
t.Fatalf("Failed to get snapshot details: %v", err)
}
// Check that the retrieved snapshot matches the original
if retrievedSnapshot.ID != snapshot.ID {
t.Errorf("Retrieved snapshot ID does not match: got %s, want %s", retrievedSnapshot.ID, snapshot.ID)
}
if retrievedSnapshot.Name != snapshot.Name {
t.Errorf("Retrieved snapshot name does not match: got %s, want %s", retrievedSnapshot.Name, snapshot.Name)
}
if len(retrievedSnapshot.Files) != len(snapshot.Files) {
t.Errorf("Retrieved snapshot has wrong number of files: got %d, want %d", len(retrievedSnapshot.Files), len(snapshot.Files))
}
}
func TestListSnapshots(t *testing.T) {
tempDir, metadataStore, blobStore, cleanup := setupTestEnvironment(t)
defer cleanup()
// Create a source directory with test files
sourceDir := filepath.Join(tempDir, "source")
if err := os.MkdirAll(sourceDir, 0755); err != nil {
t.Fatalf("Failed to create source directory: %v", err)
}
createTestFiles(t, sourceDir)
// Create a snapshot manager
manager, err := CreateSnapshotManager(metadataStore, blobStore)
if err != nil {
t.Fatalf("Failed to create snapshot manager: %v", err)
}
// Create multiple snapshots
ctx := context.Background()
snapshot1, err := manager.CreateSnapshot(ctx, sourceDir, "Snapshot 1", "")
if err != nil {
t.Fatalf("Failed to create snapshot: %v", err)
}
// Modify a file
if err := os.WriteFile(filepath.Join(sourceDir, "file1.txt"), []byte("Modified file 1"), 0644); err != nil {
t.Fatalf("Failed to modify test file: %v", err)
}
snapshot2, err := manager.CreateSnapshot(ctx, sourceDir, "Snapshot 2", snapshot1.ID)
if err != nil {
t.Fatalf("Failed to create snapshot: %v", err)
}
// List the snapshots
snapshots, err := manager.ListSnapshots(ctx)
if err != nil {
t.Fatalf("Failed to list snapshots: %v", err)
}
// Check that both snapshots are listed
if len(snapshots) != 2 {
t.Errorf("Wrong number of snapshots listed: got %d, want %d", len(snapshots), 2)
}
// Check that the snapshots have the correct information
for _, snap := range snapshots {
if snap.ID == snapshot1.ID {
if snap.Name != "Snapshot 1" {
t.Errorf("Snapshot 1 has wrong name: got %s, want %s", snap.Name, "Snapshot 1")
}
if snap.ParentID != "" {
t.Errorf("Snapshot 1 has wrong parent ID: got %s, want %s", snap.ParentID, "")
}
} else if snap.ID == snapshot2.ID {
if snap.Name != "Snapshot 2" {
t.Errorf("Snapshot 2 has wrong name: got %s, want %s", snap.Name, "Snapshot 2")
}
if snap.ParentID != snapshot1.ID {
t.Errorf("Snapshot 2 has wrong parent ID: got %s, want %s", snap.ParentID, snapshot1.ID)
}
} else {
t.Errorf("Unexpected snapshot ID: %s", snap.ID)
}
}
}
func TestDeleteSnapshot(t *testing.T) {
tempDir, metadataStore, blobStore, cleanup := setupTestEnvironment(t)
defer cleanup()
// Create a source directory with test files
sourceDir := filepath.Join(tempDir, "source")
if err := os.MkdirAll(sourceDir, 0755); err != nil {
t.Fatalf("Failed to create source directory: %v", err)
}
createTestFiles(t, sourceDir)
// Create a snapshot manager
manager, err := CreateSnapshotManager(metadataStore, blobStore)
if err != nil {
t.Fatalf("Failed to create snapshot manager: %v", err)
}
// Create a snapshot
ctx := context.Background()
snapshot, err := manager.CreateSnapshot(ctx, sourceDir, "Test Snapshot", "")
if err != nil {
t.Fatalf("Failed to create snapshot: %v", err)
}
// Delete the snapshot
err = manager.DeleteSnapshot(ctx, snapshot.ID)
if err != nil {
t.Fatalf("Failed to delete snapshot: %v", err)
}
// Try to get the deleted snapshot
_, err = manager.GetSnapshotDetails(ctx, snapshot.ID)
if err == nil {
t.Fatalf("Expected error when getting deleted snapshot, got nil")
}
// List snapshots to confirm it's gone
snapshots, err := manager.ListSnapshots(ctx)
if err != nil {
t.Fatalf("Failed to list snapshots: %v", err)
}
if len(snapshots) != 0 {
t.Errorf("Expected 0 snapshots after deletion, got %d", len(snapshots))
}
}
func TestOpenFile(t *testing.T) {
_, metadataStore, blobStore, cleanup := setupTestEnvironment(t)
defer cleanup()
// Create a source directory with test files
sourceDir := filepath.Join(blobStore.GetActiveDir(), "source")
if err := os.MkdirAll(sourceDir, 0755); err != nil {
t.Fatalf("Failed to create source directory: %v", err)
}
createTestFiles(t, sourceDir)
// Create a snapshot manager
manager, err := CreateSnapshotManager(metadataStore, blobStore)
if err != nil {
t.Fatalf("Failed to create snapshot manager: %v", err)
}
// Create a snapshot
ctx := context.Background()
snapshot, err := manager.CreateSnapshot(ctx, sourceDir, "Test Snapshot", "")
if err != nil {
t.Fatalf("Failed to create snapshot: %v", err)
}
// Open a file from the snapshot
fileReader, err := manager.OpenFile(ctx, snapshot.ID, "file1.txt")
if err != nil {
t.Fatalf("Failed to open file from snapshot: %v", err)
}
defer fileReader.Close()
// Read the file content
content, err := io.ReadAll(fileReader)
if err != nil {
t.Fatalf("Failed to read file content: %v", err)
}
// Check that the content matches the original
if string(content) != "This is file 1" {
t.Errorf("File content does not match: got %s, want %s", string(content), "This is file 1")
}
// Try to open a non-existent file
pipe, err := manager.OpenFile(ctx, snapshot.ID, "nonexistent.txt")
if err == nil {
tmp := make([]byte, 1)
_, err = pipe.Read(tmp)
if err == nil {
t.Fatalf("Expected error when opening non-existent file, got nil")
}
}
}
func TestExtractSnapshot(t *testing.T) {
tempDir, metadataStore, blobStore, cleanup := setupTestEnvironment(t)
defer cleanup()
// Create a source directory with test files
sourceDir := filepath.Join(tempDir, "source")
if err := os.MkdirAll(sourceDir, 0755); err != nil {
t.Fatalf("Failed to create source directory: %v", err)
}
createTestFiles(t, sourceDir)
// Create a snapshot manager
manager, err := CreateSnapshotManager(metadataStore, blobStore)
if err != nil {
t.Fatalf("Failed to create snapshot manager: %v", err)
}
// Create a snapshot
ctx := context.Background()
snapshot, err := manager.CreateSnapshot(ctx, sourceDir, "Test Snapshot", "")
if err != nil {
t.Fatalf("Failed to create snapshot: %v", err)
}
// Create a target directory for extraction
targetDir := filepath.Join(tempDir, "target")
if err := os.MkdirAll(targetDir, 0755); err != nil {
t.Fatalf("Failed to create target directory: %v", err)
}
// Extract the snapshot
err = manager.ExtractSnapshot(ctx, snapshot.ID, targetDir)
if err != nil {
t.Fatalf("Failed to extract snapshot: %v", err)
}
// Check that the files were extracted correctly
testFiles := map[string]string{
filepath.Join(targetDir, "file1.txt"): "This is file 1",
filepath.Join(targetDir, "file2.txt"): "This is file 2",
filepath.Join(targetDir, "subdir/subfile1.txt"): "This is subfile 1",
filepath.Join(targetDir, "subdir/subfile2.txt"): "This is subfile 2",
}
for path, expectedContent := range testFiles {
content, err := os.ReadFile(path)
if err != nil {
t.Fatalf("Failed to read extracted file %s: %v", path, err)
}
if string(content) != expectedContent {
t.Errorf("Extracted file %s has wrong content: got %s, want %s", path, string(content), expectedContent)
}
}
// Try to extract a non-existent snapshot
err = manager.ExtractSnapshot(ctx, "nonexistent-id", targetDir)
if err == nil {
t.Fatalf("Expected error when extracting non-existent snapshot, got nil")
}
}
func TestUpdateSnapshotMetadata(t *testing.T) {
tempDir, metadataStore, blobStore, cleanup := setupTestEnvironment(t)
defer cleanup()
// Create a source directory with test files
sourceDir := filepath.Join(tempDir, "source")
if err := os.MkdirAll(sourceDir, 0755); err != nil {
t.Fatalf("Failed to create source directory: %v", err)
}
createTestFiles(t, sourceDir)
// Create a snapshot manager
manager, err := CreateSnapshotManager(metadataStore, blobStore)
if err != nil {
t.Fatalf("Failed to create snapshot manager: %v", err)
}
// Create a snapshot
ctx := context.Background()
snapshot, err := manager.CreateSnapshot(ctx, sourceDir, "Test Snapshot", "")
if err != nil {
t.Fatalf("Failed to create snapshot: %v", err)
}
// Update the snapshot metadata
newName := "Updated Snapshot Name"
err = manager.UpdateSnapshotMetadata(ctx, snapshot.ID, newName)
if err != nil {
t.Fatalf("Failed to update snapshot metadata: %v", err)
}
// Get the updated snapshot
updatedSnapshot, err := manager.GetSnapshotDetails(ctx, snapshot.ID)
if err != nil {
t.Fatalf("Failed to get updated snapshot: %v", err)
}
// Check that the name was updated
if updatedSnapshot.Name != newName {
t.Errorf("Snapshot name was not updated: got %s, want %s", updatedSnapshot.Name, newName)
}
// Try to update a non-existent snapshot
err = manager.UpdateSnapshotMetadata(ctx, "nonexistent-id", "New Name")
if err == nil {
t.Fatalf("Expected error when updating non-existent snapshot, got nil")
}
}