finite_machine 0.12.1 → 0.13.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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