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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +17 -1
- data/README.md +1 -1
- data/lib/finite_machine.rb +3 -1
- data/lib/finite_machine/choice_merger.rb +2 -2
- data/lib/finite_machine/dsl.rb +4 -4
- data/lib/finite_machine/message_queue.rb +0 -1
- data/lib/finite_machine/state_machine.rb +3 -3
- data/lib/finite_machine/two_phase_lock.rb +6 -6
- data/lib/finite_machine/version.rb +1 -1
- metadata +20 -146
- data/Rakefile +0 -12
- data/benchmarks/memory_profile.rb +0 -11
- data/benchmarks/memory_usage.rb +0 -28
- data/examples/atm.rb +0 -45
- data/examples/bug_system.rb +0 -145
- data/finite_machine.gemspec +0 -30
- data/spec/integration/system_spec.rb +0 -93
- data/spec/performance/benchmark_spec.rb +0 -54
- data/spec/spec_helper.rb +0 -34
- data/spec/unit/alias_target_spec.rb +0 -89
- data/spec/unit/async_callbacks_spec.rb +0 -28
- data/spec/unit/auto_methods_spec.rb +0 -44
- data/spec/unit/callable/call_spec.rb +0 -111
- data/spec/unit/callbacks_spec.rb +0 -851
- data/spec/unit/can_spec.rb +0 -88
- data/spec/unit/cancel_callbacks_spec.rb +0 -46
- data/spec/unit/choice_spec.rb +0 -295
- data/spec/unit/define_spec.rb +0 -55
- data/spec/unit/definition_spec.rb +0 -98
- data/spec/unit/event_names_spec.rb +0 -15
- data/spec/unit/events_map/add_spec.rb +0 -23
- data/spec/unit/events_map/choice_transition_spec.rb +0 -25
- data/spec/unit/events_map/clear_spec.rb +0 -13
- data/spec/unit/events_map/events_spec.rb +0 -16
- data/spec/unit/events_map/inspect_spec.rb +0 -22
- data/spec/unit/events_map/match_transition_spec.rb +0 -35
- data/spec/unit/events_map/move_to_spec.rb +0 -45
- data/spec/unit/events_map/states_for_spec.rb +0 -17
- data/spec/unit/events_spec.rb +0 -390
- data/spec/unit/handlers_spec.rb +0 -120
- data/spec/unit/hook_event/any_state_or_event_spec.rb +0 -13
- data/spec/unit/hook_event/build_spec.rb +0 -13
- data/spec/unit/hook_event/eql_spec.rb +0 -34
- data/spec/unit/hook_event/initialize_spec.rb +0 -23
- data/spec/unit/hook_event/notify_spec.rb +0 -12
- data/spec/unit/hooks/clear_spec.rb +0 -16
- data/spec/unit/hooks/find_spec.rb +0 -19
- data/spec/unit/hooks/inspect_spec.rb +0 -25
- data/spec/unit/hooks/register_spec.rb +0 -17
- data/spec/unit/if_unless_spec.rb +0 -314
- data/spec/unit/initial_spec.rb +0 -190
- data/spec/unit/inspect_spec.rb +0 -22
- data/spec/unit/is_spec.rb +0 -49
- data/spec/unit/log_transitions_spec.rb +0 -24
- data/spec/unit/logger_spec.rb +0 -36
- data/spec/unit/message_queue_spec.rb +0 -62
- data/spec/unit/new_spec.rb +0 -50
- data/spec/unit/respond_to_spec.rb +0 -34
- data/spec/unit/state_parser/parse_spec.rb +0 -56
- data/spec/unit/states_spec.rb +0 -28
- data/spec/unit/subscribers_spec.rb +0 -40
- data/spec/unit/target_spec.rb +0 -225
- data/spec/unit/terminated_spec.rb +0 -85
- data/spec/unit/transition/check_conditions_spec.rb +0 -55
- data/spec/unit/transition/inspect_spec.rb +0 -25
- data/spec/unit/transition/matches_spec.rb +0 -21
- data/spec/unit/transition/states_spec.rb +0 -29
- data/spec/unit/transition/to_state_spec.rb +0 -19
- data/spec/unit/trigger_spec.rb +0 -18
- data/spec/unit/undefined_transition/eql_spec.rb +0 -15
- data/tasks/console.rake +0 -11
- data/tasks/coverage.rake +0 -11
- data/tasks/spec.rake +0 -34
data/benchmarks/memory_usage.rb
DELETED
@@ -1,28 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require_relative '../lib/finite_machine'
|
4
|
-
|
5
|
-
5.times do
|
6
|
-
puts
|
7
|
-
|
8
|
-
GC.start
|
9
|
-
|
10
|
-
gc_before = GC.stat
|
11
|
-
objects_before = ObjectSpace.count_objects
|
12
|
-
p objects_before[:T_OBJECT]
|
13
|
-
|
14
|
-
1_000.times do
|
15
|
-
FiniteMachine.new do
|
16
|
-
initial :green
|
17
|
-
|
18
|
-
events { event :slow, :green => :yellow }
|
19
|
-
end
|
20
|
-
end
|
21
|
-
|
22
|
-
objects_after = ObjectSpace.count_objects
|
23
|
-
gc_after = GC.stat
|
24
|
-
p objects_after[:T_OBJECT]
|
25
|
-
|
26
|
-
p "GC count: #{gc_after[:count] - gc_before[:count]}"
|
27
|
-
p "Objects count: #{objects_after[:T_OBJECT] - objects_before[:T_OBJECT]}"
|
28
|
-
end
|
data/examples/atm.rb
DELETED
@@ -1,45 +0,0 @@
|
|
1
|
-
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
2
|
-
|
3
|
-
require 'finite_machine'
|
4
|
-
|
5
|
-
class Account
|
6
|
-
attr_accessor :number
|
7
|
-
|
8
|
-
def verify(account_number, pin)
|
9
|
-
return account_number == 123456 && pin == 666
|
10
|
-
end
|
11
|
-
end
|
12
|
-
|
13
|
-
account = Account.new
|
14
|
-
|
15
|
-
atm = FiniteMachine.define do
|
16
|
-
initial :unauthorized
|
17
|
-
|
18
|
-
target account
|
19
|
-
|
20
|
-
events {
|
21
|
-
event :authorize, :unauthorized => :authorized, if: -> (account, account_number, pin) {
|
22
|
-
account.verify(account_number, pin)
|
23
|
-
}
|
24
|
-
event :deauthorize, :authorized => :unauthorized
|
25
|
-
}
|
26
|
-
|
27
|
-
callbacks {
|
28
|
-
on_exit :unauthorized do |event, account_number, pin|
|
29
|
-
# if verify(account_number, pin)
|
30
|
-
self.number = account_number
|
31
|
-
# else
|
32
|
-
# puts "Invalid Account and/or PIN"
|
33
|
-
# FiniteMachine::CANCELLED
|
34
|
-
# end
|
35
|
-
end
|
36
|
-
}
|
37
|
-
end
|
38
|
-
|
39
|
-
atm.authorize(111222, 666)
|
40
|
-
puts "authorized: #{atm.authorized?}"
|
41
|
-
puts "Number: #{account.number}"
|
42
|
-
|
43
|
-
atm.authorize(123456, 666)
|
44
|
-
puts "authorized: #{atm.authorized?}"
|
45
|
-
puts "Number: #{account.number}"
|
data/examples/bug_system.rb
DELETED
@@ -1,145 +0,0 @@
|
|
1
|
-
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
2
|
-
|
3
|
-
require 'finite_machine'
|
4
|
-
|
5
|
-
class User
|
6
|
-
attr_accessor :name
|
7
|
-
|
8
|
-
def initialize(name)
|
9
|
-
@name = name
|
10
|
-
end
|
11
|
-
end
|
12
|
-
|
13
|
-
class Manager < User
|
14
|
-
attr_accessor :developers
|
15
|
-
|
16
|
-
def initialize(name)
|
17
|
-
super
|
18
|
-
@developers = []
|
19
|
-
end
|
20
|
-
|
21
|
-
def manages(developer)
|
22
|
-
@developers << developer
|
23
|
-
end
|
24
|
-
|
25
|
-
def assign(bug)
|
26
|
-
developer = @developers.first
|
27
|
-
bug.assign
|
28
|
-
developer.bug = bug
|
29
|
-
end
|
30
|
-
end
|
31
|
-
|
32
|
-
class Tester < User
|
33
|
-
def report(bug)
|
34
|
-
bug.report
|
35
|
-
end
|
36
|
-
|
37
|
-
def reopen(bug)
|
38
|
-
bug.reopen
|
39
|
-
end
|
40
|
-
end
|
41
|
-
|
42
|
-
class Developer < User
|
43
|
-
attr_accessor :bug
|
44
|
-
|
45
|
-
def work_on
|
46
|
-
bug.start
|
47
|
-
end
|
48
|
-
|
49
|
-
def resolve
|
50
|
-
bug.close
|
51
|
-
end
|
52
|
-
end
|
53
|
-
|
54
|
-
class BugSystem
|
55
|
-
attr_accessor :managers
|
56
|
-
|
57
|
-
def initialize(managers = [])
|
58
|
-
@managers = managers
|
59
|
-
end
|
60
|
-
|
61
|
-
def notify_manager(bug)
|
62
|
-
manager = @managers.first
|
63
|
-
manager.assign(bug)
|
64
|
-
end
|
65
|
-
end
|
66
|
-
|
67
|
-
class Bug
|
68
|
-
attr_accessor :name
|
69
|
-
attr_accessor :priority
|
70
|
-
# fake belongs_to relationship
|
71
|
-
attr_accessor :bug_system
|
72
|
-
|
73
|
-
def initialize(name, priority)
|
74
|
-
@name = name
|
75
|
-
@priority = priority
|
76
|
-
end
|
77
|
-
|
78
|
-
def report
|
79
|
-
status.report
|
80
|
-
end
|
81
|
-
|
82
|
-
def assign
|
83
|
-
status.assign
|
84
|
-
end
|
85
|
-
|
86
|
-
def start
|
87
|
-
status.start
|
88
|
-
end
|
89
|
-
|
90
|
-
def close
|
91
|
-
status.close
|
92
|
-
end
|
93
|
-
|
94
|
-
def reopen
|
95
|
-
status.reopen
|
96
|
-
end
|
97
|
-
|
98
|
-
def status
|
99
|
-
context = self
|
100
|
-
@status ||= FiniteMachine.define do
|
101
|
-
target context
|
102
|
-
|
103
|
-
events {
|
104
|
-
event :report, :none => :new
|
105
|
-
event :assign, :new => :assigned
|
106
|
-
event :start, :assigned => :in_progress
|
107
|
-
event :close, [:in_progress, :reopened] => :resolved
|
108
|
-
event :reopen, :resolved => :reopened
|
109
|
-
}
|
110
|
-
|
111
|
-
callbacks {
|
112
|
-
on_enter :new do |event|
|
113
|
-
bug_system.notify_manager(self)
|
114
|
-
end
|
115
|
-
}
|
116
|
-
end
|
117
|
-
end
|
118
|
-
end
|
119
|
-
|
120
|
-
tester = Tester.new("John")
|
121
|
-
manager = Manager.new("David")
|
122
|
-
developer = Developer.new("Piotr")
|
123
|
-
manager.manages(developer)
|
124
|
-
|
125
|
-
bug_system = BugSystem.new([manager])
|
126
|
-
bug = Bug.new(:trojan, :high)
|
127
|
-
bug.bug_system = bug_system
|
128
|
-
|
129
|
-
puts "A BUG's LIFE"
|
130
|
-
puts "#1 #{bug.status.current}"
|
131
|
-
|
132
|
-
tester.report(bug)
|
133
|
-
puts "#2 #{bug.status.current}"
|
134
|
-
|
135
|
-
developer.work_on
|
136
|
-
puts "#3 #{bug.status.current}"
|
137
|
-
|
138
|
-
developer.resolve
|
139
|
-
puts "#4 #{bug.status.current}"
|
140
|
-
|
141
|
-
tester.reopen(bug)
|
142
|
-
puts "#5 #{bug.status.current}"
|
143
|
-
|
144
|
-
developer.resolve
|
145
|
-
puts "#6 #{bug.status.current}"
|
data/finite_machine.gemspec
DELETED
@@ -1,30 +0,0 @@
|
|
1
|
-
lib = File.expand_path('../lib', __FILE__)
|
2
|
-
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
3
|
-
require 'finite_machine/version'
|
4
|
-
|
5
|
-
Gem::Specification.new do |spec|
|
6
|
-
spec.name = "finite_machine"
|
7
|
-
spec.version = FiniteMachine::VERSION
|
8
|
-
spec.authors = ["Piotr Murach"]
|
9
|
-
spec.email = ["me@piotrmurach.com"]
|
10
|
-
spec.description = %q{A minimal finite state machine with a straightforward syntax. You can quickly model states, add callbacks and use object-oriented techniques to integrate with ORMs.}
|
11
|
-
spec.summary = %q{A minimal finite state machine with a straightforward syntax.}
|
12
|
-
spec.homepage = "http://piotrmurach.github.io/finite_machine/"
|
13
|
-
spec.license = "MIT"
|
14
|
-
|
15
|
-
spec.files = Dir['{lib,spec,examples,benchmarks}/**/*.rb']
|
16
|
-
spec.files += Dir['tasks/*', 'finite_machine.gemspec']
|
17
|
-
spec.files += Dir['README.md', 'CHANGELOG.md', 'LICENSE.txt', 'Rakefile']
|
18
|
-
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
19
|
-
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
20
|
-
spec.require_paths = ["lib"]
|
21
|
-
|
22
|
-
spec.required_ruby_version = '>= 2.0.0'
|
23
|
-
|
24
|
-
spec.add_runtime_dependency 'concurrent-ruby', '~> 1.0'
|
25
|
-
|
26
|
-
spec.add_development_dependency 'bundler', '>= 1.5'
|
27
|
-
spec.add_development_dependency 'rspec', '~> 3.1'
|
28
|
-
spec.add_development_dependency 'rspec-benchmark', '~> 0.4.0'
|
29
|
-
spec.add_development_dependency 'rake'
|
30
|
-
end
|
@@ -1,93 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
RSpec.describe FiniteMachine, 'system' do
|
4
|
-
|
5
|
-
it "doesn't share state between machine callbacks" do
|
6
|
-
callbacks = []
|
7
|
-
stub_const("FSM_A", Class.new(FiniteMachine::Definition) do
|
8
|
-
event :init, :none => :green
|
9
|
-
event :start, any_state => :green
|
10
|
-
|
11
|
-
on_before do |event|
|
12
|
-
callbacks << "fsmA on_before(#{event.name})"
|
13
|
-
end
|
14
|
-
on_enter_green do |event|
|
15
|
-
target.fire
|
16
|
-
callbacks << "fsmA on_enter(:green)"
|
17
|
-
end
|
18
|
-
once_on_enter_green do |event|
|
19
|
-
callbacks << "fsmA once_on_enter(:green)"
|
20
|
-
end
|
21
|
-
end)
|
22
|
-
|
23
|
-
stub_const("FSM_B", Class.new(FiniteMachine::Definition) do
|
24
|
-
event :init, :none => :stopped
|
25
|
-
event :start, :stopped => :started
|
26
|
-
|
27
|
-
on_before do |event|
|
28
|
-
callbacks << "fsmB on_before(#{event.name})"
|
29
|
-
end
|
30
|
-
on_enter_stopped do |event|
|
31
|
-
callbacks << "fsmB on_enter(:stopped)"
|
32
|
-
end
|
33
|
-
on_enter_started do |event|
|
34
|
-
callbacks << "fsmB on_enter(:started)"
|
35
|
-
end
|
36
|
-
end)
|
37
|
-
|
38
|
-
class Backend
|
39
|
-
def initialize
|
40
|
-
@fsmB = FSM_B.new
|
41
|
-
@fsmB.init
|
42
|
-
@signal = Mutex.new
|
43
|
-
end
|
44
|
-
|
45
|
-
def operate
|
46
|
-
@signal.unlock if @signal.locked?
|
47
|
-
@worker = Thread.new do
|
48
|
-
while !@signal.locked? do
|
49
|
-
sleep 0.01
|
50
|
-
end
|
51
|
-
Thread.current.abort_on_exception = true
|
52
|
-
@fsmB.start
|
53
|
-
end
|
54
|
-
end
|
55
|
-
|
56
|
-
def stopit
|
57
|
-
@signal.lock
|
58
|
-
@worker.join
|
59
|
-
end
|
60
|
-
end
|
61
|
-
|
62
|
-
class Fire
|
63
|
-
def initialize
|
64
|
-
@fsmA = FSM_A.new(self)
|
65
|
-
|
66
|
-
@backend = Backend.new
|
67
|
-
@backend.operate
|
68
|
-
end
|
69
|
-
|
70
|
-
def fire
|
71
|
-
@backend.stopit
|
72
|
-
end
|
73
|
-
|
74
|
-
def operate
|
75
|
-
#@fsmA.start # should trigger as well
|
76
|
-
@fsmA.init
|
77
|
-
end
|
78
|
-
end
|
79
|
-
|
80
|
-
fire = Fire.new
|
81
|
-
fire.operate
|
82
|
-
|
83
|
-
expect(callbacks).to match_array([
|
84
|
-
'fsmB on_before(init)',
|
85
|
-
'fsmB on_enter(:stopped)',
|
86
|
-
'fsmA on_before(init)',
|
87
|
-
'fsmA on_enter(:green)',
|
88
|
-
'fsmA once_on_enter(:green)',
|
89
|
-
'fsmB on_before(start)',
|
90
|
-
'fsmB on_enter(:started)'
|
91
|
-
])
|
92
|
-
end
|
93
|
-
end
|
@@ -1,54 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
RSpec.describe FiniteMachine, perf: true do
|
4
|
-
include RSpec::Benchmark::Matchers
|
5
|
-
|
6
|
-
class Measurement
|
7
|
-
attr_reader :steps, :loops
|
8
|
-
|
9
|
-
def initialize
|
10
|
-
@steps = 0
|
11
|
-
@loops = 0
|
12
|
-
end
|
13
|
-
|
14
|
-
def inc_step
|
15
|
-
@steps += 1
|
16
|
-
end
|
17
|
-
|
18
|
-
def inc_loop
|
19
|
-
@loops += 1
|
20
|
-
end
|
21
|
-
end
|
22
|
-
|
23
|
-
it "correctly loops through events" do
|
24
|
-
measurement = Measurement.new
|
25
|
-
|
26
|
-
fsm = FiniteMachine.new(measurement) do
|
27
|
-
initial :green
|
28
|
-
|
29
|
-
event :next, :green => :yellow,
|
30
|
-
:yellow => :red,
|
31
|
-
:red => :green
|
32
|
-
|
33
|
-
on_enter do |event| target.inc_step; true end
|
34
|
-
on_enter :red do |event| target.inc_loop; true end
|
35
|
-
end
|
36
|
-
|
37
|
-
100.times { fsm.next }
|
38
|
-
|
39
|
-
expect(measurement.steps).to eq(100)
|
40
|
-
expect(measurement.loops).to eq(100 / 3)
|
41
|
-
end
|
42
|
-
|
43
|
-
it "performs at least 400 ips" do
|
44
|
-
fsm = FiniteMachine.new do
|
45
|
-
initial :green
|
46
|
-
|
47
|
-
event :next, :green => :yellow,
|
48
|
-
:yellow => :red,
|
49
|
-
:red => :green
|
50
|
-
end
|
51
|
-
|
52
|
-
expect { fsm.next }.to perform_at_least(400).ips
|
53
|
-
end
|
54
|
-
end
|
data/spec/spec_helper.rb
DELETED
@@ -1,34 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
if ENV['COVERAGE'] || ENV['TRAVIS']
|
4
|
-
require 'simplecov'
|
5
|
-
require 'coveralls'
|
6
|
-
|
7
|
-
SimpleCov.formatter = SimpleCov::Formatter::MultiFormatter.new([
|
8
|
-
SimpleCov::Formatter::HTMLFormatter,
|
9
|
-
Coveralls::SimpleCov::Formatter
|
10
|
-
])
|
11
|
-
|
12
|
-
SimpleCov.start do
|
13
|
-
command_name 'spec'
|
14
|
-
add_filter 'spec'
|
15
|
-
end
|
16
|
-
end
|
17
|
-
|
18
|
-
require 'finite_machine'
|
19
|
-
require 'thwait'
|
20
|
-
require 'rspec-benchmark'
|
21
|
-
|
22
|
-
RSpec.configure do |config|
|
23
|
-
config.run_all_when_everything_filtered = true
|
24
|
-
config.filter_run :focus
|
25
|
-
config.raise_errors_for_deprecations!
|
26
|
-
config.mock_with :rspec do |mocks|
|
27
|
-
mocks.verify_partial_doubles = true
|
28
|
-
end
|
29
|
-
config.disable_monkey_patching!
|
30
|
-
if config.files_to_run.one?
|
31
|
-
config.default_formatter = 'doc'
|
32
|
-
end
|
33
|
-
config.order = :random
|
34
|
-
end
|
@@ -1,89 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
RSpec.describe FiniteMachine::Definition, '#alias_target' do
|
4
|
-
|
5
|
-
before do
|
6
|
-
stub_const("Car", Class.new do
|
7
|
-
def turn_reverse_lights_off
|
8
|
-
@reverse_lights = false
|
9
|
-
end
|
10
|
-
|
11
|
-
def turn_reverse_lights_on
|
12
|
-
@reverse_lights = true
|
13
|
-
end
|
14
|
-
|
15
|
-
def reverse_lights?
|
16
|
-
@reverse_lights ||= false
|
17
|
-
end
|
18
|
-
end)
|
19
|
-
end
|
20
|
-
|
21
|
-
it "aliases target" do
|
22
|
-
car = Car.new
|
23
|
-
fsm = FiniteMachine.new(car, alias_target: :delorean)
|
24
|
-
|
25
|
-
expect(fsm.target).to eq(car)
|
26
|
-
expect { fsm.car }.to raise_error(NoMethodError)
|
27
|
-
expect(fsm.delorean).to eq(car)
|
28
|
-
end
|
29
|
-
|
30
|
-
it "scopes the target alias to a state machine instance" do
|
31
|
-
delorean = Car.new
|
32
|
-
batmobile = Car.new
|
33
|
-
fsm_a = FiniteMachine.new(delorean, alias_target: :delorean)
|
34
|
-
fsm_b = FiniteMachine.new(batmobile, alias_target: :batmobile)
|
35
|
-
|
36
|
-
expect(fsm_a.delorean).to eq(delorean)
|
37
|
-
expect { fsm_a.batmobile }.to raise_error(NameError)
|
38
|
-
|
39
|
-
expect(fsm_b.batmobile).to eq(batmobile)
|
40
|
-
expect { fsm_b.delorean }.to raise_error(NameError)
|
41
|
-
end
|
42
|
-
|
43
|
-
context 'when inside definition' do
|
44
|
-
before do
|
45
|
-
stub_const("Engine", Class.new(FiniteMachine::Definition) do
|
46
|
-
initial :neutral
|
47
|
-
|
48
|
-
event :forward, [:reverse, :neutral] => :one
|
49
|
-
event :shift, :one => :two
|
50
|
-
event :shift, :two => :one
|
51
|
-
event :back, [:neutral, :one] => :reverse
|
52
|
-
|
53
|
-
on_enter :reverse do |event|
|
54
|
-
car.turn_reverse_lights_on
|
55
|
-
end
|
56
|
-
|
57
|
-
on_exit :reverse do |event|
|
58
|
-
car.turn_reverse_lights_off
|
59
|
-
end
|
60
|
-
|
61
|
-
handle FiniteMachine::InvalidStateError do |exception| end
|
62
|
-
end)
|
63
|
-
end
|
64
|
-
|
65
|
-
it "creates unique instances" do
|
66
|
-
engine_a = Engine.new(alias_target: :car)
|
67
|
-
engine_b = Engine.new(alias_target: :car)
|
68
|
-
expect(engine_a).not_to be(engine_b)
|
69
|
-
|
70
|
-
engine_a.forward
|
71
|
-
expect(engine_a.current).to eq(:one)
|
72
|
-
expect(engine_b.current).to eq(:neutral)
|
73
|
-
end
|
74
|
-
|
75
|
-
it "allows to create standalone machine" do
|
76
|
-
car = Car.new
|
77
|
-
engine = Engine.new(car, alias_target: :car)
|
78
|
-
expect(engine.current).to eq(:neutral)
|
79
|
-
|
80
|
-
engine.forward
|
81
|
-
expect(engine.current).to eq(:one)
|
82
|
-
expect(car.reverse_lights?).to be false
|
83
|
-
|
84
|
-
engine.back
|
85
|
-
expect(engine.current).to eq(:reverse)
|
86
|
-
expect(car.reverse_lights?).to be true
|
87
|
-
end
|
88
|
-
end
|
89
|
-
end
|