package backup import ( "context" "database/sql" "path/filepath" "testing" "git.eeqj.de/sneak/vaultik/internal/database" "git.eeqj.de/sneak/vaultik/internal/log" ) func TestCleanSnapshotDBEmptySnapshot(t *testing.T) { // Initialize logger log.Initialize(log.Config{}) ctx := context.Background() // Create a test database tempDir := t.TempDir() dbPath := filepath.Join(tempDir, "test.db") db, err := database.New(ctx, dbPath) if err != nil { t.Fatalf("failed to create database: %v", err) } repos := database.NewRepositories(db) // Create an empty snapshot snapshot := &database.Snapshot{ ID: "empty-snapshot", Hostname: "test-host", } err = repos.WithTx(ctx, func(ctx context.Context, tx *sql.Tx) error { return repos.Snapshots.Create(ctx, tx, snapshot) }) if err != nil { t.Fatalf("failed to create snapshot: %v", err) } // Create some files and chunks not associated with any snapshot file := &database.File{Path: "/orphan/file.txt", Size: 1000} chunk := &database.Chunk{ChunkHash: "orphan-chunk", SHA256: "orphan-chunk", Size: 500} err = repos.WithTx(ctx, func(ctx context.Context, tx *sql.Tx) error { if err := repos.Files.Create(ctx, tx, file); err != nil { return err } return repos.Chunks.Create(ctx, tx, chunk) }) if err != nil { t.Fatalf("failed to create orphan data: %v", err) } // Close the database if err := db.Close(); err != nil { t.Fatalf("failed to close database: %v", err) } // Copy database tempDBPath := filepath.Join(tempDir, "temp.db") if err := copyFile(dbPath, tempDBPath); err != nil { t.Fatalf("failed to copy database: %v", err) } // Clean the database sm := &SnapshotManager{} if err := sm.cleanSnapshotDB(ctx, tempDBPath, snapshot.ID); err != nil { t.Fatalf("failed to clean snapshot database: %v", err) } // Verify the cleaned database cleanedDB, err := database.New(ctx, tempDBPath) if err != nil { t.Fatalf("failed to open cleaned database: %v", err) } defer func() { if err := cleanedDB.Close(); err != nil { t.Errorf("failed to close database: %v", err) } }() cleanedRepos := database.NewRepositories(cleanedDB) // Verify snapshot exists verifySnapshot, err := cleanedRepos.Snapshots.GetByID(ctx, snapshot.ID) if err != nil { t.Fatalf("failed to get snapshot: %v", err) } if verifySnapshot == nil { t.Error("snapshot should exist") } // Verify orphan file is gone f, err := cleanedRepos.Files.GetByPath(ctx, file.Path) if err != nil { t.Fatalf("failed to check file: %v", err) } if f != nil { t.Error("orphan file should not exist") } // Verify orphan chunk is gone c, err := cleanedRepos.Chunks.GetByHash(ctx, chunk.ChunkHash) if err != nil { t.Fatalf("failed to check chunk: %v", err) } if c != nil { t.Error("orphan chunk should not exist") } } func TestCleanSnapshotDBNonExistentSnapshot(t *testing.T) { // Initialize logger log.Initialize(log.Config{}) ctx := context.Background() // Create a test database tempDir := t.TempDir() dbPath := filepath.Join(tempDir, "test.db") db, err := database.New(ctx, dbPath) if err != nil { t.Fatalf("failed to create database: %v", err) } // Close immediately if err := db.Close(); err != nil { t.Fatalf("failed to close database: %v", err) } // Copy database tempDBPath := filepath.Join(tempDir, "temp.db") if err := copyFile(dbPath, tempDBPath); err != nil { t.Fatalf("failed to copy database: %v", err) } // Try to clean with non-existent snapshot sm := &SnapshotManager{} err = sm.cleanSnapshotDB(ctx, tempDBPath, "non-existent-snapshot") // Should not error - it will just delete everything if err != nil { t.Fatalf("unexpected error: %v", err) } }