finite_machine 0.12.1 → 0.13.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (74) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +17 -1
  3. data/README.md +1 -1
  4. data/lib/finite_machine.rb +3 -1
  5. data/lib/finite_machine/choice_merger.rb +2 -2
  6. data/lib/finite_machine/dsl.rb +4 -4
  7. data/lib/finite_machine/message_queue.rb +0 -1
  8. data/lib/finite_machine/state_machine.rb +3 -3
  9. data/lib/finite_machine/two_phase_lock.rb +6 -6
  10. data/lib/finite_machine/version.rb +1 -1
  11. metadata +20 -146
  12. data/Rakefile +0 -12
  13. data/benchmarks/memory_profile.rb +0 -11
  14. data/benchmarks/memory_usage.rb +0 -28
  15. data/examples/atm.rb +0 -45
  16. data/examples/bug_system.rb +0 -145
  17. data/finite_machine.gemspec +0 -30
  18. data/spec/integration/system_spec.rb +0 -93
  19. data/spec/performance/benchmark_spec.rb +0 -54
  20. data/spec/spec_helper.rb +0 -34
  21. data/spec/unit/alias_target_spec.rb +0 -89
  22. data/spec/unit/async_callbacks_spec.rb +0 -28
  23. data/spec/unit/auto_methods_spec.rb +0 -44
  24. data/spec/unit/callable/call_spec.rb +0 -111
  25. data/spec/unit/callbacks_spec.rb +0 -851
  26. data/spec/unit/can_spec.rb +0 -88
  27. data/spec/unit/cancel_callbacks_spec.rb +0 -46
  28. data/spec/unit/choice_spec.rb +0 -295
  29. data/spec/unit/define_spec.rb +0 -55
  30. data/spec/unit/definition_spec.rb +0 -98
  31. data/spec/unit/event_names_spec.rb +0 -15
  32. data/spec/unit/events_map/add_spec.rb +0 -23
  33. data/spec/unit/events_map/choice_transition_spec.rb +0 -25
  34. data/spec/unit/events_map/clear_spec.rb +0 -13
  35. data/spec/unit/events_map/events_spec.rb +0 -16
  36. data/spec/unit/events_map/inspect_spec.rb +0 -22
  37. data/spec/unit/events_map/match_transition_spec.rb +0 -35
  38. data/spec/unit/events_map/move_to_spec.rb +0 -45
  39. data/spec/unit/events_map/states_for_spec.rb +0 -17
  40. data/spec/unit/events_spec.rb +0 -390
  41. data/spec/unit/handlers_spec.rb +0 -120
  42. data/spec/unit/hook_event/any_state_or_event_spec.rb +0 -13
  43. data/spec/unit/hook_event/build_spec.rb +0 -13
  44. data/spec/unit/hook_event/eql_spec.rb +0 -34
  45. data/spec/unit/hook_event/initialize_spec.rb +0 -23
  46. data/spec/unit/hook_event/notify_spec.rb +0 -12
  47. data/spec/unit/hooks/clear_spec.rb +0 -16
  48. data/spec/unit/hooks/find_spec.rb +0 -19
  49. data/spec/unit/hooks/inspect_spec.rb +0 -25
  50. data/spec/unit/hooks/register_spec.rb +0 -17
  51. data/spec/unit/if_unless_spec.rb +0 -314
  52. data/spec/unit/initial_spec.rb +0 -190
  53. data/spec/unit/inspect_spec.rb +0 -22
  54. data/spec/unit/is_spec.rb +0 -49
  55. data/spec/unit/log_transitions_spec.rb +0 -24
  56. data/spec/unit/logger_spec.rb +0 -36
  57. data/spec/unit/message_queue_spec.rb +0 -62
  58. data/spec/unit/new_spec.rb +0 -50
  59. data/spec/unit/respond_to_spec.rb +0 -34
  60. data/spec/unit/state_parser/parse_spec.rb +0 -56
  61. data/spec/unit/states_spec.rb +0 -28
  62. data/spec/unit/subscribers_spec.rb +0 -40
  63. data/spec/unit/target_spec.rb +0 -225
  64. data/spec/unit/terminated_spec.rb +0 -85
  65. data/spec/unit/transition/check_conditions_spec.rb +0 -55
  66. data/spec/unit/transition/inspect_spec.rb +0 -25
  67. data/spec/unit/transition/matches_spec.rb +0 -21
  68. data/spec/unit/transition/states_spec.rb +0 -29
  69. data/spec/unit/transition/to_state_spec.rb +0 -19
  70. data/spec/unit/trigger_spec.rb +0 -18
  71. data/spec/unit/undefined_transition/eql_spec.rb +0 -15
  72. data/tasks/console.rake +0 -11
  73. data/tasks/coverage.rake +0 -11
  74. data/tasks/spec.rake +0 -34
@@ -1,98 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- RSpec.describe FiniteMachine::Definition, 'definition' do
4
-
5
- before do
6
- class Engine < FiniteMachine::Definition
7
- initial :neutral
8
-
9
- event :forward, [:reverse, :neutral] => :one
10
- event :shift, :one => :two
11
- event :shift, :two => :one
12
- event :back, [:neutral, :one] => :reverse
13
-
14
- on_enter :reverse do |event|
15
- target.turn_reverse_lights_on
16
- end
17
-
18
- on_exit :reverse do |event|
19
- target.turn_reverse_lights_off
20
- end
21
-
22
- handle FiniteMachine::InvalidStateError do |exception| end
23
- end
24
- end
25
-
26
- it "creates unique instances" do
27
- engine_a = Engine.new
28
- engine_b = Engine.new
29
- expect(engine_a).not_to be(engine_b)
30
-
31
- expect(engine_a.current).to eq(:neutral)
32
-
33
- engine_a.forward
34
- expect(engine_a.current).to eq(:one)
35
- expect(engine_b.current).to eq(:neutral)
36
- end
37
-
38
- it "allows to create standalone machine" do
39
- stub_const("Car", Class.new do
40
- def turn_reverse_lights_off
41
- @reverse_lights = false
42
- end
43
-
44
- def turn_reverse_lights_on
45
- @reverse_lights = true
46
- end
47
-
48
- def reverse_lights?
49
- @reverse_lights ||= false
50
- end
51
- end)
52
-
53
- car = Car.new
54
- engine = Engine.new(car)
55
- expect(engine.current).to eq(:neutral)
56
-
57
- engine.forward
58
- expect(engine.current).to eq(:one)
59
- expect(car.reverse_lights?).to eq(false)
60
-
61
- engine.back
62
- expect(engine.current).to eq(:reverse)
63
- expect(car.reverse_lights?).to eq(true)
64
- end
65
-
66
- it "supports inheritance of definitions" do
67
- class GenericStateMachine < FiniteMachine::Definition
68
- initial :red
69
-
70
- event :start, :red => :green
71
-
72
- on_enter { |event| target << 'generic' }
73
- end
74
-
75
- class SpecificStateMachine < GenericStateMachine
76
- event :stop, :green => :yellow
77
-
78
- on_enter(:yellow) { |event| target << 'specific' }
79
- end
80
-
81
- called = []
82
- generic_fsm = GenericStateMachine.new(called)
83
- specific_fsm = SpecificStateMachine.new(called)
84
-
85
- expect(generic_fsm.states).to match_array([:none, :red, :green])
86
- expect(specific_fsm.states).to match_array([:none, :red, :green, :yellow])
87
-
88
- expect(specific_fsm.current).to eq(:red)
89
-
90
- specific_fsm.start
91
- expect(specific_fsm.current).to eq(:green)
92
- expect(called).to match_array(['generic'])
93
-
94
- specific_fsm.stop
95
- expect(specific_fsm.current).to eq(:yellow)
96
- expect(called).to match_array(['generic', 'generic', 'specific'])
97
- end
98
- end
@@ -1,15 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- RSpec.describe FiniteMachine, '#events' do
4
- it "retrieves all event names" do
5
- fsm = FiniteMachine.new do
6
- initial :green
7
-
8
- event :start, :red => :green
9
- event :stop, :green => :red
10
- end
11
-
12
- expect(fsm.current).to eql(:green)
13
- expect(fsm.events).to match_array([:init, :start, :stop])
14
- end
15
- end
@@ -1,23 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- RSpec.describe FiniteMachine::EventsMap, '#add' do
4
- it "adds transitions" do
5
- transition = double(:transition)
6
- events_map = described_class.new
7
-
8
- events_map.add(:validated, transition)
9
- expect(events_map[:validated]).to eq([transition])
10
-
11
- events_map.add(:validated, transition)
12
- expect(events_map[:validated]).to eq([transition, transition])
13
- end
14
-
15
- it "allows to map add operations" do
16
- events_map = described_class.new
17
- transition = double(:transition)
18
-
19
- events_map.add(:go, transition).add(:start, transition)
20
-
21
- expect(events_map.size).to eq(2)
22
- end
23
- end
@@ -1,25 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- RSpec.describe FiniteMachine::EventsMap, '#choice_transition?' do
4
- it "checks if transition has many branches" do
5
- transition_a = double(:transition_a, matches?: true)
6
- transition_b = double(:transition_b, matches?: true)
7
-
8
- events_map = described_class.new
9
- events_map.add(:go, transition_a)
10
- events_map.add(:go, transition_b)
11
-
12
- expect(events_map.choice_transition?(:go, :green)).to eq(true)
13
- end
14
-
15
- it "checks that transition has no branches" do
16
- transition_a = double(:transition_a, matches?: false)
17
- transition_b = double(:transition_b, matches?: true)
18
-
19
- events_map = described_class.new
20
- events_map.add(:go, transition_a)
21
- events_map.add(:go, transition_b)
22
-
23
- expect(events_map.choice_transition?(:go, :green)).to eq(false)
24
- end
25
- end
@@ -1,13 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- RSpec.describe FiniteMachine::EventsMap, '#clear' do
4
- it "clears map events" do
5
- event = double(:event)
6
- events_map = described_class.new
7
- events_map.add(:validated, event)
8
- expect(events_map.empty?).to be(false)
9
-
10
- events_map.clear
11
- expect(events_map.empty?).to be(true)
12
- end
13
- end
@@ -1,16 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- RSpec.describe FiniteMachine::EventsMap, '#events' do
4
- it "has no event names" do
5
- events_map = described_class.new
6
- expect(events_map.events).to eq([])
7
- end
8
-
9
- it "returns all event names" do
10
- events_map = described_class.new
11
- transition = double(:transition)
12
- events_map.add(:ready, transition)
13
- events_map.add(:go, transition)
14
- expect(events_map.events).to match_array([:ready, :go])
15
- end
16
- end
@@ -1,22 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- RSpec.describe FiniteMachine::EventsMap, '#inspect' do
4
- it "inspects empty events map" do
5
- events_map = described_class.new
6
- expect(events_map.inspect).to eq("<#FiniteMachine::EventsMap @events_map={}>")
7
- end
8
-
9
- it "inspect events map" do
10
- transition = double(:transition)
11
- events_map = described_class.new
12
- events_map.add(:validated, transition)
13
- expect(events_map.inspect).to eq("<#FiniteMachine::EventsMap @events_map=#{{validated: [transition]}}>")
14
- end
15
-
16
- it "prints events map" do
17
- transition = double(:transition)
18
- events_map = described_class.new
19
- events_map.add(:validated, transition)
20
- expect(events_map.to_s).to eq("#{{validated: [transition]}}")
21
- end
22
- end
@@ -1,35 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- RSpec.describe FiniteMachine::EventsMap, '#match_transition' do
4
- it "matches transition without conditions" do
5
- transition_a = double(:transition_a, matches?: false)
6
- transition_b = double(:transition_b, matches?: true)
7
- events_map = described_class.new
8
-
9
- events_map.add(:a, transition_a)
10
- events_map.add(:a, transition_b)
11
-
12
- expect(events_map.match_transition(:a, :green)).to eq(transition_b)
13
- end
14
-
15
- it "fails to match any transition" do
16
- events_map = described_class.new
17
-
18
- expect(events_map.match_transition(:a, :green)).to eq(nil)
19
- end
20
-
21
- it "matches transition with conditions" do
22
- transition_a = double(:transition_a, matches?: true)
23
- transition_b = double(:transition_b, matches?: true)
24
- events_map = described_class.new
25
-
26
- events_map.add(:a, transition_a)
27
- events_map.add(:a, transition_b)
28
-
29
- allow(transition_a).to receive(:check_conditions).and_return(false)
30
- allow(transition_b).to receive(:check_conditions).and_return(true)
31
-
32
- expect(events_map.match_transition_with(:a, :green, 'Piotr')).to eq(transition_b)
33
- expect(transition_a).to have_received(:check_conditions).with('Piotr')
34
- end
35
- end
@@ -1,45 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- RSpec.describe FiniteMachine::EventsMap, '#move_to' do
4
- it "moves to state by matching individual transition" do
5
- transition_a = double(:transition_a, matches?: false)
6
- transition_b = double(:transition_b, matches?: true)
7
-
8
- events_map = described_class.new
9
- events_map.add(:go, transition_a)
10
- events_map.add(:go, transition_b)
11
-
12
- allow(transition_b).to receive(:to_state).with(:yellow).and_return(:red)
13
-
14
- expect(events_map.move_to(:go, :yellow)).to eq(:red)
15
- expect(transition_b).to have_received(:to_state).with(:yellow)
16
- end
17
-
18
- it "moves to state by matching choice transition" do
19
- transition_a = double(:transition_a, matches?: true)
20
- transition_b = double(:transition_b, matches?: true)
21
-
22
- events_map = described_class.new
23
- events_map.add(:go, transition_a)
24
- events_map.add(:go, transition_b)
25
-
26
- allow(transition_a).to receive(:check_conditions).and_return(false)
27
- allow(transition_b).to receive(:check_conditions).and_return(true)
28
-
29
- allow(transition_b).to receive(:to_state).with(:green).and_return(:red)
30
-
31
- expect(events_map.move_to(:go, :green)).to eq(:red)
32
- expect(transition_b).to have_received(:to_state).with(:green)
33
- end
34
-
35
- it "moves to from state if no transition available" do
36
- transition_a = double(:transition_a, matches?: false)
37
- transition_b = double(:transition_b, matches?: false)
38
-
39
- events_map = described_class.new
40
- events_map.add(:go, transition_a)
41
- events_map.add(:go, transition_b)
42
-
43
- expect(events_map.move_to(:go, :green)).to eq(:green)
44
- end
45
- end
@@ -1,17 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- RSpec.describe FiniteMachine::EventsMap do
4
- it "finds current states for event name" do
5
- transition = spy(:transition, states: {:red => :yellow, :yellow => :green})
6
- events_map = described_class.new
7
- events_map.add(:start, transition)
8
-
9
- expect(events_map.states_for(:start)).to eq([:red, :yellow])
10
- end
11
-
12
- it "fails to find any states for event name" do
13
- events_map = described_class.new
14
-
15
- expect(events_map.states_for(:start)).to eq([])
16
- end
17
- end
@@ -1,390 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- RSpec.describe FiniteMachine, 'events' do
4
- it "allows for hash rocket syntax to describe transition" do
5
- fsm = FiniteMachine.new do
6
- initial :green
7
-
8
- event :slow, :green => :yellow
9
- event :stop, :yellow => :red
10
- end
11
-
12
- expect(fsm.current).to eql(:green)
13
- fsm.slow
14
- expect(fsm.current).to eql(:yellow)
15
- fsm.stop
16
- expect(fsm.current).to eql(:red)
17
- end
18
-
19
- it "allows for (:from | :to) key pairs to describe transition" do
20
- fsm = FiniteMachine.new do
21
- initial :green
22
-
23
- event :slow, from: :green, to: :yellow
24
- event :stop, from: :yellow, to: :red
25
- end
26
-
27
- expect(fsm.current).to eql(:green)
28
- fsm.slow
29
- expect(fsm.current).to eql(:yellow)
30
- fsm.stop
31
- expect(fsm.current).to eql(:red)
32
- end
33
-
34
- it "permits no-op event without 'to' transition" do
35
- fsm = FiniteMachine.new do
36
- initial :green
37
-
38
- event :noop, from: :green
39
- event :slow, from: :green, to: :yellow
40
- event :stop, from: :yellow, to: :red
41
- event :ready, from: :red, to: :yellow
42
- event :go, from: :yellow, to: :green
43
- end
44
-
45
- expect(fsm.current).to eql(:green)
46
-
47
- expect(fsm.can?(:noop)).to be true
48
- expect(fsm.can?(:slow)).to be true
49
-
50
- fsm.noop
51
- expect(fsm.current).to eql(:green)
52
- fsm.slow
53
- expect(fsm.current).to eql(:yellow)
54
-
55
- expect(fsm.cannot?(:noop)).to be true
56
- expect(fsm.cannot?(:slow)).to be true
57
- end
58
-
59
- it "permits event from any state using :from" do
60
- fsm = FiniteMachine.new do
61
- initial :green
62
-
63
- event :slow, from: :green, to: :yellow
64
- event :stop, from: :yellow, to: :red
65
- event :ready, from: :red, to: :yellow
66
- event :go, from: :yellow, to: :green
67
- event :run, from: any_state, to: :green
68
- end
69
-
70
- expect(fsm.current).to eql(:green)
71
-
72
- fsm.slow
73
- expect(fsm.current).to eql(:yellow)
74
- fsm.run
75
- expect(fsm.current).to eql(:green)
76
-
77
- fsm.slow
78
- expect(fsm.current).to eql(:yellow)
79
- fsm.stop
80
- expect(fsm.current).to eql(:red)
81
- fsm.run
82
- expect(fsm.current).to eql(:green)
83
-
84
- fsm.slow
85
- expect(fsm.current).to eql(:yellow)
86
- fsm.go
87
- expect(fsm.current).to eql(:green)
88
- fsm.run
89
- expect(fsm.current).to eql(:green)
90
- end
91
-
92
- it "permits event from any state for hash syntax" do
93
- fsm = FiniteMachine.new do
94
- initial :red
95
-
96
- event :start, :red => :yellow
97
- event :run, :yellow => :green
98
- event :stop, :green => :red
99
- event :go, any_state => :green
100
- end
101
-
102
- expect(fsm.current).to eql(:red)
103
-
104
- fsm.go
105
- expect(fsm.current).to eql(:green)
106
- fsm.stop
107
- fsm.start
108
- expect(fsm.current).to eql(:yellow)
109
- fsm.go
110
- expect(fsm.current).to eql(:green)
111
- end
112
-
113
- it "permits event from any state without 'from'" do
114
- fsm = FiniteMachine.new do
115
- initial :green
116
-
117
- event :slow, from: :green, to: :yellow
118
- event :stop, from: :yellow, to: :red
119
- event :ready, from: :red, to: :yellow
120
- event :go, from: :yellow, to: :green
121
- event :run, to: :green
122
- end
123
-
124
- expect(fsm.current).to eql(:green)
125
-
126
- fsm.slow
127
- expect(fsm.current).to eql(:yellow)
128
- fsm.run
129
- expect(fsm.current).to eql(:green)
130
-
131
- fsm.slow
132
- expect(fsm.current).to eql(:yellow)
133
- fsm.stop
134
- expect(fsm.current).to eql(:red)
135
- fsm.run
136
- expect(fsm.current).to eql(:green)
137
-
138
- fsm.slow
139
- expect(fsm.current).to eql(:yellow)
140
- fsm.go
141
- expect(fsm.current).to eql(:green)
142
- fsm.run
143
- expect(fsm.current).to eql(:green)
144
- end
145
-
146
- it "doesn't raise error on invalid transition for non-dangerous version" do
147
- called = []
148
- fsm = FiniteMachine.new do
149
- initial :green
150
-
151
- event :stop, from: :yellow, to: :red
152
-
153
- on_before :stop do |event| called << 'on_before_stop' end
154
- on_after :stop do |event| called << 'on_before_stop' end
155
- end
156
-
157
- expect(fsm.current).to eq(:green)
158
- expect(fsm.stop).to eq(false)
159
- expect(fsm.current).to eq(:green)
160
- expect(called).to match_array(['on_before_stop'])
161
- end
162
-
163
- context 'for non-dangerous version' do
164
- it "doesn't raise error on invalid transition and fires callbacks" do
165
- called = []
166
- fsm = FiniteMachine.new do
167
- initial :green
168
-
169
- event :stop, from: :yellow, to: :red
170
-
171
- on_before :stop do |event| called << 'on_before_stop' end
172
- on_after :stop do |event| called << 'on_before_stop' end
173
- end
174
-
175
- expect(fsm.current).to eq(:green)
176
- expect(fsm.stop).to eq(false)
177
- expect(fsm.current).to eq(:green)
178
- expect(called).to match_array(['on_before_stop'])
179
- end
180
-
181
- it "raises error on invalid transition for dangerous version" do
182
- called = []
183
- fsm = FiniteMachine.new do
184
- initial :green
185
-
186
- event :slow, from: :green, to: :yellow
187
- event :stop, from: :yellow, to: :red, silent: true
188
-
189
- on_before :stop do |event| called << 'on_before_stop' end
190
- on_after :stop do |event| called << 'on_before_stop' end
191
- end
192
-
193
- expect(fsm.current).to eql(:green)
194
- expect(fsm.stop).to eq(false)
195
- expect(called).to match_array([])
196
- end
197
- end
198
-
199
- context 'for dangerous version' do
200
- it "raises error on invalid transition without callbacks" do
201
- called = []
202
- fsm = FiniteMachine.new do
203
- initial :green
204
-
205
- event :start, :red => :yellow, silent: true
206
-
207
- on_before :start do |event| called << 'on_before_start' end
208
- on_after :start do |event| called << 'on_after_start' end
209
- end
210
-
211
- expect(fsm.current).to eq(:green)
212
- expect { fsm.start! }.to raise_error(FiniteMachine::InvalidStateError)
213
- expect(called).to eq([])
214
- expect(fsm.current).to eq(:green)
215
- end
216
-
217
- it "raises error on invalid transition with callbacks fired" do
218
- called = []
219
- fsm = FiniteMachine.new do
220
- initial :green
221
-
222
- event :start, :red => :yellow
223
-
224
- on_before :start do |event| called << 'on_before_start' end
225
- on_after :start do |event| called << 'on_after_start' end
226
- end
227
-
228
- expect(fsm.current).to eq(:green)
229
- expect { fsm.start! }.to raise_error(FiniteMachine::InvalidStateError,
230
- /inappropriate current state 'green'/)
231
- expect(called).to eq(['on_before_start'])
232
- expect(fsm.current).to eq(:green)
233
- end
234
- end
235
-
236
- context 'when multiple from states' do
237
- it "allows for array from key" do
238
- fsm = FiniteMachine.new do
239
- initial :green
240
-
241
- event :slow, :green => :yellow
242
- event :stop, [:green, :yellow] => :red
243
- event :ready, :red => :yellow
244
- event :go, [:yellow, :red] => :green
245
- end
246
-
247
- expect(fsm.current).to eql(:green)
248
-
249
- expect(fsm.can?(:slow)).to be true
250
- expect(fsm.can?(:stop)).to be true
251
- expect(fsm.cannot?(:ready)).to be true
252
- expect(fsm.cannot?(:go)).to be true
253
-
254
- fsm.slow; expect(fsm.current).to eql(:yellow)
255
- fsm.stop; expect(fsm.current).to eql(:red)
256
- fsm.ready; expect(fsm.current).to eql(:yellow)
257
- fsm.go; expect(fsm.current).to eql(:green)
258
-
259
- fsm.stop; expect(fsm.current).to eql(:red)
260
- fsm.go; expect(fsm.current).to eql(:green)
261
- end
262
-
263
- it "allows for hash of states" do
264
- fsm = FiniteMachine.new do
265
- initial :green
266
-
267
- event :slow, :green => :yellow
268
- event :stop, :green => :red, :yellow => :red
269
- event :ready, :red => :yellow
270
- event :go, :yellow => :green, :red => :green
271
- end
272
-
273
- expect(fsm.current).to eql(:green)
274
-
275
- expect(fsm.can?(:slow)).to be true
276
- expect(fsm.can?(:stop)).to be true
277
- expect(fsm.cannot?(:ready)).to be true
278
- expect(fsm.cannot?(:go)).to be true
279
-
280
- fsm.slow; expect(fsm.current).to eql(:yellow)
281
- fsm.stop; expect(fsm.current).to eql(:red)
282
- fsm.ready; expect(fsm.current).to eql(:yellow)
283
- fsm.go; expect(fsm.current).to eql(:green)
284
-
285
- fsm.stop; expect(fsm.current).to eql(:red)
286
- fsm.go; expect(fsm.current).to eql(:green)
287
- end
288
- end
289
-
290
- it "groups events with the same name" do
291
- fsm = FiniteMachine.new do
292
- initial :green
293
-
294
- event :stop, :green => :yellow
295
- event :stop, :yellow => :red
296
- event :stop, :red => :pink
297
- event :cycle, [:yellow, :red, :pink] => :green
298
- end
299
-
300
- expect(fsm.current).to eql(:green)
301
- expect(fsm.can?(:stop)).to be true
302
- fsm.stop
303
- expect(fsm.current).to eql(:yellow)
304
- fsm.stop
305
- expect(fsm.current).to eql(:red)
306
- fsm.stop
307
- expect(fsm.current).to eql(:pink)
308
- fsm.cycle
309
- expect(fsm.current).to eql(:green)
310
- fsm.stop
311
- expect(fsm.current).to eql(:yellow)
312
- end
313
-
314
- it "groups transitions under one event name" do
315
- fsm = FiniteMachine.new do
316
- initial :initial
317
-
318
- event :bump, :initial => :low,
319
- :low => :medium,
320
- :medium => :high
321
- end
322
-
323
- expect(fsm.current).to eq(:initial)
324
- fsm.bump; expect(fsm.current).to eq(:low)
325
- fsm.bump; expect(fsm.current).to eq(:medium)
326
- fsm.bump; expect(fsm.current).to eq(:high)
327
- end
328
-
329
- it "returns values for events" do
330
- fsm = FiniteMachine.new do
331
- initial :neutral
332
-
333
- event :start, :neutral => :engine_on
334
- event :drive, :engine_on => :running, if: -> { return false }
335
- event :stop, any_state => :neutral
336
-
337
- on_before(:drive) { cancel_event }
338
- on_after(:stop) { }
339
- end
340
-
341
- expect(fsm.current).to eql(:neutral)
342
- expect(fsm.start).to eql(true)
343
- expect(fsm.drive).to eql(false)
344
- expect(fsm.stop).to eql(true)
345
- expect(fsm.stop).to eql(true)
346
- end
347
-
348
- it "allows for self transition events" do
349
- digits = []
350
- callbacks = []
351
- phone = FiniteMachine.new do
352
- initial :on_hook
353
-
354
- event :digit, :on_hook => :dialing
355
- event :digit, :dialing => :dialing
356
- event :off_hook, :dialing => :alerting
357
-
358
- on_before_digit { |event, digit| digits << digit}
359
- on_before_off_hook { |event| callbacks << "dialing #{digits.join}" }
360
- end
361
-
362
- expect(phone.current).to eq(:on_hook)
363
- phone.digit(9)
364
- expect(phone.current).to eq(:dialing)
365
- phone.digit(1)
366
- expect(phone.current).to eq(:dialing)
367
- phone.digit(1)
368
- expect(phone.current).to eq(:dialing)
369
- phone.off_hook
370
- expect(phone.current).to eq(:alerting)
371
- expect(digits).to match_array(digits)
372
- expect(callbacks).to match_array(["dialing 911"])
373
- end
374
-
375
- it "executes event block" do
376
- fsm = FiniteMachine.new do
377
- initial :red
378
-
379
- event :start, :red => :green
380
- event :stop, :green => :red
381
- end
382
-
383
- expect(fsm.current).to eq(:red)
384
- called = []
385
- fsm.start do |from, to|
386
- called << "execute_start_#{from}_#{to}"
387
- end
388
- expect(called).to eq(['execute_start_red_green'])
389
- end
390
- end