pluginaweek-state_machine 0.7.6
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/CHANGELOG.rdoc +273 -0
- data/LICENSE +20 -0
- data/README.rdoc +466 -0
- data/Rakefile +98 -0
- data/examples/AutoShop_state.png +0 -0
- data/examples/Car_state.png +0 -0
- data/examples/TrafficLight_state.png +0 -0
- data/examples/Vehicle_state.png +0 -0
- data/examples/auto_shop.rb +11 -0
- data/examples/car.rb +19 -0
- data/examples/merb-rest/controller.rb +51 -0
- data/examples/merb-rest/model.rb +28 -0
- data/examples/merb-rest/view_edit.html.erb +24 -0
- data/examples/merb-rest/view_index.html.erb +23 -0
- data/examples/merb-rest/view_new.html.erb +13 -0
- data/examples/merb-rest/view_show.html.erb +17 -0
- data/examples/rails-rest/controller.rb +43 -0
- data/examples/rails-rest/migration.rb +11 -0
- data/examples/rails-rest/model.rb +23 -0
- data/examples/rails-rest/view_edit.html.erb +25 -0
- data/examples/rails-rest/view_index.html.erb +23 -0
- data/examples/rails-rest/view_new.html.erb +14 -0
- data/examples/rails-rest/view_show.html.erb +17 -0
- data/examples/traffic_light.rb +7 -0
- data/examples/vehicle.rb +31 -0
- data/init.rb +1 -0
- data/lib/state_machine.rb +429 -0
- data/lib/state_machine/assertions.rb +36 -0
- data/lib/state_machine/callback.rb +189 -0
- data/lib/state_machine/condition_proxy.rb +94 -0
- data/lib/state_machine/eval_helpers.rb +67 -0
- data/lib/state_machine/event.rb +251 -0
- data/lib/state_machine/event_collection.rb +113 -0
- data/lib/state_machine/extensions.rb +158 -0
- data/lib/state_machine/guard.rb +219 -0
- data/lib/state_machine/integrations.rb +68 -0
- data/lib/state_machine/integrations/active_record.rb +444 -0
- data/lib/state_machine/integrations/active_record/locale.rb +10 -0
- data/lib/state_machine/integrations/active_record/observer.rb +41 -0
- data/lib/state_machine/integrations/data_mapper.rb +325 -0
- data/lib/state_machine/integrations/data_mapper/observer.rb +139 -0
- data/lib/state_machine/integrations/sequel.rb +292 -0
- data/lib/state_machine/machine.rb +1431 -0
- data/lib/state_machine/machine_collection.rb +146 -0
- data/lib/state_machine/matcher.rb +123 -0
- data/lib/state_machine/matcher_helpers.rb +54 -0
- data/lib/state_machine/node_collection.rb +152 -0
- data/lib/state_machine/state.rb +249 -0
- data/lib/state_machine/state_collection.rb +112 -0
- data/lib/state_machine/transition.rb +367 -0
- data/tasks/state_machine.rake +1 -0
- data/tasks/state_machine.rb +30 -0
- data/test/classes/switch.rb +11 -0
- data/test/functional/state_machine_test.rb +941 -0
- data/test/test_helper.rb +4 -0
- data/test/unit/assertions_test.rb +40 -0
- data/test/unit/callback_test.rb +455 -0
- data/test/unit/condition_proxy_test.rb +328 -0
- data/test/unit/eval_helpers_test.rb +129 -0
- data/test/unit/event_collection_test.rb +293 -0
- data/test/unit/event_test.rb +605 -0
- data/test/unit/guard_test.rb +862 -0
- data/test/unit/integrations/active_record_test.rb +1001 -0
- data/test/unit/integrations/data_mapper_test.rb +694 -0
- data/test/unit/integrations/sequel_test.rb +486 -0
- data/test/unit/integrations_test.rb +42 -0
- data/test/unit/invalid_event_test.rb +7 -0
- data/test/unit/invalid_transition_test.rb +7 -0
- data/test/unit/machine_collection_test.rb +710 -0
- data/test/unit/machine_test.rb +1910 -0
- data/test/unit/matcher_helpers_test.rb +37 -0
- data/test/unit/matcher_test.rb +155 -0
- data/test/unit/node_collection_test.rb +207 -0
- data/test/unit/state_collection_test.rb +280 -0
- data/test/unit/state_machine_test.rb +31 -0
- data/test/unit/state_test.rb +795 -0
- data/test/unit/transition_test.rb +1113 -0
- metadata +161 -0
@@ -0,0 +1,862 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/../test_helper')
|
2
|
+
|
3
|
+
class GuardTest < Test::Unit::TestCase
|
4
|
+
def setup
|
5
|
+
@guard = StateMachine::Guard.new(:from => :parked, :to => :idling)
|
6
|
+
end
|
7
|
+
|
8
|
+
def test_should_not_raise_exception_if_implicit_option_specified
|
9
|
+
assert_nothing_raised { StateMachine::Guard.new(:invalid => :valid) }
|
10
|
+
end
|
11
|
+
|
12
|
+
def test_should_not_have_an_if_condition
|
13
|
+
assert_nil @guard.if_condition
|
14
|
+
end
|
15
|
+
|
16
|
+
def test_should_not_have_an_unless_condition
|
17
|
+
assert_nil @guard.unless_condition
|
18
|
+
end
|
19
|
+
|
20
|
+
def test_should_have_a_state_requirement
|
21
|
+
assert_equal 1, @guard.state_requirements.length
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
class GuardWithNoRequirementsTest < Test::Unit::TestCase
|
26
|
+
def setup
|
27
|
+
@object = Object.new
|
28
|
+
@guard = StateMachine::Guard.new
|
29
|
+
end
|
30
|
+
|
31
|
+
def test_should_use_all_matcher_for_event_requirement
|
32
|
+
assert_equal StateMachine::AllMatcher.instance, @guard.event_requirement
|
33
|
+
end
|
34
|
+
|
35
|
+
def test_should_use_all_matcher_for_from_state_requirement
|
36
|
+
assert_equal StateMachine::AllMatcher.instance, @guard.state_requirements.first[:from]
|
37
|
+
end
|
38
|
+
|
39
|
+
def test_should_use_all_matcher_for_to_state_requirement
|
40
|
+
assert_equal StateMachine::AllMatcher.instance, @guard.state_requirements.first[:to]
|
41
|
+
end
|
42
|
+
|
43
|
+
def test_should_match_nil_query
|
44
|
+
assert @guard.matches?(@object, nil)
|
45
|
+
end
|
46
|
+
|
47
|
+
def test_should_match_empty_query
|
48
|
+
assert @guard.matches?(@object, {})
|
49
|
+
end
|
50
|
+
|
51
|
+
def test_should_match_non_empty_query
|
52
|
+
assert @guard.matches?(@object, :to => :idling, :from => :parked, :on => :ignite)
|
53
|
+
end
|
54
|
+
|
55
|
+
def test_should_include_all_requirements_in_match
|
56
|
+
match = @guard.match(@object, nil)
|
57
|
+
|
58
|
+
assert_equal @guard.state_requirements.first[:from], match[:from]
|
59
|
+
assert_equal @guard.state_requirements.first[:to], match[:to]
|
60
|
+
assert_equal @guard.event_requirement, match[:on]
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
class GuardWithFromRequirementTest < Test::Unit::TestCase
|
65
|
+
def setup
|
66
|
+
@object = Object.new
|
67
|
+
@guard = StateMachine::Guard.new(:from => :parked)
|
68
|
+
end
|
69
|
+
|
70
|
+
def test_should_use_a_whitelist_matcher
|
71
|
+
assert_instance_of StateMachine::WhitelistMatcher, @guard.state_requirements.first[:from]
|
72
|
+
end
|
73
|
+
|
74
|
+
def test_should_match_if_not_specified
|
75
|
+
assert @guard.matches?(@object, :to => :idling)
|
76
|
+
end
|
77
|
+
|
78
|
+
def test_should_match_if_included
|
79
|
+
assert @guard.matches?(@object, :from => :parked)
|
80
|
+
end
|
81
|
+
|
82
|
+
def test_should_not_match_if_not_included
|
83
|
+
assert !@guard.matches?(@object, :from => :idling)
|
84
|
+
end
|
85
|
+
|
86
|
+
def test_should_not_match_if_nil
|
87
|
+
assert !@guard.matches?(@object, :from => nil)
|
88
|
+
end
|
89
|
+
|
90
|
+
def test_should_ignore_to
|
91
|
+
assert @guard.matches?(@object, :from => :parked, :to => :idling)
|
92
|
+
end
|
93
|
+
|
94
|
+
def test_should_ignore_on
|
95
|
+
assert @guard.matches?(@object, :from => :parked, :on => :ignite)
|
96
|
+
end
|
97
|
+
|
98
|
+
def test_should_be_included_in_known_states
|
99
|
+
assert_equal [:parked], @guard.known_states
|
100
|
+
end
|
101
|
+
|
102
|
+
def test_should_include_requirement_in_match
|
103
|
+
match = @guard.match(@object, :from => :parked)
|
104
|
+
assert_equal @guard.state_requirements.first[:from], match[:from]
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
class GuardWithMultipleFromRequirementsTest < Test::Unit::TestCase
|
109
|
+
def setup
|
110
|
+
@object = Object.new
|
111
|
+
@guard = StateMachine::Guard.new(:from => [:idling, :parked])
|
112
|
+
end
|
113
|
+
|
114
|
+
def test_should_match_if_included
|
115
|
+
assert @guard.matches?(@object, :from => :idling)
|
116
|
+
end
|
117
|
+
|
118
|
+
def test_should_not_match_if_not_included
|
119
|
+
assert !@guard.matches?(@object, :from => :first_gear)
|
120
|
+
end
|
121
|
+
|
122
|
+
def test_should_be_included_in_known_states
|
123
|
+
assert_equal [:idling, :parked], @guard.known_states
|
124
|
+
end
|
125
|
+
end
|
126
|
+
|
127
|
+
class GuardWithToRequirementTest < Test::Unit::TestCase
|
128
|
+
def setup
|
129
|
+
@object = Object.new
|
130
|
+
@guard = StateMachine::Guard.new(:to => :idling)
|
131
|
+
end
|
132
|
+
|
133
|
+
def test_should_use_a_whitelist_matcher
|
134
|
+
assert_instance_of StateMachine::WhitelistMatcher, @guard.state_requirements.first[:to]
|
135
|
+
end
|
136
|
+
|
137
|
+
def test_should_match_if_not_specified
|
138
|
+
assert @guard.matches?(@object, :from => :parked)
|
139
|
+
end
|
140
|
+
|
141
|
+
def test_should_match_if_included
|
142
|
+
assert @guard.matches?(@object, :to => :idling)
|
143
|
+
end
|
144
|
+
|
145
|
+
def test_should_not_match_if_not_included
|
146
|
+
assert !@guard.matches?(@object, :to => :parked)
|
147
|
+
end
|
148
|
+
|
149
|
+
def test_should_not_match_if_nil
|
150
|
+
assert !@guard.matches?(@object, :to => nil)
|
151
|
+
end
|
152
|
+
|
153
|
+
def test_should_ignore_from
|
154
|
+
assert @guard.matches?(@object, :to => :idling, :from => :parked)
|
155
|
+
end
|
156
|
+
|
157
|
+
def test_should_ignore_on
|
158
|
+
assert @guard.matches?(@object, :to => :idling, :on => :ignite)
|
159
|
+
end
|
160
|
+
|
161
|
+
def test_should_be_included_in_known_states
|
162
|
+
assert_equal [:idling], @guard.known_states
|
163
|
+
end
|
164
|
+
|
165
|
+
def test_should_include_requirement_in_match
|
166
|
+
match = @guard.match(@object, :to => :idling)
|
167
|
+
assert_equal @guard.state_requirements.first[:to], match[:to]
|
168
|
+
end
|
169
|
+
end
|
170
|
+
|
171
|
+
class GuardWithMultipleToRequirementsTest < Test::Unit::TestCase
|
172
|
+
def setup
|
173
|
+
@object = Object.new
|
174
|
+
@guard = StateMachine::Guard.new(:to => [:idling, :parked])
|
175
|
+
end
|
176
|
+
|
177
|
+
def test_should_match_if_included
|
178
|
+
assert @guard.matches?(@object, :to => :idling)
|
179
|
+
end
|
180
|
+
|
181
|
+
def test_should_not_match_if_not_included
|
182
|
+
assert !@guard.matches?(@object, :to => :first_gear)
|
183
|
+
end
|
184
|
+
|
185
|
+
def test_should_be_included_in_known_states
|
186
|
+
assert_equal [:idling, :parked], @guard.known_states
|
187
|
+
end
|
188
|
+
end
|
189
|
+
|
190
|
+
class GuardWithOnRequirementTest < Test::Unit::TestCase
|
191
|
+
def setup
|
192
|
+
@object = Object.new
|
193
|
+
@guard = StateMachine::Guard.new(:on => :ignite)
|
194
|
+
end
|
195
|
+
|
196
|
+
def test_should_use_a_whitelist_matcher
|
197
|
+
assert_instance_of StateMachine::WhitelistMatcher, @guard.event_requirement
|
198
|
+
end
|
199
|
+
|
200
|
+
def test_should_match_if_not_specified
|
201
|
+
assert @guard.matches?(@object, :from => :parked)
|
202
|
+
end
|
203
|
+
|
204
|
+
def test_should_match_if_included
|
205
|
+
assert @guard.matches?(@object, :on => :ignite)
|
206
|
+
end
|
207
|
+
|
208
|
+
def test_should_not_match_if_not_included
|
209
|
+
assert !@guard.matches?(@object, :on => :park)
|
210
|
+
end
|
211
|
+
|
212
|
+
def test_should_not_match_if_nil
|
213
|
+
assert !@guard.matches?(@object, :on => nil)
|
214
|
+
end
|
215
|
+
|
216
|
+
def test_should_ignore_to
|
217
|
+
assert @guard.matches?(@object, :on => :ignite, :to => :parked)
|
218
|
+
end
|
219
|
+
|
220
|
+
def test_should_ignore_from
|
221
|
+
assert @guard.matches?(@object, :on => :ignite, :from => :parked)
|
222
|
+
end
|
223
|
+
|
224
|
+
def test_should_not_be_included_in_known_states
|
225
|
+
assert_equal [], @guard.known_states
|
226
|
+
end
|
227
|
+
|
228
|
+
def test_should_include_requirement_in_match
|
229
|
+
match = @guard.match(@object, :on => :ignite)
|
230
|
+
assert_equal @guard.event_requirement, match[:on]
|
231
|
+
end
|
232
|
+
end
|
233
|
+
|
234
|
+
class GuardWithMultipleOnRequirementsTest < Test::Unit::TestCase
|
235
|
+
def setup
|
236
|
+
@object = Object.new
|
237
|
+
@guard = StateMachine::Guard.new(:on => [:ignite, :park])
|
238
|
+
end
|
239
|
+
|
240
|
+
def test_should_match_if_included
|
241
|
+
assert @guard.matches?(@object, :on => :ignite)
|
242
|
+
end
|
243
|
+
|
244
|
+
def test_should_not_match_if_not_included
|
245
|
+
assert !@guard.matches?(@object, :on => :shift_up)
|
246
|
+
end
|
247
|
+
end
|
248
|
+
|
249
|
+
class GuardWithExceptFromRequirementTest < Test::Unit::TestCase
|
250
|
+
def setup
|
251
|
+
@object = Object.new
|
252
|
+
@guard = StateMachine::Guard.new(:except_from => :parked)
|
253
|
+
end
|
254
|
+
|
255
|
+
def test_should_use_a_blacklist_matcher
|
256
|
+
assert_instance_of StateMachine::BlacklistMatcher, @guard.state_requirements.first[:from]
|
257
|
+
end
|
258
|
+
|
259
|
+
def test_should_match_if_not_included
|
260
|
+
assert @guard.matches?(@object, :from => :idling)
|
261
|
+
end
|
262
|
+
|
263
|
+
def test_should_not_match_if_included
|
264
|
+
assert !@guard.matches?(@object, :from => :parked)
|
265
|
+
end
|
266
|
+
|
267
|
+
def test_should_match_if_nil
|
268
|
+
assert @guard.matches?(@object, :from => nil)
|
269
|
+
end
|
270
|
+
|
271
|
+
def test_should_ignore_to
|
272
|
+
assert @guard.matches?(@object, :from => :idling, :to => :parked)
|
273
|
+
end
|
274
|
+
|
275
|
+
def test_should_ignore_on
|
276
|
+
assert @guard.matches?(@object, :from => :idling, :on => :ignite)
|
277
|
+
end
|
278
|
+
|
279
|
+
def test_should_be_included_in_known_states
|
280
|
+
assert_equal [:parked], @guard.known_states
|
281
|
+
end
|
282
|
+
end
|
283
|
+
|
284
|
+
class GuardWithMultipleExceptFromRequirementsTest < Test::Unit::TestCase
|
285
|
+
def setup
|
286
|
+
@object = Object.new
|
287
|
+
@guard = StateMachine::Guard.new(:except_from => [:idling, :parked])
|
288
|
+
end
|
289
|
+
|
290
|
+
def test_should_match_if_not_included
|
291
|
+
assert @guard.matches?(@object, :from => :first_gear)
|
292
|
+
end
|
293
|
+
|
294
|
+
def test_should_not_match_if_included
|
295
|
+
assert !@guard.matches?(@object, :from => :idling)
|
296
|
+
end
|
297
|
+
|
298
|
+
def test_should_be_included_in_known_states
|
299
|
+
assert_equal [:idling, :parked], @guard.known_states
|
300
|
+
end
|
301
|
+
end
|
302
|
+
|
303
|
+
class GuardWithExceptToRequirementTest < Test::Unit::TestCase
|
304
|
+
def setup
|
305
|
+
@object = Object.new
|
306
|
+
@guard = StateMachine::Guard.new(:except_to => :idling)
|
307
|
+
end
|
308
|
+
|
309
|
+
def test_should_use_a_blacklist_matcher
|
310
|
+
assert_instance_of StateMachine::BlacklistMatcher, @guard.state_requirements.first[:to]
|
311
|
+
end
|
312
|
+
|
313
|
+
def test_should_match_if_not_included
|
314
|
+
assert @guard.matches?(@object, :to => :parked)
|
315
|
+
end
|
316
|
+
|
317
|
+
def test_should_not_match_if_included
|
318
|
+
assert !@guard.matches?(@object, :to => :idling)
|
319
|
+
end
|
320
|
+
|
321
|
+
def test_should_match_if_nil
|
322
|
+
assert @guard.matches?(@object, :to => nil)
|
323
|
+
end
|
324
|
+
|
325
|
+
def test_should_ignore_from
|
326
|
+
assert @guard.matches?(@object, :to => :parked, :from => :idling)
|
327
|
+
end
|
328
|
+
|
329
|
+
def test_should_ignore_on
|
330
|
+
assert @guard.matches?(@object, :to => :parked, :on => :ignite)
|
331
|
+
end
|
332
|
+
|
333
|
+
def test_should_be_included_in_known_states
|
334
|
+
assert_equal [:idling], @guard.known_states
|
335
|
+
end
|
336
|
+
end
|
337
|
+
|
338
|
+
class GuardWithMultipleExceptToRequirementsTest < Test::Unit::TestCase
|
339
|
+
def setup
|
340
|
+
@object = Object.new
|
341
|
+
@guard = StateMachine::Guard.new(:except_to => [:idling, :parked])
|
342
|
+
end
|
343
|
+
|
344
|
+
def test_should_match_if_not_included
|
345
|
+
assert @guard.matches?(@object, :to => :first_gear)
|
346
|
+
end
|
347
|
+
|
348
|
+
def test_should_not_match_if_included
|
349
|
+
assert !@guard.matches?(@object, :to => :idling)
|
350
|
+
end
|
351
|
+
|
352
|
+
def test_should_be_included_in_known_states
|
353
|
+
assert_equal [:idling, :parked], @guard.known_states
|
354
|
+
end
|
355
|
+
end
|
356
|
+
|
357
|
+
class GuardWithExceptOnRequirementTest < Test::Unit::TestCase
|
358
|
+
def setup
|
359
|
+
@object = Object.new
|
360
|
+
@guard = StateMachine::Guard.new(:except_on => :ignite)
|
361
|
+
end
|
362
|
+
|
363
|
+
def test_should_use_a_blacklist_matcher
|
364
|
+
assert_instance_of StateMachine::BlacklistMatcher, @guard.event_requirement
|
365
|
+
end
|
366
|
+
|
367
|
+
def test_should_match_if_not_included
|
368
|
+
assert @guard.matches?(@object, :on => :park)
|
369
|
+
end
|
370
|
+
|
371
|
+
def test_should_not_match_if_included
|
372
|
+
assert !@guard.matches?(@object, :on => :ignite)
|
373
|
+
end
|
374
|
+
|
375
|
+
def test_should_match_if_nil
|
376
|
+
assert @guard.matches?(@object, :on => nil)
|
377
|
+
end
|
378
|
+
|
379
|
+
def test_should_ignore_to
|
380
|
+
assert @guard.matches?(@object, :on => :park, :to => :idling)
|
381
|
+
end
|
382
|
+
|
383
|
+
def test_should_ignore_from
|
384
|
+
assert @guard.matches?(@object, :on => :park, :from => :parked)
|
385
|
+
end
|
386
|
+
|
387
|
+
def test_should_not_be_included_in_known_states
|
388
|
+
assert_equal [], @guard.known_states
|
389
|
+
end
|
390
|
+
end
|
391
|
+
|
392
|
+
class GuardWithMultipleExceptOnRequirementsTest < Test::Unit::TestCase
|
393
|
+
def setup
|
394
|
+
@object = Object.new
|
395
|
+
@guard = StateMachine::Guard.new(:except_on => [:ignite, :park])
|
396
|
+
end
|
397
|
+
|
398
|
+
def test_should_match_if_not_included
|
399
|
+
assert @guard.matches?(@object, :on => :shift_up)
|
400
|
+
end
|
401
|
+
|
402
|
+
def test_should_not_match_if_included
|
403
|
+
assert !@guard.matches?(@object, :on => :ignite)
|
404
|
+
end
|
405
|
+
end
|
406
|
+
|
407
|
+
class GuardWithConflictingFromRequirementsTest < Test::Unit::TestCase
|
408
|
+
def test_should_raise_an_exception
|
409
|
+
exception = assert_raise(ArgumentError) { StateMachine::Guard.new(:from => :parked, :except_from => :parked) }
|
410
|
+
assert_equal 'Conflicting keys: from, except_from', exception.message
|
411
|
+
end
|
412
|
+
end
|
413
|
+
|
414
|
+
class GuardWithConflictingToRequirementsTest < Test::Unit::TestCase
|
415
|
+
def test_should_raise_an_exception
|
416
|
+
exception = assert_raise(ArgumentError) { StateMachine::Guard.new(:to => :idling, :except_to => :idling) }
|
417
|
+
assert_equal 'Conflicting keys: to, except_to', exception.message
|
418
|
+
end
|
419
|
+
end
|
420
|
+
|
421
|
+
class GuardWithConflictingOnRequirementsTest < Test::Unit::TestCase
|
422
|
+
def test_should_raise_an_exception
|
423
|
+
exception = assert_raise(ArgumentError) { StateMachine::Guard.new(:on => :ignite, :except_on => :ignite) }
|
424
|
+
assert_equal 'Conflicting keys: on, except_on', exception.message
|
425
|
+
end
|
426
|
+
end
|
427
|
+
|
428
|
+
class GuardWithDifferentRequirementsTest < Test::Unit::TestCase
|
429
|
+
def setup
|
430
|
+
@object = Object.new
|
431
|
+
@guard = StateMachine::Guard.new(:from => :parked, :to => :idling, :on => :ignite)
|
432
|
+
end
|
433
|
+
|
434
|
+
def test_should_match_empty_query
|
435
|
+
assert @guard.matches?(@object)
|
436
|
+
end
|
437
|
+
|
438
|
+
def test_should_match_if_all_requirements_match
|
439
|
+
assert @guard.matches?(@object, :from => :parked, :to => :idling, :on => :ignite)
|
440
|
+
end
|
441
|
+
|
442
|
+
def test_should_not_match_if_from_not_included
|
443
|
+
assert !@guard.matches?(@object, :from => :idling)
|
444
|
+
end
|
445
|
+
|
446
|
+
def test_should_not_match_if_to_not_included
|
447
|
+
assert !@guard.matches?(@object, :to => :parked)
|
448
|
+
end
|
449
|
+
|
450
|
+
def test_should_not_match_if_on_not_included
|
451
|
+
assert !@guard.matches?(@object, :on => :park)
|
452
|
+
end
|
453
|
+
|
454
|
+
def test_should_be_nil_if_unmatched
|
455
|
+
assert_nil @guard.match(@object, :from => :parked, :to => :idling, :on => :park)
|
456
|
+
end
|
457
|
+
|
458
|
+
def test_should_include_all_known_states
|
459
|
+
assert_equal [:parked, :idling], @guard.known_states
|
460
|
+
end
|
461
|
+
|
462
|
+
def test_should_not_duplicate_known_statse
|
463
|
+
guard = StateMachine::Guard.new(:except_from => :idling, :to => :idling, :on => :ignite)
|
464
|
+
assert_equal [:idling], guard.known_states
|
465
|
+
end
|
466
|
+
end
|
467
|
+
|
468
|
+
class GuardWithNilRequirementsTest < Test::Unit::TestCase
|
469
|
+
def setup
|
470
|
+
@object = Object.new
|
471
|
+
@guard = StateMachine::Guard.new(:from => nil, :to => nil)
|
472
|
+
end
|
473
|
+
|
474
|
+
def test_should_match_empty_query
|
475
|
+
assert @guard.matches?(@object)
|
476
|
+
end
|
477
|
+
|
478
|
+
def test_should_match_if_all_requirements_match
|
479
|
+
assert @guard.matches?(@object, :from => nil, :to => nil)
|
480
|
+
end
|
481
|
+
|
482
|
+
def test_should_not_match_if_from_not_included
|
483
|
+
assert !@guard.matches?(@object, :from => :parked)
|
484
|
+
end
|
485
|
+
|
486
|
+
def test_should_not_match_if_to_not_included
|
487
|
+
assert !@guard.matches?(@object, :to => :idling)
|
488
|
+
end
|
489
|
+
|
490
|
+
def test_should_include_all_known_states
|
491
|
+
assert_equal [nil], @guard.known_states
|
492
|
+
end
|
493
|
+
end
|
494
|
+
|
495
|
+
class GuardWithImplicitRequirementTest < Test::Unit::TestCase
|
496
|
+
def setup
|
497
|
+
@guard = StateMachine::Guard.new(:parked => :idling, :on => :ignite)
|
498
|
+
end
|
499
|
+
|
500
|
+
def test_should_create_an_event_requirement
|
501
|
+
assert_instance_of StateMachine::WhitelistMatcher, @guard.event_requirement
|
502
|
+
assert_equal [:ignite], @guard.event_requirement.values
|
503
|
+
end
|
504
|
+
|
505
|
+
def test_should_use_a_whitelist_from_matcher
|
506
|
+
assert_instance_of StateMachine::WhitelistMatcher, @guard.state_requirements.first[:from]
|
507
|
+
end
|
508
|
+
|
509
|
+
def test_should_use_a_whitelist_to_matcher
|
510
|
+
assert_instance_of StateMachine::WhitelistMatcher, @guard.state_requirements.first[:to]
|
511
|
+
end
|
512
|
+
end
|
513
|
+
|
514
|
+
class GuardWithMultipleImplicitRequirementsTest < Test::Unit::TestCase
|
515
|
+
def setup
|
516
|
+
@object = Object.new
|
517
|
+
@guard = StateMachine::Guard.new(:parked => :idling, :idling => :first_gear, :on => :ignite)
|
518
|
+
end
|
519
|
+
|
520
|
+
def test_should_create_multiple_state_requirements
|
521
|
+
assert_equal 2, @guard.state_requirements.length
|
522
|
+
end
|
523
|
+
|
524
|
+
def test_should_not_match_event_as_state_requirement
|
525
|
+
assert !@guard.matches?(@object, :from => :on, :to => :ignite)
|
526
|
+
end
|
527
|
+
|
528
|
+
def test_should_match_if_from_included_in_any
|
529
|
+
assert @guard.matches?(@object, :from => :parked)
|
530
|
+
assert @guard.matches?(@object, :from => :idling)
|
531
|
+
end
|
532
|
+
|
533
|
+
def test_should_not_match_if_from_not_included_in_any
|
534
|
+
assert !@guard.matches?(@object, :from => :first_gear)
|
535
|
+
end
|
536
|
+
|
537
|
+
def test_should_match_if_to_included_in_any
|
538
|
+
assert @guard.matches?(@object, :to => :idling)
|
539
|
+
assert @guard.matches?(@object, :to => :first_gear)
|
540
|
+
end
|
541
|
+
|
542
|
+
def test_should_not_match_if_to_not_included_in_any
|
543
|
+
assert !@guard.matches?(@object, :to => :parked)
|
544
|
+
end
|
545
|
+
|
546
|
+
def test_should_match_if_all_options_match
|
547
|
+
assert @guard.matches?(@object, :from => :parked, :to => :idling, :on => :ignite)
|
548
|
+
assert @guard.matches?(@object, :from => :idling, :to => :first_gear, :on => :ignite)
|
549
|
+
end
|
550
|
+
|
551
|
+
def test_should_not_match_if_any_options_do_not_match
|
552
|
+
assert !@guard.matches?(@object, :from => :parked, :to => :idling, :on => :park)
|
553
|
+
assert !@guard.matches?(@object, :from => :parked, :to => :first_gear, :on => :park)
|
554
|
+
end
|
555
|
+
|
556
|
+
def test_should_include_all_known_states
|
557
|
+
assert_equal [:first_gear, :idling, :parked], @guard.known_states.sort_by {|state| state.to_s}
|
558
|
+
end
|
559
|
+
|
560
|
+
def test_should_not_duplicate_known_statse
|
561
|
+
guard = StateMachine::Guard.new(:parked => :idling, :first_gear => :idling)
|
562
|
+
assert_equal [:first_gear, :idling, :parked], guard.known_states.sort_by {|state| state.to_s}
|
563
|
+
end
|
564
|
+
end
|
565
|
+
|
566
|
+
class GuardWithImplicitFromRequirementMatcherTest < Test::Unit::TestCase
|
567
|
+
def setup
|
568
|
+
@matcher = StateMachine::BlacklistMatcher.new(:parked)
|
569
|
+
@guard = StateMachine::Guard.new(@matcher => :idling)
|
570
|
+
end
|
571
|
+
|
572
|
+
def test_should_not_convert_from_to_whitelist_matcher
|
573
|
+
assert_equal @matcher, @guard.state_requirements.first[:from]
|
574
|
+
end
|
575
|
+
|
576
|
+
def test_should_convert_to_to_whitelist_matcher
|
577
|
+
assert_instance_of StateMachine::WhitelistMatcher, @guard.state_requirements.first[:to]
|
578
|
+
end
|
579
|
+
end
|
580
|
+
|
581
|
+
class GuardWithImplicitToRequirementMatcherTest < Test::Unit::TestCase
|
582
|
+
def setup
|
583
|
+
@matcher = StateMachine::BlacklistMatcher.new(:idling)
|
584
|
+
@guard = StateMachine::Guard.new(:parked => @matcher)
|
585
|
+
end
|
586
|
+
|
587
|
+
def test_should_convert_from_to_whitelist_matcher
|
588
|
+
assert_instance_of StateMachine::WhitelistMatcher, @guard.state_requirements.first[:from]
|
589
|
+
end
|
590
|
+
|
591
|
+
def test_should_not_convert_to_to_whitelist_matcher
|
592
|
+
assert_equal @matcher, @guard.state_requirements.first[:to]
|
593
|
+
end
|
594
|
+
end
|
595
|
+
|
596
|
+
class GuardWithImplicitAndExplicitRequirementsTest < Test::Unit::TestCase
|
597
|
+
def setup
|
598
|
+
@guard = StateMachine::Guard.new(:parked => :idling, :from => :parked)
|
599
|
+
end
|
600
|
+
|
601
|
+
def test_should_create_multiple_requirements
|
602
|
+
assert_equal 2, @guard.state_requirements.length
|
603
|
+
end
|
604
|
+
|
605
|
+
def test_should_create_implicit_requirements_for_implicit_options
|
606
|
+
assert(@guard.state_requirements.any? do |state_requirement|
|
607
|
+
state_requirement[:from].values == [:parked] && state_requirement[:to].values == [:idling]
|
608
|
+
end)
|
609
|
+
end
|
610
|
+
|
611
|
+
def test_should_create_implicit_requirements_for_explicit_options
|
612
|
+
assert(@guard.state_requirements.any? do |state_requirement|
|
613
|
+
state_requirement[:from].values == [:from] && state_requirement[:to].values == [:parked]
|
614
|
+
end)
|
615
|
+
end
|
616
|
+
end
|
617
|
+
|
618
|
+
class GuardWithIfConditionalTest < Test::Unit::TestCase
|
619
|
+
def setup
|
620
|
+
@object = Object.new
|
621
|
+
end
|
622
|
+
|
623
|
+
def test_should_have_an_if_condition
|
624
|
+
guard = StateMachine::Guard.new(:if => lambda {true})
|
625
|
+
assert_not_nil guard.if_condition
|
626
|
+
end
|
627
|
+
|
628
|
+
def test_should_match_if_true
|
629
|
+
guard = StateMachine::Guard.new(:if => lambda {true})
|
630
|
+
assert guard.matches?(@object)
|
631
|
+
end
|
632
|
+
|
633
|
+
def test_should_not_match_if_false
|
634
|
+
guard = StateMachine::Guard.new(:if => lambda {false})
|
635
|
+
assert !guard.matches?(@object)
|
636
|
+
end
|
637
|
+
|
638
|
+
def test_should_be_nil_if_unmatched
|
639
|
+
guard = StateMachine::Guard.new(:if => lambda {false})
|
640
|
+
assert_nil guard.match(@object)
|
641
|
+
end
|
642
|
+
end
|
643
|
+
|
644
|
+
class GuardWithMultipleIfConditionalsTest < Test::Unit::TestCase
|
645
|
+
def setup
|
646
|
+
@object = Object.new
|
647
|
+
end
|
648
|
+
|
649
|
+
def test_should_match_if_all_are_true
|
650
|
+
guard = StateMachine::Guard.new(:if => [lambda {true}, lambda {true}])
|
651
|
+
assert guard.match(@object)
|
652
|
+
end
|
653
|
+
|
654
|
+
def test_should_not_match_if_any_are_false
|
655
|
+
guard = StateMachine::Guard.new(:if => [lambda {true}, lambda {false}])
|
656
|
+
assert !guard.match(@object)
|
657
|
+
|
658
|
+
guard = StateMachine::Guard.new(:if => [lambda {false}, lambda {true}])
|
659
|
+
assert !guard.match(@object)
|
660
|
+
end
|
661
|
+
end
|
662
|
+
|
663
|
+
class GuardWithUnlessConditionalTest < Test::Unit::TestCase
|
664
|
+
def setup
|
665
|
+
@object = Object.new
|
666
|
+
end
|
667
|
+
|
668
|
+
def test_should_have_an_unless_condition
|
669
|
+
guard = StateMachine::Guard.new(:unless => lambda {true})
|
670
|
+
assert_not_nil guard.unless_condition
|
671
|
+
end
|
672
|
+
|
673
|
+
def test_should_match_if_false
|
674
|
+
guard = StateMachine::Guard.new(:unless => lambda {false})
|
675
|
+
assert guard.matches?(@object)
|
676
|
+
end
|
677
|
+
|
678
|
+
def test_should_not_match_if_true
|
679
|
+
guard = StateMachine::Guard.new(:unless => lambda {true})
|
680
|
+
assert !guard.matches?(@object)
|
681
|
+
end
|
682
|
+
|
683
|
+
def test_should_be_nil_if_unmatched
|
684
|
+
guard = StateMachine::Guard.new(:unless => lambda {true})
|
685
|
+
assert_nil guard.match(@object)
|
686
|
+
end
|
687
|
+
end
|
688
|
+
|
689
|
+
class GuardWithMultipleUnlessConditionalsTest < Test::Unit::TestCase
|
690
|
+
def setup
|
691
|
+
@object = Object.new
|
692
|
+
end
|
693
|
+
|
694
|
+
def test_should_match_if_all_are_false
|
695
|
+
guard = StateMachine::Guard.new(:unless => [lambda {false}, lambda {false}])
|
696
|
+
assert guard.match(@object)
|
697
|
+
end
|
698
|
+
|
699
|
+
def test_should_not_match_if_any_are_true
|
700
|
+
guard = StateMachine::Guard.new(:unless => [lambda {true}, lambda {false}])
|
701
|
+
assert !guard.match(@object)
|
702
|
+
|
703
|
+
guard = StateMachine::Guard.new(:unless => [lambda {false}, lambda {true}])
|
704
|
+
assert !guard.match(@object)
|
705
|
+
end
|
706
|
+
end
|
707
|
+
|
708
|
+
class GuardWithConflictingConditionalsTest < Test::Unit::TestCase
|
709
|
+
def test_should_match_if_if_is_true_and_unless_is_false
|
710
|
+
guard = StateMachine::Guard.new(:if => lambda {true}, :unless => lambda {false})
|
711
|
+
assert guard.match(@object)
|
712
|
+
end
|
713
|
+
|
714
|
+
def test_should_not_match_if_if_is_false_and_unless_is_true
|
715
|
+
guard = StateMachine::Guard.new(:if => lambda {false}, :unless => lambda {true})
|
716
|
+
assert !guard.match(@object)
|
717
|
+
end
|
718
|
+
|
719
|
+
def test_should_not_match_if_if_is_false_and_unless_is_false
|
720
|
+
guard = StateMachine::Guard.new(:if => lambda {false}, :unless => lambda {false})
|
721
|
+
assert !guard.match(@object)
|
722
|
+
end
|
723
|
+
|
724
|
+
def test_should_not_match_if_if_is_true_and_unless_is_true
|
725
|
+
guard = StateMachine::Guard.new(:if => lambda {true}, :unless => lambda {true})
|
726
|
+
assert !guard.match(@object)
|
727
|
+
end
|
728
|
+
end
|
729
|
+
|
730
|
+
begin
|
731
|
+
# Load library
|
732
|
+
require 'rubygems'
|
733
|
+
require 'graphviz'
|
734
|
+
|
735
|
+
class GuardDrawingTest < Test::Unit::TestCase
|
736
|
+
def setup
|
737
|
+
@machine = StateMachine::Machine.new(Class.new)
|
738
|
+
states = [:parked, :idling]
|
739
|
+
|
740
|
+
graph = GraphViz.new('G')
|
741
|
+
states.each {|state| graph.add_node(state.to_s)}
|
742
|
+
|
743
|
+
@guard = StateMachine::Guard.new(:from => :idling, :to => :parked)
|
744
|
+
@edges = @guard.draw(graph, :park, states)
|
745
|
+
end
|
746
|
+
|
747
|
+
def test_should_create_edges
|
748
|
+
assert_equal 1, @edges.size
|
749
|
+
end
|
750
|
+
|
751
|
+
def test_should_use_from_state_from_start_node
|
752
|
+
assert_equal 'idling', @edges.first.instance_variable_get('@xNodeOne')
|
753
|
+
end
|
754
|
+
|
755
|
+
def test_should_use_to_state_for_end_node
|
756
|
+
assert_equal 'parked', @edges.first.instance_variable_get('@xNodeTwo')
|
757
|
+
end
|
758
|
+
|
759
|
+
def test_should_use_event_name_as_label
|
760
|
+
assert_equal 'park', @edges.first['label']
|
761
|
+
end
|
762
|
+
end
|
763
|
+
|
764
|
+
class GuardDrawingWithFromRequirementTest < Test::Unit::TestCase
|
765
|
+
def setup
|
766
|
+
@machine = StateMachine::Machine.new(Class.new)
|
767
|
+
states = [:parked, :idling, :first_gear]
|
768
|
+
|
769
|
+
graph = GraphViz.new('G')
|
770
|
+
states.each {|state| graph.add_node(state.to_s)}
|
771
|
+
|
772
|
+
@guard = StateMachine::Guard.new(:from => [:idling, :first_gear], :to => :parked)
|
773
|
+
@edges = @guard.draw(graph, :park, states)
|
774
|
+
end
|
775
|
+
|
776
|
+
def test_should_generate_edges_for_each_valid_from_state
|
777
|
+
[:idling, :first_gear].each_with_index do |from_state, index|
|
778
|
+
edge = @edges[index]
|
779
|
+
assert_equal from_state.to_s, edge.instance_variable_get('@xNodeOne')
|
780
|
+
assert_equal 'parked', edge.instance_variable_get('@xNodeTwo')
|
781
|
+
end
|
782
|
+
end
|
783
|
+
end
|
784
|
+
|
785
|
+
class GuardDrawingWithExceptFromRequirementTest < Test::Unit::TestCase
|
786
|
+
def setup
|
787
|
+
@machine = StateMachine::Machine.new(Class.new)
|
788
|
+
states = [:parked, :idling, :first_gear]
|
789
|
+
|
790
|
+
graph = GraphViz.new('G')
|
791
|
+
states.each {|state| graph.add_node(state.to_s)}
|
792
|
+
|
793
|
+
@guard = StateMachine::Guard.new(:except_from => :parked, :to => :parked)
|
794
|
+
@edges = @guard.draw(graph, :park, states)
|
795
|
+
end
|
796
|
+
|
797
|
+
def test_should_generate_edges_for_each_valid_from_state
|
798
|
+
%w(idling first_gear).each_with_index do |from_state, index|
|
799
|
+
edge = @edges[index]
|
800
|
+
assert_equal from_state, edge.instance_variable_get('@xNodeOne')
|
801
|
+
assert_equal 'parked', edge.instance_variable_get('@xNodeTwo')
|
802
|
+
end
|
803
|
+
end
|
804
|
+
end
|
805
|
+
|
806
|
+
class GuardDrawingWithoutFromRequirementTest < Test::Unit::TestCase
|
807
|
+
def setup
|
808
|
+
@machine = StateMachine::Machine.new(Class.new)
|
809
|
+
states = [:parked, :idling, :first_gear]
|
810
|
+
|
811
|
+
graph = GraphViz.new('G')
|
812
|
+
states.each {|state| graph.add_node(state.to_s)}
|
813
|
+
|
814
|
+
@guard = StateMachine::Guard.new(:to => :parked)
|
815
|
+
@edges = @guard.draw(graph, :park, states)
|
816
|
+
end
|
817
|
+
|
818
|
+
def test_should_generate_edges_for_each_valid_from_state
|
819
|
+
%w(parked idling first_gear).each_with_index do |from_state, index|
|
820
|
+
edge = @edges[index]
|
821
|
+
assert_equal from_state, edge.instance_variable_get('@xNodeOne')
|
822
|
+
assert_equal 'parked', edge.instance_variable_get('@xNodeTwo')
|
823
|
+
end
|
824
|
+
end
|
825
|
+
end
|
826
|
+
|
827
|
+
class GuardDrawingWithoutToRequirementTest < Test::Unit::TestCase
|
828
|
+
def setup
|
829
|
+
@machine = StateMachine::Machine.new(Class.new)
|
830
|
+
|
831
|
+
graph = GraphViz.new('G')
|
832
|
+
graph.add_node('parked')
|
833
|
+
|
834
|
+
@guard = StateMachine::Guard.new(:from => :parked)
|
835
|
+
@edges = @guard.draw(graph, :park, [:parked])
|
836
|
+
end
|
837
|
+
|
838
|
+
def test_should_create_loopback_edge
|
839
|
+
assert_equal 'parked', @edges.first.instance_variable_get('@xNodeOne')
|
840
|
+
assert_equal 'parked', @edges.first.instance_variable_get('@xNodeTwo')
|
841
|
+
end
|
842
|
+
end
|
843
|
+
|
844
|
+
class GuardDrawingWithNilStateTest < Test::Unit::TestCase
|
845
|
+
def setup
|
846
|
+
@machine = StateMachine::Machine.new(Class.new)
|
847
|
+
|
848
|
+
graph = GraphViz.new('G')
|
849
|
+
graph.add_node('parked')
|
850
|
+
|
851
|
+
@guard = StateMachine::Guard.new(:from => :idling, :to => nil)
|
852
|
+
@edges = @guard.draw(graph, :park, [nil, :idling])
|
853
|
+
end
|
854
|
+
|
855
|
+
def test_should_generate_edges_for_each_valid_from_state
|
856
|
+
assert_equal 'idling', @edges.first.instance_variable_get('@xNodeOne')
|
857
|
+
assert_equal 'nil', @edges.first.instance_variable_get('@xNodeTwo')
|
858
|
+
end
|
859
|
+
end
|
860
|
+
rescue LoadError
|
861
|
+
$stderr.puts 'Skipping GraphViz StateMachine::Guard tests. `gem install ruby-graphviz` and try again.'
|
862
|
+
end
|