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,76 @@
|
|
1
|
+
module Statemachine
|
2
|
+
|
3
|
+
class Transition #:nodoc:
|
4
|
+
|
5
|
+
attr_reader :origin_id, :event, :action
|
6
|
+
attr_accessor :destination_id, :cond
|
7
|
+
|
8
|
+
def initialize(origin_id, destination_id, event, action, cond)
|
9
|
+
@origin_id = origin_id
|
10
|
+
@destination_id = destination_id
|
11
|
+
@event = event
|
12
|
+
@action = action
|
13
|
+
@cond = cond
|
14
|
+
end
|
15
|
+
|
16
|
+
def invoke(origin, statemachine, args)
|
17
|
+
destination = statemachine.get_state(@destination_id)
|
18
|
+
exits, entries = exits_and_entries(origin, destination)
|
19
|
+
exits.each { |exited_state| exited_state.exit(args) }
|
20
|
+
messenger = origin.statemachine.messenger
|
21
|
+
message_queue = origin.statemachine.message_queue
|
22
|
+
|
23
|
+
if @action # changed this if statement to return if action fails
|
24
|
+
if not origin.statemachine.invoke_action(@action, args, "transition action from #{origin} invoked by '#{@event}' event", messenger, message_queue)
|
25
|
+
raise StatemachineException.new("Transition to state #{destination.id} failed because action for event #{@event} return false.")
|
26
|
+
return
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
# origin.statemachine.invoke_action(@action, args, "transition action from #{origin} invoked by '#{@event}' event", messenger, message_queue) if @action
|
31
|
+
|
32
|
+
terminal_state = entries.last
|
33
|
+
entries.each { |entered_state| entered_state.activate(terminal_state.id) if entered_state.is_parallel }
|
34
|
+
|
35
|
+
terminal_state.activate if terminal_state and not terminal_state.is_parallel
|
36
|
+
|
37
|
+
entries.each { |entered_state| entered_state.enter(args) }
|
38
|
+
end
|
39
|
+
|
40
|
+
def exits_and_entries(origin, destination)
|
41
|
+
# return [], [] if origin == destination
|
42
|
+
exits = []
|
43
|
+
entries = exits_and_entries_helper(exits, origin, destination)
|
44
|
+
return exits, entries.reverse
|
45
|
+
end
|
46
|
+
|
47
|
+
def to_s
|
48
|
+
return "#{@origin_id} ---#{@event}---> #{@destination_id} : #{action} if #{cond}"
|
49
|
+
end
|
50
|
+
|
51
|
+
private
|
52
|
+
|
53
|
+
def exits_and_entries_helper(exits, exit_state, destination)
|
54
|
+
entries = entries_to_destination(exit_state, destination)
|
55
|
+
return entries if entries
|
56
|
+
return [] if exit_state == nil
|
57
|
+
|
58
|
+
exits << exit_state
|
59
|
+
exits_and_entries_helper(exits, exit_state.superstate, destination)
|
60
|
+
end
|
61
|
+
|
62
|
+
def entries_to_destination(exit_state, destination)
|
63
|
+
return nil if destination.nil?
|
64
|
+
entries = []
|
65
|
+
state = destination.resolve_startstate
|
66
|
+
while state
|
67
|
+
entries << state
|
68
|
+
return entries if exit_state == state.superstate
|
69
|
+
state = state.superstate
|
70
|
+
end
|
71
|
+
return nil
|
72
|
+
end
|
73
|
+
|
74
|
+
end
|
75
|
+
|
76
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module Statemachine
|
2
|
+
module VERSION #:nodoc:
|
3
|
+
unless defined? MAJOR
|
4
|
+
MAJOR = 1
|
5
|
+
MINOR = 2
|
6
|
+
TINY = 2
|
7
|
+
|
8
|
+
STRING = [MAJOR, MINOR, TINY].join('.')
|
9
|
+
TAG = "REL_" + [MAJOR, MINOR, TINY].join('_')
|
10
|
+
|
11
|
+
NAME = "MINT-Statemachine"
|
12
|
+
URL = "http://www.multi-access.de/open-source-software/third-party-software-extensions/"
|
13
|
+
|
14
|
+
DESCRIPTION = "#{NAME}-#{STRING} - Statemachine Library for Ruby based on statemachine from http://slagyr.github.com/statemachine\n#{URL}"
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,101 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/spec_helper'
|
2
|
+
#require 'statemachine'
|
3
|
+
#require 'lib/statemachine/action_invokation.rb'
|
4
|
+
require "noodle"
|
5
|
+
|
6
|
+
describe "Action Invokation" do
|
7
|
+
|
8
|
+
before(:each) do
|
9
|
+
@noodle = Noodle.new
|
10
|
+
end
|
11
|
+
|
12
|
+
it "Proc actions" do
|
13
|
+
sm = Statemachine.build do |smb|
|
14
|
+
smb.trans :cold, :fire, :hot, Proc.new { @cooked = true }
|
15
|
+
end
|
16
|
+
|
17
|
+
sm.context = @noodle
|
18
|
+
sm.fire
|
19
|
+
|
20
|
+
@noodle.cooked.should equal(true)
|
21
|
+
end
|
22
|
+
|
23
|
+
it "Symbol actions" do
|
24
|
+
sm = Statemachine.build do |smb|
|
25
|
+
smb.trans :cold, :fire, :hot, :cook
|
26
|
+
smb.trans :hot, :mold, :changed, :transform
|
27
|
+
end
|
28
|
+
|
29
|
+
sm.context = @noodle
|
30
|
+
sm.fire
|
31
|
+
|
32
|
+
@noodle.cooked.should equal(true)
|
33
|
+
|
34
|
+
sm.mold "capellini"
|
35
|
+
|
36
|
+
@noodle.shape.should eql("capellini")
|
37
|
+
end
|
38
|
+
|
39
|
+
it "String actions" do
|
40
|
+
sm = Statemachine.build do |smb|
|
41
|
+
smb.trans :cold, :fire, :hot, "@shape = 'fettucini'; @cooked = true"
|
42
|
+
end
|
43
|
+
sm.context = @noodle
|
44
|
+
|
45
|
+
sm.fire
|
46
|
+
@noodle.shape.should eql("fettucini")
|
47
|
+
@noodle.cooked.should equal(true)
|
48
|
+
end
|
49
|
+
|
50
|
+
it "Multiple Proc actions" do
|
51
|
+
sm = Statemachine.build do |smb|
|
52
|
+
smb.trans :cold, :fire, :hot, [Proc.new { @cooked = true }, Proc.new { @tasty = true }]
|
53
|
+
end
|
54
|
+
|
55
|
+
sm.context = @noodle
|
56
|
+
sm.fire
|
57
|
+
|
58
|
+
@noodle.cooked.should equal(true)
|
59
|
+
@noodle.tasty.should equal(true)
|
60
|
+
end
|
61
|
+
|
62
|
+
it "Multiple Symbol actions" do
|
63
|
+
sm = Statemachine.build do |smb|
|
64
|
+
smb.trans :cold, :fire, :hot, [:cook, :good]
|
65
|
+
end
|
66
|
+
|
67
|
+
sm.context = @noodle
|
68
|
+
sm.fire
|
69
|
+
|
70
|
+
@noodle.cooked.should equal(true)
|
71
|
+
@noodle.tasty.should equal(true)
|
72
|
+
end
|
73
|
+
|
74
|
+
it "Multiple actions" do
|
75
|
+
sm = Statemachine.build do |smb|
|
76
|
+
smb.trans :cold, :fire, :hot, [:cook, Proc.new { @tasty = true }, "@shape = 'fettucini'"]
|
77
|
+
end
|
78
|
+
|
79
|
+
sm.context = @noodle
|
80
|
+
sm.fire
|
81
|
+
|
82
|
+
@noodle.cooked.should equal(true)
|
83
|
+
@noodle.tasty.should equal(true)
|
84
|
+
@noodle.shape.should eql("fettucini")
|
85
|
+
end
|
86
|
+
|
87
|
+
it "No actions" do
|
88
|
+
sm = Statemachine.build do |smb|
|
89
|
+
smb.trans :cold, :fire, :hot
|
90
|
+
end
|
91
|
+
|
92
|
+
sm.context = @noodle
|
93
|
+
sm.fire
|
94
|
+
|
95
|
+
@noodle.cooked.should == false
|
96
|
+
@noodle.tasty.should == false
|
97
|
+
@noodle.shape.should =="farfalla"
|
98
|
+
end
|
99
|
+
|
100
|
+
|
101
|
+
end
|
@@ -0,0 +1,243 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/spec_helper'
|
2
|
+
|
3
|
+
describe "Builder" do
|
4
|
+
|
5
|
+
before(:each) do
|
6
|
+
@log = []
|
7
|
+
end
|
8
|
+
|
9
|
+
def check_switch(sm)
|
10
|
+
sm.state.should equal(:off)
|
11
|
+
|
12
|
+
sm.toggle
|
13
|
+
@log[0].should eql("toggle on")
|
14
|
+
sm.state.should equal(:on)
|
15
|
+
|
16
|
+
sm.toggle
|
17
|
+
@log[1].should eql("toggle off")
|
18
|
+
sm.state.should equal(:off)
|
19
|
+
end
|
20
|
+
|
21
|
+
it "Building a the switch, relaxed" do
|
22
|
+
sm = Statemachine.build do
|
23
|
+
trans :off, :toggle, :on, Proc.new { @log << "toggle on" }
|
24
|
+
trans :on, :toggle, :off, Proc.new { @log << "toggle off" }
|
25
|
+
end
|
26
|
+
sm.context = self
|
27
|
+
|
28
|
+
check_switch sm
|
29
|
+
end
|
30
|
+
|
31
|
+
it "Building a the switch, strict" do
|
32
|
+
sm = Statemachine.build do
|
33
|
+
state(:off) { |s| s.event :toggle, :on, Proc.new { @log << "toggle on" } }
|
34
|
+
state(:on) { |s| s.event :toggle, :off, Proc.new { @log << "toggle off" } }
|
35
|
+
end
|
36
|
+
sm.context = self
|
37
|
+
|
38
|
+
check_switch sm
|
39
|
+
end
|
40
|
+
|
41
|
+
it "Adding a superstate to the switch" do
|
42
|
+
the_context = self
|
43
|
+
sm = Statemachine.build do
|
44
|
+
superstate :operation do
|
45
|
+
event :admin, :testing, lambda { @log << "testing" }
|
46
|
+
trans :off, :toggle, :on, lambda { @log << "toggle on" }
|
47
|
+
trans :on, :toggle, :off, lambda { @log << "toggle off" }
|
48
|
+
startstate :on
|
49
|
+
end
|
50
|
+
trans :testing, :resume, :operation, lambda { @log << "resuming" }
|
51
|
+
startstate :off
|
52
|
+
context the_context
|
53
|
+
end
|
54
|
+
|
55
|
+
sm.state.should equal(:off)
|
56
|
+
sm.toggle
|
57
|
+
sm.admin
|
58
|
+
sm.state.should equal(:testing)
|
59
|
+
sm.resume
|
60
|
+
sm.state.should equal(:on)
|
61
|
+
@log.join(",").should eql("toggle on,testing,resuming")
|
62
|
+
end
|
63
|
+
|
64
|
+
it "entry exit actions" do
|
65
|
+
the_context = self
|
66
|
+
sm = Statemachine.build do
|
67
|
+
state :off do
|
68
|
+
on_entry Proc.new { @log << "enter off" }
|
69
|
+
event :toggle, :on, lambda { @log << "toggle on" }
|
70
|
+
on_exit Proc.new { @log << "exit off" }
|
71
|
+
end
|
72
|
+
trans :on, :toggle, :off, lambda { @log << "toggle off" }
|
73
|
+
context the_context
|
74
|
+
end
|
75
|
+
|
76
|
+
sm.toggle
|
77
|
+
sm.state.should equal(:on)
|
78
|
+
sm.toggle
|
79
|
+
sm.state.should equal(:off)
|
80
|
+
|
81
|
+
@log.join(",").should eql("enter off,exit off,toggle on,toggle off,enter off")
|
82
|
+
end
|
83
|
+
|
84
|
+
it "History state" do
|
85
|
+
the_context = self
|
86
|
+
sm = Statemachine.build do
|
87
|
+
superstate :operation do
|
88
|
+
event :admin, :testing, lambda { @log << "testing" }
|
89
|
+
state :off do |off|
|
90
|
+
on_entry Proc.new { @log << "enter off" }
|
91
|
+
event :toggle, :on, lambda { @log << "toggle on" }
|
92
|
+
end
|
93
|
+
trans :on, :toggle, :off, lambda { @log << "toggle off" }
|
94
|
+
startstate :on
|
95
|
+
end
|
96
|
+
trans :testing, :resume, :operation_H, lambda { @log << "resuming" }
|
97
|
+
startstate :off
|
98
|
+
context the_context
|
99
|
+
end
|
100
|
+
|
101
|
+
sm.admin
|
102
|
+
sm.resume
|
103
|
+
sm.state.should equal(:off)
|
104
|
+
|
105
|
+
@log.join(",").should eql("enter off,testing,resuming,enter off")
|
106
|
+
end
|
107
|
+
|
108
|
+
it "entry and exit action created from superstate builder" do
|
109
|
+
the_context = self
|
110
|
+
sm = Statemachine.build do
|
111
|
+
trans :off, :toggle, :on, Proc.new { @log << "toggle on" }
|
112
|
+
on_entry_of :off, Proc.new { @log << "entering off" }
|
113
|
+
trans :on, :toggle, :off, Proc.new { @log << "toggle off" }
|
114
|
+
on_exit_of :on, Proc.new { @log << "exiting on" }
|
115
|
+
context the_context
|
116
|
+
end
|
117
|
+
|
118
|
+
sm.toggle
|
119
|
+
sm.toggle
|
120
|
+
|
121
|
+
@log.join(",").should eql("entering off,toggle on,exiting on,toggle off,entering off")
|
122
|
+
|
123
|
+
end
|
124
|
+
|
125
|
+
it "superstate as startstate" do
|
126
|
+
|
127
|
+
lambda do
|
128
|
+
sm = Statemachine.build do
|
129
|
+
superstate :mario_bros do
|
130
|
+
trans :luigi, :bother, :mario
|
131
|
+
end
|
132
|
+
end
|
133
|
+
|
134
|
+
sm.state.should equal(:luigi)
|
135
|
+
end.should_not raise_error(Exception)
|
136
|
+
end
|
137
|
+
|
138
|
+
it "setting the start state before any other states declared" do
|
139
|
+
|
140
|
+
sm = Statemachine.build do
|
141
|
+
startstate :right
|
142
|
+
trans :left, :push, :middle
|
143
|
+
trans :middle, :push, :right
|
144
|
+
trans :right, :pull, :middle
|
145
|
+
end
|
146
|
+
|
147
|
+
sm.state.should equal(:right)
|
148
|
+
sm.pull
|
149
|
+
sm.state.should equal(:middle)
|
150
|
+
end
|
151
|
+
|
152
|
+
it "setting start state which is in a super state" do
|
153
|
+
sm = Statemachine.build do
|
154
|
+
startstate :right
|
155
|
+
superstate :table do
|
156
|
+
event :tilt, :floor
|
157
|
+
trans :left, :push, :middle
|
158
|
+
trans :middle, :push, :right
|
159
|
+
trans :right, :pull, :middle
|
160
|
+
end
|
161
|
+
state :floor
|
162
|
+
end
|
163
|
+
|
164
|
+
sm.state.should equal(:right)
|
165
|
+
sm.pull
|
166
|
+
sm.state.should equal(:middle)
|
167
|
+
sm.push
|
168
|
+
sm.state.should equal(:right)
|
169
|
+
sm.tilt
|
170
|
+
sm.state.should equal(:floor)
|
171
|
+
end
|
172
|
+
|
173
|
+
it "can set context" do
|
174
|
+
widget = Object.new
|
175
|
+
sm = Statemachine.build do
|
176
|
+
context widget
|
177
|
+
end
|
178
|
+
|
179
|
+
sm.context.should be(widget)
|
180
|
+
end
|
181
|
+
|
182
|
+
it "statemachine will be set on context if possible" do
|
183
|
+
class Widget
|
184
|
+
attr_accessor :statemachine
|
185
|
+
end
|
186
|
+
widget = Widget.new
|
187
|
+
|
188
|
+
sm = Statemachine.build do
|
189
|
+
context widget
|
190
|
+
end
|
191
|
+
|
192
|
+
sm.context.should be(widget)
|
193
|
+
widget.statemachine.should be(sm)
|
194
|
+
end
|
195
|
+
|
196
|
+
it "should have an on_event" do
|
197
|
+
sm = Statemachine.build do
|
198
|
+
startstate :start
|
199
|
+
state :start do
|
200
|
+
on_event :go, :transition_to => :new_state
|
201
|
+
end
|
202
|
+
end
|
203
|
+
sm.go
|
204
|
+
sm.state.should == :new_state
|
205
|
+
end
|
206
|
+
|
207
|
+
it "should trigger actions using on_event" do
|
208
|
+
sm = Statemachine.build do
|
209
|
+
startstate :start
|
210
|
+
state :start do
|
211
|
+
on_event :go, :transition_to => :new_state, :and_perform => :action
|
212
|
+
end
|
213
|
+
end
|
214
|
+
object = mock("context")
|
215
|
+
object.stub(:action) { true }
|
216
|
+
sm.context = object
|
217
|
+
object.should_receive(:action)
|
218
|
+
|
219
|
+
sm.go
|
220
|
+
end
|
221
|
+
|
222
|
+
it "should have a transition_from" do
|
223
|
+
sm = Statemachine.build do
|
224
|
+
transition_from :start, :on_event => :go, :transition_to => :new_state
|
225
|
+
end
|
226
|
+
|
227
|
+
sm.go
|
228
|
+
sm.state.should == :new_state
|
229
|
+
end
|
230
|
+
|
231
|
+
it "should trigger actions on transition_from" do
|
232
|
+
sm = Statemachine.build do
|
233
|
+
transition_from :start, :on_event => :go, :transition_to => :new_state, :and_perform => :action
|
234
|
+
end
|
235
|
+
object = mock("context")
|
236
|
+
object.stub(:action) { true }
|
237
|
+
sm.context = object
|
238
|
+
object.should_receive(:action)
|
239
|
+
|
240
|
+
sm.go
|
241
|
+
end
|
242
|
+
end
|
243
|
+
|
@@ -0,0 +1,111 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/spec_helper'
|
2
|
+
|
3
|
+
describe "Default Transition" do
|
4
|
+
|
5
|
+
before(:each) do
|
6
|
+
@sm = Statemachine.build do
|
7
|
+
trans :default_state, :start, :test_state
|
8
|
+
|
9
|
+
state :test_state do
|
10
|
+
default :default_state
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
it "the default transition is set" do
|
16
|
+
test_state = @sm.get_state(:test_state)
|
17
|
+
test_state.default_transition.should_not be(nil)
|
18
|
+
test_state.transition_for(:fake_event).should_not be(nil)
|
19
|
+
end
|
20
|
+
|
21
|
+
it "Should go to the default_state with any event" do
|
22
|
+
@sm.start
|
23
|
+
@sm.fake_event
|
24
|
+
|
25
|
+
@sm.state.should eql(:default_state)
|
26
|
+
end
|
27
|
+
|
28
|
+
it "default transition can have actions" do
|
29
|
+
me = self
|
30
|
+
@sm = Statemachine.build do
|
31
|
+
trans :default_state, :start, :test_state
|
32
|
+
|
33
|
+
state :test_state do
|
34
|
+
default :default_state, :hi
|
35
|
+
end
|
36
|
+
context me
|
37
|
+
end
|
38
|
+
|
39
|
+
@sm.start
|
40
|
+
@sm.blah
|
41
|
+
|
42
|
+
@sm.state.should eql(:default_state)
|
43
|
+
@hi.should eql(true)
|
44
|
+
end
|
45
|
+
|
46
|
+
def hi
|
47
|
+
@hi = true
|
48
|
+
end
|
49
|
+
|
50
|
+
it "superstate supports the default" do
|
51
|
+
@sm = Statemachine.build do
|
52
|
+
superstate :test_superstate do
|
53
|
+
default :default_state
|
54
|
+
|
55
|
+
state :start_state
|
56
|
+
state :default_state
|
57
|
+
end
|
58
|
+
|
59
|
+
startstate :start_state
|
60
|
+
end
|
61
|
+
|
62
|
+
@sm.blah
|
63
|
+
@sm.state.should eql(:default_state)
|
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
|
+
it "should use not use superstate's default before using it's own default" do
|
87
|
+
@sm = Statemachine.build do
|
88
|
+
superstate :super do
|
89
|
+
default :super_default
|
90
|
+
state :base do
|
91
|
+
default :base_default
|
92
|
+
end
|
93
|
+
end
|
94
|
+
state :super_default
|
95
|
+
state :base_default
|
96
|
+
startstate :base
|
97
|
+
end
|
98
|
+
|
99
|
+
@sm.blah
|
100
|
+
@sm.state.should eql(:base_default)
|
101
|
+
end
|
102
|
+
|
103
|
+
it "should be marshalable" do
|
104
|
+
dump = Marshal.dump(@sm)
|
105
|
+
loaded = Marshal.load(dump)
|
106
|
+
loaded.state.should eql(:default_state)
|
107
|
+
end
|
108
|
+
|
109
|
+
|
110
|
+
|
111
|
+
end
|