Skip to content

Commit 250b10b

Browse files
committed
Merge branch 'master' into feat/statewithargs
2 parents 4eaa7d4 + 8279b62 commit 250b10b

14 files changed

Lines changed: 526 additions & 129 deletions

.github/workflows/test.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ jobs:
44
test:
55
strategy:
66
matrix:
7-
go-version: [1.21.x, 1.22.x]
7+
go-version: [1.24.x, 1.25.x]
88
platform: [ubuntu-latest, macos-latest, windows-latest]
99
runs-on: ${{ matrix.platform }}
1010
steps:

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -221,7 +221,7 @@ This can then be rendered by tools that support the DOT graph language, such as
221221

222222
This is the complete Phone Call graph as builded in `example_test.go`.
223223

224-
![Phone Call graph](assets/phone-graph.png?raw=true "Phone Call complete DOT")
224+
![Phone Call graph](assets/phone-graph.svg?raw=true "Phone Call complete DOT")
225225

226226
## Project Goals
227227

actions_test.go

Lines changed: 130 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,130 @@
1+
package stateless
2+
3+
import (
4+
"context"
5+
"testing"
6+
)
7+
8+
func TestStateMachine_Fire_IgnoredTriggerMustBeIgnoredInSubstate(t *testing.T) {
9+
sm := NewStateMachine(stateB)
10+
sm.Configure(stateA).
11+
Permit(triggerX, stateC)
12+
13+
sm.Configure(stateB).
14+
SubstateOf(stateA).
15+
Ignore(triggerX)
16+
17+
sm.Fire(triggerX)
18+
19+
if got := sm.MustState(); got != stateB {
20+
t.Errorf("sm.MustState() = %v, want %v", got, stateB)
21+
}
22+
}
23+
24+
func TestStateMachine_Fire_IgnoreIfTrue_TriggerMustBeIgnored(t *testing.T) {
25+
sm := NewStateMachine(stateB)
26+
sm.Configure(stateA).
27+
Permit(triggerX, stateC)
28+
29+
sm.Configure(stateB).
30+
SubstateOf(stateA).
31+
Ignore(triggerX, func(_ context.Context, _ ...any) bool {
32+
return true
33+
})
34+
35+
sm.Fire(triggerX)
36+
37+
if got := sm.MustState(); got != stateB {
38+
t.Errorf("sm.MustState() = %v, want %v", got, stateB)
39+
}
40+
}
41+
42+
func TestStateMachine_Fire_IgnoreIfFalse_TriggerMustNotBeIgnored(t *testing.T) {
43+
sm := NewStateMachine(stateB)
44+
sm.Configure(stateA).
45+
Permit(triggerX, stateC)
46+
47+
sm.Configure(stateB).
48+
SubstateOf(stateA).
49+
Ignore(triggerX, func(_ context.Context, _ ...any) bool {
50+
return false
51+
})
52+
53+
sm.Fire(triggerX)
54+
55+
if got := sm.MustState(); got != stateC {
56+
t.Errorf("sm.MustState() = %v, want %v", got, stateC)
57+
}
58+
}
59+
60+
func TestStateMachine_Fire_SuperStateShouldNotExitOnSubStateTransition(t *testing.T) {
61+
sm := NewStateMachine(stateA)
62+
record := []string{}
63+
64+
sm.Configure(stateA).
65+
OnEntry(func(_ context.Context, _ ...any) error {
66+
record = append(record, "Entered state A")
67+
return nil
68+
}).
69+
OnExit(func(_ context.Context, _ ...any) error {
70+
record = append(record, "Exited state A")
71+
return nil
72+
}).
73+
Permit(triggerX, stateB)
74+
75+
sm.Configure(stateB). // Our super state
76+
InitialTransition(stateC).
77+
OnEntry(func(_ context.Context, _ ...any) error {
78+
record = append(record, "Entered super state B")
79+
return nil
80+
}).
81+
OnExit(func(_ context.Context, _ ...any) error {
82+
record = append(record, "Exited super state B")
83+
return nil
84+
})
85+
86+
sm.Configure(stateC). // Our first sub state
87+
SubstateOf(stateB).
88+
OnEntry(func(_ context.Context, _ ...any) error {
89+
record = append(record, "Entered sub state C")
90+
return nil
91+
}).
92+
OnExit(func(_ context.Context, _ ...any) error {
93+
record = append(record, "Exited sub state C")
94+
return nil
95+
}).
96+
Permit(triggerY, stateD)
97+
98+
sm.Configure(stateD). // Our second sub state
99+
SubstateOf(stateB).
100+
OnEntry(func(_ context.Context, _ ...any) error {
101+
record = append(record, "Entered sub state D")
102+
return nil
103+
}).
104+
OnExit(func(_ context.Context, _ ...any) error {
105+
record = append(record, "Exited sub state D")
106+
return nil
107+
})
108+
109+
sm.Fire(triggerX)
110+
sm.Fire(triggerY)
111+
112+
expected := []string{
113+
"Exited state A",
114+
"Entered super state B",
115+
"Entered sub state C",
116+
"Exited sub state C",
117+
"Entered sub state D",
118+
}
119+
120+
if len(record) != len(expected) {
121+
t.Errorf("record length = %v, want %v", len(record), len(expected))
122+
return
123+
}
124+
125+
for i, v := range expected {
126+
if record[i] != v {
127+
t.Errorf("record[%d] = %v, want %v", i, record[i], v)
128+
}
129+
}
130+
}

assets/phone-graph.png

-63.4 KB
Binary file not shown.

assets/phone-graph.svg

Lines changed: 115 additions & 0 deletions
Loading

go.mod

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
module github.com/qmuntal/stateless
22

3-
go 1.19
3+
go 1.24

0 commit comments

Comments
 (0)