Skip to content

Commit 724834a

Browse files
committed
states - unsupported AST kind *ast.InterfaceType
Fixes #144 Signed-off-by: Spolti <[email protected]>
1 parent 8994e2b commit 724834a

23 files changed

+993
-516
lines changed

model/action.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ type Action struct {
3333
// References a sub-workflow to be executed
3434
SubFlowRef *WorkflowRef `json:"subFlowRef,omitempty"`
3535
// Sleep Defines time period workflow execution should sleep before / after function execution
36-
Sleep Sleep `json:"sleep,omitempty"`
36+
Sleep *Sleep `json:"sleep,omitempty"`
3737
// RetryRef References a defined workflow retry definition. If not defined the default retry policy is assumed
3838
RetryRef string `json:"retryRef,omitempty"`
3939
// List of unique references to defined workflow errors for which the action should not be retried. Used only when `autoRetries` is set to `true`

model/callback_state.go

Lines changed: 22 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -14,22 +14,37 @@
1414

1515
package model
1616

17+
import (
18+
"encoding/json"
19+
)
20+
1721
// CallbackState executes a function and waits for callback event that indicates
1822
// completion of the task.
1923
type CallbackState struct {
20-
BaseState
2124
// Defines the action to be executed
2225
Action Action `json:"action" validate:"required"`
2326
// References a unique callback event name in the defined workflow events
2427
EventRef string `json:"eventRef" validate:"required"`
25-
// Time period to wait for incoming events (ISO 8601 format)
26-
Timeouts *CallbackStateTimeout `json:"timeouts" validate:"omitempty"`
27-
// Event data filter
28-
EventDataFilter EventDataFilter `json:"eventDataFilter,omitempty"`
28+
// Time period to wait for incoming events (ISO 8601 format) TODO test Marshal
29+
Timeouts *CallbackStateTimeout `json:"timeouts,omitempty"`
30+
// Event data filter TODO test it
31+
EventDataFilter *EventDataFilter `json:"eventDataFilter,omitempty"`
2932
}
3033

31-
func (in *CallbackState) DeepCopyState() State {
32-
return in
34+
func (a *CallbackState) MarshalJSON() ([]byte, error) {
35+
if a == nil {
36+
return []byte("null"), nil
37+
}
38+
type Alias CallbackState
39+
custom, err := json.Marshal(&struct {
40+
*Alias
41+
// TODO verify if only th e alias is enough
42+
Timeouts *CallbackStateTimeout `json:"timeouts,omitempty"`
43+
}{
44+
Alias: (*Alias)(a),
45+
Timeouts: a.Timeouts,
46+
})
47+
return custom, err
3348
}
3449

3550
// CallbackStateTimeout defines timeout settings for callback state

model/callback_state_test.go

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
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+
"testing"
19+
20+
"github.com/stretchr/testify/assert"
21+
22+
val "github.com/serverlessworkflow/sdk-go/v2/validator"
23+
)
24+
25+
func TestCallbackStateStructLevelValidation(t *testing.T) {
26+
type testCase struct {
27+
desp string
28+
callbackStateObj State
29+
err string
30+
}
31+
testCases := []testCase{
32+
{
33+
desp: "normal",
34+
callbackStateObj: State{
35+
BaseState: BaseState{
36+
Name: "callbackTest",
37+
Type: StateTypeCallback,
38+
},
39+
CallbackState: &CallbackState{
40+
Action: Action{
41+
ID: "1",
42+
Name: "action1",
43+
},
44+
EventRef: "refExample",
45+
},
46+
},
47+
err: ``,
48+
},
49+
{
50+
desp: "missing required EventRef",
51+
callbackStateObj: State{
52+
BaseState: BaseState{
53+
Name: "callbackTest",
54+
Type: StateTypeCallback,
55+
},
56+
CallbackState: &CallbackState{
57+
Action: Action{
58+
ID: "1",
59+
Name: "action1",
60+
},
61+
},
62+
},
63+
err: `Key: 'State.CallbackState.EventRef' Error:Field validation for 'EventRef' failed on the 'required' tag`,
64+
},
65+
// TODO need to register custom types
66+
//{
67+
// desp: "missing required Action",
68+
// callbackStateObj: State{
69+
// BaseState: BaseState{
70+
// Name: "callbackTest",
71+
// Type: StateTypeCallback,
72+
// },
73+
// CallbackState: &CallbackState{
74+
// EventRef: "refExample",
75+
// },
76+
// },
77+
// err: `Key: 'State.CallbackState.Action' Error:Field validation for 'Action' failed on the 'required' tag`,
78+
//},
79+
}
80+
for _, tc := range testCases {
81+
t.Run(tc.desp, func(t *testing.T) {
82+
err := val.GetValidator().Struct(&tc.callbackStateObj)
83+
84+
if tc.err != "" {
85+
assert.Error(t, err)
86+
assert.Regexp(t, tc.err, err)
87+
return
88+
}
89+
90+
assert.NoError(t, err)
91+
})
92+
}
93+
}

model/delay_state.go

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,8 @@ package model
1616

1717
// DelayState Causes the workflow execution to delay for a specified duration
1818
type DelayState struct {
19-
BaseState
2019
// Amount of time (ISO 8601 format) to delay
2120
TimeDelay string `json:"timeDelay" validate:"required,iso8601duration"`
2221
}
2322

24-
func (in *DelayState) DeepCopyState() State {
25-
return in
26-
}
23+
// TODO add marshal tests

model/delay_state_test.go

Lines changed: 15 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -25,42 +25,48 @@ import (
2525
func TestDelayStateStructLevelValidation(t *testing.T) {
2626
type testCase struct {
2727
desp string
28-
delayStateObj DelayState
28+
delayStateObj State
2929
err string
3030
}
3131
testCases := []testCase{
3232
{
3333
desp: "normal",
34-
delayStateObj: DelayState{
34+
delayStateObj: State{
3535
BaseState: BaseState{
3636
Name: "1",
3737
Type: "delay",
3838
},
39-
TimeDelay: "PT5S",
39+
DelayState: &DelayState{
40+
TimeDelay: "PT5S",
41+
},
4042
},
4143
err: ``,
4244
},
4345
{
4446
desp: "missing required timeDelay",
45-
delayStateObj: DelayState{
47+
delayStateObj: State{
4648
BaseState: BaseState{
4749
Name: "1",
4850
Type: "delay",
4951
},
50-
TimeDelay: "",
52+
DelayState: &DelayState{
53+
TimeDelay: "",
54+
},
5155
},
52-
err: `Key: 'DelayState.TimeDelay' Error:Field validation for 'TimeDelay' failed on the 'required' tag`,
56+
err: `Key: 'State.DelayState.TimeDelay' Error:Field validation for 'TimeDelay' failed on the 'required' tag`,
5357
},
5458
{
5559
desp: "invalid timeDelay duration",
56-
delayStateObj: DelayState{
60+
delayStateObj: State{
5761
BaseState: BaseState{
5862
Name: "1",
5963
Type: "delay",
6064
},
61-
TimeDelay: "P5S",
65+
DelayState: &DelayState{
66+
TimeDelay: "P5S",
67+
},
6268
},
63-
err: `Key: 'DelayState.TimeDelay' Error:Field validation for 'TimeDelay' failed on the 'iso8601duration' tag`,
69+
err: `Key: 'State.DelayState.TimeDelay' Error:Field validation for 'TimeDelay' failed on the 'iso8601duration' tag`,
6470
},
6571
}
6672
for _, tc := range testCases {

model/event_state.go

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ import (
2222
// EventState used to wait for events from event sources, then consumes them and invoke one or more actions to run in sequence or parallel
2323
type EventState struct {
2424
// TODO: EventState doesn't have usedForCompensation field.
25-
BaseState
25+
//BaseState
2626

2727
// If true consuming one of the defined events causes its associated actions to be performed.
2828
// If false all the defined events must be consumed in order for actions to be performed
@@ -34,8 +34,20 @@ type EventState struct {
3434
Timeouts *EventStateTimeout `json:"timeouts,omitempty"`
3535
}
3636

37-
func (e *EventState) DeepCopyState() State {
38-
return e
37+
func (a *EventState) MarshalJSON() ([]byte, error) {
38+
if a == nil {
39+
return []byte("null"), nil
40+
}
41+
type Alias EventState
42+
custom, err := json.Marshal(&struct {
43+
*Alias
44+
// TODO verify if only th e alias is enough
45+
Timeouts *EventStateTimeout `json:"timeouts,omitempty"`
46+
}{
47+
Alias: (*Alias)(a),
48+
Timeouts: a.Timeouts,
49+
})
50+
return custom, err
3951
}
4052

4153
type eventStateForUnmarshal EventState

model/event_state_test.go

Lines changed: 32 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -25,55 +25,59 @@ func TestEventStateUnmarshalJSON(t *testing.T) {
2525
type testCase struct {
2626
desp string
2727
data string
28-
expect EventState
28+
expect State
2929
err string
3030
}
3131
testCases := []testCase{
3232
{
3333
desp: "all fields set",
34-
data: `{"name": "1", "Type": "event", "exclusive": false, "onEvents": [{"eventRefs": ["E1", "E2"], "actionMode": "parallel"}], "timeouts": {"actionExecTimeout": "PT5M", "eventTimeout": "PT5M", "stateExecTimeout": "PT5M"}}`,
35-
expect: EventState{
34+
data: `{"name": "1", "type": "event", "exclusive": false, "onEvents": [{"eventRefs": ["E1", "E2"], "actionMode": "parallel"}], "timeouts": {"actionExecTimeout": "PT5M", "eventTimeout": "PT5M", "stateExecTimeout": "PT5M"}}`,
35+
expect: State{
3636
BaseState: BaseState{
3737
Name: "1",
3838
Type: StateTypeEvent,
3939
},
40-
Exclusive: false,
41-
OnEvents: []OnEvents{
42-
{
43-
EventRefs: []string{"E1", "E2"},
44-
ActionMode: "parallel",
40+
EventState: &EventState{
41+
Exclusive: false,
42+
OnEvents: []OnEvents{
43+
{
44+
EventRefs: []string{"E1", "E2"},
45+
ActionMode: "parallel",
46+
},
4547
},
46-
},
47-
Timeouts: &EventStateTimeout{
48-
EventTimeout: "PT5M",
49-
ActionExecTimeout: "PT5M",
50-
StateExecTimeout: &StateExecTimeout{
51-
Total: "PT5M",
48+
Timeouts: &EventStateTimeout{
49+
EventTimeout: "PT5M",
50+
ActionExecTimeout: "PT5M",
51+
StateExecTimeout: &StateExecTimeout{
52+
Total: "PT5M",
53+
},
5254
},
5355
},
5456
},
5557
err: ``,
5658
},
5759
{
5860
desp: "default exclusive",
59-
data: `{"name": "1", "Type": "event", "onEvents": [{"eventRefs": ["E1", "E2"], "actionMode": "parallel"}], "timeouts": {"actionExecTimeout": "PT5M", "eventTimeout": "PT5M", "stateExecTimeout": "PT5M"}}`,
60-
expect: EventState{
61+
data: `{"name": "1", "type": "event", "onEvents": [{"eventRefs": ["E1", "E2"], "actionMode": "parallel"}], "timeouts": {"actionExecTimeout": "PT5M", "eventTimeout": "PT5M", "stateExecTimeout": "PT5M"}}`,
62+
expect: State{
6163
BaseState: BaseState{
6264
Name: "1",
6365
Type: StateTypeEvent,
6466
},
65-
Exclusive: true,
66-
OnEvents: []OnEvents{
67-
{
68-
EventRefs: []string{"E1", "E2"},
69-
ActionMode: "parallel",
67+
EventState: &EventState{
68+
Exclusive: true,
69+
OnEvents: []OnEvents{
70+
{
71+
EventRefs: []string{"E1", "E2"},
72+
ActionMode: "parallel",
73+
},
7074
},
71-
},
72-
Timeouts: &EventStateTimeout{
73-
EventTimeout: "PT5M",
74-
ActionExecTimeout: "PT5M",
75-
StateExecTimeout: &StateExecTimeout{
76-
Total: "PT5M",
75+
Timeouts: &EventStateTimeout{
76+
EventTimeout: "PT5M",
77+
ActionExecTimeout: "PT5M",
78+
StateExecTimeout: &StateExecTimeout{
79+
Total: "PT5M",
80+
},
7781
},
7882
},
7983
},
@@ -82,7 +86,7 @@ func TestEventStateUnmarshalJSON(t *testing.T) {
8286
}
8387
for _, tc := range testCases {
8488
t.Run(tc.desp, func(t *testing.T) {
85-
v := EventState{}
89+
v := State{}
8690
err := json.Unmarshal([]byte(tc.data), &v)
8791

8892
if tc.err != "" {

model/foreach_state.go

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ const (
4343

4444
// ForEachState used to execute actions for each element of a data set.
4545
type ForEachState struct {
46-
BaseState
46+
//BaseState
4747
// Workflow expression selecting an array element of the states data
4848
InputCollection string `json:"inputCollection" validate:"required"`
4949
// Workflow expression specifying an array element of the states data to add the results of each iteration
@@ -54,15 +54,27 @@ type ForEachState struct {
5454
BatchSize *intstr.IntOrString `json:"batchSize,omitempty"`
5555
// Actions to be executed for each of the elements of inputCollection
5656
Actions []Action `json:"actions,omitempty" validate:"required,min=1,dive"`
57-
// State specific timeout
57+
// State specific timeout TODO test Marshal
5858
Timeouts *ForEachStateTimeout `json:"timeouts,omitempty"`
5959
// Mode Specifies how iterations are to be performed (sequentially or in parallel)
6060
// Defaults to parallel
6161
Mode ForEachModeType `json:"mode,omitempty"`
6262
}
6363

64-
func (f *ForEachState) DeepCopyState() State {
65-
return f
64+
func (a *ForEachState) MarshalJSON() ([]byte, error) {
65+
if a == nil {
66+
return []byte("null"), nil
67+
}
68+
type Alias ForEachState
69+
custom, err := json.Marshal(&struct {
70+
*Alias
71+
// TODO verify if only th e alias is enough
72+
Timeouts *ForEachStateTimeout `json:"timeouts,omitempty"`
73+
}{
74+
Alias: (*Alias)(a),
75+
Timeouts: a.Timeouts,
76+
})
77+
return custom, err
6678
}
6779

6880
type forEachStateForUnmarshal ForEachState

0 commit comments

Comments
 (0)