MINT-statemachine 1.2.2
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 +135 -0
- data/LICENSE +16 -0
- data/MINT-statemachine.gemspec +27 -0
- data/README.rdoc +69 -0
- data/Rakefile +88 -0
- data/TODO +2 -0
- data/lib/statemachine.rb +26 -0
- data/lib/statemachine/action_invokation.rb +83 -0
- data/lib/statemachine/builder.rb +383 -0
- data/lib/statemachine/generate/dot_graph.rb +1 -0
- data/lib/statemachine/generate/dot_graph/dot_graph_statemachine.rb +127 -0
- data/lib/statemachine/generate/java.rb +1 -0
- data/lib/statemachine/generate/java/java_statemachine.rb +265 -0
- data/lib/statemachine/generate/src_builder.rb +48 -0
- data/lib/statemachine/generate/util.rb +50 -0
- data/lib/statemachine/parallelstate.rb +196 -0
- data/lib/statemachine/state.rb +102 -0
- data/lib/statemachine/statemachine.rb +279 -0
- data/lib/statemachine/stub_context.rb +26 -0
- data/lib/statemachine/superstate.rb +53 -0
- data/lib/statemachine/transition.rb +76 -0
- data/lib/statemachine/version.rb +17 -0
- data/spec/action_invokation_spec.rb +101 -0
- data/spec/builder_spec.rb +243 -0
- data/spec/default_transition_spec.rb +111 -0
- data/spec/generate/dot_graph/dot_graph_stagemachine_spec.rb +27 -0
- data/spec/generate/java/java_statemachine_spec.rb +349 -0
- data/spec/history_spec.rb +107 -0
- data/spec/noodle.rb +23 -0
- data/spec/sm_action_parameterization_spec.rb +99 -0
- data/spec/sm_activation_spec.rb +116 -0
- data/spec/sm_entry_exit_actions_spec.rb +99 -0
- data/spec/sm_odds_n_ends_spec.rb +67 -0
- data/spec/sm_parallel_state_spec.rb +207 -0
- data/spec/sm_simple_spec.rb +26 -0
- data/spec/sm_super_state_spec.rb +55 -0
- data/spec/sm_turnstile_spec.rb +76 -0
- data/spec/spec_helper.rb +121 -0
- data/spec/transition_spec.rb +107 -0
- metadata +115 -0
@@ -0,0 +1,27 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../../spec_helper'
|
2
|
+
require 'statemachine/generate/dot_graph/dot_graph_statemachine'
|
3
|
+
|
4
|
+
describe Statemachine::Statemachine, "(Turn Stile)" do
|
5
|
+
include TurnstileStatemachine
|
6
|
+
|
7
|
+
before(:each) do
|
8
|
+
remove_test_dir("dot")
|
9
|
+
@output = test_dir("dot")
|
10
|
+
create_turnstile
|
11
|
+
end
|
12
|
+
|
13
|
+
# it "should output to console when no output dir provided" do
|
14
|
+
# # Note - this test doesn't verify output to the console, but it does
|
15
|
+
# # ensure that the to_dot call does not fail if not output is provided.
|
16
|
+
# @sm.to_dot
|
17
|
+
# end
|
18
|
+
|
19
|
+
it "should generate a basic graph declaration" do
|
20
|
+
@sm.to_dot(:output => @output)
|
21
|
+
|
22
|
+
dot = load_lines(@output, "main.dot")
|
23
|
+
|
24
|
+
dot.should_not equal(nil)
|
25
|
+
dot[0].include?("digraph").should == true
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,349 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + "/../../spec_helper")
|
2
|
+
require 'statemachine/generate/java/java_statemachine'
|
3
|
+
|
4
|
+
describe Statemachine::Statemachine, "(Java)" do
|
5
|
+
|
6
|
+
before(:each) do
|
7
|
+
remove_test_dir("java")
|
8
|
+
@output = test_dir("java")
|
9
|
+
@sm = Statemachine.build {}
|
10
|
+
end
|
11
|
+
|
12
|
+
def generate_turnstile_sm
|
13
|
+
@sm = Statemachine.build do
|
14
|
+
trans :locked, :coin, :unlocked, :unlock
|
15
|
+
trans :unlocked, :pass, :locked, :lock
|
16
|
+
trans :locked, :pass, :locked, :alarm
|
17
|
+
trans :unlocked, :coin, :locked, :thanks
|
18
|
+
end
|
19
|
+
|
20
|
+
@sm.to_java(:output => @output, :name => "JavaTurnstile", :package => "test.turnstile")
|
21
|
+
end
|
22
|
+
|
23
|
+
def generate_complex_turnstile_sm
|
24
|
+
@sm = Statemachine.build do
|
25
|
+
superstate :operational do
|
26
|
+
on_entry :operate
|
27
|
+
on_exit :beep
|
28
|
+
state :locked do
|
29
|
+
on_entry :lock
|
30
|
+
event :coin, :unlocked
|
31
|
+
event :pass, :locked, :alarm
|
32
|
+
end
|
33
|
+
state :unlocked do
|
34
|
+
on_entry :unlock
|
35
|
+
event :coin, :unlocked, :thanks
|
36
|
+
event :pass, :locked
|
37
|
+
end
|
38
|
+
event :diagnose, :diagnostics
|
39
|
+
end
|
40
|
+
state :diagnostics do
|
41
|
+
on_entry :disable
|
42
|
+
on_exit :beep
|
43
|
+
event :operate, :operational
|
44
|
+
end
|
45
|
+
stub_context :verbose => true
|
46
|
+
end
|
47
|
+
|
48
|
+
@sm.to_java(:output => @output, :name => "JavaTurnstile", :package => "test.turnstile")
|
49
|
+
end
|
50
|
+
|
51
|
+
# def load_lines(*segs)
|
52
|
+
# filename = File.join(*segs)
|
53
|
+
# File.should exist( filename)
|
54
|
+
# return IO.read(filename).split("\n")
|
55
|
+
# end
|
56
|
+
|
57
|
+
def empty_sm_lines
|
58
|
+
@sm.to_java(:name => "JavaTest", :output => @output, :package => "test.blank")
|
59
|
+
return load_lines(@output, "test", "blank", "JavaTest.java")
|
60
|
+
end
|
61
|
+
|
62
|
+
def turnstile_lines
|
63
|
+
generate_turnstile_sm
|
64
|
+
return load_lines(@output, "test", "turnstile", "JavaTurnstile.java")
|
65
|
+
end
|
66
|
+
|
67
|
+
def turnstile_context_lines
|
68
|
+
generate_turnstile_sm
|
69
|
+
return load_lines(@output, "test", "turnstile", "JavaTurnstileContext.java")
|
70
|
+
end
|
71
|
+
|
72
|
+
def complex_turnstile_lines
|
73
|
+
generate_complex_turnstile_sm
|
74
|
+
return load_lines(@output, "test", "turnstile", "JavaTurnstile.java")
|
75
|
+
end
|
76
|
+
|
77
|
+
def find_lines_after(lines, goose)
|
78
|
+
while !lines.empty?
|
79
|
+
return lines if lines.shift.strip == goose
|
80
|
+
end
|
81
|
+
raise "Can't find desired line: #{goose}"
|
82
|
+
end
|
83
|
+
|
84
|
+
it "should error if no output dir is specified" do
|
85
|
+
lambda { @sm.to_java }.should raise_error("Please specify an output directory. (:output => 'where/you/want/your/code')")
|
86
|
+
end
|
87
|
+
|
88
|
+
it "should error if output dir doesn't exist" do
|
89
|
+
lambda { @sm.to_java(:output => "/blah") }.should raise_error("Output dir '/blah' doesn't exist.")
|
90
|
+
end
|
91
|
+
|
92
|
+
it "should error if no class name is specified" do
|
93
|
+
lambda { @sm.to_java(:output => @output) }.should raise_error("Please specify a name for the statemachine. (:name => 'SomeName')")
|
94
|
+
end
|
95
|
+
|
96
|
+
it "should generate a class" do
|
97
|
+
@sm.to_java(:name => "JavaTest", :output => @output)
|
98
|
+
File.should exist(File.join(@output, "JavaTest.java"))
|
99
|
+
end
|
100
|
+
|
101
|
+
it "should generate a class in a package" do
|
102
|
+
lines = empty_sm_lines
|
103
|
+
|
104
|
+
lines.shift.should == "// This file was generated by the Ruby Statemachine Library (http://slagyr.github.com/statemachine)."
|
105
|
+
lines.shift.include?("// Generated at ").should == true
|
106
|
+
lines.shift.should == "package test.blank;"
|
107
|
+
lines.shift.should == ""
|
108
|
+
lines.shift.should == "public class JavaTest"
|
109
|
+
lines.shift.should == "{"
|
110
|
+
lines.last.should == "}"
|
111
|
+
end
|
112
|
+
|
113
|
+
it "should generate the constructor" do
|
114
|
+
lines = find_lines_after(empty_sm_lines, "// Statemachine constructor")
|
115
|
+
|
116
|
+
lines.shift.should == " public JavaTest(JavaTestContext context)"
|
117
|
+
lines.shift.should == " {"
|
118
|
+
lines.shift.should == " this.context = context;"
|
119
|
+
lines.shift.should == " }"
|
120
|
+
lines.shift.should == ""
|
121
|
+
end
|
122
|
+
|
123
|
+
it "should generate sm boilerplate code" do
|
124
|
+
lines = find_lines_after(empty_sm_lines, "// The following is boiler plate code standard to all statemachines")
|
125
|
+
|
126
|
+
lines.shift.should == " public JavaTestContext getContext()"
|
127
|
+
lines.shift.should == " {"
|
128
|
+
lines.shift.should == " return context;"
|
129
|
+
lines.shift.should == " }"
|
130
|
+
lines.shift.should == ""
|
131
|
+
lines.shift.should == " public State getState()"
|
132
|
+
lines.shift.should == " {"
|
133
|
+
lines.shift.should == " return state;"
|
134
|
+
lines.shift.should == " }"
|
135
|
+
lines.shift.should == ""
|
136
|
+
lines.shift.should == " public void setState(State newState)"
|
137
|
+
lines.shift.should == " {"
|
138
|
+
lines.shift.should == " state = newState;"
|
139
|
+
lines.shift.should == " }"
|
140
|
+
end
|
141
|
+
|
142
|
+
it "should generate the sm exception" do
|
143
|
+
lines = empty_sm_lines
|
144
|
+
lines = find_lines_after(lines, "// Standard exception class added to all statemachines.")
|
145
|
+
|
146
|
+
lines.shift.should == " public static class StatemachineException extends RuntimeException"
|
147
|
+
lines.shift.should == " {"
|
148
|
+
lines.shift.should == " public StatemachineException(State state, String event)"
|
149
|
+
lines.shift.should == " {"
|
150
|
+
lines.shift.should == " super(\"Missing transition from '\" + state.getClass().getSimpleName() + \"' with the '\" + event + \"' event.\");"
|
151
|
+
lines.shift.should == " }"
|
152
|
+
lines.shift.should == " }"
|
153
|
+
end
|
154
|
+
|
155
|
+
it "should generate base state" do
|
156
|
+
lines = empty_sm_lines
|
157
|
+
lines = find_lines_after(lines, "// The base state")
|
158
|
+
|
159
|
+
lines.shift.should == " public static abstract class State"
|
160
|
+
lines.shift.should == " {"
|
161
|
+
lines.shift.should == " protected JavaTest statemachine;"
|
162
|
+
lines.shift.should == ""
|
163
|
+
lines.shift.should == " public State(JavaTest statemachine)"
|
164
|
+
lines.shift.should == " {"
|
165
|
+
lines.shift.should == " this.statemachine = statemachine;"
|
166
|
+
lines.shift.should == " }"
|
167
|
+
lines.shift.should == ""
|
168
|
+
lines.shift.should == " }"
|
169
|
+
end
|
170
|
+
|
171
|
+
it "should generate the context" do
|
172
|
+
@sm.to_java(:name => "JavaTest", :output => @output, :package => "com.blah")
|
173
|
+
|
174
|
+
filename = File.join(@output, "com", "blah", "JavaTestContext.java")
|
175
|
+
File.should exist(filename)
|
176
|
+
lines = IO.read(filename).split("\n")
|
177
|
+
|
178
|
+
lines.shift.should == "// This file was generated by the Ruby Statemachine Library (http://slagyr.github.com/statemachine)."
|
179
|
+
lines.shift.include?("// Generated at ").should == true
|
180
|
+
lines.shift.should == "package com.blah;"
|
181
|
+
lines.shift.should == ""
|
182
|
+
lines.shift.should == "public interface JavaTestContext"
|
183
|
+
lines.shift.should == "{"
|
184
|
+
lines.shift.should == " // Actions"
|
185
|
+
lines.shift.should == "}"
|
186
|
+
lines.should be_empty
|
187
|
+
end
|
188
|
+
|
189
|
+
it "should generate the state instance variables" do
|
190
|
+
lines = find_lines_after(turnstile_lines, "// Instance variables")
|
191
|
+
|
192
|
+
lines.shift.should == " public final State LOCKED = new LockedState(this);"
|
193
|
+
lines.shift.should == " public final State UNLOCKED = new UnlockedState(this);"
|
194
|
+
lines.shift.should == " private State state = LOCKED;"
|
195
|
+
lines.shift.should == ""
|
196
|
+
lines.shift.should == " private JavaTurnstileContext context;"
|
197
|
+
end
|
198
|
+
|
199
|
+
it "should generate all the sm event handlers" do
|
200
|
+
lines = find_lines_after(turnstile_lines, "// Event delegation")
|
201
|
+
|
202
|
+
lines.shift.should == " public void coin()"
|
203
|
+
lines.shift.should == " {"
|
204
|
+
lines.shift.should == " state.coin();"
|
205
|
+
lines.shift.should == " }"
|
206
|
+
lines.shift.should == ""
|
207
|
+
lines.shift.should == " public void pass()"
|
208
|
+
lines.shift.should == " {"
|
209
|
+
lines.shift.should == " state.pass();"
|
210
|
+
lines.shift.should == " }"
|
211
|
+
lines.shift.should == ""
|
212
|
+
end
|
213
|
+
|
214
|
+
it "should generate all the default event handlers" do
|
215
|
+
lines = find_lines_after(turnstile_lines, "// The base state")
|
216
|
+
|
217
|
+
lines.shift.should == " public static abstract class State"
|
218
|
+
lines.shift.should == " {"
|
219
|
+
lines.shift.should == " protected JavaTurnstile statemachine;"
|
220
|
+
lines.shift.should == ""
|
221
|
+
lines.shift.should == " public State(JavaTurnstile statemachine)"
|
222
|
+
lines.shift.should == " {"
|
223
|
+
lines.shift.should == " this.statemachine = statemachine;"
|
224
|
+
lines.shift.should == " }"
|
225
|
+
lines.shift.should == ""
|
226
|
+
lines.shift.should == " public void coin()"
|
227
|
+
lines.shift.should == " {"
|
228
|
+
lines.shift.should == " throw new StatemachineException(this, \"coin\");"
|
229
|
+
lines.shift.should == " }"
|
230
|
+
lines.shift.should == ""
|
231
|
+
lines.shift.should == " public void pass()"
|
232
|
+
lines.shift.should == " {"
|
233
|
+
lines.shift.should == " throw new StatemachineException(this, \"pass\");"
|
234
|
+
lines.shift.should == " }"
|
235
|
+
lines.shift.should == ""
|
236
|
+
lines.shift.should == " }"
|
237
|
+
end
|
238
|
+
|
239
|
+
it "should generate state classes" do
|
240
|
+
lines = find_lines_after(turnstile_lines, "// State implementations")
|
241
|
+
|
242
|
+
lines.shift.should == " public static class LockedState extends State"
|
243
|
+
lines.shift.should == " {"
|
244
|
+
lines.shift.should == " public LockedState(JavaTurnstile statemachine)"
|
245
|
+
lines.shift.should == " {"
|
246
|
+
lines.shift.should == " super(statemachine);"
|
247
|
+
lines.shift.should == " }"
|
248
|
+
lines.shift.should == ""
|
249
|
+
lines.shift.should == " public void coin()"
|
250
|
+
lines.shift.should == " {"
|
251
|
+
lines.shift.should == " statemachine.getContext().unlock();"
|
252
|
+
lines.shift.should == " statemachine.setState(statemachine.UNLOCKED);"
|
253
|
+
lines.shift.should == " }"
|
254
|
+
lines.shift.should == ""
|
255
|
+
lines.shift.should == " public void pass()"
|
256
|
+
lines.shift.should == " {"
|
257
|
+
lines.shift.should == " statemachine.getContext().alarm();"
|
258
|
+
lines.shift.should == " statemachine.setState(statemachine.LOCKED);"
|
259
|
+
lines.shift.should == " }"
|
260
|
+
lines.shift.should == ""
|
261
|
+
lines.shift.should == " }"
|
262
|
+
lines.shift.should == ""
|
263
|
+
lines.shift.should == " public static class UnlockedState extends State"
|
264
|
+
lines.shift.should == " {"
|
265
|
+
lines.shift.should == " public UnlockedState(JavaTurnstile statemachine)"
|
266
|
+
lines.shift.should == " {"
|
267
|
+
lines.shift.should == " super(statemachine);"
|
268
|
+
lines.shift.should == " }"
|
269
|
+
lines.shift.should == ""
|
270
|
+
lines.shift.should == " public void coin()"
|
271
|
+
lines.shift.should == " {"
|
272
|
+
lines.shift.should == " statemachine.getContext().thanks();"
|
273
|
+
lines.shift.should == " statemachine.setState(statemachine.LOCKED);"
|
274
|
+
lines.shift.should == " }"
|
275
|
+
lines.shift.should == ""
|
276
|
+
lines.shift.should == " public void pass()"
|
277
|
+
lines.shift.should == " {"
|
278
|
+
lines.shift.should == " statemachine.getContext().lock();"
|
279
|
+
lines.shift.should == " statemachine.setState(statemachine.LOCKED);"
|
280
|
+
lines.shift.should == " }"
|
281
|
+
lines.shift.should == ""
|
282
|
+
lines.shift.should == " }"
|
283
|
+
lines.shift.should == ""
|
284
|
+
end
|
285
|
+
|
286
|
+
it "should generate all the context methods" do
|
287
|
+
lines = find_lines_after(turnstile_context_lines, "// Actions")
|
288
|
+
|
289
|
+
lines.shift.should == " void alarm();"
|
290
|
+
lines.shift.should == " void lock();"
|
291
|
+
lines.shift.should == " void thanks();"
|
292
|
+
lines.shift.should == " void unlock();"
|
293
|
+
end
|
294
|
+
|
295
|
+
it "should generate complext state instances" do
|
296
|
+
lines = find_lines_after(complex_turnstile_lines, "// Instance variables")
|
297
|
+
|
298
|
+
lines.shift.should == " public final State DIAGNOSTICS = new DiagnosticsState(this);"
|
299
|
+
lines.shift.should == " public final State LOCKED = new LockedState(this);"
|
300
|
+
lines.shift.should == " public final State UNLOCKED = new UnlockedState(this);"
|
301
|
+
lines.shift.should == " public final State OPERATIONAL = LOCKED;"
|
302
|
+
lines.shift.should == " private State state = LOCKED;"
|
303
|
+
end
|
304
|
+
|
305
|
+
it "should generate entry actions on startup" do
|
306
|
+
lines = find_lines_after(complex_turnstile_lines, "// Statemachine constructor")
|
307
|
+
|
308
|
+
lines.shift.should == " public JavaTurnstile(JavaTurnstileContext context)"
|
309
|
+
lines.shift.should == " {"
|
310
|
+
lines.shift.should == " this.context = context;"
|
311
|
+
lines.shift.should == " context.operate();"
|
312
|
+
lines.shift.should == " context.lock();"
|
313
|
+
lines.shift.should == " }"
|
314
|
+
lines.shift.should == ""
|
315
|
+
end
|
316
|
+
|
317
|
+
it "should add entry/exit actions to each transition" do
|
318
|
+
lines = find_lines_after(complex_turnstile_lines, "public static class LockedState extends State")
|
319
|
+
|
320
|
+
lines.shift.should == " {"
|
321
|
+
lines.shift.should == " public LockedState(JavaTurnstile statemachine)"
|
322
|
+
lines.shift.should == " {"
|
323
|
+
lines.shift.should == " super(statemachine);"
|
324
|
+
lines.shift.should == " }"
|
325
|
+
lines.shift.should == ""
|
326
|
+
lines.shift.should == " public void coin()"
|
327
|
+
lines.shift.should == " {"
|
328
|
+
lines.shift.should == " statemachine.setState(statemachine.UNLOCKED);"
|
329
|
+
lines.shift.should == " statemachine.getContext().unlock();"
|
330
|
+
lines.shift.should == " }"
|
331
|
+
lines.shift.should == ""
|
332
|
+
lines.shift.should == " public void diagnose()"
|
333
|
+
lines.shift.should == " {"
|
334
|
+
lines.shift.should == " statemachine.getContext().beep();"
|
335
|
+
lines.shift.should == " statemachine.setState(statemachine.DIAGNOSTICS);"
|
336
|
+
lines.shift.should == " statemachine.getContext().disable();"
|
337
|
+
lines.shift.should == " }"
|
338
|
+
lines.shift.should == ""
|
339
|
+
lines.shift.should == " public void pass()"
|
340
|
+
lines.shift.should == " {"
|
341
|
+
lines.shift.should == " statemachine.getContext().alarm();"
|
342
|
+
lines.shift.should == " statemachine.setState(statemachine.LOCKED);"
|
343
|
+
lines.shift.should == " statemachine.getContext().lock();" # this has been added since my modifications don't know why'
|
344
|
+
lines.shift.should == " }"
|
345
|
+
lines.shift.should == ""
|
346
|
+
lines.shift.should == " }"
|
347
|
+
end
|
348
|
+
|
349
|
+
end
|
@@ -0,0 +1,107 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/spec_helper'
|
2
|
+
|
3
|
+
describe "History States" do
|
4
|
+
|
5
|
+
before(:each) do
|
6
|
+
@sm = Statemachine.build do
|
7
|
+
superstate :operate do
|
8
|
+
trans :on, :toggle, :off
|
9
|
+
trans :off, :toggle, :on
|
10
|
+
event :fiddle, :middle
|
11
|
+
end
|
12
|
+
trans :middle, :fiddle, :operate_H
|
13
|
+
trans :middle, :dream, :on_H
|
14
|
+
trans :middle, :faddle, :on
|
15
|
+
startstate :middle
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
it "no history allowed for concrete states" do
|
20
|
+
lambda {
|
21
|
+
@sm.dream
|
22
|
+
}.should raise_error(Statemachine::StatemachineException, "No history exists for 'on' state since it is not a super state.")
|
23
|
+
end
|
24
|
+
|
25
|
+
it "error when trying to use history that doesn't exist yet" do
|
26
|
+
lambda {
|
27
|
+
@sm.fiddle
|
28
|
+
}.should raise_error(Statemachine::StatemachineException, "'operate' superstate doesn't have any history yet.")
|
29
|
+
end
|
30
|
+
|
31
|
+
it "reseting the statemachine resets history" do
|
32
|
+
@sm.faddle
|
33
|
+
@sm.fiddle
|
34
|
+
@sm.get_state(:operate).history_id.should eql(:on)
|
35
|
+
|
36
|
+
@sm.reset
|
37
|
+
@sm.get_state(:operate).history_id.should eql(nil)
|
38
|
+
end
|
39
|
+
|
40
|
+
end
|
41
|
+
|
42
|
+
describe "History Default" do
|
43
|
+
|
44
|
+
before(:each) do
|
45
|
+
@sm = Statemachine.build do
|
46
|
+
superstate :operate do
|
47
|
+
trans :on, :toggle, :off
|
48
|
+
trans :off, :toggle, :on
|
49
|
+
event :fiddle, :middle
|
50
|
+
default_history :on
|
51
|
+
end
|
52
|
+
trans :middle, :fiddle, :operate_H
|
53
|
+
startstate :middle
|
54
|
+
trans :middle, :faddle, :on
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
it "default history" do
|
59
|
+
@sm.fiddle
|
60
|
+
@sm.state.should eql(:on)
|
61
|
+
end
|
62
|
+
|
63
|
+
it "reseting the statemachine resets history" do
|
64
|
+
@sm.faddle
|
65
|
+
@sm.toggle
|
66
|
+
@sm.fiddle
|
67
|
+
@sm.get_state(:operate).history_id.should eql(:off)
|
68
|
+
|
69
|
+
@sm.reset
|
70
|
+
@sm.get_state(:operate).history_id.should eql(:on)
|
71
|
+
end
|
72
|
+
|
73
|
+
end
|
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
|
+
|