package pause import ( "fmt" "testing" "time" "github.com/stretchr/testify/assert" ) func TestRequestPause(t *testing.T) { tmpDir := t.TempDir() sm := NewSnapshotManager(tmpDir) ph := NewPauseHandler(sm) signal := &PauseSignal{ WorkflowID: "wf-1", Reason: "manual pause", RequestedAt: time.Now(), } err := ph.RequestPause(signal) assert.NoError(t, err) assert.True(t, ph.IsPaused("wf-1")) } func TestRequestResume(t *testing.T) { tmpDir := t.TempDir() sm := NewSnapshotManager(tmpDir) ph := NewPauseHandler(sm) // First pause ph.RequestPause(&PauseSignal{WorkflowID: "wf-1", Reason: "pause", RequestedAt: time.Now()}) assert.True(t, ph.IsPaused("wf-1")) // Then resume err := ph.RequestResume(&ResumeSignal{WorkflowID: "wf-1", Reason: "resume", RequestedAt: time.Now()}) assert.NoError(t, err) assert.False(t, ph.IsPaused("wf-1")) } func TestIsPaused(t *testing.T) { tmpDir := t.TempDir() sm := NewSnapshotManager(tmpDir) ph := NewPauseHandler(sm) assert.False(t, ph.IsPaused("wf-1")) ph.RequestPause(&PauseSignal{WorkflowID: "wf-1", Reason: "pause", RequestedAt: time.Now()}) assert.True(t, ph.IsPaused("wf-1")) } func TestGetPauseState(t *testing.T) { tmpDir := t.TempDir() sm := NewSnapshotManager(tmpDir) ph := NewPauseHandler(sm) ph.RequestPause(&PauseSignal{WorkflowID: "wf-1", Reason: "pause", RequestedAt: time.Now()}) state := ph.GetPauseState("wf-1") assert.NotNil(t, state) assert.Equal(t, "wf-1", state.WorkflowID) assert.True(t, state.IsPaused) assert.Equal(t, "pause", state.PauseReason) } func TestSaveSnapshot(t *testing.T) { tmpDir := t.TempDir() sm := NewSnapshotManager(tmpDir) ph := NewPauseHandler(sm) snapshot, err := ph.SaveSnapshot( "wf-1", "stage1", []string{"T1.1"}, []string{"T1.2"}, nil, "T1.2", "activity-1", nil, nil, nil, ) assert.NoError(t, err) assert.NotNil(t, snapshot) assert.Equal(t, "wf-1", snapshot.WorkflowID) } func TestRestoreSnapshot(t *testing.T) { tmpDir := t.TempDir() sm := NewSnapshotManager(tmpDir) ph := NewPauseHandler(sm) // Save snapshot ph.SaveSnapshot("wf-1", "stage1", []string{"T1.1"}, []string{"T1.2"}, nil, "T1.2", "", nil, nil, nil) // Restore it snapshot, err := ph.RestoreSnapshot("wf-1") assert.NoError(t, err) assert.NotNil(t, snapshot) assert.Equal(t, "wf-1", snapshot.WorkflowID) } func TestResetPauseState(t *testing.T) { tmpDir := t.TempDir() sm := NewSnapshotManager(tmpDir) ph := NewPauseHandler(sm) ph.RequestPause(&PauseSignal{WorkflowID: "wf-1", Reason: "pause", RequestedAt: time.Now()}) assert.True(t, ph.IsPaused("wf-1")) err := ph.ResetPauseState("wf-1") assert.NoError(t, err) assert.Nil(t, ph.GetPauseState("wf-1")) } func TestGetAllPauseStates(t *testing.T) { tmpDir := t.TempDir() sm := NewSnapshotManager(tmpDir) ph := NewPauseHandler(sm) ph.RequestPause(&PauseSignal{WorkflowID: "wf-1", Reason: "pause", RequestedAt: time.Now()}) ph.RequestPause(&PauseSignal{WorkflowID: "wf-2", Reason: "pause", RequestedAt: time.Now()}) ph.RequestPause(&PauseSignal{WorkflowID: "wf-3", Reason: "pause", RequestedAt: time.Now()}) states := ph.GetAllPauseStates() assert.Equal(t, 3, len(states)) } func TestGetPauseStats(t *testing.T) { tmpDir := t.TempDir() sm := NewSnapshotManager(tmpDir) ph := NewPauseHandler(sm) ph.RequestPause(&PauseSignal{WorkflowID: "wf-1", Reason: "pause", RequestedAt: time.Now()}) ph.RequestPause(&PauseSignal{WorkflowID: "wf-2", Reason: "pause", RequestedAt: time.Now()}) ph.RequestResume(&ResumeSignal{WorkflowID: "wf-1", Reason: "resume", RequestedAt: time.Now()}) stats := ph.GetPauseStats() assert.Equal(t, 2, stats["total"]) assert.Equal(t, 1, stats["paused"]) assert.Equal(t, 1, stats["resumed"]) } func TestPauseStateFields(t *testing.T) { tmpDir := t.TempDir() sm := NewSnapshotManager(tmpDir) ph := NewPauseHandler(sm) pausedTime := time.Now() ph.RequestPause(&PauseSignal{WorkflowID: "wf-1", Reason: "manual pause", RequestedAt: pausedTime}) state := ph.GetPauseState("wf-1") assert.Equal(t, "wf-1", state.WorkflowID) assert.True(t, state.IsPaused) assert.Equal(t, "manual pause", state.PauseReason) assert.NotZero(t, state.PausedAt) } func TestResumedAt(t *testing.T) { tmpDir := t.TempDir() sm := NewSnapshotManager(tmpDir) ph := NewPauseHandler(sm) ph.RequestPause(&PauseSignal{WorkflowID: "wf-1", Reason: "pause", RequestedAt: time.Now()}) ph.RequestResume(&ResumeSignal{WorkflowID: "wf-1", Reason: "resume", RequestedAt: time.Now()}) state := ph.GetPauseState("wf-1") assert.NotNil(t, state.ResumedAt) } func TestResumeNotPausedError(t *testing.T) { tmpDir := t.TempDir() sm := NewSnapshotManager(tmpDir) ph := NewPauseHandler(sm) // Try to resume without pausing first err := ph.RequestResume(&ResumeSignal{WorkflowID: "wf-1", Reason: "resume", RequestedAt: time.Now()}) assert.Error(t, err) } func TestNilSignals(t *testing.T) { tmpDir := t.TempDir() sm := NewSnapshotManager(tmpDir) ph := NewPauseHandler(sm) err := ph.RequestPause(nil) assert.Error(t, err) err = ph.RequestResume(nil) assert.Error(t, err) } func TestMultipleWorkflowsPause(t *testing.T) { tmpDir := t.TempDir() sm := NewSnapshotManager(tmpDir) ph := NewPauseHandler(sm) for i := 1; i <= 5; i++ { wfID := fmt.Sprintf("wf-%d", i) ph.RequestPause(&PauseSignal{WorkflowID: wfID, Reason: "pause", RequestedAt: time.Now()}) } states := ph.GetAllPauseStates() assert.Equal(t, 5, len(states)) for _, state := range states { assert.True(t, state.IsPaused) } } func TestWaitForPauseOrResume(t *testing.T) { tmpDir := t.TempDir() sm := NewSnapshotManager(tmpDir) ph := NewPauseHandler(sm) // Send pause signal in goroutine go func() { time.Sleep(100 * time.Millisecond) ph.RequestPause(&PauseSignal{WorkflowID: "wf-1", Reason: "pause", RequestedAt: time.Now()}) }() // Wait for pause isPaused, err := ph.WaitForPauseOrResume("wf-1", 1*time.Second) assert.NoError(t, err) assert.True(t, isPaused) } func TestWaitTimeout(t *testing.T) { tmpDir := t.TempDir() sm := NewSnapshotManager(tmpDir) ph := NewPauseHandler(sm) // Wait with timeout should fail _, err := ph.WaitForPauseOrResume("wf-1", 100*time.Millisecond) assert.Error(t, err) } func TestSnapshotWithPause(t *testing.T) { tmpDir := t.TempDir() sm := NewSnapshotManager(tmpDir) ph := NewPauseHandler(sm) // Save snapshot before pausing snapshot, err := ph.SaveSnapshot("wf-1", "stage1", []string{"T1.1"}, []string{"T1.2"}, nil, "T1.2", "", nil, nil, nil) assert.NoError(t, err) // Pause ph.RequestPause(&PauseSignal{WorkflowID: "wf-1", Reason: "pause", RequestedAt: time.Now()}) // State should have snapshot state := ph.GetPauseState("wf-1") assert.NotNil(t, state) assert.NotNil(t, state.CurrentSnapshot) assert.Equal(t, snapshot.WorkflowID, state.CurrentSnapshot.WorkflowID) }