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") } }