Files
correx/testing/projections/src/test/kotlin/OrchestrationReducerTest.kt
T
kami fc7b879891 feature(event-sourcing): baseline for the architecture review fixes.
- fixed the tool overlay in tui.
- fixed tool calling - added schemas.
- getting all sessionIds via event store.
- instead of sending all events on the replay - there's a new way for replaying.
- session snapshot is now a thing getting sent for previously created sessions.
- added logging to important parts.
- revert workflowId from WorkflowCompletedEvent.
2026-05-24 18:57:56 +04:00

148 lines
5.4 KiB
Kotlin

import com.correx.core.events.events.OrchestrationPausedEvent
import com.correx.core.events.events.OrchestrationResumedEvent
import com.correx.core.events.events.RetryAttemptedEvent
import com.correx.core.events.events.WorkflowCompletedEvent
import com.correx.core.events.events.WorkflowFailedEvent
import com.correx.core.events.events.WorkflowStartedEvent
import com.correx.core.events.orchestration.OrchestrationState
import com.correx.core.events.orchestration.OrchestrationStatus
import com.correx.core.events.types.SessionId
import com.correx.core.events.types.StageId
import com.correx.core.kernel.orchestration.DefaultOrchestrationReducer
import com.correx.testing.fixtures.EventFixtures.stored
import org.junit.jupiter.api.Assertions.assertEquals
import org.junit.jupiter.api.Assertions.assertFalse
import org.junit.jupiter.api.Assertions.assertNull
import org.junit.jupiter.api.Assertions.assertTrue
import org.junit.jupiter.api.Test
class OrchestrationReducerTest {
private val reducer = DefaultOrchestrationReducer()
private val sessionId = SessionId("s1")
private val stageId = StageId("stage-1")
private val workflowId = "workflow-test"
private val state = OrchestrationState(workflowId, stageId)
@Test
fun `WorkflowStartedEvent sets status to RUNNING`() {
val state = reducer.reduce(
state,
stored(payload = WorkflowStartedEvent(sessionId, workflowId, stageId)),
)
assertEquals(OrchestrationStatus.RUNNING, state.status)
assertEquals(stageId, state.currentStageId)
}
@Test
fun `WorkflowFailedEvent sets status to FAILED and failure reason`() {
val started = reducer.reduce(
state,
stored(payload = WorkflowStartedEvent(sessionId, workflowId, stageId)),
)
val failed = reducer.reduce(
started,
stored(payload = WorkflowFailedEvent(sessionId, stageId, "Something went wrong", false)),
)
assertFalse(failed.failureReason.isNullOrBlank())
assertEquals(OrchestrationStatus.FAILED, failed.status)
}
@Test
fun `WorkflowCompletedEvent sets status to COMPLETED`() {
val started = reducer.reduce(
state,
stored(payload = WorkflowStartedEvent(sessionId, workflowId, stageId)),
)
val completed = reducer.reduce(
started,
stored(payload = WorkflowCompletedEvent(sessionId, stageId, 1)),
)
assertTrue(completed.failureReason.isNullOrBlank())
assertEquals(OrchestrationStatus.COMPLETED, completed.status)
assertEquals(stageId, completed.currentStageId)
}
@Test
fun `OrchestrationPausedEvent sets status to PAUSED with reason and pending approval`() {
val started = reducer.reduce(
state,
stored(payload = WorkflowStartedEvent(sessionId, workflowId, stageId)),
)
val paused = reducer.reduce(
started,
stored(payload = OrchestrationPausedEvent(sessionId, stageId, "Requires user approval")),
)
assertFalse(paused.pauseReason.isNullOrBlank())
assertEquals(OrchestrationStatus.PAUSED, paused.status)
assertTrue(paused.pendingApproval)
}
@Test
fun `OrchestrationResumedEvent sets status to RUNNING with null reason and no pending approval`() {
val started = reducer.reduce(
state,
stored(payload = WorkflowStartedEvent(sessionId, workflowId, stageId)),
)
val paused = reducer.reduce(
started,
stored(payload = OrchestrationPausedEvent(sessionId, stageId, "Requires user approval")),
)
val resumed = reducer.reduce(
paused,
stored(payload = OrchestrationResumedEvent(sessionId, stageId)),
)
assertTrue(resumed.pauseReason.isNullOrBlank())
assertEquals(OrchestrationStatus.RUNNING, resumed.status)
assertFalse(resumed.pendingApproval)
}
@Test
fun `RetryAttemptedEvent sets status to RUNNING with null reason and no pending approval`() {
val started = reducer.reduce(
state,
stored(payload = WorkflowStartedEvent(sessionId, workflowId, stageId)),
)
val failed = reducer.reduce(
started,
stored(payload = WorkflowFailedEvent(sessionId, stageId, "Something went wrong", false)),
)
val retrying1 = reducer.reduce(
failed,
stored(payload = RetryAttemptedEvent(sessionId, stageId, 1, 3, "Something went wrong")),
)
val retrying2 = reducer.reduce(
retrying1,
stored(payload = RetryAttemptedEvent(sessionId, stageId, 2, 3, "Something went wrong")),
)
val retrying3 = reducer.reduce(
retrying2,
stored(payload = RetryAttemptedEvent(sessionId, stageId, 3, 3, "Something went wrong")),
)
assertTrue(retrying1.retryCount < retrying2.retryCount && retrying2.retryCount < retrying3.retryCount)
assertEquals(OrchestrationStatus.RUNNING, retrying1.status)
assertNull(retrying1.failureReason)
}
@Test
fun `unrelated event does nothing`() {
val started = reducer.reduce(
state,
stored(payload = WorkflowStartedEvent(sessionId, workflowId, stageId)),
)
val unrelated = reducer.reduce(started, stored())
assertEquals(started, unrelated)
}
}