statemachine 0.3.0 → 0.4.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.
- data/CHANGES +10 -0
- data/TODO +1 -1
- data/lib/statemachine/state.rb +1 -1
- data/lib/statemachine/statemachine.rb +33 -8
- data/lib/statemachine/version.rb +1 -1
- data/spec/action_invokation_spec.rb +10 -10
- data/spec/builder_spec.rb +36 -36
- data/spec/default_transition_spec.rb +28 -6
- data/spec/history_spec.rb +44 -11
- data/spec/sm_action_parameterization_spec.rb +37 -37
- data/spec/sm_entry_exit_actions_spec.rb +18 -18
- data/spec/sm_odds_n_ends_spec.rb +31 -14
- data/spec/sm_simple_spec.rb +5 -5
- data/spec/sm_super_state_spec.rb +10 -10
- data/spec/sm_turnstile_spec.rb +27 -27
- data/spec/spec_helper.rb +5 -5
- data/spec/transition_spec.rb +36 -36
- metadata +3 -3
data/CHANGES
CHANGED
@@ -1,5 +1,15 @@
|
|
1
1
|
= Statemachine Changelog
|
2
2
|
|
3
|
+
== Version 0.4.0
|
4
|
+
|
5
|
+
Feature enhancements
|
6
|
+
* enabled nested superstate history
|
7
|
+
* TransitionMissingException's are raised when the statemachine can't respond to an event
|
8
|
+
* Statmachine overrides respond_to? to respond to valid events.
|
9
|
+
|
10
|
+
Behavior Fixes
|
11
|
+
* fixed default transition so that superstate transitions have priority over default
|
12
|
+
|
3
13
|
== Version 0.3.0
|
4
14
|
|
5
15
|
Feature enhancements
|
data/TODO
CHANGED
data/lib/statemachine/state.rb
CHANGED
@@ -22,8 +22,8 @@ module Statemachine
|
|
22
22
|
|
23
23
|
def transition_for(event)
|
24
24
|
transition = @transitions[event]
|
25
|
+
transition = @superstate.transition_for(event) if @superstate and not transition
|
25
26
|
transition = @default_transition if not transition
|
26
|
-
transition = @superstate.transition_for(event) if @superstate and not transition
|
27
27
|
return transition
|
28
28
|
end
|
29
29
|
|
@@ -3,6 +3,9 @@ module Statemachine
|
|
3
3
|
class StatemachineException < Exception
|
4
4
|
end
|
5
5
|
|
6
|
+
class TransitionMissingException < Exception
|
7
|
+
end
|
8
|
+
|
6
9
|
# Used at runtime to execute the behavior of the statemachine.
|
7
10
|
# Should be created by using the Statemachine.build method.
|
8
11
|
#
|
@@ -86,7 +89,7 @@ module Statemachine
|
|
86
89
|
if transition
|
87
90
|
transition.invoke(@state, self, args)
|
88
91
|
else
|
89
|
-
raise
|
92
|
+
raise TransitionMissingException.new("#{@state} does not respond to the '#{event}' event.")
|
90
93
|
end
|
91
94
|
else
|
92
95
|
raise StatemachineException.new("The state machine isn't in any state while processing the '#{event}' event.")
|
@@ -104,8 +107,7 @@ module Statemachine
|
|
104
107
|
superstate_id = base_id(id)
|
105
108
|
superstate = @states[superstate_id]
|
106
109
|
raise StatemachineException.new("No history exists for #{superstate} since it is not a super state.") if superstate.is_concrete?
|
107
|
-
|
108
|
-
return superstate.history
|
110
|
+
return load_history(superstate)
|
109
111
|
else
|
110
112
|
state = State.new(id, @root, self)
|
111
113
|
@states[id] = state
|
@@ -125,13 +127,24 @@ module Statemachine
|
|
125
127
|
end
|
126
128
|
end
|
127
129
|
|
130
|
+
def respond_to?(message)
|
131
|
+
return true if super(message)
|
132
|
+
return true if @state.transition_for(message)
|
133
|
+
return false
|
134
|
+
end
|
135
|
+
|
128
136
|
def method_missing(message, *args) #:nodoc:
|
129
137
|
if @state and @state.transition_for(message)
|
130
|
-
|
131
|
-
|
132
|
-
|
138
|
+
process_event(message.to_sym, *args)
|
139
|
+
# method = self.method(:process_event)
|
140
|
+
# params = [message.to_sym].concat(args)
|
141
|
+
# method.call(*params)
|
133
142
|
else
|
134
|
-
|
143
|
+
begin
|
144
|
+
super(message, args)
|
145
|
+
rescue NoMethodError
|
146
|
+
process_event(message.to_sym, *args)
|
147
|
+
end
|
135
148
|
end
|
136
149
|
end
|
137
150
|
|
@@ -145,6 +158,18 @@ module Statemachine
|
|
145
158
|
return history_id.to_s[0...-2].to_sym
|
146
159
|
end
|
147
160
|
|
161
|
+
def load_history(superstate)
|
162
|
+
100.times do
|
163
|
+
history = superstate.history
|
164
|
+
raise StatemachineException.new("#{superstate} doesn't have any history yet.") if not history
|
165
|
+
if history.is_concrete?
|
166
|
+
return history
|
167
|
+
else
|
168
|
+
superstate = history
|
169
|
+
end
|
170
|
+
end
|
171
|
+
raise StatemachineException.new("No history found within 100 levels of nested superstates.")
|
172
|
+
end
|
173
|
+
|
148
174
|
end
|
149
|
-
|
150
175
|
end
|
data/lib/statemachine/version.rb
CHANGED
@@ -19,13 +19,13 @@ class Noodle
|
|
19
19
|
|
20
20
|
end
|
21
21
|
|
22
|
-
|
22
|
+
describe "Action Invokation" do
|
23
23
|
|
24
|
-
|
24
|
+
before(:each) do
|
25
25
|
@noodle = Noodle.new
|
26
26
|
end
|
27
27
|
|
28
|
-
|
28
|
+
it "Proc actions" do
|
29
29
|
sm = Statemachine.build do |smb|
|
30
30
|
smb.trans :cold, :fire, :hot, Proc.new { @cooked = true }
|
31
31
|
end
|
@@ -33,10 +33,10 @@ context "Action Invokation" do
|
|
33
33
|
sm.context = @noodle
|
34
34
|
sm.fire
|
35
35
|
|
36
|
-
@noodle.cooked.
|
36
|
+
@noodle.cooked.should equal(true)
|
37
37
|
end
|
38
38
|
|
39
|
-
|
39
|
+
it "Symbol actions" do
|
40
40
|
sm = Statemachine.build do |smb|
|
41
41
|
smb.trans :cold, :fire, :hot, :cook
|
42
42
|
smb.trans :hot, :mold, :changed, :transform
|
@@ -45,22 +45,22 @@ context "Action Invokation" do
|
|
45
45
|
sm.context = @noodle
|
46
46
|
sm.fire
|
47
47
|
|
48
|
-
@noodle.cooked.
|
48
|
+
@noodle.cooked.should equal(true)
|
49
49
|
|
50
50
|
sm.mold "capellini"
|
51
51
|
|
52
|
-
@noodle.shape.
|
52
|
+
@noodle.shape.should eql("capellini")
|
53
53
|
end
|
54
54
|
|
55
|
-
|
55
|
+
it "String actions" do
|
56
56
|
sm = Statemachine.build do |smb|
|
57
57
|
smb.trans :cold, :fire, :hot, "@shape = 'fettucini'; @cooked = true"
|
58
58
|
end
|
59
59
|
sm.context = @noodle
|
60
60
|
|
61
61
|
sm.fire
|
62
|
-
@noodle.shape.
|
63
|
-
@noodle.cooked.
|
62
|
+
@noodle.shape.should eql("fettucini")
|
63
|
+
@noodle.cooked.should equal(true)
|
64
64
|
end
|
65
65
|
|
66
66
|
|
data/spec/builder_spec.rb
CHANGED
@@ -1,24 +1,24 @@
|
|
1
1
|
require File.dirname(__FILE__) + '/spec_helper'
|
2
2
|
|
3
|
-
|
3
|
+
describe "Builder" do
|
4
4
|
|
5
|
-
|
5
|
+
before(:each) do
|
6
6
|
@log = []
|
7
7
|
end
|
8
8
|
|
9
9
|
def check_switch(sm)
|
10
|
-
sm.state.
|
10
|
+
sm.state.should equal(:off)
|
11
11
|
|
12
12
|
sm.toggle
|
13
|
-
@log[0].
|
14
|
-
sm.state.
|
13
|
+
@log[0].should eql("toggle on")
|
14
|
+
sm.state.should equal(:on)
|
15
15
|
|
16
16
|
sm.toggle
|
17
|
-
@log[1].
|
18
|
-
sm.state.
|
17
|
+
@log[1].should eql("toggle off")
|
18
|
+
sm.state.should equal(:off)
|
19
19
|
end
|
20
20
|
|
21
|
-
|
21
|
+
it "Building a the switch, relaxed" do
|
22
22
|
sm = Statemachine.build do
|
23
23
|
trans :off, :toggle, :on, Proc.new { @log << "toggle on" }
|
24
24
|
trans :on, :toggle, :off, Proc.new { @log << "toggle off" }
|
@@ -28,7 +28,7 @@ context "Builder" do
|
|
28
28
|
check_switch sm
|
29
29
|
end
|
30
30
|
|
31
|
-
|
31
|
+
it "Building a the switch, strict" do
|
32
32
|
sm = Statemachine.build do
|
33
33
|
state(:off) { |s| s.event :toggle, :on, Proc.new { @log << "toggle on" } }
|
34
34
|
state(:on) { |s| s.event :toggle, :off, Proc.new { @log << "toggle off" } }
|
@@ -38,7 +38,7 @@ context "Builder" do
|
|
38
38
|
check_switch sm
|
39
39
|
end
|
40
40
|
|
41
|
-
|
41
|
+
it "Adding a superstate to the switch" do
|
42
42
|
the_context = self
|
43
43
|
sm = Statemachine.build do
|
44
44
|
superstate :operation do
|
@@ -52,16 +52,16 @@ context "Builder" do
|
|
52
52
|
context the_context
|
53
53
|
end
|
54
54
|
|
55
|
-
sm.state.
|
55
|
+
sm.state.should equal(:off)
|
56
56
|
sm.toggle
|
57
57
|
sm.admin
|
58
|
-
sm.state.
|
58
|
+
sm.state.should equal(:testing)
|
59
59
|
sm.resume
|
60
|
-
sm.state.
|
61
|
-
@log.join(",").
|
60
|
+
sm.state.should equal(:on)
|
61
|
+
@log.join(",").should eql("toggle on,testing,resuming")
|
62
62
|
end
|
63
63
|
|
64
|
-
|
64
|
+
it "entry exit actions" do
|
65
65
|
the_context = self
|
66
66
|
sm = Statemachine.build do
|
67
67
|
state :off do
|
@@ -74,14 +74,14 @@ context "Builder" do
|
|
74
74
|
end
|
75
75
|
|
76
76
|
sm.toggle
|
77
|
-
sm.state.
|
77
|
+
sm.state.should equal(:on)
|
78
78
|
sm.toggle
|
79
|
-
sm.state.
|
79
|
+
sm.state.should equal(:off)
|
80
80
|
|
81
|
-
@log.join(",").
|
81
|
+
@log.join(",").should eql("enter off,exit off,toggle on,toggle off,enter off")
|
82
82
|
end
|
83
83
|
|
84
|
-
|
84
|
+
it "History state" do
|
85
85
|
the_context = self
|
86
86
|
sm = Statemachine.build do
|
87
87
|
superstate :operation do
|
@@ -100,12 +100,12 @@ context "Builder" do
|
|
100
100
|
|
101
101
|
sm.admin
|
102
102
|
sm.resume
|
103
|
-
sm.state.
|
103
|
+
sm.state.should equal(:off)
|
104
104
|
|
105
|
-
@log.join(",").
|
105
|
+
@log.join(",").should eql("enter off,testing,resuming,enter off")
|
106
106
|
end
|
107
107
|
|
108
|
-
|
108
|
+
it "entry and exit action created from superstate builder" do
|
109
109
|
the_context = self
|
110
110
|
sm = Statemachine.build do
|
111
111
|
trans :off, :toggle, :on, Proc.new { @log << "toggle on" }
|
@@ -118,11 +118,11 @@ context "Builder" do
|
|
118
118
|
sm.toggle
|
119
119
|
sm.toggle
|
120
120
|
|
121
|
-
@log.join(",").
|
121
|
+
@log.join(",").should eql("entering off,toggle on,exiting on,toggle off,entering off")
|
122
122
|
|
123
123
|
end
|
124
124
|
|
125
|
-
|
125
|
+
it "superstate as startstate" do
|
126
126
|
|
127
127
|
lambda do
|
128
128
|
sm = Statemachine.build do
|
@@ -131,11 +131,11 @@ context "Builder" do
|
|
131
131
|
end
|
132
132
|
end
|
133
133
|
|
134
|
-
sm.state.
|
135
|
-
end.
|
134
|
+
sm.state.should equal(:luigi)
|
135
|
+
end.should_not raise_error(Exception)
|
136
136
|
end
|
137
137
|
|
138
|
-
|
138
|
+
it "setting the start state before any other states declared" do
|
139
139
|
|
140
140
|
sm = Statemachine.build do
|
141
141
|
startstate :right
|
@@ -144,12 +144,12 @@ context "Builder" do
|
|
144
144
|
trans :right, :pull, :middle
|
145
145
|
end
|
146
146
|
|
147
|
-
sm.state.
|
147
|
+
sm.state.should equal(:right)
|
148
148
|
sm.pull
|
149
|
-
sm.state.
|
149
|
+
sm.state.should equal(:middle)
|
150
150
|
end
|
151
151
|
|
152
|
-
|
152
|
+
it "setting start state which is in a super state" do
|
153
153
|
sm = Statemachine.build do
|
154
154
|
startstate :right
|
155
155
|
superstate :table do
|
@@ -161,16 +161,16 @@ context "Builder" do
|
|
161
161
|
state :floor
|
162
162
|
end
|
163
163
|
|
164
|
-
sm.state.
|
164
|
+
sm.state.should equal(:right)
|
165
165
|
sm.pull
|
166
|
-
sm.state.
|
166
|
+
sm.state.should equal(:middle)
|
167
167
|
sm.push
|
168
|
-
sm.state.
|
168
|
+
sm.state.should equal(:right)
|
169
169
|
sm.tilt
|
170
|
-
sm.state.
|
170
|
+
sm.state.should equal(:floor)
|
171
171
|
end
|
172
172
|
|
173
|
-
|
173
|
+
it "can set context" do
|
174
174
|
widget = Object.new
|
175
175
|
sm = Statemachine.build do
|
176
176
|
context widget
|
@@ -179,7 +179,7 @@ context "Builder" do
|
|
179
179
|
sm.context.should be(widget)
|
180
180
|
end
|
181
181
|
|
182
|
-
|
182
|
+
it "statemachine will be set on context if possible" do
|
183
183
|
class Widget
|
184
184
|
attr_accessor :statemachine
|
185
185
|
end
|
@@ -1,8 +1,8 @@
|
|
1
1
|
require File.dirname(__FILE__) + '/spec_helper'
|
2
2
|
|
3
|
-
|
3
|
+
describe "Default Transition" do
|
4
4
|
|
5
|
-
|
5
|
+
before(:each) do
|
6
6
|
@sm = Statemachine.build do
|
7
7
|
trans :default_state, :start, :test_state
|
8
8
|
|
@@ -12,20 +12,20 @@ context "Default Transition" do
|
|
12
12
|
end
|
13
13
|
end
|
14
14
|
|
15
|
-
|
15
|
+
it "the default transition is set" do
|
16
16
|
test_state = @sm.get_state(:test_state)
|
17
17
|
test_state.default_transition.should_not be(nil)
|
18
18
|
test_state.transition_for(:fake_event).should_not be(nil)
|
19
19
|
end
|
20
20
|
|
21
|
-
|
21
|
+
it "Should go to the default_state with any event" do
|
22
22
|
@sm.start
|
23
23
|
@sm.fake_event
|
24
24
|
|
25
25
|
@sm.state.should eql(:default_state)
|
26
26
|
end
|
27
27
|
|
28
|
-
|
28
|
+
it "default transition can have actions" do
|
29
29
|
me = self
|
30
30
|
@sm = Statemachine.build do
|
31
31
|
trans :default_state, :start, :test_state
|
@@ -47,7 +47,7 @@ context "Default Transition" do
|
|
47
47
|
@hi = true
|
48
48
|
end
|
49
49
|
|
50
|
-
|
50
|
+
it "superstate supports the default" do
|
51
51
|
@sm = Statemachine.build do
|
52
52
|
superstate :test_superstate do
|
53
53
|
default :default_state
|
@@ -62,4 +62,26 @@ context "Default Transition" do
|
|
62
62
|
@sm.blah
|
63
63
|
@sm.state.should eql(:default_state)
|
64
64
|
end
|
65
|
+
|
66
|
+
it "superstate transitions do not go to the default state" do
|
67
|
+
@sm = Statemachine.build do
|
68
|
+
superstate :test_superstate do
|
69
|
+
event :not_default, :not_default_state
|
70
|
+
|
71
|
+
state :start_state do
|
72
|
+
default :default_state
|
73
|
+
end
|
74
|
+
|
75
|
+
state :default_state
|
76
|
+
end
|
77
|
+
|
78
|
+
startstate :start_state
|
79
|
+
end
|
80
|
+
|
81
|
+
@sm.state = :start_state
|
82
|
+
@sm.not_default
|
83
|
+
@sm.state.should eql(:not_default_state)
|
84
|
+
end
|
85
|
+
|
86
|
+
|
65
87
|
end
|
data/spec/history_spec.rb
CHANGED
@@ -1,8 +1,8 @@
|
|
1
1
|
require File.dirname(__FILE__) + '/spec_helper'
|
2
2
|
|
3
|
-
|
3
|
+
describe "History States" do
|
4
4
|
|
5
|
-
|
5
|
+
before(:each) do
|
6
6
|
@sm = Statemachine.build do
|
7
7
|
superstate :operate do
|
8
8
|
trans :on, :toggle, :off
|
@@ -16,19 +16,19 @@ context "History States" do
|
|
16
16
|
end
|
17
17
|
end
|
18
18
|
|
19
|
-
|
19
|
+
it "no history allowed for concrete states" do
|
20
20
|
lambda {
|
21
21
|
@sm.dream
|
22
|
-
}.
|
22
|
+
}.should raise_error(Statemachine::StatemachineException, "No history exists for 'on' state since it is not a super state.")
|
23
23
|
end
|
24
24
|
|
25
|
-
|
25
|
+
it "error when trying to use history that doesn't exist yet" do
|
26
26
|
lambda {
|
27
27
|
@sm.fiddle
|
28
|
-
}.
|
28
|
+
}.should raise_error(Statemachine::StatemachineException, "'operate' superstate doesn't have any history yet.")
|
29
29
|
end
|
30
30
|
|
31
|
-
|
31
|
+
it "reseting the statemachine resets history" do
|
32
32
|
@sm.faddle
|
33
33
|
@sm.fiddle
|
34
34
|
@sm.get_state(:operate).history.id.should eql(:on)
|
@@ -39,9 +39,9 @@ context "History States" do
|
|
39
39
|
|
40
40
|
end
|
41
41
|
|
42
|
-
|
42
|
+
describe "History Default" do
|
43
43
|
|
44
|
-
|
44
|
+
before(:each) do
|
45
45
|
@sm = Statemachine.build do
|
46
46
|
superstate :operate do
|
47
47
|
trans :on, :toggle, :off
|
@@ -55,12 +55,12 @@ context "History Default" do
|
|
55
55
|
end
|
56
56
|
end
|
57
57
|
|
58
|
-
|
58
|
+
it "default history" do
|
59
59
|
@sm.fiddle
|
60
60
|
@sm.state.should eql(:on)
|
61
61
|
end
|
62
62
|
|
63
|
-
|
63
|
+
it "reseting the statemachine resets history" do
|
64
64
|
@sm.faddle
|
65
65
|
@sm.toggle
|
66
66
|
@sm.fiddle
|
@@ -72,3 +72,36 @@ context "History Default" do
|
|
72
72
|
|
73
73
|
end
|
74
74
|
|
75
|
+
describe "Nested Superstates" do
|
76
|
+
|
77
|
+
before(:each) do
|
78
|
+
@sm = Statemachine.build do
|
79
|
+
|
80
|
+
superstate :grandpa do
|
81
|
+
trans :start, :go, :daughter
|
82
|
+
event :sister, :great_auntie
|
83
|
+
|
84
|
+
superstate :papa do
|
85
|
+
state :son
|
86
|
+
state :daughter
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
state :great_auntie do
|
91
|
+
event :foo, :grandpa_H
|
92
|
+
end
|
93
|
+
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
it "should use history of sub superstates when transitioning itto it's own history" do
|
98
|
+
@sm.go
|
99
|
+
@sm.sister
|
100
|
+
@sm.foo
|
101
|
+
|
102
|
+
@sm.state.should eql(:daughter)
|
103
|
+
end
|
104
|
+
|
105
|
+
end
|
106
|
+
|
107
|
+
|
@@ -1,99 +1,99 @@
|
|
1
1
|
require File.dirname(__FILE__) + '/spec_helper'
|
2
2
|
|
3
|
-
|
3
|
+
describe "State Machine Odds And Ends" do
|
4
4
|
include SwitchStatemachine
|
5
5
|
|
6
|
-
|
6
|
+
before(:each) do
|
7
7
|
create_switch
|
8
8
|
end
|
9
9
|
|
10
|
-
|
10
|
+
it "action with one parameter" do
|
11
11
|
Statemachine.build(@sm) { |s| s.trans :off, :set, :on, Proc.new { |value| @status = value } }
|
12
12
|
@sm.set "blue"
|
13
|
-
@status.
|
14
|
-
@sm.state.
|
13
|
+
@status.should eql("blue")
|
14
|
+
@sm.state.should equal(:on)
|
15
15
|
end
|
16
16
|
|
17
|
-
|
17
|
+
it "action with two parameters" do
|
18
18
|
Statemachine.build(@sm) { |s| s.trans :off, :set, :on, Proc.new { |a, b| @status = [a, b].join(",") } }
|
19
19
|
@sm.set "blue", "green"
|
20
|
-
@status.
|
21
|
-
@sm.state.
|
20
|
+
@status.should eql("blue,green")
|
21
|
+
@sm.state.should equal(:on)
|
22
22
|
end
|
23
23
|
|
24
|
-
|
24
|
+
it "action with three parameters" do
|
25
25
|
Statemachine.build(@sm) { |s| s.trans :off, :set, :on, Proc.new { |a, b, c| @status = [a, b, c].join(",") } }
|
26
26
|
@sm.set "blue", "green", "red"
|
27
|
-
@status.
|
28
|
-
@sm.state.
|
27
|
+
@status.should eql("blue,green,red")
|
28
|
+
@sm.state.should equal(:on)
|
29
29
|
end
|
30
30
|
|
31
|
-
|
31
|
+
it "action with four parameters" do
|
32
32
|
Statemachine.build(@sm) { |s| s.trans :off, :set, :on, Proc.new { |a, b, c, d| @status = [a, b, c, d].join(",") } }
|
33
33
|
@sm.set "blue", "green", "red", "orange"
|
34
|
-
@status.
|
35
|
-
@sm.state.
|
34
|
+
@status.should eql("blue,green,red,orange")
|
35
|
+
@sm.state.should equal(:on)
|
36
36
|
end
|
37
37
|
|
38
|
-
|
38
|
+
it "action with five parameters" do
|
39
39
|
Statemachine.build(@sm) { |s| s.trans :off, :set, :on, Proc.new { |a, b, c, d, e| @status = [a, b, c, d, e].join(",") } }
|
40
40
|
@sm.set "blue", "green", "red", "orange", "yellow"
|
41
|
-
@status.
|
42
|
-
@sm.state.
|
41
|
+
@status.should eql("blue,green,red,orange,yellow")
|
42
|
+
@sm.state.should equal(:on)
|
43
43
|
end
|
44
44
|
|
45
|
-
|
45
|
+
it "action with six parameters" do
|
46
46
|
Statemachine.build(@sm) { |s| s.trans :off, :set, :on, Proc.new { |a, b, c, d, e, f| @status = [a, b, c, d, e, f].join(",") } }
|
47
47
|
@sm.set "blue", "green", "red", "orange", "yellow", "indigo"
|
48
|
-
@status.
|
49
|
-
@sm.state.
|
48
|
+
@status.should eql("blue,green,red,orange,yellow,indigo")
|
49
|
+
@sm.state.should equal(:on)
|
50
50
|
end
|
51
51
|
|
52
|
-
|
52
|
+
it "action with seven parameters" do
|
53
53
|
Statemachine.build(@sm) { |s| s.trans :off, :set, :on, Proc.new { |a, b, c, d, e, f, g| @status = [a, b, c, d, e, f, g].join(",") } }
|
54
54
|
@sm.set "blue", "green", "red", "orange", "yellow", "indigo", "violet"
|
55
|
-
@status.
|
56
|
-
@sm.state.
|
55
|
+
@status.should eql("blue,green,red,orange,yellow,indigo,violet")
|
56
|
+
@sm.state.should equal(:on)
|
57
57
|
end
|
58
58
|
|
59
|
-
|
59
|
+
it "action with eight parameters" do
|
60
60
|
Statemachine.build(@sm) { |s| s.trans :off, :set, :on, Proc.new { |a, b, c, d, e, f, g, h| @status = [a, b, c, d, e, f, g, h].join(",") } }
|
61
61
|
@sm.set "blue", "green", "red", "orange", "yellow", "indigo", "violet", "ultra-violet"
|
62
|
-
@status.
|
63
|
-
@sm.state.
|
62
|
+
@status.should eql("blue,green,red,orange,yellow,indigo,violet,ultra-violet")
|
63
|
+
@sm.state.should equal(:on)
|
64
64
|
end
|
65
65
|
|
66
|
-
|
66
|
+
it "calling process_event with parameters" do
|
67
67
|
Statemachine.build(@sm) { |s| s.trans :off, :set, :on, Proc.new { |a, b, c| @status = [a, b, c].join(",") } }
|
68
68
|
@sm.process_event(:set, "blue", "green", "red")
|
69
|
-
@status.
|
70
|
-
@sm.state.
|
69
|
+
@status.should eql("blue,green,red")
|
70
|
+
@sm.state.should equal(:on)
|
71
71
|
end
|
72
72
|
|
73
|
-
|
73
|
+
it "Insufficient params" do
|
74
74
|
Statemachine.build(@sm) { |s| s.trans :off, :set, :on, Proc.new { |a, b, c| @status = [a, b, c].join(",") } }
|
75
|
-
lambda { @sm.set "blue", "green" }.
|
75
|
+
lambda { @sm.set "blue", "green" }.should raise_error(Statemachine::StatemachineException,
|
76
76
|
"Insufficient parameters. (transition action from 'off' state invoked by 'set' event)")
|
77
77
|
end
|
78
78
|
|
79
|
-
|
79
|
+
it "infinate args" do
|
80
80
|
Statemachine.build(@sm) { |s| s.trans :off, :set, :on, Proc.new { |*a| @status = a.join(",") } }
|
81
81
|
@sm.set(1, 2, 3)
|
82
|
-
@status.
|
82
|
+
@status.should eql("1,2,3")
|
83
83
|
|
84
84
|
@sm.state = :off
|
85
85
|
@sm.set(1, 2, 3, 4, 5, 6)
|
86
|
-
@status.
|
86
|
+
@status.should eql("1,2,3,4,5,6")
|
87
87
|
end
|
88
88
|
|
89
|
-
|
89
|
+
it "Insufficient params when params are infinate" do
|
90
90
|
Statemachine.build(@sm) { |s| s.trans :off, :set, :on, Proc.new { |a, *b| @status = a.to_s + ":" + b.join(",") } }
|
91
91
|
@sm.set(1, 2, 3)
|
92
|
-
@status.
|
92
|
+
@status.should eql("1:2,3")
|
93
93
|
|
94
94
|
@sm.state = :off
|
95
95
|
|
96
|
-
lambda { @sm.set }.
|
96
|
+
lambda { @sm.set }.should raise_error(Statemachine::StatemachineException,
|
97
97
|
"Insufficient parameters. (transition action from 'off' state invoked by 'set' event)")
|
98
98
|
end
|
99
99
|
end
|
@@ -1,8 +1,8 @@
|
|
1
1
|
require File.dirname(__FILE__) + '/spec_helper'
|
2
2
|
|
3
|
-
|
3
|
+
describe "State Machine Entry and Exit Actions" do
|
4
4
|
|
5
|
-
|
5
|
+
before(:each) do
|
6
6
|
@log = []
|
7
7
|
@sm = Statemachine.build do
|
8
8
|
trans :off, :toggle, :on, Proc.new { @log << "on" }
|
@@ -11,50 +11,50 @@ context "State Machine Entry and Exit Actions" do
|
|
11
11
|
@sm.context = self
|
12
12
|
end
|
13
13
|
|
14
|
-
|
14
|
+
it "entry action" do
|
15
15
|
@sm.get_state(:on).entry_action = Proc.new { @log << "entered_on" }
|
16
16
|
|
17
17
|
@sm.toggle
|
18
18
|
|
19
|
-
@log.join(",").
|
19
|
+
@log.join(",").should eql("on,entered_on")
|
20
20
|
end
|
21
21
|
|
22
|
-
|
22
|
+
it "exit action" do
|
23
23
|
@sm.get_state(:off).exit_action = Proc.new { @log << "exited_off" }
|
24
24
|
|
25
25
|
@sm.toggle
|
26
26
|
|
27
|
-
@log.join(",").
|
27
|
+
@log.join(",").should eql("exited_off,on")
|
28
28
|
end
|
29
29
|
|
30
|
-
|
30
|
+
it "exit and entry" do
|
31
31
|
@sm.get_state(:off).exit_action = Proc.new { @log << "exited_off" }
|
32
32
|
@sm.get_state(:on).entry_action = Proc.new { @log << "entered_on" }
|
33
33
|
|
34
34
|
@sm.toggle
|
35
35
|
|
36
|
-
@log.join(",").
|
36
|
+
@log.join(",").should eql("exited_off,on,entered_on")
|
37
37
|
end
|
38
38
|
|
39
|
-
|
39
|
+
it "entry and exit actions may be parameterized" do
|
40
40
|
@sm.get_state(:off).exit_action = Proc.new { |a| @log << "exited_off(#{a})" }
|
41
41
|
@sm.get_state(:on).entry_action = Proc.new { |a, b| @log << "entered_on(#{a},#{b})" }
|
42
42
|
|
43
43
|
@sm.toggle "one", "two"
|
44
44
|
|
45
|
-
@log.join(",").
|
45
|
+
@log.join(",").should eql("exited_off(one),on,entered_on(one,two)")
|
46
46
|
end
|
47
47
|
|
48
|
-
|
48
|
+
it "current state is set prior to exit and entry actions" do
|
49
49
|
@sm.get_state(:off).exit_action = Proc.new { @log << @sm.state }
|
50
50
|
@sm.get_state(:on).entry_action = Proc.new { @log << @sm.state }
|
51
51
|
|
52
52
|
@sm.toggle
|
53
53
|
|
54
|
-
@log.join(",").
|
54
|
+
@log.join(",").should eql("off,on,on")
|
55
55
|
end
|
56
56
|
|
57
|
-
|
57
|
+
it "current state is set prior to exit and entry actions even with super states" do
|
58
58
|
@sm = Statemachine::Statemachine.new
|
59
59
|
Statemachine.build(@sm) do
|
60
60
|
superstate :off_super do
|
@@ -72,18 +72,18 @@ context "State Machine Entry and Exit Actions" do
|
|
72
72
|
@sm.context = self
|
73
73
|
|
74
74
|
@sm.toggle
|
75
|
-
@log.join(",").
|
75
|
+
@log.join(",").should eql("off,super_on,on")
|
76
76
|
end
|
77
77
|
|
78
|
-
|
78
|
+
it "entry actions invokes another event" do
|
79
79
|
@sm.get_state(:on).entry_action = Proc.new { @sm.toggle }
|
80
80
|
|
81
81
|
@sm.toggle
|
82
|
-
@log.join(",").
|
83
|
-
@sm.state.
|
82
|
+
@log.join(",").should eql("on,off")
|
83
|
+
@sm.state.should equal(:off)
|
84
84
|
end
|
85
85
|
|
86
|
-
|
86
|
+
it "startstate's entry action should be called when the statemachine starts" do
|
87
87
|
the_context = self
|
88
88
|
@sm = Statemachine.build do
|
89
89
|
trans :a, :b, :c
|
data/spec/sm_odds_n_ends_spec.rb
CHANGED
@@ -1,41 +1,58 @@
|
|
1
1
|
require File.dirname(__FILE__) + '/spec_helper'
|
2
2
|
|
3
|
-
|
3
|
+
describe "State Machine Odds And Ends" do
|
4
4
|
include SwitchStatemachine
|
5
5
|
|
6
|
-
|
6
|
+
before(:each) do
|
7
7
|
create_switch
|
8
8
|
end
|
9
9
|
|
10
|
-
|
11
|
-
|
10
|
+
it "method missing delegates to super in case of no event" do
|
11
|
+
$method_missing_called = false
|
12
|
+
module Blah
|
13
|
+
def method_missing(message, *args)
|
14
|
+
$method_missing_called = true
|
15
|
+
end
|
16
|
+
end
|
17
|
+
@sm.extend(Blah)
|
18
|
+
@sm.blah
|
19
|
+
$method_missing_called.should eql(true)
|
20
|
+
end
|
21
|
+
|
22
|
+
it "should raise TransistionMissingException when the state doesn't respond to the event" do
|
23
|
+
lambda { @sm.blah }.should raise_error(Statemachine::TransitionMissingException, "'off' state does not respond to the 'blah' event.")
|
24
|
+
end
|
25
|
+
|
26
|
+
it "should respond to valid events" do
|
27
|
+
@sm.respond_to?(:toggle).should eql(true)
|
28
|
+
@sm.respond_to?(:blah).should eql(false)
|
12
29
|
end
|
13
30
|
|
14
|
-
|
15
|
-
@sm.state.
|
31
|
+
it "set state with string" do
|
32
|
+
@sm.state.should equal(:off)
|
16
33
|
@sm.state = "on"
|
17
|
-
@sm.state.
|
34
|
+
@sm.state.should equal(:on)
|
18
35
|
end
|
19
36
|
|
20
|
-
|
21
|
-
@sm.state.
|
37
|
+
it "set state with symbol" do
|
38
|
+
@sm.state.should equal(:off)
|
22
39
|
@sm.state = :on
|
23
|
-
@sm.state.
|
40
|
+
@sm.state.should equal(:on)
|
24
41
|
end
|
25
42
|
|
26
|
-
|
43
|
+
it "process event accepts strings" do
|
27
44
|
@sm.process_event("toggle")
|
28
|
-
@sm.state.
|
45
|
+
@sm.state.should equal(:on)
|
29
46
|
end
|
30
47
|
|
31
|
-
|
48
|
+
it "states without transitions are valid" do
|
32
49
|
@sm = Statemachine.build do
|
33
50
|
trans :middle, :push, :stuck
|
34
51
|
startstate :middle
|
35
52
|
end
|
36
53
|
|
37
54
|
@sm.push
|
38
|
-
@sm.state.
|
55
|
+
@sm.state.should equal(:stuck)
|
39
56
|
end
|
40
57
|
|
41
58
|
end
|
data/spec/sm_simple_spec.rb
CHANGED
@@ -1,23 +1,23 @@
|
|
1
1
|
require File.dirname(__FILE__) + '/spec_helper'
|
2
2
|
|
3
|
-
|
4
|
-
|
3
|
+
describe "simple cases:" do
|
4
|
+
before(:each) do
|
5
5
|
@sm = Statemachine::Statemachine.new
|
6
6
|
@sm.context = self
|
7
7
|
@count = 0
|
8
8
|
@proc = Proc.new {@count = @count + 1}
|
9
9
|
end
|
10
10
|
|
11
|
-
|
11
|
+
it "reset" do
|
12
12
|
Statemachine.build(@sm) { |s| s.trans :start, :blah, :end, @proc }
|
13
13
|
@sm.process_event(:blah)
|
14
14
|
|
15
15
|
@sm.reset
|
16
16
|
|
17
|
-
@sm.state.
|
17
|
+
@sm.state.should equal(:start)
|
18
18
|
end
|
19
19
|
|
20
|
-
|
20
|
+
it "no proc in transition" do
|
21
21
|
Statemachine.build(@sm) { |s| s.trans :on, :flip, :off }
|
22
22
|
|
23
23
|
@sm.flip
|
data/spec/sm_super_state_spec.rb
CHANGED
@@ -1,9 +1,9 @@
|
|
1
1
|
require File.dirname(__FILE__) + '/spec_helper'
|
2
2
|
|
3
|
-
|
3
|
+
describe "Turn Stile" do
|
4
4
|
include TurnstileStatemachine
|
5
5
|
|
6
|
-
|
6
|
+
before(:each) do
|
7
7
|
create_turnstile
|
8
8
|
|
9
9
|
@out_out_order = false
|
@@ -22,19 +22,19 @@ context "Turn Stile" do
|
|
22
22
|
@sm.context = self
|
23
23
|
end
|
24
24
|
|
25
|
-
|
25
|
+
it "substates respond to superstate transitions" do
|
26
26
|
@sm.process_event(:maintain)
|
27
|
-
@sm.state.
|
28
|
-
@locked.
|
29
|
-
@out_of_order.
|
27
|
+
@sm.state.should equal(:maintenance)
|
28
|
+
@locked.should equal(true)
|
29
|
+
@out_of_order.should equal(true)
|
30
30
|
end
|
31
31
|
|
32
|
-
|
32
|
+
it "after transitions, substates respond to superstate transitions" do
|
33
33
|
@sm.coin
|
34
34
|
@sm.maintain
|
35
|
-
@sm.state.
|
36
|
-
@locked.
|
37
|
-
@out_of_order.
|
35
|
+
@sm.state.should equal(:maintenance)
|
36
|
+
@locked.should equal(false)
|
37
|
+
@out_of_order.should equal(true)
|
38
38
|
end
|
39
39
|
|
40
40
|
end
|
data/spec/sm_turnstile_spec.rb
CHANGED
@@ -1,18 +1,18 @@
|
|
1
1
|
require File.dirname(__FILE__) + '/spec_helper'
|
2
2
|
|
3
|
-
|
3
|
+
describe "Turn Stile" do
|
4
4
|
include TurnstileStatemachine
|
5
5
|
|
6
|
-
|
6
|
+
before(:each) do
|
7
7
|
create_turnstile
|
8
8
|
end
|
9
9
|
|
10
|
-
|
10
|
+
it "connections" do
|
11
11
|
locked_state = @sm.get_state(:locked)
|
12
12
|
unlocked_state = @sm.get_state(:unlocked)
|
13
13
|
|
14
|
-
locked_state.transitions.length.
|
15
|
-
unlocked_state.transitions.length.
|
14
|
+
locked_state.transitions.length.should equal(2)
|
15
|
+
unlocked_state.transitions.length.should equal(2)
|
16
16
|
|
17
17
|
check_transition(locked_state.transitions[:coin], :locked, :unlocked, :coin, @unlock)
|
18
18
|
check_transition(locked_state.transitions[:pass], :locked, :locked, :pass, @alarm)
|
@@ -20,57 +20,57 @@ context "Turn Stile" do
|
|
20
20
|
check_transition(unlocked_state.transitions[:coin], :unlocked, :locked, :coin, @thankyou)
|
21
21
|
end
|
22
22
|
|
23
|
-
|
23
|
+
it "start state" do
|
24
24
|
@sm.reset
|
25
|
-
@sm.startstate.should
|
26
|
-
@sm.state.should
|
25
|
+
@sm.startstate.should equal(:locked)
|
26
|
+
@sm.state.should equal(:locked)
|
27
27
|
end
|
28
28
|
|
29
|
-
|
29
|
+
it "bad event" do
|
30
30
|
begin
|
31
31
|
@sm.process_event(:blah)
|
32
32
|
self.should.fail_with_message("Exception expected")
|
33
33
|
rescue Exception => e
|
34
|
-
e.class.should
|
35
|
-
e.to_s.
|
34
|
+
e.class.should equal(Statemachine::TransitionMissingException)
|
35
|
+
e.to_s.should eql("'locked' state does not respond to the 'blah' event.")
|
36
36
|
end
|
37
37
|
end
|
38
38
|
|
39
|
-
|
39
|
+
it "locked state with a coin" do
|
40
40
|
@sm.process_event(:coin)
|
41
41
|
|
42
|
-
@sm.state.should
|
43
|
-
@locked.should
|
42
|
+
@sm.state.should equal(:unlocked)
|
43
|
+
@locked.should equal(false)
|
44
44
|
end
|
45
45
|
|
46
|
-
|
46
|
+
it "locked state with pass event" do
|
47
47
|
@sm.process_event(:pass)
|
48
48
|
|
49
|
-
@sm.state.should
|
50
|
-
@locked.should
|
51
|
-
@alarm_status.should
|
49
|
+
@sm.state.should equal(:locked)
|
50
|
+
@locked.should equal(true)
|
51
|
+
@alarm_status.should equal(true)
|
52
52
|
end
|
53
53
|
|
54
|
-
|
54
|
+
it "unlocked state with coin" do
|
55
55
|
@sm.process_event(:coin)
|
56
56
|
@sm.process_event(:coin)
|
57
57
|
|
58
|
-
@sm.state.should
|
59
|
-
@thankyou_status.should
|
58
|
+
@sm.state.should equal(:locked)
|
59
|
+
@thankyou_status.should equal(true)
|
60
60
|
end
|
61
61
|
|
62
|
-
|
62
|
+
it "unlocked state with pass event" do
|
63
63
|
@sm.process_event(:coin)
|
64
64
|
@sm.process_event(:pass)
|
65
65
|
|
66
|
-
@sm.state.should
|
67
|
-
@locked.should
|
66
|
+
@sm.state.should equal(:locked)
|
67
|
+
@locked.should equal(true)
|
68
68
|
end
|
69
69
|
|
70
|
-
|
70
|
+
it "events invoked via method_missing" do
|
71
71
|
@sm.coin
|
72
|
-
@sm.state.should
|
72
|
+
@sm.state.should equal(:unlocked)
|
73
73
|
@sm.pass
|
74
|
-
@sm.state.should
|
74
|
+
@sm.state.should equal(:locked)
|
75
75
|
end
|
76
76
|
end
|
data/spec/spec_helper.rb
CHANGED
@@ -4,11 +4,11 @@ require 'spec'
|
|
4
4
|
require 'statemachine'
|
5
5
|
|
6
6
|
def check_transition(transition, origin_id, destination_id, event, action)
|
7
|
-
transition.
|
8
|
-
transition.event.
|
9
|
-
transition.origin_id.
|
10
|
-
transition.destination_id.
|
11
|
-
transition.action.
|
7
|
+
transition.should_not equal(nil)
|
8
|
+
transition.event.should equal(event)
|
9
|
+
transition.origin_id.should equal(origin_id)
|
10
|
+
transition.destination_id.should equal(destination_id)
|
11
|
+
transition.action.should eql(action)
|
12
12
|
end
|
13
13
|
|
14
14
|
module SwitchStatemachine
|
data/spec/transition_spec.rb
CHANGED
@@ -1,107 +1,107 @@
|
|
1
1
|
require File.dirname(__FILE__) + '/spec_helper'
|
2
2
|
|
3
|
-
|
3
|
+
describe "Transition Calculating Exits and Entries" do
|
4
4
|
|
5
|
-
|
5
|
+
before(:each) do
|
6
6
|
@transition = Statemachine::Transition.new(nil, nil, nil, nil)
|
7
7
|
end
|
8
8
|
|
9
|
-
|
9
|
+
it "to nil" do
|
10
10
|
@a = Statemachine::State.new("a", nil, nil)
|
11
11
|
exits, entries = @transition.exits_and_entries(@a, nil)
|
12
|
-
exits.to_s.
|
13
|
-
entries.to_s.
|
14
|
-
entries.length.
|
12
|
+
exits.to_s.should eql([@a].to_s)
|
13
|
+
entries.to_s.should eql([].to_s)
|
14
|
+
entries.length.should equal(0)
|
15
15
|
end
|
16
16
|
|
17
|
-
|
17
|
+
it "to itself" do
|
18
18
|
@a = Statemachine::State.new("a", nil, nil)
|
19
19
|
exits, entries = @transition.exits_and_entries(@a, @a)
|
20
|
-
exits.to_s.
|
21
|
-
entries.to_s.
|
20
|
+
exits.to_s.should eql([@a].to_s)
|
21
|
+
entries.to_s.should eql([@a].to_s)
|
22
22
|
end
|
23
23
|
|
24
|
-
|
24
|
+
it "to friend" do
|
25
25
|
@a = Statemachine::State.new("a", nil, nil)
|
26
26
|
@b = Statemachine::State.new("b", nil, nil)
|
27
27
|
exits, entries = @transition.exits_and_entries(@a, @b)
|
28
|
-
exits.to_s.
|
29
|
-
entries.to_s.
|
28
|
+
exits.to_s.should eql([@a].to_s)
|
29
|
+
entries.to_s.should eql([@b].to_s)
|
30
30
|
end
|
31
31
|
|
32
|
-
|
32
|
+
it "to parent" do
|
33
33
|
@b = Statemachine::State.new("b", nil, nil)
|
34
34
|
@a = Statemachine::State.new("a", @b, nil)
|
35
35
|
exits, entries = @transition.exits_and_entries(@a, @b)
|
36
|
-
exits.to_s.
|
37
|
-
entries.to_s.
|
36
|
+
exits.to_s.should eql([@a, @b].to_s)
|
37
|
+
entries.to_s.should eql([@b].to_s)
|
38
38
|
end
|
39
39
|
|
40
|
-
|
40
|
+
it "to uncle" do
|
41
41
|
@b = Statemachine::State.new("b", nil, nil)
|
42
42
|
@a = Statemachine::State.new("a", @b, nil)
|
43
43
|
@c = Statemachine::State.new("c", nil, nil)
|
44
44
|
exits, entries = @transition.exits_and_entries(@a, @c)
|
45
|
-
exits.to_s.
|
46
|
-
entries.to_s.
|
45
|
+
exits.to_s.should eql([@a, @b].to_s)
|
46
|
+
entries.to_s.should eql([@c].to_s)
|
47
47
|
end
|
48
48
|
|
49
|
-
|
49
|
+
it "to cousin" do
|
50
50
|
@b = Statemachine::State.new("b", nil, nil)
|
51
51
|
@d = Statemachine::State.new("d", nil, nil)
|
52
52
|
@a = Statemachine::State.new("a", @b, nil)
|
53
53
|
@c = Statemachine::State.new("c", @d, nil)
|
54
54
|
exits, entries = @transition.exits_and_entries(@a, @c)
|
55
|
-
exits.to_s.
|
56
|
-
entries.to_s.
|
55
|
+
exits.to_s.should eql([@a, @b].to_s)
|
56
|
+
entries.to_s.should eql([@d, @c].to_s)
|
57
57
|
end
|
58
58
|
|
59
|
-
|
59
|
+
it "to nephew" do
|
60
60
|
@b = Statemachine::State.new("b", nil, nil)
|
61
61
|
@c = Statemachine::State.new("c", nil, nil)
|
62
62
|
@a = Statemachine::State.new("a", @b, nil)
|
63
63
|
exits, entries = @transition.exits_and_entries(@c, @a)
|
64
|
-
exits.to_s.
|
65
|
-
entries.to_s.
|
64
|
+
exits.to_s.should eql([@c].to_s)
|
65
|
+
entries.to_s.should eql([@b,@a].to_s)
|
66
66
|
end
|
67
67
|
|
68
|
-
|
68
|
+
it "to sister" do
|
69
69
|
@c = Statemachine::State.new("c", nil, nil)
|
70
70
|
@a = Statemachine::State.new("a", @c, nil)
|
71
71
|
@b = Statemachine::State.new("b", @c, nil)
|
72
72
|
exits, entries = @transition.exits_and_entries(@a, @b)
|
73
|
-
exits.to_s.
|
74
|
-
entries.to_s.
|
73
|
+
exits.to_s.should eql([@a].to_s)
|
74
|
+
entries.to_s.should eql([@b].to_s)
|
75
75
|
end
|
76
76
|
|
77
|
-
|
77
|
+
it "to second cousin" do
|
78
78
|
@c = Statemachine::State.new("c", nil, nil)
|
79
79
|
@b = Statemachine::State.new("b", @c, nil)
|
80
80
|
@a = Statemachine::State.new("a", @b, nil)
|
81
81
|
@e = Statemachine::State.new("e", @c, nil)
|
82
82
|
@d = Statemachine::State.new("d", @e, nil)
|
83
83
|
exits, entries = @transition.exits_and_entries(@a, @d)
|
84
|
-
exits.to_s.
|
85
|
-
entries.to_s.
|
84
|
+
exits.to_s.should eql([@a, @b].to_s)
|
85
|
+
entries.to_s.should eql([@e, @d].to_s)
|
86
86
|
end
|
87
87
|
|
88
|
-
|
88
|
+
it "to grandparent" do
|
89
89
|
@c = Statemachine::State.new("c", nil, nil)
|
90
90
|
@b = Statemachine::State.new("b", @c, nil)
|
91
91
|
@a = Statemachine::State.new("a", @b, nil)
|
92
92
|
exits, entries = @transition.exits_and_entries(@a, @c)
|
93
|
-
exits.to_s.
|
94
|
-
entries.to_s.
|
93
|
+
exits.to_s.should eql([@a, @b, @c].to_s)
|
94
|
+
entries.to_s.should eql([@c].to_s)
|
95
95
|
end
|
96
96
|
|
97
|
-
|
97
|
+
it "to parent's grandchild" do
|
98
98
|
@c = Statemachine::State.new("c", nil, nil)
|
99
99
|
@b = Statemachine::State.new("b", @c, nil)
|
100
100
|
@a = Statemachine::State.new("a", @b, nil)
|
101
101
|
@d = Statemachine::State.new("d", @c, nil)
|
102
102
|
exits, entries = @transition.exits_and_entries(@d, @a)
|
103
|
-
exits.to_s.
|
104
|
-
entries.to_s.
|
103
|
+
exits.to_s.should eql([@d].to_s)
|
104
|
+
entries.to_s.should eql([@b, @a].to_s)
|
105
105
|
end
|
106
106
|
|
107
107
|
end
|
metadata
CHANGED
@@ -3,9 +3,9 @@ rubygems_version: 0.9.1
|
|
3
3
|
specification_version: 1
|
4
4
|
name: statemachine
|
5
5
|
version: !ruby/object:Gem::Version
|
6
|
-
version: 0.
|
7
|
-
date: 2007-
|
8
|
-
summary: Statemachine-0.
|
6
|
+
version: 0.4.0
|
7
|
+
date: 2007-05-17 00:00:00 -05:00
|
8
|
+
summary: Statemachine-0.4.0 - Statemachine Library for Ruby http://statemachine.rubyforge.org/
|
9
9
|
require_paths:
|
10
10
|
- lib
|
11
11
|
email: statemachine-devel@rubyforge.org
|