-
Notifications
You must be signed in to change notification settings - Fork 0
/
mario_test.go
163 lines (147 loc) · 3.63 KB
/
mario_test.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
package fsm_test
import (
"context"
"testing"
"github.com/andygeiss/fsm"
)
const (
EventGotFeather = iota
EventGotFireFlower
EventGotMushroom
)
const (
StateMarioCape = iota
StateMarioFire
StateMarioSmall
StateMarioSuper
StateMarioUndefined
)
type config struct {
event chan int
stateMario int
}
func capeMario(ctx context.Context, cfg *config) fsm.StateFn[*config] {
cfg.stateMario = StateMarioCape
select {
case event := <-cfg.event:
switch event {
case EventGotFireFlower:
return fireMario(ctx, cfg)
}
case <-ctx.Done():
return nil
}
return nil
}
func fireMario(ctx context.Context, cfg *config) fsm.StateFn[*config] {
cfg.stateMario = StateMarioFire
select {
case event := <-cfg.event:
switch event {
case EventGotFeather:
return capeMario(ctx, cfg)
}
case <-ctx.Done():
return nil
}
return nil
}
func smallMario(ctx context.Context, cfg *config) fsm.StateFn[*config] {
cfg.stateMario = StateMarioSmall
select {
case event := <-cfg.event:
switch event {
case EventGotFeather:
return capeMario(ctx, cfg)
case EventGotFireFlower:
return fireMario(ctx, cfg)
case EventGotMushroom:
return superMario(ctx, cfg)
}
case <-ctx.Done():
return nil
}
return nil
}
func superMario(ctx context.Context, cfg *config) fsm.StateFn[*config] {
cfg.stateMario = StateMarioSuper
select {
case event := <-cfg.event:
switch event {
case EventGotFeather:
return capeMario(ctx, cfg)
case EventGotFireFlower:
return fireMario(ctx, cfg)
}
case <-ctx.Done():
return nil
}
return nil
}
func TestMario(t *testing.T) {
testcases := []struct {
desc string
startFn fsm.StateFn[*config]
startState int
event int
targetState int
}{
{desc: "Given smallMario When EventGotMushroom Should Be StateMarioSuper",
startFn: smallMario,
startState: StateMarioUndefined,
event: EventGotMushroom,
targetState: StateMarioSuper,
},
{desc: "Given smallMario When EventGotFeather Should Be StateMarioCape",
startFn: smallMario,
startState: StateMarioUndefined,
event: EventGotFeather,
targetState: StateMarioCape,
},
{desc: "Given smallMario When EventGotFireFlower Should Be StateMarioFire",
startFn: smallMario,
startState: StateMarioUndefined,
event: EventGotFireFlower,
targetState: StateMarioFire,
},
{desc: "Given superMario When EventGotFeather Should Be StateMarioCape",
startFn: superMario,
startState: StateMarioUndefined,
event: EventGotFeather,
targetState: StateMarioCape,
},
{desc: "Given superMario When EventGotFireFlower Should Be StateMarioFire",
startFn: superMario,
startState: StateMarioUndefined,
event: EventGotFireFlower,
targetState: StateMarioFire,
},
{desc: "Given fireMario When EventGotFeather Should Be StateMarioCape",
startFn: fireMario,
startState: StateMarioUndefined,
event: EventGotFeather,
targetState: StateMarioCape,
},
{desc: "Given capeMario When EventGotFireFlower Should Be StateMarioFire",
startFn: capeMario,
startState: StateMarioUndefined,
event: EventGotFireFlower,
targetState: StateMarioFire,
},
}
for _, testcase := range testcases {
t.Run(testcase.desc, func(t *testing.T) {
ctx, cancel := setup()
defer cancel()
cfg := &config{event: make(chan int), stateMario: testcase.startState}
go fsm.Run(testcase.startFn, ctx, cfg)
go func() { cfg.event <- testcase.event }()
select {
case <-ctx.Done():
}
if cfg.stateMario != testcase.targetState {
t.Errorf("stateMario should be %d, but got %d", testcase.targetState, cfg.stateMario)
}
})
}
}