Implement Milestone 1
This commit is contained in:
300
internal/commands/undo_test.go
Normal file
300
internal/commands/undo_test.go
Normal file
@ -0,0 +1,300 @@
|
||||
package commands
|
||||
|
||||
import (
|
||||
"path/filepath"
|
||||
"testing"
|
||||
|
||||
"git.dws.rip/DWS/onyx/internal/core"
|
||||
"git.dws.rip/DWS/onyx/internal/storage"
|
||||
)
|
||||
|
||||
func TestUndoWithEmptyOplog(t *testing.T) {
|
||||
// Create a temporary directory for testing
|
||||
tempDir := t.TempDir()
|
||||
|
||||
// Initialize the repository
|
||||
repo := &core.OnyxRepository{}
|
||||
err := repo.Init(tempDir)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to initialize repository: %v", err)
|
||||
}
|
||||
|
||||
// Open the repository
|
||||
openedRepo, err := core.Open(tempDir)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to open repository: %v", err)
|
||||
}
|
||||
defer openedRepo.Close()
|
||||
|
||||
// Try to undo with empty oplog
|
||||
oplogPath := filepath.Join(openedRepo.GetOnyxPath(), "oplog")
|
||||
reader := storage.NewOplogReader(oplogPath)
|
||||
|
||||
isEmpty, err := reader.IsEmpty()
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to check if oplog is empty: %v", err)
|
||||
}
|
||||
|
||||
if !isEmpty {
|
||||
t.Errorf("Expected oplog to be empty after init")
|
||||
}
|
||||
|
||||
_, err = reader.ReadLastEntry()
|
||||
if err == nil {
|
||||
t.Errorf("Expected error when reading from empty oplog, got nil")
|
||||
}
|
||||
}
|
||||
|
||||
func TestUndoAfterOperation(t *testing.T) {
|
||||
// Create a temporary directory for testing
|
||||
tempDir := t.TempDir()
|
||||
|
||||
// Initialize the repository
|
||||
repo := &core.OnyxRepository{}
|
||||
err := repo.Init(tempDir)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to initialize repository: %v", err)
|
||||
}
|
||||
|
||||
// Open the repository
|
||||
openedRepo, err := core.Open(tempDir)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to open repository: %v", err)
|
||||
}
|
||||
defer openedRepo.Close()
|
||||
|
||||
// Perform an operation with transaction
|
||||
txn, err := core.NewTransaction(openedRepo)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to create transaction: %v", err)
|
||||
}
|
||||
|
||||
err = txn.ExecuteWithTransaction("test_operation", "Test operation for undo", func() error {
|
||||
// Simulate some operation
|
||||
return nil
|
||||
})
|
||||
txn.Close()
|
||||
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to execute transaction: %v", err)
|
||||
}
|
||||
|
||||
// Verify the oplog has an entry
|
||||
oplogPath := filepath.Join(openedRepo.GetOnyxPath(), "oplog")
|
||||
reader := storage.NewOplogReader(oplogPath)
|
||||
|
||||
isEmpty, err := reader.IsEmpty()
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to check if oplog is empty: %v", err)
|
||||
}
|
||||
|
||||
if isEmpty {
|
||||
t.Errorf("Expected oplog to have entries after operation")
|
||||
}
|
||||
|
||||
// Read the last entry
|
||||
lastEntry, err := reader.ReadLastEntry()
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to read last entry: %v", err)
|
||||
}
|
||||
|
||||
if lastEntry.Operation != "test_operation" {
|
||||
t.Errorf("Expected operation to be 'test_operation', got %q", lastEntry.Operation)
|
||||
}
|
||||
|
||||
if lastEntry.Description != "Test operation for undo" {
|
||||
t.Errorf("Expected description to be 'Test operation for undo', got %q", lastEntry.Description)
|
||||
}
|
||||
|
||||
// Verify state_before and state_after are captured
|
||||
if lastEntry.StateBefore == nil {
|
||||
t.Errorf("Expected state_before to be captured")
|
||||
}
|
||||
|
||||
if lastEntry.StateAfter == nil {
|
||||
t.Errorf("Expected state_after to be captured")
|
||||
}
|
||||
}
|
||||
|
||||
func TestSequentialUndos(t *testing.T) {
|
||||
// Create a temporary directory for testing
|
||||
tempDir := t.TempDir()
|
||||
|
||||
// Initialize the repository
|
||||
repo := &core.OnyxRepository{}
|
||||
err := repo.Init(tempDir)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to initialize repository: %v", err)
|
||||
}
|
||||
|
||||
// Open the repository
|
||||
openedRepo, err := core.Open(tempDir)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to open repository: %v", err)
|
||||
}
|
||||
defer openedRepo.Close()
|
||||
|
||||
// Perform multiple operations
|
||||
operations := []string{"operation1", "operation2", "operation3"}
|
||||
|
||||
for _, op := range operations {
|
||||
txn, err := core.NewTransaction(openedRepo)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to create transaction: %v", err)
|
||||
}
|
||||
|
||||
err = txn.ExecuteWithTransaction(op, "Test "+op, func() error {
|
||||
return nil
|
||||
})
|
||||
txn.Close()
|
||||
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to execute transaction for %s: %v", op, err)
|
||||
}
|
||||
}
|
||||
|
||||
// Verify we have 3 entries
|
||||
oplogPath := filepath.Join(openedRepo.GetOnyxPath(), "oplog")
|
||||
reader := storage.NewOplogReader(oplogPath)
|
||||
|
||||
count, err := reader.Count()
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to count oplog entries: %v", err)
|
||||
}
|
||||
|
||||
if count != 3 {
|
||||
t.Errorf("Expected 3 oplog entries, got %d", count)
|
||||
}
|
||||
|
||||
// Read all entries to verify order
|
||||
entries, err := reader.ReadAllEntries()
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to read all entries: %v", err)
|
||||
}
|
||||
|
||||
for i, entry := range entries {
|
||||
expectedOp := operations[i]
|
||||
if entry.Operation != expectedOp {
|
||||
t.Errorf("Entry %d: expected operation %q, got %q", i, expectedOp, entry.Operation)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestUndoStack(t *testing.T) {
|
||||
// Create a temporary directory for testing
|
||||
tempDir := t.TempDir()
|
||||
|
||||
// Initialize the repository
|
||||
repo := &core.OnyxRepository{}
|
||||
err := repo.Init(tempDir)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to initialize repository: %v", err)
|
||||
}
|
||||
|
||||
// Open the repository
|
||||
openedRepo, err := core.Open(tempDir)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to open repository: %v", err)
|
||||
}
|
||||
defer openedRepo.Close()
|
||||
|
||||
// Perform multiple operations
|
||||
operations := []string{"op1", "op2", "op3"}
|
||||
|
||||
for _, op := range operations {
|
||||
txn, err := core.NewTransaction(openedRepo)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to create transaction: %v", err)
|
||||
}
|
||||
|
||||
err = txn.ExecuteWithTransaction(op, "Test "+op, func() error {
|
||||
return nil
|
||||
})
|
||||
txn.Close()
|
||||
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to execute transaction for %s: %v", op, err)
|
||||
}
|
||||
}
|
||||
|
||||
// Get the undo stack
|
||||
oplogPath := filepath.Join(openedRepo.GetOnyxPath(), "oplog")
|
||||
reader := storage.NewOplogReader(oplogPath)
|
||||
|
||||
undoStack, err := reader.GetUndoStack()
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to get undo stack: %v", err)
|
||||
}
|
||||
|
||||
if len(undoStack) != 3 {
|
||||
t.Errorf("Expected undo stack size of 3, got %d", len(undoStack))
|
||||
}
|
||||
|
||||
// Verify the stack is in reverse order (most recent first)
|
||||
expectedOps := []string{"op3", "op2", "op1"}
|
||||
for i, entry := range undoStack {
|
||||
if entry.Operation != expectedOps[i] {
|
||||
t.Errorf("Undo stack[%d]: expected operation %q, got %q", i, expectedOps[i], entry.Operation)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestOplogEntryMetadata(t *testing.T) {
|
||||
// Create a temporary directory for testing
|
||||
tempDir := t.TempDir()
|
||||
|
||||
// Initialize the repository
|
||||
repo := &core.OnyxRepository{}
|
||||
err := repo.Init(tempDir)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to initialize repository: %v", err)
|
||||
}
|
||||
|
||||
// Open the repository
|
||||
openedRepo, err := core.Open(tempDir)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to open repository: %v", err)
|
||||
}
|
||||
defer openedRepo.Close()
|
||||
|
||||
// Perform an operation with metadata
|
||||
txn, err := core.NewTransaction(openedRepo)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to create transaction: %v", err)
|
||||
}
|
||||
|
||||
metadata := map[string]string{
|
||||
"key1": "value1",
|
||||
"key2": "value2",
|
||||
}
|
||||
|
||||
err = txn.ExecuteWithTransactionAndMetadata("test_op", "Test with metadata", metadata, func() error {
|
||||
return nil
|
||||
})
|
||||
txn.Close()
|
||||
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to execute transaction with metadata: %v", err)
|
||||
}
|
||||
|
||||
// Read the entry and verify metadata
|
||||
oplogPath := filepath.Join(openedRepo.GetOnyxPath(), "oplog")
|
||||
reader := storage.NewOplogReader(oplogPath)
|
||||
|
||||
lastEntry, err := reader.ReadLastEntry()
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to read last entry: %v", err)
|
||||
}
|
||||
|
||||
if lastEntry.Metadata == nil {
|
||||
t.Fatalf("Expected metadata to be present")
|
||||
}
|
||||
|
||||
if lastEntry.Metadata["key1"] != "value1" {
|
||||
t.Errorf("Expected metadata key1=value1, got %q", lastEntry.Metadata["key1"])
|
||||
}
|
||||
|
||||
if lastEntry.Metadata["key2"] != "value2" {
|
||||
t.Errorf("Expected metadata key2=value2, got %q", lastEntry.Metadata["key2"])
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user