Skip to content

Commit 06e3fb4

Browse files
authored
Merge pull request #27 from API-Flows/validate-action-steps
Validate action steps
2 parents e04cc67 + 29e3fb5 commit 06e3fb4

File tree

2 files changed

+141
-22
lines changed

2 files changed

+141
-22
lines changed

src/main/java/com/apiflows/parser/OpenAPIWorkflowValidator.java

Lines changed: 44 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,18 @@
11
package com.apiflows.parser;
22

33
import com.apiflows.model.*;
4-
import io.swagger.models.auth.In;
4+
import com.fasterxml.jackson.core.JsonPointer;
5+
import io.swagger.v3.oas.models.media.Schema;
56

67
import java.util.*;
78
import java.util.regex.Pattern;
89

910
public class OpenAPIWorkflowValidator {
1011

1112
private OpenAPIWorkflow openAPIWorkflow = null;
12-
private Set<String> workflowIds = new HashSet<>();
13-
private Map<String, Set<String>> stepIds = new HashMap<>();
13+
Set<String> workflowIds = new HashSet<>();
14+
Map<String, Set<String>> stepIds = new HashMap<>();
15+
Set<Schema> components = new HashSet<>();
1416

1517
OpenAPIWorkflowValidator() {
1618
}
@@ -179,7 +181,7 @@ List<String> validateStep(Step step, String workflowId ) {
179181
}
180182

181183
if(step.getDependsOn() != null) {
182-
if(this.stepIds.get(workflowId) == null || !this.stepIds.get(workflowId).contains(step.getDependsOn())) {
184+
if(!stepExists(workflowId, step.getDependsOn())) {
183185
errors.add("'Step " + stepId + " 'dependsOn' is invalid (no such a step exists)");
184186
}
185187

@@ -193,11 +195,11 @@ List<String> validateStep(Step step, String workflowId ) {
193195
}
194196

195197
for(SuccessAction successAction: step.getOnSuccess()) {
196-
errors.addAll(validateSuccessAction(successAction, stepId));
198+
errors.addAll(validateSuccessAction(workflowId, stepId, successAction));
197199
}
198200

199201
for(FailureAction failureAction : step.getOnFailure()) {
200-
errors.addAll(validateFailureAction(failureAction, stepId));
202+
errors.addAll(validateFailureAction(workflowId, stepId, failureAction));
201203

202204
}
203205

@@ -239,7 +241,7 @@ List<String> validateParameter(Parameter parameter, String workflowId ) {
239241
return errors;
240242
}
241243

242-
List<String> validateSuccessAction(SuccessAction successAction, String stepId) {
244+
List<String> validateSuccessAction(String workflowId, String stepId, SuccessAction successAction) {
243245
List<String> SUPPORTED_VALUES = Arrays.asList("end", "goto");
244246

245247
List<String> errors = new ArrayList<>();
@@ -262,10 +264,17 @@ List<String> validateSuccessAction(SuccessAction successAction, String stepId) {
262264
errors.add("Step " + stepId + " SuccessAction cannot define both workflowId and stepId");
263265
}
264266

267+
if(successAction.getStepId() != null && successAction.getType() != null && successAction.getType().equals("goto")) {
268+
// when type `goto` stepId must exist (if provided)
269+
if (!stepExists(workflowId, successAction.getStepId())) {
270+
errors.add("Step " + stepId + " SuccessAction stepId is invalid (no such a step exists)");
271+
}
272+
}
273+
265274
return errors;
266275
}
267276

268-
List<String> validateFailureAction(FailureAction failureAction, String stepId) {
277+
List<String> validateFailureAction(String workflowId, String stepId, FailureAction failureAction) {
269278
List<String> SUPPORTED_VALUES = Arrays.asList("end", "retry", "goto");
270279

271280
List<String> errors = new ArrayList<>();
@@ -298,6 +307,15 @@ List<String> validateFailureAction(FailureAction failureAction, String stepId) {
298307

299308
}
300309

310+
if(failureAction.getStepId() != null && failureAction.getType() != null
311+
&& (failureAction.getType().equals("goto") || failureAction.getType().equals("retry"))) {
312+
// when type `goto` or `retry` stepId must exist (if provided)
313+
if (!stepExists(workflowId, failureAction.getStepId())) {
314+
errors.add("Step " + stepId + " FailureAction stepId is invalid (no such a step exists)");
315+
}
316+
}
317+
318+
301319
return errors;
302320
}
303321

@@ -422,4 +440,22 @@ List<String> loadStepIds(List<Workflow> workflows) {
422440
return errors;
423441
}
424442

443+
boolean stepExists(String workflowId, String stepId) {
444+
return this.stepIds.get(workflowId) != null && this.stepIds.get(workflowId).contains(stepId);
445+
}
446+
447+
public boolean isValidJsonPointer(String jsonPointerString) {
448+
449+
boolean ret;
450+
451+
try {
452+
JsonPointer jsonPointer = JsonPointer.compile(jsonPointerString);
453+
ret = true;
454+
} catch (IllegalArgumentException e) {
455+
ret = false;
456+
}
457+
458+
return ret;
459+
}
460+
425461
}

src/test/java/com/apiflows/parser/OpenAPIWorkflowValidatorTest.java

Lines changed: 97 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,7 @@
33
import com.apiflows.model.*;
44
import org.junit.jupiter.api.Test;
55

6-
import java.util.ArrayList;
7-
import java.util.List;
6+
import java.util.*;
87

98
import static org.junit.jupiter.api.Assertions.*;
109

@@ -235,7 +234,9 @@ void validateParameterWithoutValue() {
235234

236235
@Test
237236
void validateSuccessAction() {
237+
String workflowId = "w1";
238238
String stepId = "step-one";
239+
239240
SuccessAction successAction = new SuccessAction()
240241
.type("end")
241242
.stepId("step-one");
@@ -244,12 +245,14 @@ void validateSuccessAction() {
244245
new Criterion()
245246
.context("$statusCode == 200"));
246247

247-
assertEquals(0, validator.validateSuccessAction(successAction, stepId).size());
248+
assertEquals(0, validator.validateSuccessAction(workflowId, stepId, successAction).size());
248249
}
249250

250251
@Test
251252
void validateSuccessActionInvalidType() {
253+
String workflowId = "w1";
252254
String stepId = "step-one";
255+
253256
SuccessAction successAction = new SuccessAction()
254257
.type("invalid-type")
255258
.stepId("step-one");
@@ -258,12 +261,14 @@ void validateSuccessActionInvalidType() {
258261
new Criterion()
259262
.context("$statusCode == 200"));
260263

261-
assertEquals(1, validator.validateSuccessAction(successAction, stepId).size());
264+
assertEquals(1, validator.validateSuccessAction(workflowId, stepId, successAction).size());
262265
}
263266

264267
@Test
265268
void validateSuccessActionMissingEntity() {
269+
String workflowId = "w1";
266270
String stepId = "step-one";
271+
267272
SuccessAction successAction = new SuccessAction()
268273
.type("end")
269274
.stepId(null)
@@ -273,12 +278,14 @@ void validateSuccessActionMissingEntity() {
273278
new Criterion()
274279
.context("$statusCode == 200"));
275280

276-
assertEquals(1, validator.validateSuccessAction(successAction, stepId).size());
281+
assertEquals(1, validator.validateSuccessAction(workflowId, stepId, successAction).size());
277282
}
278283

279284
@Test
280285
void validateSuccessActionInvalidEntity() {
286+
String workflowId = "w1";
281287
String stepId = "step-one";
288+
282289
SuccessAction successAction = new SuccessAction()
283290
.type("end")
284291
.stepId("step-one")
@@ -288,9 +295,33 @@ void validateSuccessActionInvalidEntity() {
288295
new Criterion()
289296
.condition("$statusCode == 200"));
290297

291-
assertEquals(1, validator.validateSuccessAction(successAction, stepId).size());
298+
assertEquals(1, validator.validateSuccessAction(workflowId, stepId, successAction).size());
299+
}
300+
301+
@Test
302+
void validateSuccessActionInvalidStepId() {
303+
String workflowId = "w1";
304+
305+
OpenAPIWorkflowValidator validator = new OpenAPIWorkflowValidator();
306+
307+
Map<String, Set<String>> stepIds = new HashMap<>();
308+
stepIds.put("w1", Set.of("step-one", "step-two", "step-three"));
309+
310+
validator.stepIds = stepIds;
311+
312+
String stepId = "step-one";
313+
SuccessAction successAction = new SuccessAction()
314+
.type("goto")
315+
.stepId("step-dummy");
316+
317+
successAction.addCriteria(
318+
new Criterion()
319+
.context("$statusCode == 200"));
320+
321+
assertEquals(1, validator.validateSuccessAction(workflowId, stepId, successAction).size());
292322
}
293323

324+
294325
@Test
295326
void validateCriterion() {
296327
String stepId = "step-one";
@@ -338,9 +369,11 @@ void validateCriterionMissingContext() {
338369

339370
@Test
340371
void validateFailureAction() {
372+
String workflowId = "w1";
341373
String stepId = "step-one";
374+
342375
FailureAction failureAction = new FailureAction()
343-
.type("retry")
376+
.type("end")
344377
.stepId("step-one")
345378
.retryAfter(1000L)
346379
.retryLimit(3);
@@ -349,12 +382,14 @@ void validateFailureAction() {
349382
new Criterion()
350383
.context("$statusCode == 200"));
351384

352-
assertEquals(0, validator.validateFailureAction(failureAction, stepId).size());
385+
assertEquals(0, validator.validateFailureAction(workflowId, stepId, failureAction).size());
353386
}
354387

355388
@Test
356389
void validateFailureActionInvalidType() {
390+
String workflowId = "w1";
357391
String stepId = "step-one";
392+
358393
FailureAction failureAction = new FailureAction()
359394
.type("dummy")
360395
.stepId("step-one")
@@ -365,14 +400,16 @@ void validateFailureActionInvalidType() {
365400
new Criterion()
366401
.context("$statusCode == 200"));
367402

368-
assertEquals(1, validator.validateFailureAction(failureAction, stepId).size());
403+
assertEquals(1, validator.validateFailureAction(workflowId, stepId, failureAction).size());
369404
}
370405

371406
@Test
372407
void validateFailureActionInvalidRetrySettings() {
408+
String workflowId = "w1";
373409
String stepId = "step-one";
410+
374411
FailureAction failureAction = new FailureAction()
375-
.type("retry")
412+
.type("end")
376413
.stepId("step-one")
377414
.retryAfter(-1000L)
378415
.retryLimit(-3);
@@ -381,12 +418,14 @@ void validateFailureActionInvalidRetrySettings() {
381418
new Criterion()
382419
.context("$statusCode == 200"));
383420

384-
assertEquals(2, validator.validateFailureAction(failureAction, stepId).size());
421+
assertEquals(2, validator.validateFailureAction(workflowId, stepId, failureAction).size());
385422
}
386423

387424
@Test
388425
void validateFailureActionMissingEntity() {
426+
String workflowId = "w1";
389427
String stepId = "step-one";
428+
390429
FailureAction failureAction = new FailureAction()
391430
.type("retry")
392431
.stepId(null)
@@ -398,14 +437,16 @@ void validateFailureActionMissingEntity() {
398437
new Criterion()
399438
.context("$statusCode == 200"));
400439

401-
assertEquals(1, validator.validateFailureAction(failureAction, stepId).size());
440+
assertEquals(1, validator.validateFailureAction(workflowId, stepId, failureAction).size());
402441
}
403442

404443
@Test
405444
void validateFailureActionInvalidEntity() {
445+
String workflowId = "w1";
406446
String stepId = "step-one";
447+
407448
FailureAction failureAction = new FailureAction()
408-
.type("retry")
449+
.type("end")
409450
.stepId("step-one")
410451
.workflowId("workflow-test")
411452
.retryAfter(1000L)
@@ -415,9 +456,35 @@ void validateFailureActionInvalidEntity() {
415456
new Criterion()
416457
.context("$statusCode == 200"));
417458

418-
assertEquals(1, validator.validateFailureAction(failureAction, stepId).size());
459+
assertEquals(1, validator.validateFailureAction(workflowId, stepId, failureAction).size());
460+
}
461+
462+
@Test
463+
void validateFailureActionInvalidStepId() {
464+
String workflowId = "w1";
465+
String stepId = "step-one";
466+
467+
OpenAPIWorkflowValidator validator = new OpenAPIWorkflowValidator();
468+
469+
Map<String, Set<String>> stepIds = new HashMap<>();
470+
stepIds.put("w1", Set.of("step-one", "step-two", "step-three"));
471+
472+
validator.stepIds = stepIds;
473+
474+
FailureAction failureAction = new FailureAction()
475+
.type("retry")
476+
.stepId("step-dummy")
477+
.retryAfter(1000L)
478+
.retryLimit(3);
479+
480+
failureAction.addCriteria(
481+
new Criterion()
482+
.context("$statusCode == 200"));
483+
484+
assertEquals(1, validator.validateFailureAction(workflowId, stepId, failureAction).size());
419485
}
420486

487+
421488
@Test
422489
void loadWorkflowIWithDuplicateIds() {
423490
List<Workflow> list = List.of(
@@ -493,4 +560,20 @@ void invalidComponentKey() {
493560
assertFalse(new OpenAPIWorkflowValidator().isValidComponentKey("pagination order"));
494561
}
495562

563+
564+
@Test
565+
void isValidJsonPointer() {
566+
assertTrue(new OpenAPIWorkflowValidator().isValidJsonPointer("/user/id"));
567+
}
568+
569+
@Test
570+
void invalidJsonPointer() {
571+
assertFalse(new OpenAPIWorkflowValidator().isValidJsonPointer("user/id"));
572+
}
573+
574+
// @Test
575+
// void isValidJsonPointer2() {
576+
// assertTrue(new OpenAPIWorkflowValidator().isValidJsonPointer("#/petId"));
577+
// }
578+
496579
}

0 commit comments

Comments
 (0)