diff --git a/validation/src/main/java/io/serverlessworkflow/validation/WorkflowValidatorImpl.java b/validation/src/main/java/io/serverlessworkflow/validation/WorkflowValidatorImpl.java index 84dbb432..739f24ea 100644 --- a/validation/src/main/java/io/serverlessworkflow/validation/WorkflowValidatorImpl.java +++ b/validation/src/main/java/io/serverlessworkflow/validation/WorkflowValidatorImpl.java @@ -144,40 +144,7 @@ public List validate() { if (s instanceof OperationState) { OperationState operationState = (OperationState) s; - - List actions = operationState.getActions(); - for (Action action : actions) { - if (action.getFunctionRef() != null) { - if (action.getFunctionRef().getRefName().isEmpty()) { - addValidationError( - "Operation State action functionRef should not be null or empty", - ValidationError.WORKFLOW_VALIDATION); - } - - if (!haveFunctionDefinition( - action.getFunctionRef().getRefName(), functions)) { - addValidationError( - "Operation State action functionRef does not reference an existing workflow function definition", - ValidationError.WORKFLOW_VALIDATION); - } - } - - if (action.getEventRef() != null) { - - if (!haveEventsDefinition( - action.getEventRef().getTriggerEventRef(), events)) { - addValidationError( - "Operation State action trigger event def does not reference an existing workflow event definition", - ValidationError.WORKFLOW_VALIDATION); - } - - if (!haveEventsDefinition(action.getEventRef().getResultEventRef(), events)) { - addValidationError( - "Operation State action results event def does not reference an existing workflow event definition", - ValidationError.WORKFLOW_VALIDATION); - } - } - } + checkActionsDefinition(operationState.getActions(), functions, events); } if (s instanceof EventState) { @@ -281,6 +248,7 @@ public List validate() { if (s instanceof ForEachState) { ForEachState forEachState = (ForEachState) s; + checkActionsDefinition(forEachState.getActions(), functions, events); if (forEachState.getInputCollection() == null || forEachState.getInputCollection().isEmpty()) { addValidationError( @@ -334,6 +302,50 @@ public WorkflowValidator reset() { return this; } + private void checkActionsDefinition( + List actions, List functions, List events) { + if (actions == null) { + return; + } + for (Action action : actions) { + if (action.getFunctionRef() != null) { + if (action.getFunctionRef().getRefName().isEmpty()) { + addValidationError( + String.format( + "State action '%s' functionRef should not be null or empty", action.getName()), + ValidationError.WORKFLOW_VALIDATION); + } + + if (!haveFunctionDefinition(action.getFunctionRef().getRefName(), functions)) { + addValidationError( + String.format( + "State action '%s' functionRef does not reference an existing workflow function definition", + action.getName()), + ValidationError.WORKFLOW_VALIDATION); + } + } + + if (action.getEventRef() != null) { + + if (!haveEventsDefinition(action.getEventRef().getTriggerEventRef(), events)) { + addValidationError( + String.format( + "State action '%s' trigger event def does not reference an existing workflow event definition", + action.getName()), + ValidationError.WORKFLOW_VALIDATION); + } + + if (!haveEventsDefinition(action.getEventRef().getResultEventRef(), events)) { + addValidationError( + String.format( + "State action '%s' results event def does not reference an existing workflow event definition", + action.getName()), + ValidationError.WORKFLOW_VALIDATION); + } + } + } + } + private boolean haveFunctionDefinition(String functionName, List functions) { if (functions != null) { FunctionDefinition fun = diff --git a/validation/src/test/java/io/serverlessworkflow/validation/test/WorkflowValidationTest.java b/validation/src/test/java/io/serverlessworkflow/validation/test/WorkflowValidationTest.java index 6ccef44f..0bc2f3e4 100644 --- a/validation/src/test/java/io/serverlessworkflow/validation/test/WorkflowValidationTest.java +++ b/validation/src/test/java/io/serverlessworkflow/validation/test/WorkflowValidationTest.java @@ -29,6 +29,7 @@ import io.serverlessworkflow.api.interfaces.WorkflowValidator; import io.serverlessworkflow.api.retry.RetryDefinition; import io.serverlessworkflow.api.start.Start; +import io.serverlessworkflow.api.states.ForEachState; import io.serverlessworkflow.api.states.OperationState; import io.serverlessworkflow.api.states.SleepState; import io.serverlessworkflow.api.validation.ValidationError; @@ -173,7 +174,7 @@ public void testOperationStateNoFunctionRef() { Assertions.assertEquals(1, validationErrors.size()); Assertions.assertEquals( - "Operation State action functionRef does not reference an existing workflow function definition", + "State action 'null' functionRef does not reference an existing workflow function definition", validationErrors.get(0).getMessage()); } @@ -333,4 +334,37 @@ void testEventCall() { .withEnd(new End()))); Assertions.assertTrue(new WorkflowValidatorImpl().setWorkflow(workflow).validate().isEmpty()); } + + /** + * @see Validation missing out + * on refname in foreach>actions + */ + @Test + void testActionDefForEach() { + Workflow workflow = + new Workflow() + .withId("test-workflow") + .withVersion("1.0") + .withStart(new Start().withStateName("TestingForEach")) + .withFunctions(new Functions(Arrays.asList(new FunctionDefinition("Test")))) + .withStates( + Arrays.asList( + new ForEachState() + .withName("TestingForEach") + .withInputCollection("${ .archives }") + .withIterationParam("archive") + .withOutputCollection("${ .output}") + .withActions( + Arrays.asList( + new Action() + .withName("callFn") + .withFunctionRef(new FunctionRef("DoesNotExist")))) + .withEnd(new End()))); + final List validationErrors = + new WorkflowValidatorImpl().setWorkflow(workflow).validate(); + Assertions.assertEquals(1, validationErrors.size()); + Assertions.assertEquals( + "State action 'callFn' functionRef does not reference an existing workflow function definition", + validationErrors.get(0).getMessage()); + } }