Skip to content

Commit 6a4e16c

Browse files
author
André R. de Miranda
authored
Workflow validations (#156)
* Workflow validations workflow parameters validations: * id and key: add required_without * start: required, create a custom validator to check if state exists on the workflow states Others: * Workflow.Start: if the start is not defined, use the first workflow state * State.UnmarshalJSON: removed return from switch not need * State.UnmarshalJSON: when state type is nil return a error message Signed-off-by: André R. de Miranda <andre@galgo.tech> * Not check state exists if start.StateName is empty Signed-off-by: André R. de Miranda <andre@galgo.tech> * Workflow state requires "State.End" or "State.Transition" Signed-off-by: André R. de Miranda <andre@galgo.tech> * Remove require from Workflow.Start and remove assert Workflow.Start from parser/parser_test.go Signed-off-by: André R. de Miranda <andre@galgo.tech> * Move validator to *_validator.go. Changes with validator "transition" and "end" validator: add to BaseState; fix failed unit tests; refactor SwitchState validator. Signed-off-by: André R. de Miranda <andre@galgo.tech> * Add simple check if transitions exist Signed-off-by: André R. de Miranda <andre@galgo.tech> * Remove the `NextState` check that is empty. Already been checked as required in the `Transition` struct field. Signed-off-by: André R. de Miranda <andre@galgo.tech> * Move function validTransitionAndEnd to workflow_validator.go Signed-off-by: André R. de Miranda <andre@galgo.tech> --------- Signed-off-by: André R. de Miranda <andre@galgo.tech>
1 parent d76e8d0 commit 6a4e16c

33 files changed

+1722
-1016
lines changed

model/callback_state_test.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,9 @@ func TestCallbackStateStructLevelValidation(t *testing.T) {
3535
BaseState: BaseState{
3636
Name: "callbackTest",
3737
Type: StateTypeCallback,
38+
End: &End{
39+
Terminate: true,
40+
},
3841
},
3942
CallbackState: &CallbackState{
4043
Action: Action{

model/delay_state_test.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,9 @@ func TestDelayStateStructLevelValidation(t *testing.T) {
3535
BaseState: BaseState{
3636
Name: "1",
3737
Type: "delay",
38+
End: &End{
39+
Terminate: true,
40+
},
3841
},
3942
DelayState: &DelayState{
4043
TimeDelay: "PT5S",

model/event.go

Lines changed: 0 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,6 @@ package model
1616

1717
import (
1818
"encoding/json"
19-
"reflect"
20-
21-
val "github.com/serverlessworkflow/sdk-go/v2/validator"
22-
23-
validator "github.com/go-playground/validator/v10"
2419
)
2520

2621
// EventKind defines this event as either `consumed` or `produced`
@@ -34,18 +29,6 @@ const (
3429
EventKindProduced EventKind = "produced"
3530
)
3631

37-
func init() {
38-
val.GetValidator().RegisterStructValidation(EventStructLevelValidation, Event{})
39-
}
40-
41-
// EventStructLevelValidation custom validator for event kind consumed
42-
func EventStructLevelValidation(structLevel validator.StructLevel) {
43-
event := structLevel.Current().Interface().(Event)
44-
if event.Kind == EventKindConsumed && len(event.Type) == 0 {
45-
structLevel.ReportError(reflect.ValueOf(event.Type), "Type", "type", "reqtypeconsumed", "")
46-
}
47-
}
48-
4932
// Event used to define events and their correlations
5033
type Event struct {
5134
Common `json:",inline"`

model/event_test.go

Lines changed: 0 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -19,54 +19,8 @@ import (
1919
"testing"
2020

2121
"github.com/stretchr/testify/assert"
22-
23-
val "github.com/serverlessworkflow/sdk-go/v2/validator"
2422
)
2523

26-
func TestEventRefStructLevelValidation(t *testing.T) {
27-
type testCase struct {
28-
name string
29-
eventRef EventRef
30-
err string
31-
}
32-
33-
testCases := []testCase{
34-
{
35-
name: "valid resultEventTimeout",
36-
eventRef: EventRef{
37-
TriggerEventRef: "example valid",
38-
ResultEventRef: "example valid",
39-
ResultEventTimeout: "PT1H",
40-
Invoke: InvokeKindSync,
41-
},
42-
err: ``,
43-
},
44-
{
45-
name: "invalid resultEventTimeout",
46-
eventRef: EventRef{
47-
TriggerEventRef: "example invalid",
48-
ResultEventRef: "example invalid red",
49-
ResultEventTimeout: "10hs",
50-
Invoke: InvokeKindSync,
51-
},
52-
err: `Key: 'EventRef.ResultEventTimeout' Error:Field validation for 'ResultEventTimeout' failed on the 'iso8601duration' tag`,
53-
},
54-
}
55-
56-
for _, tc := range testCases {
57-
t.Run(tc.name, func(t *testing.T) {
58-
err := val.GetValidator().Struct(tc.eventRef)
59-
60-
if tc.err != "" {
61-
assert.Error(t, err)
62-
assert.Regexp(t, tc.err, err)
63-
return
64-
}
65-
assert.NoError(t, err)
66-
})
67-
}
68-
}
69-
7024
func TestEventRefUnmarshalJSON(t *testing.T) {
7125
type testCase struct {
7226
desp string

model/event_validator.go

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
// Copyright 2021 The Serverless Workflow Specification Authors
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
package model
16+
17+
import (
18+
"reflect"
19+
20+
validator "github.com/go-playground/validator/v10"
21+
val "github.com/serverlessworkflow/sdk-go/v2/validator"
22+
)
23+
24+
func init() {
25+
val.GetValidator().RegisterStructValidation(eventStructLevelValidation, Event{})
26+
}
27+
28+
// eventStructLevelValidation custom validator for event kind consumed
29+
func eventStructLevelValidation(structLevel validator.StructLevel) {
30+
event := structLevel.Current().Interface().(Event)
31+
if event.Kind == EventKindConsumed && len(event.Type) == 0 {
32+
structLevel.ReportError(reflect.ValueOf(event.Type), "Type", "type", "reqtypeconsumed", "")
33+
}
34+
}

model/event_validator_test.go

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
// Copyright 2021 The Serverless Workflow Specification Authors
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
package model
16+
17+
import (
18+
"testing"
19+
20+
val "github.com/serverlessworkflow/sdk-go/v2/validator"
21+
"github.com/stretchr/testify/assert"
22+
)
23+
24+
func TestEventRefStructLevelValidation(t *testing.T) {
25+
type testCase struct {
26+
name string
27+
eventRef EventRef
28+
err string
29+
}
30+
31+
testCases := []testCase{
32+
{
33+
name: "valid resultEventTimeout",
34+
eventRef: EventRef{
35+
TriggerEventRef: "example valid",
36+
ResultEventRef: "example valid",
37+
ResultEventTimeout: "PT1H",
38+
Invoke: InvokeKindSync,
39+
},
40+
err: ``,
41+
},
42+
{
43+
name: "invalid resultEventTimeout",
44+
eventRef: EventRef{
45+
TriggerEventRef: "example invalid",
46+
ResultEventRef: "example invalid red",
47+
ResultEventTimeout: "10hs",
48+
Invoke: InvokeKindSync,
49+
},
50+
err: `Key: 'EventRef.ResultEventTimeout' Error:Field validation for 'ResultEventTimeout' failed on the 'iso8601duration' tag`,
51+
},
52+
}
53+
54+
for _, tc := range testCases {
55+
t.Run(tc.name, func(t *testing.T) {
56+
err := val.GetValidator().Struct(tc.eventRef)
57+
58+
if tc.err != "" {
59+
assert.Error(t, err)
60+
assert.Regexp(t, tc.err, err)
61+
return
62+
}
63+
assert.NoError(t, err)
64+
})
65+
}
66+
}

model/foreach_state.go

Lines changed: 0 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -15,22 +15,12 @@
1515
package model
1616

1717
import (
18-
"context"
1918
"encoding/json"
2019
"fmt"
21-
"reflect"
22-
"strconv"
2320

24-
validator "github.com/go-playground/validator/v10"
2521
"k8s.io/apimachinery/pkg/util/intstr"
26-
27-
val "github.com/serverlessworkflow/sdk-go/v2/validator"
2822
)
2923

30-
func init() {
31-
val.GetValidator().RegisterStructValidationCtx(ForEachStateStructLevelValidation, ForEachState{})
32-
}
33-
3424
// ForEachModeType Specifies how iterations are to be performed (sequentially or in parallel)
3525
type ForEachModeType string
3626

@@ -86,36 +76,6 @@ func (f *ForEachState) UnmarshalJSON(data []byte) error {
8676
return nil
8777
}
8878

89-
// ForEachStateStructLevelValidation custom validator for ForEachState
90-
func ForEachStateStructLevelValidation(_ context.Context, structLevel validator.StructLevel) {
91-
stateObj := structLevel.Current().Interface().(ForEachState)
92-
93-
if stateObj.Mode != ForEachModeTypeParallel {
94-
return
95-
}
96-
97-
if stateObj.BatchSize == nil {
98-
return
99-
}
100-
101-
switch stateObj.BatchSize.Type {
102-
case intstr.Int:
103-
if stateObj.BatchSize.IntVal <= 0 {
104-
structLevel.ReportError(reflect.ValueOf(stateObj.BatchSize), "BatchSize", "batchSize", "gt0", "")
105-
}
106-
case intstr.String:
107-
v, err := strconv.Atoi(stateObj.BatchSize.StrVal)
108-
if err != nil {
109-
structLevel.ReportError(reflect.ValueOf(stateObj.BatchSize), "BatchSize", "batchSize", "gt0", err.Error())
110-
return
111-
}
112-
113-
if v <= 0 {
114-
structLevel.ReportError(reflect.ValueOf(stateObj.BatchSize), "BatchSize", "batchSize", "gt0", "")
115-
}
116-
}
117-
}
118-
11979
// ForEachStateTimeout defines timeout settings for foreach state
12080
type ForEachStateTimeout struct {
12181
StateExecTimeout *StateExecTimeout `json:"stateExecTimeout,omitempty"`

0 commit comments

Comments
 (0)