package recovery import ( "errors" "path/filepath" "testing" "github.com/stretchr/testify/assert" ) func TestDeadletterQueue(t *testing.T) { tmpDir := t.TempDir() queuePath := filepath.Join(tmpDir, "deadletter.json") dq := NewDeadletterQueue(queuePath) item := &DeadletterItem{ ID: "task-1", Type: "activity", WorkflowID: "wf-1", Error: "test error", AttemptCount: 1, MaxAttempts: 3, Recoverable: true, } // Add item err := dq.Add(item) assert.NoError(t, err) assert.Equal(t, 1, dq.Count()) // Get item retrieved := dq.Get("task-1") assert.NotNil(t, retrieved) assert.Equal(t, "task-1", retrieved.ID) assert.NotZero(t, retrieved.CreatedAt) assert.NotZero(t, retrieved.UpdatedAt) // Remove item err = dq.Remove("task-1") assert.NoError(t, err) assert.Equal(t, 0, dq.Count()) } func TestDeadletterQueuePersistence(t *testing.T) { tmpDir := t.TempDir() queuePath := filepath.Join(tmpDir, "deadletter.json") // Create and add item dq1 := NewDeadletterQueue(queuePath) item := &DeadletterItem{ ID: "task-1", Type: "activity", WorkflowID: "wf-1", Error: "test error", Recoverable: true, } err := dq1.Add(item) assert.NoError(t, err) // Create new queue instance and load dq2 := NewDeadletterQueue(queuePath) err = dq2.Load() assert.NoError(t, err) // Verify item was loaded assert.Equal(t, 1, dq2.Count()) retrieved := dq2.Get("task-1") assert.NotNil(t, retrieved) assert.Equal(t, "task-1", retrieved.ID) } func TestDeadletterQueueGetAll(t *testing.T) { tmpDir := t.TempDir() queuePath := filepath.Join(tmpDir, "deadletter.json") dq := NewDeadletterQueue(queuePath) // Add multiple items for i := 1; i <= 3; i++ { item := &DeadletterItem{ ID: "task-" + string(rune(48+i)), Type: "activity", WorkflowID: "wf-1", Error: "error", } dq.Add(item) } all := dq.GetAll() assert.Equal(t, 3, len(all)) } func TestDeadletterQueueGetRecoverable(t *testing.T) { tmpDir := t.TempDir() queuePath := filepath.Join(tmpDir, "deadletter.json") dq := NewDeadletterQueue(queuePath) // Add recoverable item dq.Add(&DeadletterItem{ ID: "task-1", Type: "activity", WorkflowID: "wf-1", Recoverable: true, }) // Add non-recoverable item dq.Add(&DeadletterItem{ ID: "task-2", Type: "activity", WorkflowID: "wf-1", Recoverable: false, }) recoverable := dq.GetRecoverable() assert.Equal(t, 1, len(recoverable)) assert.Equal(t, "task-1", recoverable[0].ID) } func TestDeadletterQueueResolve(t *testing.T) { tmpDir := t.TempDir() queuePath := filepath.Join(tmpDir, "deadletter.json") dq := NewDeadletterQueue(queuePath) dq.Add(&DeadletterItem{ ID: "task-1", Type: "activity", WorkflowID: "wf-1", }) // Resolve item err := dq.Resolve("task-1", "manually recovered") assert.NoError(t, err) item := dq.Get("task-1") assert.NotNil(t, item) assert.Equal(t, "manually recovered", item.RecoveryNote) } func TestDeadletterQueueEmpty(t *testing.T) { tmpDir := t.TempDir() queuePath := filepath.Join(tmpDir, "deadletter.json") dq := NewDeadletterQueue(queuePath) assert.True(t, dq.IsEmpty()) assert.Equal(t, 0, dq.Count()) dq.Add(&DeadletterItem{ID: "task-1"}) assert.False(t, dq.IsEmpty()) assert.Equal(t, 1, dq.Count()) } func TestCreateDeadletterItem(t *testing.T) { err := errors.New("test error") data := map[string]any{"key": "value"} item := CreateDeadletterItem("task-1", "activity", "wf-1", err, data, true) assert.Equal(t, "task-1", item.ID) assert.Equal(t, "activity", item.Type) assert.Equal(t, "wf-1", item.WorkflowID) assert.Equal(t, "test error", item.Error) assert.Equal(t, 1, item.AttemptCount) assert.Equal(t, 3, item.MaxAttempts) assert.True(t, item.Recoverable) assert.NotZero(t, item.CreatedAt) assert.NotZero(t, item.UpdatedAt) } func TestDeadletterQueueNoFile(t *testing.T) { tmpDir := t.TempDir() queuePath := filepath.Join(tmpDir, "nonexistent.json") dq := NewDeadletterQueue(queuePath) // Loading non-existent file should not error err := dq.Load() assert.NoError(t, err) assert.True(t, dq.IsEmpty()) } func TestDeadletterRemoveNonexistent(t *testing.T) { tmpDir := t.TempDir() queuePath := filepath.Join(tmpDir, "deadletter.json") dq := NewDeadletterQueue(queuePath) // Removing non-existent item should not error err := dq.Remove("nonexistent") assert.NoError(t, err) } func TestDeadletterResolveNonexistent(t *testing.T) { tmpDir := t.TempDir() queuePath := filepath.Join(tmpDir, "deadletter.json") dq := NewDeadletterQueue(queuePath) // Resolving non-existent item should error err := dq.Resolve("nonexistent", "note") assert.Error(t, err) }