MINT-scxml 1.0.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/.gemtest +0 -0
- data/Gemfile +5 -0
- data/Gemfile.lock +18 -0
- data/History.txt +4 -0
- data/MINT-scxml.gemspec +35 -0
- data/Manifest.txt +49 -0
- data/README.rdoc +50 -0
- data/Rakefile +31 -0
- data/lib/MINT-scxml.rb +5 -0
- data/lib/MINT-scxml/scxml-parser.rb +228 -0
- data/spec/atm_spec.rb +69 -0
- data/spec/parser_spec.rb +394 -0
- data/spec/spec.opts +6 -0
- data/spec/spec_helper.rb +8 -0
- data/spec/test_handgestures_spec.rb +53 -0
- data/spec/testmachines/atm_enhanced.rb +129 -0
- data/spec/testmachines/handgestures-scxmlgui.png +0 -0
- data/spec/testmachines/handgestures-scxmlgui.scxml +106 -0
- data/spec/testmachines/multiplestates.rb +25 -0
- data/spec/testmachines/traffic_light_enhanced.rb +56 -0
- data/spec/testmachines/vending_machine1.rb +18 -0
- data/spec/testmachines/vending_machine2.rb +42 -0
- data/spec/testmachines/vending_machine3.rb +48 -0
- data/spec/testmachines/vending_machine4.rb +29 -0
- data/spec_helper.rb +8 -0
- data/statemachines/AICommand_scxml_spec.rb +38 -0
- data/statemachines/AIO_scxml_spec.rb +36 -0
- data/statemachines/aui-scxml/AIC.scxml +26 -0
- data/statemachines/aui-scxml/AICommand.scxml +34 -0
- data/statemachines/aui-scxml/AICommand2.scxml +32 -0
- data/statemachines/aui-scxml/AIO.scxml +25 -0
- data/statemachines/aui/AIC.rb +29 -0
- data/statemachines/aui/AIChoiceElement.rb +32 -0
- data/statemachines/aui/AICommand.rb +34 -0
- data/statemachines/aui/AIIN.rb +7 -0
- data/statemachines/aui/AIINContinous.rb +41 -0
- data/statemachines/aui/AIMultiChoice.rb +46 -0
- data/statemachines/aui/AIMultiChoiceElement.rb +46 -0
- data/statemachines/aui/AIOUTContinous.rb +41 -0
- data/statemachines/aui/AISingleChoice.rb +42 -0
- data/statemachines/aui/AISingleChoiceElement.rb +45 -0
- data/statemachines/aui/aio.rb +28 -0
- data/statemachines/specs/AICommand_spec.rb +58 -0
- data/statemachines/specs/AIINContinous_spec.rb +61 -0
- data/statemachines/specs/AIMultiChoiceElement_spec.rb +70 -0
- data/statemachines/specs/AIMultiChoice_spec.rb +56 -0
- data/statemachines/specs/AIOUTContinous_spec.rb +71 -0
- data/statemachines/specs/AIO_spec.rb +53 -0
- data/statemachines/specs/AISingleChoiceElement_spec.rb +58 -0
- data/statemachines/specs/AISingleChoice_spec.rb +68 -0
- metadata +146 -0
data/spec/parser_spec.rb
ADDED
@@ -0,0 +1,394 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/spec_helper'
|
2
|
+
|
3
|
+
describe 'The StatemachineParser for' do
|
4
|
+
describe 'states' do
|
5
|
+
begin
|
6
|
+
describe 'without a superstate' 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
|
+
<transition event="event4" target="state2">
|
17
|
+
<log expr="transition executing"/>
|
18
|
+
</transition>
|
19
|
+
</state>
|
20
|
+
|
21
|
+
<state id="state2">
|
22
|
+
<transition event="event2" target="state3"/>
|
23
|
+
</state>
|
24
|
+
|
25
|
+
<state id="state3">
|
26
|
+
<transition event="event3" target="state1"/>
|
27
|
+
</state>
|
28
|
+
</scxml>
|
29
|
+
EOS
|
30
|
+
|
31
|
+
@sm = parser.build_from_scxml_string scxml
|
32
|
+
end
|
33
|
+
|
34
|
+
it "should start with the correct initial state without initial attribute set" do
|
35
|
+
@sm.state.should==:state1
|
36
|
+
end
|
37
|
+
|
38
|
+
it "should support transitions " do
|
39
|
+
@sm.event1
|
40
|
+
@sm.state.should==:state2
|
41
|
+
@sm.event2
|
42
|
+
@sm.state.should==:state3
|
43
|
+
@sm.event3
|
44
|
+
@sm.state.should==:state1
|
45
|
+
end
|
46
|
+
|
47
|
+
it "should support logging inside a transition" do
|
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
|
+
|
59
|
+
scxml = <<EOS
|
60
|
+
<?xml version="1.0"?>
|
61
|
+
<scxml xmlns="http://www.w3.org/2005/07/scxml" version="1.0" profile="ecmascript" initial="off">
|
62
|
+
<state id="super" initial="child2">
|
63
|
+
<state id="child1">
|
64
|
+
<transition event="event1" target="child2">
|
65
|
+
<log expr="'This is action1'"/>
|
66
|
+
</transition>
|
67
|
+
</state>
|
68
|
+
<state id="child2">
|
69
|
+
<transition event="event2" target="child3">
|
70
|
+
<log expr="'This is action2'"/>
|
71
|
+
</transition>
|
72
|
+
</state>
|
73
|
+
<state id="child3">
|
74
|
+
<transition event="event3" target="child1">
|
75
|
+
<log expr="'This is action3'"/>
|
76
|
+
</transition>
|
77
|
+
</state>
|
78
|
+
</state>
|
79
|
+
</scxml>
|
80
|
+
EOS
|
81
|
+
@sm = parser.build_from_scxml_string scxml
|
82
|
+
end
|
83
|
+
|
84
|
+
it "should start with the correct state" do
|
85
|
+
@sm.state.should==:child2
|
86
|
+
end
|
87
|
+
|
88
|
+
it "should support transitions and logging inside transitions" do
|
89
|
+
@messenger.should_receive(:puts).with("'This is action2'" )
|
90
|
+
@sm.event2
|
91
|
+
@sm.state.should==:child3
|
92
|
+
|
93
|
+
@messenger.should_receive(:puts).with("'This is action3'" )
|
94
|
+
@sm.event3
|
95
|
+
@sm.state.should==:child1
|
96
|
+
|
97
|
+
@messenger.should_receive(:puts).with("'This is action1'" )
|
98
|
+
@sm.event1
|
99
|
+
@sm.state.should==:child2
|
100
|
+
end
|
101
|
+
|
102
|
+
it 'should start with the correct state even if the initial state has not been explicitly set' do
|
103
|
+
scxml = <<EOS
|
104
|
+
<?xml version="1.0"?>
|
105
|
+
<scxml xmlns="http://www.w3.org/2005/07/scxml" version="1.0" profile="ecmascript" initial="off">
|
106
|
+
<state id="state">
|
107
|
+
<state id="state1">
|
108
|
+
<transition event="event1" target="state2">
|
109
|
+
<log expr="'This is action1'"/>
|
110
|
+
</transition>
|
111
|
+
</state>
|
112
|
+
<state id="state2">
|
113
|
+
<transition event="event2" target="state3">
|
114
|
+
<log expr="'This is action2'"/>
|
115
|
+
</transition>
|
116
|
+
</state>
|
117
|
+
</state>
|
118
|
+
</scxml>
|
119
|
+
EOS
|
120
|
+
parser = StatemachineParser.new
|
121
|
+
@sm = parser.build_from_scxml_string scxml
|
122
|
+
@sm.state.should==:state1
|
123
|
+
|
124
|
+
end
|
125
|
+
end
|
126
|
+
describe "in double nested superstates" do
|
127
|
+
before (:each) do
|
128
|
+
|
129
|
+
parser = StatemachineParser.new
|
130
|
+
scxml = <<EOS
|
131
|
+
<?xml version="1.0"?>
|
132
|
+
<scxml xmlns="http://www.w3.org/2005/07/scxml" version="1.0" profile="ecmascript" initial="off">
|
133
|
+
<state id="state1" initial="state12">
|
134
|
+
<transition event="to_state2" target="state2"/>
|
135
|
+
<state id="state11" initial="state111">
|
136
|
+
<state id="state111">
|
137
|
+
<transition event="to_state12" target="state12"/>
|
138
|
+
</state>
|
139
|
+
<transition event="to_state111" target="state111"/>
|
140
|
+
<transition event="to_state13" target="state13"/>
|
141
|
+
</state>
|
142
|
+
<state id="state12">
|
143
|
+
<transition event="to_state13" target="state13"/>
|
144
|
+
</state>
|
145
|
+
<state id="state13">
|
146
|
+
<transition event="to_state11" target="state11"/>
|
147
|
+
</state>
|
148
|
+
</state>
|
149
|
+
<state id="state2"/>
|
150
|
+
</scxml>
|
151
|
+
EOS
|
152
|
+
|
153
|
+
@sm = parser.build_from_scxml_string scxml
|
154
|
+
end
|
155
|
+
|
156
|
+
it "should support starting with the correct inital state that has been excplicitely set" do
|
157
|
+
@sm.state.should==:state12
|
158
|
+
@sm.to_state13
|
159
|
+
@sm.to_state11
|
160
|
+
@sm.state.should==:state111
|
161
|
+
end
|
162
|
+
|
163
|
+
it "should support transitions the are defined for a superstate to get into a nested state of the same superstate" do
|
164
|
+
@sm.to_state13
|
165
|
+
@sm.to_state11
|
166
|
+
@sm.to_state111
|
167
|
+
@sm.state.should==:state111
|
168
|
+
@sm.to_state12
|
169
|
+
@sm.state.should==:state12
|
170
|
+
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
|
+
|
199
|
+
scxml = <<EOS
|
200
|
+
<scxml id="SCXML" xmlns="http://www.w3.org/2005/07/scxml">
|
201
|
+
<state id="state1">
|
202
|
+
<transition event="to_state2" target="state2"/>
|
203
|
+
</state>
|
204
|
+
<state id="state2">
|
205
|
+
<onentry>
|
206
|
+
<log expr="'inside state2 onentry'"/>
|
207
|
+
<send type="'x-mint'" target="target" event="fax.SEND"/>
|
208
|
+
</onentry>
|
209
|
+
<onexit>
|
210
|
+
<log expr="'inside state2 onexit'"/>
|
211
|
+
</onexit>
|
212
|
+
<transition event="to_state1" target="state1">
|
213
|
+
<send type="'x-mint'" target="target-2" event="fax.SEND-2"/>
|
214
|
+
</transition>
|
215
|
+
</state>
|
216
|
+
|
217
|
+
</scxml>
|
218
|
+
EOS
|
219
|
+
|
220
|
+
@sm = parser.build_from_scxml_string scxml
|
221
|
+
end
|
222
|
+
|
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
|
+
end
|
252
|
+
end
|
253
|
+
end
|
254
|
+
|
255
|
+
describe 'parallel' do
|
256
|
+
before (:each) do
|
257
|
+
parser = StatemachineParser.new
|
258
|
+
|
259
|
+
scxml = <<EOS
|
260
|
+
<?xml version="1.0"?>
|
261
|
+
<scxml id="SCXML" xmlns="http://www.w3.org/2005/07/scxml">
|
262
|
+
<state id="state0">
|
263
|
+
<transition event="to_p" target="parallel"/>
|
264
|
+
</state>
|
265
|
+
<state id="p_super">
|
266
|
+
<transition event="to_0" target="state0"/>
|
267
|
+
<parallel id="parallel">
|
268
|
+
<state id="state1">
|
269
|
+
<state id="state11">
|
270
|
+
<transition event="to_12" cond="In('state22')" target="state12"/>
|
271
|
+
</state>
|
272
|
+
<state id="state12">
|
273
|
+
<transition event="to_11" cond="In('state21')" target="state12"/>
|
274
|
+
</state>
|
275
|
+
</state>
|
276
|
+
|
277
|
+
<state id="state2" initial="state22">
|
278
|
+
<state id="state21">
|
279
|
+
<transition event="to_22" target="state22"/>
|
280
|
+
</state>
|
281
|
+
<state id="state22">
|
282
|
+
<transition event="to_21" target="state21"/>
|
283
|
+
</state>
|
284
|
+
</state>
|
285
|
+
</parallel>
|
286
|
+
</state>
|
287
|
+
</scxml>
|
288
|
+
EOS
|
289
|
+
|
290
|
+
@sm = parser.build_from_scxml_string scxml
|
291
|
+
end
|
292
|
+
|
293
|
+
it "start with the initial state and transition to the parallel states" do
|
294
|
+
@sm.states_id.should == [:state0]
|
295
|
+
@sm.process_event(:to_p)
|
296
|
+
@sm.states_id.should == [:state11,:state22]
|
297
|
+
end
|
298
|
+
|
299
|
+
it "support transitions for both parallel superstates" do
|
300
|
+
@sm.states_id.should == [:state0]
|
301
|
+
@sm.process_event(:to_p)
|
302
|
+
@sm.process_event(:to_12)
|
303
|
+
@sm.In(:state12).should == true
|
304
|
+
@sm.process_event(:to_21)
|
305
|
+
@sm.In(:state21).should == true
|
306
|
+
@sm.states_id.should == [:state12,:state21]
|
307
|
+
end
|
308
|
+
|
309
|
+
it "support testing with 'in' condition for primitive states " do
|
310
|
+
@sm.states_id.should == [:state0]
|
311
|
+
@sm.process_event(:to_p)
|
312
|
+
@sm.process_event(:to_12)
|
313
|
+
@sm.In(:state12).should == true
|
314
|
+
end
|
315
|
+
|
316
|
+
it "support testing with 'in' condition for superstates " do
|
317
|
+
@sm.states_id.should == [:state0]
|
318
|
+
@sm.process_event(:to_p)
|
319
|
+
@sm.process_event(:to_12)
|
320
|
+
@sm.In(:state1).should == true
|
321
|
+
end
|
322
|
+
|
323
|
+
it "support testing with 'in' condition for parallel superstates " do
|
324
|
+
@sm.states_id.should == [:state0]
|
325
|
+
@sm.process_event(:to_p)
|
326
|
+
@sm.process_event(:to_12)
|
327
|
+
@sm.In(:state2).should == true
|
328
|
+
@sm.In(:state1).should == true
|
329
|
+
end
|
330
|
+
end
|
331
|
+
|
332
|
+
describe 'with history' do
|
333
|
+
before (:each) do
|
334
|
+
|
335
|
+
parser = StatemachineParser.new
|
336
|
+
|
337
|
+
scxml = <<EOS
|
338
|
+
<?xml version="1.0"?>
|
339
|
+
<scxml id="SCXML" xmlns="http://www.w3.org/2005/07/scxml">
|
340
|
+
<state id="state0">
|
341
|
+
<transition event="to_p" target="parallel"/>
|
342
|
+
</state>
|
343
|
+
<state id="p_super">
|
344
|
+
<transition event="to_0" target="state0"/>
|
345
|
+
<parallel id="parallel">
|
346
|
+
<state id="state1">
|
347
|
+
<state id="state11">
|
348
|
+
<transition event="to_12" cond="In('state22')" target="state12"/>
|
349
|
+
</state>
|
350
|
+
<state id="state12">
|
351
|
+
<transition event="to_11" cond="In('state21')" target="state12"/>
|
352
|
+
</state>
|
353
|
+
<history id="history" type="deep">
|
354
|
+
<transition target="state11"/>
|
355
|
+
</history>
|
356
|
+
</state>
|
357
|
+
|
358
|
+
<state id="state2" initial="state22">
|
359
|
+
<state id="state21">
|
360
|
+
<transition event="to_22" target="state22"/>
|
361
|
+
</state>
|
362
|
+
<state id="state22">
|
363
|
+
<transition event="to_21" target="state21"/>
|
364
|
+
</state>
|
365
|
+
</state>
|
366
|
+
</parallel>
|
367
|
+
</state>
|
368
|
+
</scxml>
|
369
|
+
EOS
|
370
|
+
|
371
|
+
@sm = parser.build_from_scxml_string scxml
|
372
|
+
end
|
373
|
+
|
374
|
+
it "start with the initial state and transition to the parallel states" do
|
375
|
+
@sm.states_id.should == [:state0]
|
376
|
+
@sm.process_event(:to_p)
|
377
|
+
@sm.states_id.should == [:state11,:state22]
|
378
|
+
end
|
379
|
+
|
380
|
+
it "should leave the parallel states and return in the correct states" do
|
381
|
+
@sm.states_id.should == [:state0]
|
382
|
+
@sm.process_event(:to_p)
|
383
|
+
@sm.states_id.should == [:state11,:state22]
|
384
|
+
@sm.process_event(:to_12)
|
385
|
+
@sm.states_id.should == [:state12,:state22]
|
386
|
+
@sm.process_event(:to_0)
|
387
|
+
@sm.states_id.should == [:state0]
|
388
|
+
@sm.process_event(:to_p)
|
389
|
+
@sm.states_id.should == [:state12,:state22]
|
390
|
+
end
|
391
|
+
end
|
392
|
+
end
|
393
|
+
end
|
394
|
+
|
data/spec/spec.opts
ADDED
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,53 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/spec_helper'
|
2
|
+
|
3
|
+
class TestContext
|
4
|
+
def print_distance
|
5
|
+
end
|
6
|
+
def start_confirm_timeout
|
7
|
+
end
|
8
|
+
def stop_confirm_timeout
|
9
|
+
end
|
10
|
+
def reset_confirm_ticker
|
11
|
+
end
|
12
|
+
def command_timeout_start_prev
|
13
|
+
end
|
14
|
+
def command_timeout_start_next
|
15
|
+
end
|
16
|
+
def command_timeout_stop
|
17
|
+
end
|
18
|
+
def issued_rev
|
19
|
+
end
|
20
|
+
def issued_next
|
21
|
+
end
|
22
|
+
def tick
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
describe 'state' do
|
27
|
+
before (:each) do
|
28
|
+
context = TestContext.new
|
29
|
+
parser = StatemachineParser.new(context)
|
30
|
+
@sm = parser.build_from_scxml "spec/testmachines/handgestures-scxmlgui.scxml"
|
31
|
+
end
|
32
|
+
|
33
|
+
it "should start with the correct initial state >no_hands<" do
|
34
|
+
@sm.state.should==:no_hands
|
35
|
+
end
|
36
|
+
|
37
|
+
it "should support transition to superstate and find correct start state" do
|
38
|
+
@sm.one_hand
|
39
|
+
@sm.state.should==:wait_one
|
40
|
+
end
|
41
|
+
|
42
|
+
it "should leave a deeply nested state through a superstate transition" do
|
43
|
+
@sm.two_hands
|
44
|
+
@sm.state.should==:wait_two
|
45
|
+
@sm.narrow
|
46
|
+
@sm.state.should==:narrowing
|
47
|
+
@sm.confirm
|
48
|
+
@sm.state.should==:narrowed
|
49
|
+
@sm.no_hands # transition defined in superstate!
|
50
|
+
@sm.state.should == :no_hands
|
51
|
+
end
|
52
|
+
|
53
|
+
end
|