From f9822a1550ad7f1e760bb70411d00b9d3d9987a4 Mon Sep 17 00:00:00 2001 From: Beppe Catanese Date: Sun, 4 Feb 2024 23:12:11 +0100 Subject: [PATCH 1/2] Merge with feat branch --- .../parser/OpenAPIWorkflowValidator.java | 18 +++++++++++++++++- .../parser/OpenAPIWorkflowValidatorTest.java | 16 ++++++++++++++++ 2 files changed, 33 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/apiflows/parser/OpenAPIWorkflowValidator.java b/src/main/java/com/apiflows/parser/OpenAPIWorkflowValidator.java index ae6e80b..449b8e8 100644 --- a/src/main/java/com/apiflows/parser/OpenAPIWorkflowValidator.java +++ b/src/main/java/com/apiflows/parser/OpenAPIWorkflowValidator.java @@ -1,7 +1,8 @@ package com.apiflows.parser; import com.apiflows.model.*; -import io.swagger.models.auth.In; +import com.fasterxml.jackson.core.JsonPointer; +import io.swagger.v3.oas.models.media.Schema; import java.util.*; import java.util.regex.Pattern; @@ -11,6 +12,7 @@ public class OpenAPIWorkflowValidator { private OpenAPIWorkflow openAPIWorkflow = null; private Set workflowIds = new HashSet<>(); private Map> stepIds = new HashMap<>(); + private Set components = new HashSet<>(); OpenAPIWorkflowValidator() { } @@ -422,4 +424,18 @@ List loadStepIds(List workflows) { return errors; } + public boolean isValidJsonPointer(String jsonPointerString) { + + boolean ret; + + try { + JsonPointer jsonPointer = JsonPointer.compile(jsonPointerString); + ret = true; + } catch (IllegalArgumentException e) { + ret = false; + } + + return ret; + } + } diff --git a/src/test/java/com/apiflows/parser/OpenAPIWorkflowValidatorTest.java b/src/test/java/com/apiflows/parser/OpenAPIWorkflowValidatorTest.java index 4b2c3e6..8a74b95 100644 --- a/src/test/java/com/apiflows/parser/OpenAPIWorkflowValidatorTest.java +++ b/src/test/java/com/apiflows/parser/OpenAPIWorkflowValidatorTest.java @@ -493,4 +493,20 @@ void invalidComponentKey() { assertFalse(new OpenAPIWorkflowValidator().isValidComponentKey("pagination order")); } + + @Test + void isValidJsonPointer() { + assertTrue(new OpenAPIWorkflowValidator().isValidJsonPointer("/user/id")); + } + + @Test + void invalidJsonPointer() { + assertFalse(new OpenAPIWorkflowValidator().isValidJsonPointer("user/id")); + } + +// @Test +// void isValidJsonPointer2() { +// assertTrue(new OpenAPIWorkflowValidator().isValidJsonPointer("#/petId")); +// } + } \ No newline at end of file From 29e3fb5b716dc2eb20c5eb0e615c08aa0b7b4736 Mon Sep 17 00:00:00 2001 From: Beppe Catanese Date: Tue, 6 Feb 2024 09:28:41 +0100 Subject: [PATCH 2/2] Validate stepId exists (when applicable) --- .../parser/OpenAPIWorkflowValidator.java | 36 +++++-- .../parser/OpenAPIWorkflowValidatorTest.java | 95 ++++++++++++++++--- 2 files changed, 109 insertions(+), 22 deletions(-) diff --git a/src/main/java/com/apiflows/parser/OpenAPIWorkflowValidator.java b/src/main/java/com/apiflows/parser/OpenAPIWorkflowValidator.java index 449b8e8..353d0e8 100644 --- a/src/main/java/com/apiflows/parser/OpenAPIWorkflowValidator.java +++ b/src/main/java/com/apiflows/parser/OpenAPIWorkflowValidator.java @@ -10,9 +10,9 @@ public class OpenAPIWorkflowValidator { private OpenAPIWorkflow openAPIWorkflow = null; - private Set workflowIds = new HashSet<>(); - private Map> stepIds = new HashMap<>(); - private Set components = new HashSet<>(); + Set workflowIds = new HashSet<>(); + Map> stepIds = new HashMap<>(); + Set components = new HashSet<>(); OpenAPIWorkflowValidator() { } @@ -181,7 +181,7 @@ List validateStep(Step step, String workflowId ) { } if(step.getDependsOn() != null) { - if(this.stepIds.get(workflowId) == null || !this.stepIds.get(workflowId).contains(step.getDependsOn())) { + if(!stepExists(workflowId, step.getDependsOn())) { errors.add("'Step " + stepId + " 'dependsOn' is invalid (no such a step exists)"); } @@ -195,11 +195,11 @@ List validateStep(Step step, String workflowId ) { } for(SuccessAction successAction: step.getOnSuccess()) { - errors.addAll(validateSuccessAction(successAction, stepId)); + errors.addAll(validateSuccessAction(workflowId, stepId, successAction)); } for(FailureAction failureAction : step.getOnFailure()) { - errors.addAll(validateFailureAction(failureAction, stepId)); + errors.addAll(validateFailureAction(workflowId, stepId, failureAction)); } @@ -241,7 +241,7 @@ List validateParameter(Parameter parameter, String workflowId ) { return errors; } - List validateSuccessAction(SuccessAction successAction, String stepId) { + List validateSuccessAction(String workflowId, String stepId, SuccessAction successAction) { List SUPPORTED_VALUES = Arrays.asList("end", "goto"); List errors = new ArrayList<>(); @@ -264,10 +264,17 @@ List validateSuccessAction(SuccessAction successAction, String stepId) { errors.add("Step " + stepId + " SuccessAction cannot define both workflowId and stepId"); } + if(successAction.getStepId() != null && successAction.getType() != null && successAction.getType().equals("goto")) { + // when type `goto` stepId must exist (if provided) + if (!stepExists(workflowId, successAction.getStepId())) { + errors.add("Step " + stepId + " SuccessAction stepId is invalid (no such a step exists)"); + } + } + return errors; } - List validateFailureAction(FailureAction failureAction, String stepId) { + List validateFailureAction(String workflowId, String stepId, FailureAction failureAction) { List SUPPORTED_VALUES = Arrays.asList("end", "retry", "goto"); List errors = new ArrayList<>(); @@ -300,6 +307,15 @@ List validateFailureAction(FailureAction failureAction, String stepId) { } + if(failureAction.getStepId() != null && failureAction.getType() != null + && (failureAction.getType().equals("goto") || failureAction.getType().equals("retry"))) { + // when type `goto` or `retry` stepId must exist (if provided) + if (!stepExists(workflowId, failureAction.getStepId())) { + errors.add("Step " + stepId + " FailureAction stepId is invalid (no such a step exists)"); + } + } + + return errors; } @@ -424,6 +440,10 @@ List loadStepIds(List workflows) { return errors; } + boolean stepExists(String workflowId, String stepId) { + return this.stepIds.get(workflowId) != null && this.stepIds.get(workflowId).contains(stepId); + } + public boolean isValidJsonPointer(String jsonPointerString) { boolean ret; diff --git a/src/test/java/com/apiflows/parser/OpenAPIWorkflowValidatorTest.java b/src/test/java/com/apiflows/parser/OpenAPIWorkflowValidatorTest.java index 8a74b95..4139391 100644 --- a/src/test/java/com/apiflows/parser/OpenAPIWorkflowValidatorTest.java +++ b/src/test/java/com/apiflows/parser/OpenAPIWorkflowValidatorTest.java @@ -3,8 +3,7 @@ import com.apiflows.model.*; import org.junit.jupiter.api.Test; -import java.util.ArrayList; -import java.util.List; +import java.util.*; import static org.junit.jupiter.api.Assertions.*; @@ -235,7 +234,9 @@ void validateParameterWithoutValue() { @Test void validateSuccessAction() { + String workflowId = "w1"; String stepId = "step-one"; + SuccessAction successAction = new SuccessAction() .type("end") .stepId("step-one"); @@ -244,12 +245,14 @@ void validateSuccessAction() { new Criterion() .context("$statusCode == 200")); - assertEquals(0, validator.validateSuccessAction(successAction, stepId).size()); + assertEquals(0, validator.validateSuccessAction(workflowId, stepId, successAction).size()); } @Test void validateSuccessActionInvalidType() { + String workflowId = "w1"; String stepId = "step-one"; + SuccessAction successAction = new SuccessAction() .type("invalid-type") .stepId("step-one"); @@ -258,12 +261,14 @@ void validateSuccessActionInvalidType() { new Criterion() .context("$statusCode == 200")); - assertEquals(1, validator.validateSuccessAction(successAction, stepId).size()); + assertEquals(1, validator.validateSuccessAction(workflowId, stepId, successAction).size()); } @Test void validateSuccessActionMissingEntity() { + String workflowId = "w1"; String stepId = "step-one"; + SuccessAction successAction = new SuccessAction() .type("end") .stepId(null) @@ -273,12 +278,14 @@ void validateSuccessActionMissingEntity() { new Criterion() .context("$statusCode == 200")); - assertEquals(1, validator.validateSuccessAction(successAction, stepId).size()); + assertEquals(1, validator.validateSuccessAction(workflowId, stepId, successAction).size()); } @Test void validateSuccessActionInvalidEntity() { + String workflowId = "w1"; String stepId = "step-one"; + SuccessAction successAction = new SuccessAction() .type("end") .stepId("step-one") @@ -288,9 +295,33 @@ void validateSuccessActionInvalidEntity() { new Criterion() .condition("$statusCode == 200")); - assertEquals(1, validator.validateSuccessAction(successAction, stepId).size()); + assertEquals(1, validator.validateSuccessAction(workflowId, stepId, successAction).size()); + } + + @Test + void validateSuccessActionInvalidStepId() { + String workflowId = "w1"; + + OpenAPIWorkflowValidator validator = new OpenAPIWorkflowValidator(); + + Map> stepIds = new HashMap<>(); + stepIds.put("w1", Set.of("step-one", "step-two", "step-three")); + + validator.stepIds = stepIds; + + String stepId = "step-one"; + SuccessAction successAction = new SuccessAction() + .type("goto") + .stepId("step-dummy"); + + successAction.addCriteria( + new Criterion() + .context("$statusCode == 200")); + + assertEquals(1, validator.validateSuccessAction(workflowId, stepId, successAction).size()); } + @Test void validateCriterion() { String stepId = "step-one"; @@ -338,9 +369,11 @@ void validateCriterionMissingContext() { @Test void validateFailureAction() { + String workflowId = "w1"; String stepId = "step-one"; + FailureAction failureAction = new FailureAction() - .type("retry") + .type("end") .stepId("step-one") .retryAfter(1000L) .retryLimit(3); @@ -349,12 +382,14 @@ void validateFailureAction() { new Criterion() .context("$statusCode == 200")); - assertEquals(0, validator.validateFailureAction(failureAction, stepId).size()); + assertEquals(0, validator.validateFailureAction(workflowId, stepId, failureAction).size()); } @Test void validateFailureActionInvalidType() { + String workflowId = "w1"; String stepId = "step-one"; + FailureAction failureAction = new FailureAction() .type("dummy") .stepId("step-one") @@ -365,14 +400,16 @@ void validateFailureActionInvalidType() { new Criterion() .context("$statusCode == 200")); - assertEquals(1, validator.validateFailureAction(failureAction, stepId).size()); + assertEquals(1, validator.validateFailureAction(workflowId, stepId, failureAction).size()); } @Test void validateFailureActionInvalidRetrySettings() { + String workflowId = "w1"; String stepId = "step-one"; + FailureAction failureAction = new FailureAction() - .type("retry") + .type("end") .stepId("step-one") .retryAfter(-1000L) .retryLimit(-3); @@ -381,12 +418,14 @@ void validateFailureActionInvalidRetrySettings() { new Criterion() .context("$statusCode == 200")); - assertEquals(2, validator.validateFailureAction(failureAction, stepId).size()); + assertEquals(2, validator.validateFailureAction(workflowId, stepId, failureAction).size()); } @Test void validateFailureActionMissingEntity() { + String workflowId = "w1"; String stepId = "step-one"; + FailureAction failureAction = new FailureAction() .type("retry") .stepId(null) @@ -398,14 +437,16 @@ void validateFailureActionMissingEntity() { new Criterion() .context("$statusCode == 200")); - assertEquals(1, validator.validateFailureAction(failureAction, stepId).size()); + assertEquals(1, validator.validateFailureAction(workflowId, stepId, failureAction).size()); } @Test void validateFailureActionInvalidEntity() { + String workflowId = "w1"; String stepId = "step-one"; + FailureAction failureAction = new FailureAction() - .type("retry") + .type("end") .stepId("step-one") .workflowId("workflow-test") .retryAfter(1000L) @@ -415,9 +456,35 @@ void validateFailureActionInvalidEntity() { new Criterion() .context("$statusCode == 200")); - assertEquals(1, validator.validateFailureAction(failureAction, stepId).size()); + assertEquals(1, validator.validateFailureAction(workflowId, stepId, failureAction).size()); + } + + @Test + void validateFailureActionInvalidStepId() { + String workflowId = "w1"; + String stepId = "step-one"; + + OpenAPIWorkflowValidator validator = new OpenAPIWorkflowValidator(); + + Map> stepIds = new HashMap<>(); + stepIds.put("w1", Set.of("step-one", "step-two", "step-three")); + + validator.stepIds = stepIds; + + FailureAction failureAction = new FailureAction() + .type("retry") + .stepId("step-dummy") + .retryAfter(1000L) + .retryLimit(3); + + failureAction.addCriteria( + new Criterion() + .context("$statusCode == 200")); + + assertEquals(1, validator.validateFailureAction(workflowId, stepId, failureAction).size()); } + @Test void loadWorkflowIWithDuplicateIds() { List list = List.of(