ardm-is-state_machine 1.2.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 (43) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +35 -0
  3. data/.travis.yml +11 -0
  4. data/Gemfile +65 -0
  5. data/LICENSE +20 -0
  6. data/README.rdoc +102 -0
  7. data/Rakefile +4 -0
  8. data/ardm-is-state_machine.gemspec +24 -0
  9. data/lib/ardm-is-state_machine.rb +1 -0
  10. data/lib/dm-is-state_machine.rb +10 -0
  11. data/lib/dm-is-state_machine/is/data/event.rb +25 -0
  12. data/lib/dm-is-state_machine/is/data/machine.rb +90 -0
  13. data/lib/dm-is-state_machine/is/data/state.rb +21 -0
  14. data/lib/dm-is-state_machine/is/dsl/event_dsl.rb +81 -0
  15. data/lib/dm-is-state_machine/is/dsl/state_dsl.rb +40 -0
  16. data/lib/dm-is-state_machine/is/state_machine.rb +139 -0
  17. data/lib/dm-is-state_machine/is/version.rb +7 -0
  18. data/spec/examples/invalid_events.rb +20 -0
  19. data/spec/examples/invalid_states.rb +20 -0
  20. data/spec/examples/invalid_transitions_1.rb +22 -0
  21. data/spec/examples/invalid_transitions_2.rb +22 -0
  22. data/spec/examples/light_switch.rb +25 -0
  23. data/spec/examples/slot_machine.rb +48 -0
  24. data/spec/examples/traffic_light.rb +48 -0
  25. data/spec/integration/inheritance_spec.rb +11 -0
  26. data/spec/integration/invalid_events_spec.rb +11 -0
  27. data/spec/integration/invalid_states_spec.rb +11 -0
  28. data/spec/integration/invalid_transitions_spec.rb +21 -0
  29. data/spec/integration/slot_machine_spec.rb +86 -0
  30. data/spec/integration/traffic_light_spec.rb +181 -0
  31. data/spec/rcov.opts +6 -0
  32. data/spec/spec.opts +4 -0
  33. data/spec/spec_helper.rb +11 -0
  34. data/spec/unit/data/event_spec.rb +27 -0
  35. data/spec/unit/data/machine_spec.rb +102 -0
  36. data/spec/unit/data/state_spec.rb +21 -0
  37. data/spec/unit/dsl/event_dsl_spec.rb +55 -0
  38. data/spec/unit/dsl/state_dsl_spec.rb +24 -0
  39. data/spec/unit/state_machine_spec.rb +28 -0
  40. data/tasks/spec.rake +38 -0
  41. data/tasks/yard.rake +9 -0
  42. data/tasks/yardstick.rake +19 -0
  43. metadata +132 -0
@@ -0,0 +1,86 @@
1
+ require 'spec_helper'
2
+ require 'examples/slot_machine'
3
+
4
+ describe SlotMachine do
5
+
6
+ before(:each) do
7
+ @sm = SlotMachine.new
8
+ end
9
+
10
+ it "should have a 'mode' column" do
11
+ @sm.attributes.should have_key(:mode)
12
+ end
13
+
14
+ it "should have a 'power_on' column" do
15
+ @sm.attributes.should have_key(:power_on)
16
+ end
17
+
18
+ it "should not have a 'state' column" do
19
+ @sm.attributes.should_not have_key(:state)
20
+ end
21
+
22
+ it "should start in the off state" do
23
+ @sm.mode.should == "off"
24
+ end
25
+
26
+ it "should start with power_on == false" do
27
+ @sm.power_on.should == false
28
+ end
29
+
30
+ describe "in :off mode" do
31
+
32
+ before(:each) do
33
+ @sm.mode = :off
34
+ @sm.power_on = false
35
+ end
36
+
37
+ it "should allow the mode to be set" do
38
+ @sm.mode = :idle
39
+ @sm.save
40
+ @sm.mode.should == "idle"
41
+ end
42
+
43
+ it "turn_on! should work from off mode" do
44
+ @sm.turn_on!
45
+ @sm.mode.should == "idle"
46
+ @sm.power_on.should == true
47
+ end
48
+
49
+ it "turn_on! should not work twice in a row" do
50
+ @sm.turn_on!
51
+ lambda {
52
+ @sm.turn_on!
53
+ }.should raise_error(DataMapper::Is::StateMachine::InvalidEvent)
54
+ end
55
+
56
+ end
57
+
58
+ describe "in :idle mode" do
59
+
60
+ before(:each) do
61
+ @sm.mode = :idle
62
+ @sm.power_on = true
63
+ end
64
+
65
+ it "turn_on! should raise error" do
66
+ lambda {
67
+ @sm.turn_on!
68
+ }.should raise_error(DataMapper::Is::StateMachine::InvalidEvent)
69
+ end
70
+
71
+ it "turn_off! should work" do
72
+ @sm.turn_off!
73
+ @sm.mode.should == "off"
74
+ @sm.power_on.should == false
75
+ end
76
+
77
+ it "turn_off! should not work twice in a row" do
78
+ @sm.turn_off!
79
+ lambda {
80
+ @sm.turn_off!
81
+ }.should raise_error(DataMapper::Is::StateMachine::InvalidEvent)
82
+ end
83
+
84
+ end
85
+
86
+ end
@@ -0,0 +1,181 @@
1
+ require 'spec_helper'
2
+ require 'examples/traffic_light'
3
+
4
+ describe TrafficLight do
5
+
6
+ before(:each) do
7
+ @t = TrafficLight.new
8
+ end
9
+
10
+ it "should have a 'color' column" do
11
+ @t.attributes.should have_key(:color)
12
+ end
13
+
14
+ it "should not have a 'state' column" do
15
+ @t.attributes.should_not have_key(:state)
16
+ end
17
+
18
+ it "should start off in the green state" do
19
+ @t.color.should == "green"
20
+ end
21
+
22
+ it "should allow the color to be set" do
23
+ @t.color = :yellow
24
+ @t.save
25
+ @t.color.should == "yellow"
26
+ end
27
+
28
+ it "should have called the :enter Proc" do
29
+ @t.log.should == %w(G)
30
+ end
31
+
32
+ it "should call the original initialize method" do
33
+ @t.init.should == [:init]
34
+ end
35
+
36
+ describe 'forward!' do
37
+
38
+ it "should respond to :forward!" do
39
+ @t.respond_to?(:forward!).should == true
40
+ end
41
+
42
+ it "should transition to :yellow, :red, :green" do
43
+ @t.color.should == "green"
44
+ @t.forward!
45
+ @t.color.should == "yellow"
46
+ @t.log.should == %w(G Y)
47
+ @t.forward!
48
+ @t.color.should == "red"
49
+ @t.log.should == %w(G Y R)
50
+ @t.forward!
51
+ @t.color.should == "green"
52
+ @t.log.should == %w(G Y R G)
53
+ @t.should be_new
54
+ end
55
+
56
+ it "should skip to :yellow then transition to :red, :green, :yellow" do
57
+ @t.color = :yellow
58
+ @t.color.should == "yellow"
59
+ @t.log.should == %w(G)
60
+ @t.forward!
61
+ @t.color.should == "red"
62
+ @t.log.should == %w(G R)
63
+ @t.forward!
64
+ @t.color.should == "green"
65
+ @t.log.should == %w(G R G)
66
+ @t.forward!
67
+ @t.color.should == "yellow"
68
+ @t.log.should == %w(G R G Y)
69
+ @t.should be_new
70
+ end
71
+
72
+ it "should skip to :red then transition to :green, :yellow, :red" do
73
+ @t.color = :red
74
+ @t.color.should == "red"
75
+ @t.log.should == %w(G)
76
+ @t.forward!
77
+ @t.color.should == "green"
78
+ @t.log.should == %w(G G)
79
+ @t.forward!
80
+ @t.color.should == "yellow"
81
+ @t.log.should == %w(G G Y)
82
+ @t.forward!
83
+ @t.color.should == "red"
84
+ @t.log.should == %w(G G Y R)
85
+ @t.should be_new
86
+ end
87
+
88
+ end
89
+
90
+ describe 'backward!' do
91
+
92
+ it "should respond to 'backward!'" do
93
+ @t.respond_to?(:backward!).should == true
94
+ end
95
+
96
+ it "should transition to :red, :yellow, :green" do
97
+ @t.color.should == "green"
98
+ @t.log.should == %w(G)
99
+ @t.backward!
100
+ @t.color.should == "red"
101
+ @t.log.should == %w(G R)
102
+ @t.backward!
103
+ @t.color.should == "yellow"
104
+ @t.log.should == %w(G R Y)
105
+ @t.backward!
106
+ @t.color.should == "green"
107
+ @t.log.should == %w(G R Y G)
108
+ @t.should be_new
109
+ end
110
+
111
+ it "should skip to :yellow then transition to :green, :red, :yellow" do
112
+ @t.color = :yellow
113
+ @t.color.should == "yellow"
114
+ @t.log.should == %w(G)
115
+ @t.backward!
116
+ @t.color.should == "green"
117
+ @t.log.should == %w(G G)
118
+ @t.backward!
119
+ @t.color.should == "red"
120
+ @t.log.should == %w(G G R)
121
+ @t.backward!
122
+ @t.color.should == "yellow"
123
+ @t.log.should == %w(G G R Y)
124
+ @t.should be_new
125
+ end
126
+
127
+ it "should skip to :red then transition to :yellow, :green, :red" do
128
+ @t.color = :red
129
+ @t.color.should == "red"
130
+ @t.log.should == %w(G)
131
+ @t.backward!
132
+ @t.color.should == "yellow"
133
+ @t.log.should == %w(G Y)
134
+ @t.backward!
135
+ @t.color.should == "green"
136
+ @t.log.should == %w(G Y G)
137
+ @t.backward!
138
+ @t.color.should == "red"
139
+ @t.log.should == %w(G Y G R)
140
+ @t.should be_new
141
+ end
142
+
143
+ end
144
+
145
+ describe "hooks" do
146
+
147
+ it "should log initial state before state is changed on a before hook" do
148
+ @t.forward!
149
+ @t.before_hook_log.should == %w(green)
150
+ @t.forward!
151
+ @t.before_hook_log.should == %w(green yellow)
152
+ @t.forward!
153
+ @t.before_hook_log.should == %w(green yellow red)
154
+ end
155
+
156
+ it "should log final state before state is changed on a before hook" do
157
+ @t.forward!
158
+ @t.after_hook_log.should == %w(yellow)
159
+ @t.forward!
160
+ @t.after_hook_log.should == %w(yellow red)
161
+ @t.forward!
162
+ @t.after_hook_log.should == %w(yellow red green)
163
+ end
164
+
165
+ end
166
+
167
+ describe "overwriting event methods" do
168
+
169
+ before(:all) do
170
+ TrafficLight.class_eval "def forward!(added_param); log << added_param; transition!(:forward); end"
171
+ end
172
+
173
+ it "should transition normally with added functionality" do
174
+ @t.color.should == "green"
175
+ @t.forward!("test")
176
+ @t.color.should == "yellow"
177
+ @t.log.should == %w(G test Y)
178
+ end
179
+
180
+ end
181
+ end
@@ -0,0 +1,6 @@
1
+ --exclude "spec,^/"
2
+ --sort coverage
3
+ --callsites
4
+ --xrefs
5
+ --profile
6
+ --text-summary
@@ -0,0 +1,4 @@
1
+ --colour
2
+ --loadby random
3
+ --format profile
4
+ --backtrace
@@ -0,0 +1,11 @@
1
+ require 'dm-core/spec/setup'
2
+ require 'dm-core/spec/lib/adapter_helpers'
3
+
4
+ require 'dm-is-state_machine'
5
+ require 'dm-migrations'
6
+
7
+ DataMapper::Spec.setup
8
+
9
+ Spec::Runner.configure do |config|
10
+ config.extend(DataMapper::Spec::Adapters::Helpers)
11
+ end
@@ -0,0 +1,27 @@
1
+ require 'spec_helper'
2
+
3
+ module EventHelper
4
+ def new_event(*args)
5
+ DataMapper::Is::StateMachine::Data::Event.new(*args)
6
+ end
7
+ end
8
+
9
+ describe DataMapper::Is::StateMachine::Data::Event do
10
+ include EventHelper
11
+
12
+ before(:each) do
13
+ @machine = mock("machine")
14
+ @event = new_event(:ping, @machine)
15
+ end
16
+
17
+ it "#initialize should work" do
18
+ @event.name.should == :ping
19
+ @event.machine.should == @machine
20
+ @event.transitions.should == []
21
+ end
22
+
23
+ it "#add_transition should work" do
24
+ @event.add_transition(:nothing, :pinged)
25
+ @event.transitions.should == [{:from => :nothing, :to => :pinged }]
26
+ end
27
+ end
@@ -0,0 +1,102 @@
1
+ require 'spec_helper'
2
+
3
+ module MachineHelper
4
+ def new_machine(*args)
5
+ DataMapper::Is::StateMachine::Data::Machine.new(*args)
6
+ end
7
+
8
+ def new_state(name, machine, options = {})
9
+ mock(name, :name => name, :machine => machine, :options => options)
10
+ end
11
+
12
+ def new_event(name, machine)
13
+ mock(name, :name => name, :machine => machine)
14
+ end
15
+ end
16
+
17
+ describe DataMapper::Is::StateMachine::Data::Machine do
18
+ include MachineHelper
19
+
20
+ describe "new Machine, no events" do
21
+ before(:each) do
22
+ @machine = new_machine(:power, :off)
23
+ end
24
+
25
+ it "#column should work" do
26
+ @machine.column.should == :power
27
+ end
28
+
29
+ it "#initial should work" do
30
+ @machine.initial.should == :off
31
+ end
32
+
33
+ it "#events should work" do
34
+ @machine.events.should == []
35
+ end
36
+
37
+ it "#states should work" do
38
+ @machine.states.should == []
39
+ end
40
+
41
+ it "#find_event should return nothing" do
42
+ @machine.find_event(:turn_on).should == nil
43
+ end
44
+
45
+ it "#fire_event should raise error" do
46
+ lambda {
47
+ @machine.fire_event(:turn_on, nil)
48
+ }.should raise_error(DataMapper::Is::StateMachine::InvalidEvent)
49
+ end
50
+ end
51
+
52
+ describe "new Machine, 2 states, 1 event" do
53
+ before(:each) do
54
+ @machine = new_machine(:power, :off)
55
+ @machine.states << (@off_state = new_state(:off, @machine))
56
+ @machine.states << (@on_state = new_state(:on, @machine))
57
+ @machine.events << (@turn_on = new_event(:turn_on, @machine))
58
+ @turn_on.stub!(:transitions).and_return([{ :from => :off, :to => :on }])
59
+ end
60
+
61
+ it "#column should work" do
62
+ @machine.column.should == :power
63
+ end
64
+
65
+ it "#initial should work" do
66
+ @machine.initial.should == :off
67
+ end
68
+
69
+ it "#events should work" do
70
+ @machine.events.should == [@turn_on]
71
+ end
72
+
73
+ it "#states should work" do
74
+ @machine.states.should == [@off_state, @on_state]
75
+ end
76
+
77
+ it "#current_state should work" do
78
+ @machine.current_state.should == @off_state
79
+ end
80
+
81
+ it "#current_state_name should work" do
82
+ @machine.current_state_name.should == :off
83
+ end
84
+
85
+ it "#find_event should return nothing" do
86
+ @machine.find_event(:turn_on).should == @turn_on
87
+ end
88
+
89
+ it "#fire_event should change state" do
90
+ resource = mock("resource")
91
+ resource.should_receive(:run_hook_if_present).exactly(2).times.with(nil)
92
+ @machine.fire_event(:turn_on, resource)
93
+ @machine.current_state.should == @on_state
94
+ @machine.current_state_name.should == :on
95
+ end
96
+
97
+ end
98
+
99
+ # TODO: spec fire_event where :run_hook_if_present fires two times,
100
+ # but with :enter the first and :exit the second.
101
+
102
+ end
@@ -0,0 +1,21 @@
1
+ require 'spec_helper'
2
+
3
+ module StateHelper
4
+ def new_state(*args)
5
+ DataMapper::Is::StateMachine::Data::State.new(*args)
6
+ end
7
+ end
8
+
9
+ describe DataMapper::Is::StateMachine::Data::State do
10
+ include StateHelper
11
+
12
+ before(:each) do
13
+ @machine = mock("machine")
14
+ @state = new_state(:off, @machine)
15
+ end
16
+
17
+ it "#initialize should work" do
18
+ @state.name.should == :off
19
+ @state.machine.should == @machine
20
+ end
21
+ end