Files
correx/testing/integration/src/test/kotlin/ValidationPipelineIntegrationTest.kt
T
kami f827685ed0 chore(damn): detekt, build, tests, formatting
fixed detekt issues where possible.
fixed disttar failing build because tools is added twice in the server module.
added workflowId where required.
fixed some tests not being recognized because of runBlocking without explicit return type.
formatting + imports.
2026-05-22 00:10:05 +04:00

74 lines
3.0 KiB
Kotlin

import com.correx.core.events.types.StageId
import com.correx.core.events.types.TransitionId
import com.correx.core.transitions.graph.StageConfig
import com.correx.core.transitions.graph.TransitionEdge
import com.correx.core.transitions.graph.WorkflowGraph
import com.correx.core.transitions.resolution.TransitionOrdering
import com.correx.core.validation.approval.ApprovalTrigger
import com.correx.core.validation.graph.GraphValidator
import com.correx.core.validation.model.ValidationContext
import com.correx.core.validation.pipeline.ValidationOutcome
import com.correx.core.validation.pipeline.ValidationPipeline
import com.correx.core.validation.semantic.SemanticValidator
import com.correx.core.validation.semantic.rules.CyclePolicyBindingRule
import com.correx.core.validation.transition.TransitionValidator
import com.correx.testing.fixtures.CycleFixtures
import com.correx.testing.fixtures.WorkflowFixtures
import kotlinx.coroutines.runBlocking
import org.junit.jupiter.api.Assertions.assertFalse
import org.junit.jupiter.api.Assertions.assertInstanceOf
import org.junit.jupiter.api.Test
class ValidationPipelineIntegrationTest {
private val pipeline = ValidationPipeline(
validators = listOf(
GraphValidator(),
TransitionValidator(TransitionOrdering.comparator),
SemanticValidator(
rules = listOf(
CyclePolicyBindingRule(requirePolicyForCycles = true),
),
),
),
approvalTrigger = ApprovalTrigger()
)
@Test
fun `full validation pipeline returns NeedsApproval when cycles are unbound`(): Unit = runBlocking {
val graph = WorkflowFixtures.simpleGraph()
val cycles = listOf(CycleFixtures.simpleCycle())
val context = ValidationContext(
graph = graph,
detectedCycles = cycles,
cyclePolicies = emptySet(),
)
val outcome = pipeline.validate(context)
assertInstanceOf(ValidationOutcome.NeedsApproval::class.java, outcome)
}
@Test
fun `rejected outcome retryable is false - set by validator, not orchestrator`(): Unit = runBlocking {
// A dangling transition triggers GraphValidator ERROR → Rejected(retryable=false).
// Ownership rule: the validator sets retryable; the orchestrator must only read it.
val a = StageId("A")
val ghost = StageId("GHOST")
val graphWithDanglingTransition = WorkflowGraph(
id = "workflow-test",
stages = mapOf(a to StageConfig()),
transitions = setOf(TransitionEdge(TransitionId("t1"), from = a, to = ghost) { true }),
start = a,
)
val pipeline = ValidationPipeline(validators = listOf(GraphValidator()), approvalTrigger = null)
val outcome = pipeline.validate(ValidationContext(graph = graphWithDanglingTransition))
assertInstanceOf(ValidationOutcome.Rejected::class.java, outcome)
assertFalse((outcome as ValidationOutcome.Rejected).retryable)
}
}