Skip to content

Commit 4afc5f3

Browse files
author
André R. de Miranda
authored
Validate the refs exists (#164)
* Add validator with context to validate the refs (functions, events, retries, etc) exists Signed-off-by: André R. de Miranda <andre@galgo.tech> * Valid errors exist and change unique_struct to unique Signed-off-by: André R. de Miranda <andre@galgo.tech> * Fix lint Signed-off-by: André R. de Miranda <andre@galgo.tech> * Add transition and compensation validations. Refactor state exists Signed-off-by: André R. de Miranda <andre@galgo.tech> * Json ignore field Signed-off-by: André R. de Miranda <andre@galgo.tech> * Fix tests Signed-off-by: André R. de Miranda <andre@galgo.tech> * Add validations: OnEvent.EventRefs, EventCondition.EventRef, and FunctionType Signed-off-by: André R. de Miranda <andre@galgo.tech> * Fix tests Signed-off-by: André R. de Miranda <andre@galgo.tech> * Replace oneof to oneofkind, and improve the error message Signed-off-by: André R. de Miranda <andre@galgo.tech> * Validation refactoring for each struct to have its test case. Revision suggestions Signed-off-by: André R. de Miranda <andre@galgo.tech> * Add validation oneofkind validation auth struct Signed-off-by: André R. de Miranda <andre@galgo.tech> * Add new tests and improve error description Signed-off-by: André R. de Miranda <andre@galgo.tech> * Add new unit tests, refactor intstr validator, and add new validation description Signed-off-by: André R. de Miranda <andre@galgo.tech> * Remove reflection from validation Signed-off-by: André R. de Miranda <andre@galgo.tech> * Remove commented code Signed-off-by: André R. de Miranda <andre@galgo.tech> --------- Signed-off-by: André R. de Miranda <andre@galgo.tech>
1 parent 5110906 commit 4afc5f3

File tree

70 files changed

+3645
-1625
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

70 files changed

+3645
-1625
lines changed

hack/deepcopy-gen.sh

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,5 +44,6 @@ if [ "${GENS}" = "all" ] || grep -qw "deepcopy" <<<"${GENS}"; then
4444
"${GOPATH}/bin/deepcopy-gen" -v 1 \
4545
--input-dirs ./model -O zz_generated.deepcopy \
4646
--go-header-file "${SCRIPT_ROOT}/hack/boilerplate.txt" \
47+
--output-base ./
4748
"$@"
4849
fi

model/action.go

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@
1414

1515
package model
1616

17+
import "github.com/serverlessworkflow/sdk-go/v2/util"
18+
1719
// Action specify invocations of services or other workflows during workflow execution.
1820
type Action struct {
1921
// Defines Unique action identifier.
@@ -61,7 +63,7 @@ type actionUnmarshal Action
6163
// UnmarshalJSON implements json.Unmarshaler
6264
func (a *Action) UnmarshalJSON(data []byte) error {
6365
a.ApplyDefault()
64-
return unmarshalObject("action", data, (*actionUnmarshal)(a))
66+
return util.UnmarshalObject("action", data, (*actionUnmarshal)(a))
6567
}
6668

6769
// ApplyDefault set the default values for Action
@@ -93,7 +95,7 @@ type functionRefUnmarshal FunctionRef
9395
// UnmarshalJSON implements json.Unmarshaler
9496
func (f *FunctionRef) UnmarshalJSON(data []byte) error {
9597
f.ApplyDefault()
96-
return unmarshalPrimitiveOrObject("functionRef", data, &f.RefName, (*functionRefUnmarshal)(f))
98+
return util.UnmarshalPrimitiveOrObject("functionRef", data, &f.RefName, (*functionRefUnmarshal)(f))
9799
}
98100

99101
// ApplyDefault set the default values for Function Ref
@@ -117,5 +119,5 @@ type sleepUnmarshal Sleep
117119

118120
// UnmarshalJSON implements json.Unmarshaler
119121
func (s *Sleep) UnmarshalJSON(data []byte) error {
120-
return unmarshalObject("sleep", data, (*sleepUnmarshal)(s))
122+
return util.UnmarshalObject("sleep", data, (*sleepUnmarshal)(s))
121123
}

model/action_data_filter.go

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@
1414

1515
package model
1616

17+
import "github.com/serverlessworkflow/sdk-go/v2/util"
18+
1719
// ActionDataFilter used to filter action data results.
1820
// +optional
1921
// +optional
@@ -40,7 +42,7 @@ type actionDataFilterUnmarshal ActionDataFilter
4042
// UnmarshalJSON implements json.Unmarshaler
4143
func (a *ActionDataFilter) UnmarshalJSON(data []byte) error {
4244
a.ApplyDefault()
43-
return unmarshalObject("actionDataFilter", data, (*actionDataFilterUnmarshal)(a))
45+
return util.UnmarshalObject("actionDataFilter", data, (*actionDataFilterUnmarshal)(a))
4446
}
4547

4648
// ApplyDefault set the default values for Action Data Filter
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
// Copyright 2022 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 "testing"
18+
19+
func TestActionDataFilterStructLevelValidation(t *testing.T) {
20+
testCases := []ValidationCase{}
21+
StructLevelValidationCtx(t, testCases)
22+
}

model/action_test.go

Lines changed: 0 additions & 73 deletions
Original file line numberDiff line numberDiff line change
@@ -19,81 +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 TestSleepValidate(t *testing.T) {
27-
type testCase struct {
28-
desp string
29-
sleep Sleep
30-
err string
31-
}
32-
testCases := []testCase{
33-
{
34-
desp: "all field empty",
35-
sleep: Sleep{
36-
Before: "",
37-
After: "",
38-
},
39-
err: ``,
40-
},
41-
{
42-
desp: "only before field",
43-
sleep: Sleep{
44-
Before: "PT5M",
45-
After: "",
46-
},
47-
err: ``,
48-
},
49-
{
50-
desp: "only after field",
51-
sleep: Sleep{
52-
Before: "",
53-
After: "PT5M",
54-
},
55-
err: ``,
56-
},
57-
{
58-
desp: "all field",
59-
sleep: Sleep{
60-
Before: "PT5M",
61-
After: "PT5M",
62-
},
63-
err: ``,
64-
},
65-
{
66-
desp: "invalid before value",
67-
sleep: Sleep{
68-
Before: "T5M",
69-
After: "PT5M",
70-
},
71-
err: `Key: 'Sleep.Before' Error:Field validation for 'Before' failed on the 'iso8601duration' tag`,
72-
},
73-
{
74-
desp: "invalid after value",
75-
sleep: Sleep{
76-
Before: "PT5M",
77-
After: "T5M",
78-
},
79-
err: `Key: 'Sleep.After' Error:Field validation for 'After' failed on the 'iso8601duration' tag`,
80-
},
81-
}
82-
for _, tc := range testCases {
83-
t.Run(tc.desp, func(t *testing.T) {
84-
err := val.GetValidator().Struct(tc.sleep)
85-
86-
if tc.err != "" {
87-
assert.Error(t, err)
88-
assert.Regexp(t, tc.err, err)
89-
return
90-
}
91-
92-
assert.NoError(t, err)
93-
})
94-
}
95-
}
96-
9724
func TestFunctionRefUnmarshalJSON(t *testing.T) {
9825
type testCase struct {
9926
desp string

model/action_validator.go

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
// Copyright 2022 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+
validator "github.com/go-playground/validator/v10"
19+
20+
val "github.com/serverlessworkflow/sdk-go/v2/validator"
21+
)
22+
23+
func init() {
24+
val.GetValidator().RegisterStructValidationCtx(ValidationWrap(actionStructLevelValidationCtx), Action{})
25+
val.GetValidator().RegisterStructValidationCtx(ValidationWrap(functionRefStructLevelValidation), FunctionRef{})
26+
}
27+
28+
func actionStructLevelValidationCtx(ctx ValidatorContext, structLevel validator.StructLevel) {
29+
action := structLevel.Current().Interface().(Action)
30+
31+
if action.FunctionRef == nil && action.EventRef == nil && action.SubFlowRef == nil {
32+
structLevel.ReportError(action.FunctionRef, "FunctionRef", "FunctionRef", "required_without", "")
33+
return
34+
}
35+
36+
values := []bool{
37+
action.FunctionRef != nil,
38+
action.EventRef != nil,
39+
action.SubFlowRef != nil,
40+
}
41+
42+
if validationNotExclusiveParamters(values) {
43+
structLevel.ReportError(action.FunctionRef, "FunctionRef", "FunctionRef", val.TagExclusive, "")
44+
structLevel.ReportError(action.EventRef, "EventRef", "EventRef", val.TagExclusive, "")
45+
structLevel.ReportError(action.SubFlowRef, "SubFlowRef", "SubFlowRef", val.TagExclusive, "")
46+
}
47+
48+
if action.RetryRef != "" && !ctx.ExistRetry(action.RetryRef) {
49+
structLevel.ReportError(action.RetryRef, "RetryRef", "RetryRef", val.TagExists, "")
50+
}
51+
}
52+
53+
func functionRefStructLevelValidation(ctx ValidatorContext, structLevel validator.StructLevel) {
54+
functionRef := structLevel.Current().Interface().(FunctionRef)
55+
if !ctx.ExistFunction(functionRef.RefName) {
56+
structLevel.ReportError(functionRef.RefName, "RefName", "RefName", val.TagExists, functionRef.RefName)
57+
}
58+
}

0 commit comments

Comments
 (0)