statemachine 0.3.0 → 0.4.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|