MINT-scxml 1.0.0 → 1.1.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/Gemfile +2 -2
- data/Gemfile.lock +12 -4
- data/History.txt +14 -0
- data/MINT-scxml.gemspec +26 -20
- data/Manifest.txt +2 -15
- data/README.rdoc +1 -1
- data/Rakefile +1 -7
- data/lib/MINT-scxml.rb +1 -1
- data/lib/MINT-scxml/scxml-parser.rb +213 -75
- data/spec/if_spec.rb +209 -0
- data/spec/parser_spec.rb +465 -208
- data/spec/spec_helper.rb +1 -1
- data/spec/test_handgestures_spec.rb +2 -1
- data/spec/testmachines/button.scxml +52 -0
- metadata +64 -78
- data/statemachines/aui-scxml/AIC.scxml +0 -26
- data/statemachines/aui-scxml/AICommand.scxml +0 -34
- data/statemachines/aui-scxml/AICommand2.scxml +0 -32
- data/statemachines/aui-scxml/AIO.scxml +0 -25
- data/statemachines/aui/AIC.rb +0 -29
- data/statemachines/aui/AIChoiceElement.rb +0 -32
- data/statemachines/aui/AICommand.rb +0 -34
- data/statemachines/aui/AIIN.rb +0 -7
- data/statemachines/aui/AIINContinous.rb +0 -41
- data/statemachines/aui/AIMultiChoice.rb +0 -46
- data/statemachines/aui/AIMultiChoiceElement.rb +0 -46
- data/statemachines/aui/AIOUTContinous.rb +0 -41
- data/statemachines/aui/AISingleChoice.rb +0 -42
- data/statemachines/aui/AISingleChoiceElement.rb +0 -45
- data/statemachines/aui/aio.rb +0 -28
data/spec/if_spec.rb
ADDED
@@ -0,0 +1,209 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/spec_helper'
|
2
|
+
|
3
|
+
describe 'The StatemachineParser for' do
|
4
|
+
describe 'states' do
|
5
|
+
begin
|
6
|
+
describe 'with if/else' do
|
7
|
+
before (:each) do
|
8
|
+
@messenger = mock("messenger" )
|
9
|
+
|
10
|
+
parser = StatemachineParser.new(nil,@messenger)
|
11
|
+
|
12
|
+
scxml = <<EOS
|
13
|
+
<scxml id="SCXML" xmlns="http://www.w3.org/2005/07/scxml">
|
14
|
+
<state id="state1">
|
15
|
+
<transition event="event1" target="state2">
|
16
|
+
<if cond="1 > 2">
|
17
|
+
<log expr="should have failed"/>
|
18
|
+
<else/>
|
19
|
+
<log expr="should have worked"/>
|
20
|
+
</if>
|
21
|
+
</transition>
|
22
|
+
</state>
|
23
|
+
|
24
|
+
<state id="state2">
|
25
|
+
<transition event="event2" target="state1"/>
|
26
|
+
</state>
|
27
|
+
</scxml>
|
28
|
+
EOS
|
29
|
+
|
30
|
+
@sm = parser.build_from_scxml_string scxml
|
31
|
+
@sm.reset
|
32
|
+
end
|
33
|
+
|
34
|
+
it "should support logging inside a transition" do
|
35
|
+
@messenger.should_receive(:puts).with("should have worked" )
|
36
|
+
@sm.event1
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
describe 'with if/elseif/else' do
|
41
|
+
before (:each) do
|
42
|
+
@messenger = mock("messenger" )
|
43
|
+
|
44
|
+
parser = StatemachineParser.new(nil,@messenger)
|
45
|
+
|
46
|
+
scxml = <<EOS
|
47
|
+
<scxml id="SCXML" xmlns="http://www.w3.org/2005/07/scxml">
|
48
|
+
<state id="state1">
|
49
|
+
<transition event="event1" target="state2">
|
50
|
+
<if cond="1 > 2">
|
51
|
+
<log expr="should have failed"/>
|
52
|
+
<elseif cond="1 < 2"/>
|
53
|
+
<log expr="should have worked"/>
|
54
|
+
<else/>
|
55
|
+
<log expr="should not have entered"/>
|
56
|
+
</if>
|
57
|
+
</transition>
|
58
|
+
</state>
|
59
|
+
|
60
|
+
<state id="state2">
|
61
|
+
<transition event="event2" target="state1"/>
|
62
|
+
</state>
|
63
|
+
</scxml>
|
64
|
+
EOS
|
65
|
+
|
66
|
+
@sm = parser.build_from_scxml_string scxml
|
67
|
+
@sm.reset
|
68
|
+
end
|
69
|
+
|
70
|
+
it "should support logging inside a transition" do
|
71
|
+
@messenger.should_receive(:puts).with("should have worked" )
|
72
|
+
@sm.event1
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
describe 'with nested ifs' do
|
77
|
+
before (:each) do
|
78
|
+
@messenger = mock("messenger" )
|
79
|
+
|
80
|
+
parser = StatemachineParser.new(nil,@messenger)
|
81
|
+
|
82
|
+
scxml = <<EOS
|
83
|
+
<scxml id="SCXML" xmlns="http://www.w3.org/2005/07/scxml">
|
84
|
+
<state id="state1">
|
85
|
+
<transition event="event1" target="state2">
|
86
|
+
<if cond="1 <= 2">
|
87
|
+
<if cond="1 == 2">
|
88
|
+
<log expr="should have failed"/>
|
89
|
+
<else/>
|
90
|
+
<log expr="should have worked"/>
|
91
|
+
</if>
|
92
|
+
<elseif cond="1 > 2"/>
|
93
|
+
<log expr="should not have entered"/>
|
94
|
+
<else/>
|
95
|
+
<log expr="should not have entered"/>
|
96
|
+
</if>
|
97
|
+
</transition>
|
98
|
+
</state>
|
99
|
+
|
100
|
+
<state id="state2">
|
101
|
+
<transition event="event2" target="state1"/>
|
102
|
+
</state>
|
103
|
+
</scxml>
|
104
|
+
EOS
|
105
|
+
|
106
|
+
@sm = parser.build_from_scxml_string scxml
|
107
|
+
@sm.reset
|
108
|
+
end
|
109
|
+
|
110
|
+
it "should support logging inside a transition" do
|
111
|
+
@messenger.should_receive(:puts).with("should have worked" )
|
112
|
+
@sm.event1
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
describe 'with multiple nested ifs' do
|
117
|
+
before (:each) do
|
118
|
+
@messenger = mock("messenger" )
|
119
|
+
|
120
|
+
parser = StatemachineParser.new(nil,@messenger)
|
121
|
+
|
122
|
+
scxml = <<EOS
|
123
|
+
<scxml id="SCXML" xmlns="http://www.w3.org/2005/07/scxml">
|
124
|
+
<state id="state1">
|
125
|
+
<transition event="event1" target="state2">
|
126
|
+
<if cond="10 < 20">
|
127
|
+
<if cond="10 == 20">
|
128
|
+
<log expr="should have failed"/>
|
129
|
+
<elseif cond="10 <= 15"/>
|
130
|
+
<if cond="10 < 15">
|
131
|
+
<log expr="should have worked"/>
|
132
|
+
</if>
|
133
|
+
<else/>
|
134
|
+
<log expr="should not have entered"/>
|
135
|
+
</if>
|
136
|
+
<elseif cond="10 > 20"/>
|
137
|
+
<log expr="should not have entered"/>
|
138
|
+
<else/>
|
139
|
+
<log expr="should not have entered"/>
|
140
|
+
</if>
|
141
|
+
</transition>
|
142
|
+
</state>
|
143
|
+
|
144
|
+
<state id="state2">
|
145
|
+
<transition event="event2" target="state1"/>
|
146
|
+
</state>
|
147
|
+
</scxml>
|
148
|
+
EOS
|
149
|
+
|
150
|
+
@sm = parser.build_from_scxml_string scxml
|
151
|
+
@sm.reset
|
152
|
+
end
|
153
|
+
|
154
|
+
it "should support logging inside a transition" do
|
155
|
+
@messenger.should_receive(:puts).with("should have worked" )
|
156
|
+
@sm.event1
|
157
|
+
end
|
158
|
+
end
|
159
|
+
describe 'with multiple nested ifs' do
|
160
|
+
before (:each) do
|
161
|
+
@messenger = mock("messenger" )
|
162
|
+
|
163
|
+
parser = StatemachineParser.new(nil,@messenger)
|
164
|
+
|
165
|
+
scxml = <<EOS
|
166
|
+
<scxml id="SCXML" xmlns="http://www.w3.org/2005/07/scxml">
|
167
|
+
<state id="state1">
|
168
|
+
<transition event="event1" target="state2">
|
169
|
+
<if cond="10 < 20">
|
170
|
+
<if cond="10 == 20">
|
171
|
+
<log expr="should have failed"/>
|
172
|
+
<elseif cond="10 <= 15"/>
|
173
|
+
<if cond="10 < 15">
|
174
|
+
<if cond="10 < 10">
|
175
|
+
<log expr="should have failed"/>
|
176
|
+
<else/>
|
177
|
+
<log expr="should have worked"/>
|
178
|
+
</if>
|
179
|
+
</if>
|
180
|
+
<else/>
|
181
|
+
<log expr="should not have entered"/>
|
182
|
+
</if>
|
183
|
+
<elseif cond="10 > 20"/>
|
184
|
+
<log expr="should not have entered"/>
|
185
|
+
<else/>
|
186
|
+
<log expr="should not have entered"/>
|
187
|
+
</if>
|
188
|
+
</transition>
|
189
|
+
</state>
|
190
|
+
|
191
|
+
<state id="state2">
|
192
|
+
<transition event="event2" target="state1"/>
|
193
|
+
</state>
|
194
|
+
</scxml>
|
195
|
+
EOS
|
196
|
+
|
197
|
+
@sm = parser.build_from_scxml_string scxml
|
198
|
+
@sm.reset
|
199
|
+
end
|
200
|
+
|
201
|
+
it "should support logging inside a transition" do
|
202
|
+
@messenger.should_receive(:puts).with("should have worked" )
|
203
|
+
@sm.event1
|
204
|
+
end
|
205
|
+
end
|
206
|
+
end
|
207
|
+
end
|
208
|
+
end
|
209
|
+
|
data/spec/parser_spec.rb
CHANGED
@@ -2,15 +2,15 @@ require File.dirname(__FILE__) + '/spec_helper'
|
|
2
2
|
|
3
3
|
describe 'The StatemachineParser for' do
|
4
4
|
describe 'states' do
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
parser = StatemachineParser.new(nil,@messenger)
|
5
|
+
begin
|
6
|
+
describe 'without a superstate' do
|
7
|
+
before (:each) do
|
8
|
+
@messenger = mock("messenger" )
|
11
9
|
|
12
|
-
|
13
|
-
|
10
|
+
parser = StatemachineParser.new(nil,@messenger)
|
11
|
+
|
12
|
+
scxml = <<EOS
|
13
|
+
<scxml name="SCXML" xmlns="http://www.w3.org/2005/07/scxml">
|
14
14
|
<state id="state1">
|
15
15
|
<transition event="event1" target="state2"/>
|
16
16
|
<transition event="event4" target="state2">
|
@@ -28,37 +28,38 @@ describe 'The StatemachineParser for' do
|
|
28
28
|
</scxml>
|
29
29
|
EOS
|
30
30
|
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
31
|
+
@sm = parser.build_from_scxml_string scxml
|
32
|
+
@sm.reset
|
33
|
+
end
|
34
|
+
|
35
|
+
it "should start with the correct initial state without initial attribute set" do
|
36
|
+
@sm.state.should==:state1
|
37
|
+
end
|
38
|
+
|
39
|
+
it "should support transitions " do
|
40
|
+
@sm.event1
|
41
|
+
@sm.state.should==:state2
|
42
|
+
@sm.event2
|
43
|
+
@sm.state.should==:state3
|
44
|
+
@sm.event3
|
45
|
+
@sm.state.should==:state1
|
46
|
+
end
|
47
|
+
|
48
|
+
it "should support logging inside a transition" do
|
49
|
+
@messenger.should_receive(:puts).with("transition executing" )
|
50
|
+
@sm.event4
|
51
|
+
end
|
36
52
|
end
|
37
53
|
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
@sm.event2
|
42
|
-
@sm.state.should==:state3
|
43
|
-
@sm.event3
|
44
|
-
@sm.state.should==:state1
|
45
|
-
end
|
54
|
+
describe "in the same superstate" do
|
55
|
+
before (:each) do
|
56
|
+
@messenger = mock("messenger" )
|
46
57
|
|
47
|
-
|
48
|
-
@messenger.should_receive(:puts).with("transition executing" )
|
49
|
-
@sm.event4
|
50
|
-
end
|
51
|
-
end
|
52
|
-
|
53
|
-
describe "in the same superstate" do
|
54
|
-
before (:each) do
|
55
|
-
@messenger = mock("messenger" )
|
56
|
-
|
57
|
-
parser = StatemachineParser.new(nil,@messenger)
|
58
|
+
parser = StatemachineParser.new(nil,@messenger)
|
58
59
|
|
59
|
-
|
60
|
+
scxml = <<EOS
|
60
61
|
<?xml version="1.0"?>
|
61
|
-
<scxml xmlns="http://www.w3.org/2005/07/scxml" version="1.0" profile="ecmascript"
|
62
|
+
<scxml xmlns="http://www.w3.org/2005/07/scxml" version="1.0" profile="ecmascript">
|
62
63
|
<state id="super" initial="child2">
|
63
64
|
<state id="child1">
|
64
65
|
<transition event="event1" target="child2">
|
@@ -78,31 +79,32 @@ EOS
|
|
78
79
|
</state>
|
79
80
|
</scxml>
|
80
81
|
EOS
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
82
|
+
@sm = parser.build_from_scxml_string scxml
|
83
|
+
@sm.reset
|
84
|
+
end
|
85
|
+
|
86
|
+
it "should start with the correct state" do
|
87
|
+
@sm.state.should==:child2
|
88
|
+
end
|
89
|
+
|
90
|
+
it "should support transitions and logging inside transitions" do
|
91
|
+
@messenger.should_receive(:puts).with("'This is action2'" )
|
92
|
+
@sm.event2
|
93
|
+
@sm.state.should==:child3
|
94
|
+
|
95
|
+
@messenger.should_receive(:puts).with("'This is action3'" )
|
96
|
+
@sm.event3
|
97
|
+
@sm.state.should==:child1
|
98
|
+
|
99
|
+
@messenger.should_receive(:puts).with("'This is action1'" )
|
100
|
+
@sm.event1
|
101
|
+
@sm.state.should==:child2
|
102
|
+
end
|
103
|
+
|
104
|
+
it 'should start with the correct state even if the initial state has not been explicitly set' do
|
105
|
+
scxml = <<EOS
|
104
106
|
<?xml version="1.0"?>
|
105
|
-
<scxml xmlns="http://www.w3.org/2005/07/scxml" version="1.0" profile="ecmascript"
|
107
|
+
<scxml xmlns="http://www.w3.org/2005/07/scxml" version="1.0" profile="ecmascript">
|
106
108
|
<state id="state">
|
107
109
|
<state id="state1">
|
108
110
|
<transition event="event1" target="state2">
|
@@ -117,19 +119,21 @@ EOS
|
|
117
119
|
</state>
|
118
120
|
</scxml>
|
119
121
|
EOS
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
end
|
125
|
-
end
|
126
|
-
describe "in double nested superstates" do
|
127
|
-
before (:each) do
|
122
|
+
parser = StatemachineParser.new
|
123
|
+
@sm = parser.build_from_scxml_string scxml
|
124
|
+
@sm.reset
|
125
|
+
@sm.state.should==:state1
|
128
126
|
|
129
|
-
|
130
|
-
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
130
|
+
describe "in double nested superstates" do
|
131
|
+
before (:each) do
|
132
|
+
|
133
|
+
parser = StatemachineParser.new
|
134
|
+
scxml = <<EOS
|
131
135
|
<?xml version="1.0"?>
|
132
|
-
<scxml xmlns="http://www.w3.org/2005/07/scxml" version="1.0" profile="ecmascript"
|
136
|
+
<scxml xmlns="http://www.w3.org/2005/07/scxml" version="1.0" profile="ecmascript">
|
133
137
|
<state id="state1" initial="state12">
|
134
138
|
<transition event="to_state2" target="state2"/>
|
135
139
|
<state id="state11" initial="state111">
|
@@ -150,115 +154,103 @@ EOS
|
|
150
154
|
</scxml>
|
151
155
|
EOS
|
152
156
|
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
157
|
+
@sm = parser.build_from_scxml_string scxml
|
158
|
+
@sm.reset
|
159
|
+
end
|
160
|
+
|
161
|
+
it "should support starting with the correct inital state that has been excplicitely set" do
|
162
|
+
@sm.state.should==:state12
|
163
|
+
@sm.to_state13
|
164
|
+
@sm.to_state11
|
165
|
+
@sm.state.should==:state111
|
166
|
+
end
|
167
|
+
|
168
|
+
it "should support transitions the are defined for a superstate to get into a nested state of the same superstate" do
|
169
|
+
@sm.to_state13
|
170
|
+
@sm.to_state11
|
171
|
+
@sm.to_state111
|
172
|
+
@sm.state.should==:state111
|
173
|
+
@sm.to_state12
|
174
|
+
@sm.state.should==:state12
|
175
|
+
end
|
176
|
+
it "should support transitions the are defined for a superstate to get into another state on the same level of the superstate" do
|
177
|
+
@sm.to_state13
|
178
|
+
@sm.to_state11
|
179
|
+
@sm.to_state111
|
180
|
+
@sm.state.should==:state111
|
181
|
+
@sm.to_state13
|
182
|
+
@sm.state.should==:state13
|
183
|
+
end
|
184
|
+
|
185
|
+
it "should support transitions the are defined from a super-superstate " do
|
186
|
+
@sm.to_state13
|
187
|
+
@sm.to_state11
|
188
|
+
@sm.to_state111
|
189
|
+
@sm.state.should==:state111
|
190
|
+
@sm.to_state2
|
191
|
+
@sm.state.should==:state2
|
192
|
+
end
|
170
193
|
end
|
171
|
-
it "should support transitions the are defined for a superstate to get into another state on the same level of the superstate" do
|
172
|
-
@sm.to_state13
|
173
|
-
@sm.to_state11
|
174
|
-
@sm.to_state111
|
175
|
-
@sm.state.should==:state111
|
176
|
-
@sm.to_state13
|
177
|
-
@sm.state.should==:state13
|
178
|
-
end
|
179
|
-
|
180
|
-
it "should support transitions the are defined from a super-superstate " do
|
181
|
-
@sm.to_state13
|
182
|
-
@sm.to_state11
|
183
|
-
@sm.to_state111
|
184
|
-
@sm.state.should==:state111
|
185
|
-
@sm.to_state2
|
186
|
-
@sm.state.should==:state2
|
187
|
-
end
|
188
|
-
end
|
189
|
-
|
190
|
-
describe 'with onentry or onexit' do
|
191
|
-
|
192
|
-
before (:each) do
|
193
|
-
@messenger = mock("messenger" )
|
194
|
-
|
195
|
-
@message_queue = mock("message_queue" )
|
196
|
-
|
197
|
-
parser = StatemachineParser.new(nil, @messenger, @message_queue)
|
198
194
|
|
199
|
-
|
195
|
+
describe 'with spontaneous transitions' do
|
196
|
+
before (:each) do
|
197
|
+
@log = ""
|
198
|
+
parser = StatemachineParser.new(nil,nil)
|
199
|
+
scxml = <<EOS
|
200
200
|
<scxml id="SCXML" xmlns="http://www.w3.org/2005/07/scxml">
|
201
|
-
<state id="
|
202
|
-
<transition event="to_state2" target="state2"/>
|
203
|
-
</state>
|
204
|
-
<state id="state2">
|
201
|
+
<state id="off">
|
205
202
|
<onentry>
|
206
|
-
|
207
|
-
<send type="'x-mint'" target="target" event="fax.SEND"/>
|
203
|
+
<script>Proc.new {puts "entering off"}</script>
|
208
204
|
</onentry>
|
209
205
|
<onexit>
|
210
|
-
|
206
|
+
<script>Proc.new {puts "exiting off"}</script>
|
211
207
|
</onexit>
|
212
|
-
|
213
|
-
|
214
|
-
|
208
|
+
<transition event="toggle" target="on">
|
209
|
+
<script>@log += "on"</script>
|
210
|
+
</transition>
|
211
|
+
<transition target="done" cond="@log == 'onoff'"/>
|
215
212
|
</state>
|
216
213
|
|
214
|
+
<state id="on">
|
215
|
+
<transition event="toggle" target="off">
|
216
|
+
<script>@log += "off"</script>
|
217
|
+
</transition>
|
218
|
+
</state>
|
217
219
|
</scxml>
|
218
220
|
EOS
|
219
221
|
|
220
|
-
|
221
|
-
|
222
|
+
@sm = parser.build_from_scxml_string scxml
|
223
|
+
@sm.reset
|
224
|
+
@sm.context = self
|
225
|
+
end
|
226
|
+
|
227
|
+
it "should be done" do
|
228
|
+
@sm.toggle
|
229
|
+
@sm.state.should == :on
|
230
|
+
@sm.toggle
|
231
|
+
@sm.state.should == :done
|
232
|
+
end
|
233
|
+
|
234
|
+
it "should execute inside parallel states as well" do
|
235
|
+
parser = StatemachineParser.new(nil,nil)
|
236
|
+
@sm = parser.build_from_scxml(File.dirname(__FILE__) + "/testmachines/button.scxml")
|
237
|
+
@sm.reset
|
238
|
+
@sm.position
|
239
|
+
@sm.calculated
|
240
|
+
@sm.process_event :display
|
241
|
+
@sm.states_id.should == [:displayed,:released]
|
242
|
+
end
|
222
243
|
|
223
|
-
it "should consider onentry" do
|
224
|
-
@messenger.should_receive(:puts).with("'inside state2 onentry'" )
|
225
|
-
@message_queue.should_receive(:send).with("target","fax.SEND")
|
226
|
-
@sm.to_state2
|
227
|
-
end
|
228
|
-
|
229
|
-
it "should consider onexit" do
|
230
|
-
@messenger.should_receive(:puts).with("'inside state2 onentry'" )
|
231
|
-
@message_queue.should_receive(:send).with("target","fax.SEND")
|
232
|
-
@sm.to_state2
|
233
|
-
@messenger.should_receive(:puts).with("'inside state2 onexit'" )
|
234
|
-
@message_queue.should_receive(:send).with("target-2","fax.SEND-2")
|
235
|
-
@sm.to_state1
|
236
|
-
end
|
237
|
-
|
238
|
-
it "should receive send inside onentry" do
|
239
|
-
@messenger.should_receive(:puts).with("'inside state2 onentry'" )
|
240
|
-
@message_queue.should_receive(:send).with("target","fax.SEND")
|
241
|
-
@sm.to_state2
|
242
|
-
end
|
243
|
-
|
244
|
-
it "should receive send inside a transition" do
|
245
|
-
@messenger.should_receive(:puts).with("'inside state2 onentry'" )
|
246
|
-
@message_queue.should_receive(:send).with("target","fax.SEND")
|
247
|
-
@sm.to_state2
|
248
|
-
@messenger.should_receive(:puts).with("'inside state2 onexit'" )
|
249
|
-
@message_queue.should_receive(:send).with("target-2","fax.SEND-2")
|
250
|
-
@sm.to_state1
|
251
244
|
end
|
252
245
|
end
|
253
|
-
end
|
254
246
|
|
255
|
-
|
247
|
+
describe 'parallel' do
|
256
248
|
before (:each) do
|
257
249
|
parser = StatemachineParser.new
|
258
250
|
|
259
251
|
scxml = <<EOS
|
260
252
|
<?xml version="1.0"?>
|
261
|
-
<scxml
|
253
|
+
<scxml name="SCXML" xmlns="http://www.w3.org/2005/07/scxml">
|
262
254
|
<state id="state0">
|
263
255
|
<transition event="to_p" target="parallel"/>
|
264
256
|
</state>
|
@@ -267,10 +259,10 @@ EOS
|
|
267
259
|
<parallel id="parallel">
|
268
260
|
<state id="state1">
|
269
261
|
<state id="state11">
|
270
|
-
<transition event="to_12" cond="In(
|
262
|
+
<transition event="to_12" cond="In(:state22)" target="state12"/>
|
271
263
|
</state>
|
272
264
|
<state id="state12">
|
273
|
-
<transition event="to_11" cond="In(
|
265
|
+
<transition event="to_11" cond="In(:state21)" target="state12"/>
|
274
266
|
</state>
|
275
267
|
</state>
|
276
268
|
|
@@ -288,12 +280,20 @@ EOS
|
|
288
280
|
EOS
|
289
281
|
|
290
282
|
@sm = parser.build_from_scxml_string scxml
|
283
|
+
@sm.reset
|
291
284
|
end
|
292
285
|
|
293
286
|
it "start with the initial state and transition to the parallel states" do
|
294
287
|
@sm.states_id.should == [:state0]
|
295
288
|
@sm.process_event(:to_p)
|
296
|
-
@sm.states_id.should ==
|
289
|
+
@sm.states_id.should == [:state11, :state22]
|
290
|
+
|
291
|
+
end
|
292
|
+
|
293
|
+
it "start set active root statemachine state to parallel id after transition to the parallel states" do
|
294
|
+
@sm.states_id.should == [:state0]
|
295
|
+
@sm.process_event(:to_p)
|
296
|
+
@sm.state.should == :parallel
|
297
297
|
end
|
298
298
|
|
299
299
|
it "support transitions for both parallel superstates" do
|
@@ -310,9 +310,9 @@ EOS
|
|
310
310
|
@sm.states_id.should == [:state0]
|
311
311
|
@sm.process_event(:to_p)
|
312
312
|
@sm.process_event(:to_12)
|
313
|
-
|
313
|
+
@sm.In(:state12).should == true
|
314
314
|
end
|
315
|
-
|
315
|
+
|
316
316
|
it "support testing with 'in' condition for superstates " do
|
317
317
|
@sm.states_id.should == [:state0]
|
318
318
|
@sm.process_event(:to_p)
|
@@ -327,68 +327,325 @@ EOS
|
|
327
327
|
@sm.In(:state2).should == true
|
328
328
|
@sm.In(:state1).should == true
|
329
329
|
end
|
330
|
-
end
|
331
330
|
|
332
|
-
|
333
|
-
|
331
|
+
it "should only transition if In is satisfied" do
|
332
|
+
@sm.states_id.should == [:state0]
|
333
|
+
@sm.process_event(:to_p)
|
334
|
+
@sm.process_event(:to_21)
|
335
|
+
@sm.states_id.should == [:state11,:state21]
|
336
|
+
@sm.process_event(:to_12)
|
337
|
+
@sm.states_id.should == [:state11,:state21]
|
338
|
+
end
|
339
|
+
end
|
334
340
|
|
341
|
+
describe "History States with default history state" do
|
342
|
+
before(:each) do
|
335
343
|
parser = StatemachineParser.new
|
336
344
|
|
337
345
|
scxml = <<EOS
|
338
|
-
|
339
|
-
<
|
340
|
-
<
|
341
|
-
|
346
|
+
<scxml id="SCXML" initial="state1" name="history" xmlns="http://www.w3.org/2005/07/scxml"><!-- node-size-and-position x=0.0 y=0.0 w=280.0 h=250.0 -->
|
347
|
+
<state id="state1"><!-- node-size-and-position x=10.0 y=30.0 w=100.0 h=30.0 -->
|
348
|
+
<transition event="to_3" target="state3"></transition>
|
349
|
+
</state>
|
350
|
+
<state id="state3" initial="state3_1"><!-- node-size-and-position x=140.0 y=30.0 w=130.0 h=200.0 -->
|
351
|
+
<transition event="to_1" target="state1"></transition>
|
352
|
+
<state id="state3_1"><!-- node-size-and-position x=20.0 y=40.0 w=100.0 h=30.0 -->
|
353
|
+
<transition event="to_3_2" target="state3_2"></transition>
|
342
354
|
</state>
|
343
|
-
<state id="
|
344
|
-
|
345
|
-
|
346
|
-
|
347
|
-
|
348
|
-
|
349
|
-
|
350
|
-
|
351
|
-
|
352
|
-
</state>
|
353
|
-
<history id="history" type="deep">
|
354
|
-
<transition target="state11"/>
|
355
|
-
</history>
|
356
|
-
</state>
|
355
|
+
<state id="state3_2"><!-- node-size-and-position x=20.0 y=150.0 w=100.0 h=30.0 -->
|
356
|
+
<transition event="to_3_1" target="state3_1"><!-- edge-path [state3_1] x=110.0 y=110.0 --></transition>
|
357
|
+
</state>
|
358
|
+
<history id="H" type="deep"><!-- node-size-and-position x=10.0 y=110.0 w=40.0 h=30.0 -->
|
359
|
+
<transition target="state3_2"></transition>
|
360
|
+
</history>
|
361
|
+
</state>
|
362
|
+
</scxml>
|
363
|
+
EOS
|
357
364
|
|
358
|
-
|
359
|
-
|
360
|
-
|
361
|
-
|
362
|
-
|
363
|
-
|
364
|
-
|
365
|
-
|
366
|
-
|
365
|
+
@sm = parser.build_from_scxml_string scxml
|
366
|
+
@sm.reset
|
367
|
+
end
|
368
|
+
|
369
|
+
|
370
|
+
it "default history" do
|
371
|
+
@sm.process_event(:to_3)
|
372
|
+
@sm.state.should eql(:state3_2)
|
373
|
+
end
|
374
|
+
|
375
|
+
it "reseting the statemachine resets history" do
|
376
|
+
@sm.process_event(:to_3)
|
377
|
+
@sm.process_event(:to_3_1)
|
378
|
+
@sm.process_event(:to_1)
|
379
|
+
@sm.get_state(:state3).history_id.should eql(:state3_1)
|
380
|
+
|
381
|
+
@sm.reset
|
382
|
+
@sm.get_state(:state3).history_id.should eql(:state3_2)
|
383
|
+
end
|
384
|
+
end
|
385
|
+
|
386
|
+
describe "History States without default history state" do
|
387
|
+
before(:each) do
|
388
|
+
parser = StatemachineParser.new
|
389
|
+
|
390
|
+
scxml = <<EOS
|
391
|
+
<scxml id="SCXML" initial="state1" name="history" xmlns="http://www.w3.org/2005/07/scxml"><!-- node-size-and-position x=0.0 y=0.0 w=280.0 h=250.0 -->
|
392
|
+
<state id="state1"><!-- node-size-and-position x=10.0 y=30.0 w=100.0 h=30.0 -->
|
393
|
+
<transition event="to_3" target="state3"></transition>
|
394
|
+
</state>
|
395
|
+
<state id="state3" initial="state3_1"><!-- node-size-and-position x=140.0 y=30.0 w=130.0 h=200.0 -->
|
396
|
+
<transition event="to_1" target="state1"></transition>
|
397
|
+
<state id="state3_1"><!-- node-size-and-position x=20.0 y=40.0 w=100.0 h=30.0 -->
|
398
|
+
<transition event="to_3_2" target="state3_2"></transition>
|
399
|
+
</state>
|
400
|
+
<state id="state3_2"><!-- node-size-and-position x=20.0 y=150.0 w=100.0 h=30.0 -->
|
401
|
+
<transition event="to_3_1" target="state3_1"><!-- edge-path [state3_1] x=110.0 y=110.0 --></transition>
|
367
402
|
</state>
|
403
|
+
<history id="H" type="deep"><!-- node-size-and-position x=10.0 y=110.0 w=40.0 h=30.0 -->
|
404
|
+
</history>
|
405
|
+
</state>
|
368
406
|
</scxml>
|
369
407
|
EOS
|
370
408
|
|
371
409
|
@sm = parser.build_from_scxml_string scxml
|
410
|
+
@sm.reset
|
372
411
|
end
|
373
412
|
|
374
|
-
|
375
|
-
|
376
|
-
@sm.process_event(:
|
377
|
-
@sm.
|
413
|
+
|
414
|
+
it "reseting the statemachine resets history" do
|
415
|
+
@sm.process_event(:to_3)
|
416
|
+
@sm.process_event(:to_1)
|
417
|
+
@sm.get_state(:state3).history_id.should eql(:state3_1)
|
418
|
+
|
419
|
+
@sm.reset
|
420
|
+
@sm.get_state(:state3).history_id.should eql(nil)
|
378
421
|
end
|
422
|
+
end
|
379
423
|
|
380
|
-
|
381
|
-
|
382
|
-
|
383
|
-
|
384
|
-
|
385
|
-
|
386
|
-
|
387
|
-
|
388
|
-
|
389
|
-
|
424
|
+
describe "Nested Superstates" do
|
425
|
+
before(:each) do
|
426
|
+
parser = StatemachineParser.new
|
427
|
+
|
428
|
+
scxml = <<EOS
|
429
|
+
<scxml id="SCXML" initial="grandpa" name="history" xmlns="http://www.w3.org/2005/07/scxml"><!-- node-size-and-position x=0.0 y=0.0 w=250.0 h=270.0 -->
|
430
|
+
<state id="grandpa" initial="start"><!-- node-size-and-position x=10.0 y=30.0 w=230.0 h=110.0 -->
|
431
|
+
<transition event="sister" target="great_auntie"></transition>
|
432
|
+
<state id="papa" initial="son"><!-- node-size-and-position x=10.0 y=30.0 w=150.0 h=70.0 -->
|
433
|
+
<state id="daughter"><!-- node-size-and-position x=70.0 y=30.0 w=70.0 h=30.0 --></state>
|
434
|
+
<state id="son"><!-- node-size-and-position x=10.0 y=30.0 w=50.0 h=30.0 --></state>
|
435
|
+
</state>
|
436
|
+
<state id="start"><!-- node-size-and-position x=170.0 y=30.0 w=50.0 h=30.0 -->
|
437
|
+
<transition event="go" target="daughter"></transition>
|
438
|
+
</state>
|
439
|
+
<history id="H" type="deep"><!-- node-size-and-position x=180.0 y=70.0 w=30.0 h=30.0 --></history>
|
440
|
+
</state>
|
441
|
+
<state id="great_auntie"><!-- node-size-and-position x=100.0 y=230.0 w=100.0 h=30.0 -->
|
442
|
+
<transition event="foo" target="grandpa"><!-- edge-path [grandpa] x=200.0 y=200.0 --></transition>
|
443
|
+
</state>
|
444
|
+
</scxml>
|
445
|
+
EOS
|
446
|
+
|
447
|
+
@sm = parser.build_from_scxml_string scxml
|
448
|
+
@sm.reset
|
390
449
|
end
|
391
|
-
|
450
|
+
|
451
|
+
it "should use history of sub superstates when transitioning itto it's own history" do
|
452
|
+
@sm.go
|
453
|
+
@sm.sister
|
454
|
+
@sm.foo
|
455
|
+
|
456
|
+
@sm.state.should eql(:daughter)
|
457
|
+
end
|
458
|
+
end
|
459
|
+
|
460
|
+
describe "On_entry and on_exit actions in" do
|
461
|
+
begin
|
462
|
+
describe 'states' do
|
463
|
+
|
464
|
+
before (:each) do
|
465
|
+
@messenger = mock("messenger" )
|
466
|
+
|
467
|
+
@message_queue = mock("message_queue" )
|
468
|
+
|
469
|
+
parser = StatemachineParser.new(nil, @messenger, @message_queue)
|
470
|
+
|
471
|
+
scxml = <<EOS
|
472
|
+
<scxml name="SCXML" xmlns="http://www.w3.org/2005/07/scxml">
|
473
|
+
<state id="state1">
|
474
|
+
<transition event="to_state2" target="state2"/>
|
475
|
+
</state>
|
476
|
+
<state id="state2">
|
477
|
+
<onentry>
|
478
|
+
<log expr="'inside state2 onentry'"/>
|
479
|
+
<send type="'x-mint'" target="target" event="fax.SEND"/>
|
480
|
+
</onentry>
|
481
|
+
<onexit>
|
482
|
+
<log expr="'inside state2 onexit'"/>
|
483
|
+
</onexit>
|
484
|
+
<transition event="to_state1" target="state1">
|
485
|
+
<send type="'x-mint'" target="target-2" event="fax.SEND-2"/>
|
486
|
+
</transition>
|
487
|
+
</state>
|
488
|
+
|
489
|
+
</scxml>
|
490
|
+
EOS
|
491
|
+
|
492
|
+
@sm = parser.build_from_scxml_string scxml
|
493
|
+
@sm.reset
|
494
|
+
end
|
495
|
+
|
496
|
+
it "should consider onentry" do
|
497
|
+
@messenger.should_receive(:puts).with("'inside state2 onentry'" )
|
498
|
+
@message_queue.should_receive(:send).with("target","fax.SEND")
|
499
|
+
@sm.to_state2
|
500
|
+
end
|
501
|
+
|
502
|
+
it "should consider onexit" do
|
503
|
+
@messenger.should_receive(:puts).with("'inside state2 onentry'" )
|
504
|
+
@message_queue.should_receive(:send).with("target","fax.SEND")
|
505
|
+
@sm.to_state2
|
506
|
+
@messenger.should_receive(:puts).with("'inside state2 onexit'" )
|
507
|
+
@message_queue.should_receive(:send).with("target-2","fax.SEND-2")
|
508
|
+
@sm.to_state1
|
509
|
+
end
|
510
|
+
|
511
|
+
it "should receive send inside onentry" do
|
512
|
+
@messenger.should_receive(:puts).with("'inside state2 onentry'" )
|
513
|
+
@message_queue.should_receive(:send).with("target","fax.SEND")
|
514
|
+
@sm.to_state2
|
515
|
+
end
|
516
|
+
|
517
|
+
it "should receive send inside a transition" do
|
518
|
+
@messenger.should_receive(:puts).with("'inside state2 onentry'" )
|
519
|
+
@message_queue.should_receive(:send).with("target","fax.SEND")
|
520
|
+
@sm.to_state2
|
521
|
+
@messenger.should_receive(:puts).with("'inside state2 onexit'" )
|
522
|
+
@message_queue.should_receive(:send).with("target-2","fax.SEND-2")
|
523
|
+
@sm.to_state1
|
524
|
+
end
|
525
|
+
end
|
526
|
+
|
527
|
+
describe 'superstates inside a parallel state' do
|
528
|
+
before (:each) do
|
529
|
+
def hello_world
|
530
|
+
@log = "Hello world!"
|
531
|
+
end
|
532
|
+
|
533
|
+
def goodbye
|
534
|
+
@log = "Goodbye cruel world!"
|
535
|
+
end
|
536
|
+
parser = StatemachineParser.new(nil,nil)
|
537
|
+
|
538
|
+
scxml = <<EOS
|
539
|
+
<scxml initial="disconnected" name="Mouse" version="0.9" xmlns="http://www.w3.org/2005/07/scxml"><!-- node-size-and-position x=0.0 y=0.0 w=662.0 h=660.0 -->
|
540
|
+
<state id="disconnected"><!-- node-size-and-position x=280.0 y=60.0 w=100.0 h=50.0 -->
|
541
|
+
<transition event="connect" target="connected"></transition>
|
542
|
+
</state>
|
543
|
+
<parallel id="connected"><!-- node-size-and-position x=70.0 y=190.0 w=500.0 h=470.0 -->
|
544
|
+
<transition event="disconnect" target="disconnected"><!-- edge-path [disconnected] x=400.0 y=160.0 --></transition>
|
545
|
+
<state id="leftbutton" initial="released"><!-- node-size-and-position x=40.0 y=50.0 w=210.0 h=210.0 -->
|
546
|
+
<onentry>
|
547
|
+
<script>hello_world</script>
|
548
|
+
</onentry>
|
549
|
+
<onexit>
|
550
|
+
<script>goodbye </script>
|
551
|
+
</onexit>
|
552
|
+
<state id="released"><!-- node-size-and-position x=20.0 y=50.0 w=140.0 h=40.0 -->
|
553
|
+
<transition event="press" target="pressed"><!-- edge-path [pressed] x=60.0 y=110.0 pointx=0.0 pointy=-40.0 offsetx=0.0 offsety=-5.0 --></transition>
|
554
|
+
</state>
|
555
|
+
<state id="pressed"><!-- node-size-and-position x=30.0 y=140.0 w=120.0 h=40.0 -->
|
556
|
+
<transition event="release" target="released"><!-- edge-path [released] x=140.0 y=120.0 --></transition>
|
557
|
+
</state>
|
558
|
+
</state>
|
559
|
+
<state id="pointer" initial="stopped"><!-- node-size-and-position x=270.0 y=50.0 w=210.0 h=210.0 -->
|
560
|
+
<state id="stopped"><!-- node-size-and-position x=50.0 y=60.0 w=100.0 h=40.0 -->
|
561
|
+
<transition event="move" target="moving"><!-- edge-path [moving] x=140.0 y=120.0 --></transition>
|
562
|
+
</state>
|
563
|
+
<state id="moving"><!-- node-size-and-position x=30.0 y=150.0 w=100.0 h=40.0 -->
|
564
|
+
<transition event="stop" target="stopped"><!-- edge-path [stopped] x=50.0 y=130.0 pointx=0.0 pointy=2.0 offsetx=-15.0 offsety=-2.0 --></transition>
|
565
|
+
</state>
|
566
|
+
</state>
|
567
|
+
</parallel>
|
568
|
+
</scxml>
|
569
|
+
EOS
|
570
|
+
|
571
|
+
@sm = parser.build_from_scxml_string scxml
|
572
|
+
@sm.reset
|
573
|
+
@sm.context = self
|
574
|
+
end
|
575
|
+
|
576
|
+
it "should support on entry for superstate inside a parallel state" do
|
577
|
+
@sm.connect
|
578
|
+
@log.should=="Hello world!"
|
579
|
+
end
|
580
|
+
|
581
|
+
it "should support on exit for superstate inside a parallel state" do
|
582
|
+
@sm.connect
|
583
|
+
@sm.disconnect
|
584
|
+
@log.should=="Goodbye cruel world!"
|
585
|
+
end
|
586
|
+
|
587
|
+
end
|
588
|
+
|
589
|
+
describe 'parallel states' do
|
590
|
+
before (:each) do
|
591
|
+
def hello_world
|
592
|
+
@log = "Hello world!"
|
593
|
+
end
|
594
|
+
def goodbye
|
595
|
+
@log = "Goodbye cruel world!"
|
596
|
+
end
|
597
|
+
parser = StatemachineParser.new(nil,nil)
|
598
|
+
|
599
|
+
scxml = <<EOS
|
600
|
+
<scxml initial="disconnected" name="Mouse" version="0.9" xmlns="http://www.w3.org/2005/07/scxml"><!-- node-size-and-position x=0.0 y=0.0 w=662.0 h=660.0 -->
|
601
|
+
<state id="disconnected"><!-- node-size-and-position x=280.0 y=60.0 w=100.0 h=50.0 -->
|
602
|
+
<transition event="connect" target="connected"></transition>
|
603
|
+
</state>
|
604
|
+
<parallel id="connected"><!-- node-size-and-position x=70.0 y=190.0 w=500.0 h=470.0 -->
|
605
|
+
<onentry>
|
606
|
+
<script>hello_world</script>
|
607
|
+
</onentry>
|
608
|
+
<onexit>
|
609
|
+
<script>goodbye </script>
|
610
|
+
</onexit>
|
611
|
+
<transition event="disconnect" target="disconnected"><!-- edge-path [disconnected] x=400.0 y=160.0 --></transition>
|
612
|
+
<state id="leftbutton" initial="released"><!-- node-size-and-position x=40.0 y=50.0 w=210.0 h=210.0 -->
|
613
|
+
<state id="released"><!-- node-size-and-position x=20.0 y=50.0 w=140.0 h=40.0 -->
|
614
|
+
<transition event="press" target="pressed"><!-- edge-path [pressed] x=60.0 y=110.0 pointx=0.0 pointy=-40.0 offsetx=0.0 offsety=-5.0 --></transition>
|
615
|
+
</state>
|
616
|
+
<state id="pressed"><!-- node-size-and-position x=30.0 y=140.0 w=120.0 h=40.0 -->
|
617
|
+
<transition event="release" target="released"><!-- edge-path [released] x=140.0 y=120.0 --></transition>
|
618
|
+
</state>
|
619
|
+
</state>
|
620
|
+
<state id="pointer" initial="stopped"><!-- node-size-and-position x=270.0 y=50.0 w=210.0 h=210.0 -->
|
621
|
+
<state id="stopped"><!-- node-size-and-position x=50.0 y=60.0 w=100.0 h=40.0 -->
|
622
|
+
<transition event="move" target="moving"><!-- edge-path [moving] x=140.0 y=120.0 --></transition>
|
623
|
+
</state>
|
624
|
+
<state id="moving"><!-- node-size-and-position x=30.0 y=150.0 w=100.0 h=40.0 -->
|
625
|
+
<transition event="stop" target="stopped"><!-- edge-path [stopped] x=50.0 y=130.0 pointx=0.0 pointy=2.0 offsetx=-15.0 offsety=-2.0 --></transition>
|
626
|
+
</state>
|
627
|
+
</state>
|
628
|
+
</parallel>
|
629
|
+
</scxml>
|
630
|
+
EOS
|
631
|
+
|
632
|
+
@sm = parser.build_from_scxml_string scxml
|
633
|
+
@sm.reset
|
634
|
+
@sm.context = self
|
635
|
+
end
|
636
|
+
|
637
|
+
it "should support on entry for parallel states" do
|
638
|
+
@sm.connect
|
639
|
+
@log.should=="Hello world!"
|
640
|
+
end
|
641
|
+
|
642
|
+
it "should support on exit for parallel states" do
|
643
|
+
@sm.connect
|
644
|
+
@sm.disconnect
|
645
|
+
@log.should=="Goodbye cruel world!"
|
646
|
+
end
|
647
|
+
end
|
648
|
+
end
|
649
|
+
end
|
392
650
|
end
|
393
651
|
end
|
394
|
-
|