motion-state-machine 0.8.2 → 0.8.3
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/Rakefile +2 -2
- data/lib/motion-state-machine/base.rb +4 -1
- data/lib/motion-state-machine/state.rb +19 -20
- data/lib/motion-state-machine/transition.rb +9 -7
- data/lib/motion-state-machine/version.rb +1 -1
- data/spec/benchmark_spec.rb +19 -23
- data/spec/notification_transition_spec.rb +3 -0
- data/spec/timed_transition_spec.rb +15 -5
- data/spec/transition_spec.rb +8 -8
- metadata +10 -11
data/Rakefile
CHANGED
@@ -4,11 +4,11 @@ $:.unshift("/Library/RubyMotion/lib")
|
|
4
4
|
|
5
5
|
require 'rubygems'
|
6
6
|
require 'rake'
|
7
|
-
require 'motion/project'
|
7
|
+
require 'motion/project/template/ios'
|
8
8
|
require "bundler/gem_tasks"
|
9
|
-
|
10
9
|
Bundler.setup
|
11
10
|
Bundler.require
|
11
|
+
Bundler::GemHelper.install_tasks
|
12
12
|
|
13
13
|
Motion::Project::App.setup do |app|
|
14
14
|
app.name = 'Spec Suite'
|
@@ -55,7 +55,8 @@ module StateMachine
|
|
55
55
|
# @return [StateMachine::Base] a new StateMachine object
|
56
56
|
|
57
57
|
def initialize(options)
|
58
|
-
super
|
58
|
+
super(options)
|
59
|
+
|
59
60
|
@name = options[:name] || "State machine"
|
60
61
|
@verbose = !!options[:verbose]
|
61
62
|
@state_symbols_to_states = {}
|
@@ -73,6 +74,8 @@ module StateMachine
|
|
73
74
|
|
74
75
|
@current_state = waiting_for_start_state
|
75
76
|
@current_state.send :enter!
|
77
|
+
|
78
|
+
self
|
76
79
|
end
|
77
80
|
|
78
81
|
|
@@ -351,28 +351,27 @@ module StateMachine
|
|
351
351
|
possible_transitions =
|
352
352
|
@transition_map[event_type][event_trigger_value]
|
353
353
|
|
354
|
-
|
355
|
-
|
356
|
-
|
357
|
-
|
358
|
-
|
359
|
-
|
360
|
-
|
361
|
-
|
362
|
-
|
363
|
-
|
364
|
-
|
365
|
-
|
366
|
-
|
367
|
-
|
368
|
-
|
369
|
-
|
370
|
-
|
371
|
-
|
372
|
-
end
|
354
|
+
return if possible_transitions.empty?
|
355
|
+
allowed_transitions = possible_transitions.select(&:allowed?)
|
356
|
+
|
357
|
+
if allowed_transitions.empty?
|
358
|
+
@state_machine.log "All transitions are disallowed for "\
|
359
|
+
"#{event_type}:#{event_trigger_value}."
|
360
|
+
elsif allowed_transitions.count > 1
|
361
|
+
list = allowed_transitions.collect do |t|
|
362
|
+
"-> #{t.options[:to]}"
|
363
|
+
end
|
364
|
+
raise RuntimeError,
|
365
|
+
"Not sure which transition to trigger "\
|
366
|
+
"when #{symbol} while #{self} (allowed: #{list}). "\
|
367
|
+
"Please make sure guard conditions exclude each other."
|
368
|
+
else
|
369
|
+
transition = allowed_transitions.first
|
370
|
+
unless transition.nil?
|
371
|
+
transition.send :unguarded_execute
|
373
372
|
end
|
374
|
-
|
375
373
|
end
|
374
|
+
|
376
375
|
end
|
377
376
|
|
378
377
|
end
|
@@ -332,7 +332,7 @@ module StateMachine
|
|
332
332
|
@state_machine.log "Starting timeout -> #{options[:to]}, "\
|
333
333
|
"after #{options[:after]}"
|
334
334
|
delay = event_trigger_value
|
335
|
-
interval =
|
335
|
+
interval = Dispatch::TIME_FOREVER
|
336
336
|
leeway = @options[:leeway] || 0.001
|
337
337
|
queue = @state_machine.initial_queue
|
338
338
|
@timer = Dispatch::Source.timer(delay, interval, leeway, queue) do
|
@@ -374,15 +374,17 @@ module StateMachine
|
|
374
374
|
end
|
375
375
|
|
376
376
|
def arm
|
377
|
-
NSNotificationCenter.defaultCenter.
|
378
|
-
|
379
|
-
|
380
|
-
|
381
|
-
|
377
|
+
@observer = NSNotificationCenter.defaultCenter.addObserverForName event_trigger_value,
|
378
|
+
object: nil,
|
379
|
+
queue: NSOperationQueue.mainQueue,
|
380
|
+
usingBlock: -> notification {
|
381
|
+
handle_in_initial_queue
|
382
|
+
state_machine.log "Registered notification #{event_trigger_value}"
|
383
|
+
}
|
382
384
|
end
|
383
385
|
|
384
386
|
def unarm
|
385
|
-
NSNotificationCenter.defaultCenter.removeObserver
|
387
|
+
NSNotificationCenter.defaultCenter.removeObserver @observer
|
386
388
|
@state_machine.log "Removed as observer"
|
387
389
|
end
|
388
390
|
|
data/spec/benchmark_spec.rb
CHANGED
@@ -8,28 +8,26 @@ class LoopingThreeStateMachine < StateMachine::Base
|
|
8
8
|
attr_accessor :steps, :loops
|
9
9
|
attr_accessor :is_dead
|
10
10
|
|
11
|
-
|
12
|
-
super(start_state: :first_state)
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
11
|
+
def initialize
|
12
|
+
super(start_state: :first_state).tap do |fsm|
|
13
|
+
fsm.steps = 0
|
14
|
+
fsm.loops = 0
|
15
|
+
|
16
|
+
fsm.when :first_state do |state|
|
17
|
+
state.transition_to :second_state, on: :next,
|
18
|
+
action: proc { @steps += 1 }
|
19
|
+
end
|
20
|
+
|
21
|
+
fsm.when :second_state do |state|
|
22
|
+
state.transition_to :third_state, on: :next,
|
23
|
+
action: proc { @steps += 1 }
|
24
|
+
end
|
25
|
+
|
26
|
+
fsm.when :third_state do |state|
|
27
|
+
state.transition_to :first_state, on: :next,
|
28
|
+
action: proc { @steps += 1; @loops += 1 }
|
29
|
+
end
|
25
30
|
end
|
26
|
-
|
27
|
-
self.when :third_state do |state|
|
28
|
-
state.transition_to :first_state, on: :next,
|
29
|
-
action: proc { @steps += 1; @loops += 1 }
|
30
|
-
end
|
31
|
-
|
32
|
-
self
|
33
31
|
end
|
34
32
|
end
|
35
33
|
|
@@ -62,8 +60,6 @@ describe LoopingThreeStateMachine do
|
|
62
60
|
|
63
61
|
handle_time = NSDate.date.timeIntervalSinceDate started_on
|
64
62
|
|
65
|
-
send_time.should < 0.2
|
66
|
-
|
67
63
|
frequency = event_count / handle_time
|
68
64
|
frequency.should > 10000
|
69
65
|
|
@@ -21,11 +21,13 @@ describe StateMachine::NotificationTransition do
|
|
21
21
|
@fired.should == false
|
22
22
|
|
23
23
|
NSNotificationCenter.defaultCenter.postNotificationName "SomeNotification", object: nil
|
24
|
+
sleep 0.1
|
24
25
|
@state_machine.current_state.symbol.should == :notified
|
25
26
|
@fired.should == true
|
26
27
|
@fired = false
|
27
28
|
|
28
29
|
NSNotificationCenter.defaultCenter.postNotificationName "SomeNotification", object: nil
|
30
|
+
sleep 0.1
|
29
31
|
@state_machine.current_state.symbol.should == :notified
|
30
32
|
@fired.should == false
|
31
33
|
end
|
@@ -49,6 +51,7 @@ describe StateMachine::NotificationTransition do
|
|
49
51
|
@fired = false
|
50
52
|
|
51
53
|
NSNotificationCenter.defaultCenter.postNotificationName "SomeNotification", object: nil
|
54
|
+
sleep 0.1
|
52
55
|
@state_machine.current_state.symbol.should == :notified
|
53
56
|
@fired.should == false
|
54
57
|
end
|
@@ -1,11 +1,12 @@
|
|
1
1
|
describe StateMachine::TimedTransition do
|
2
2
|
|
3
3
|
before do
|
4
|
+
@count = 0
|
4
5
|
@state_machine = StateMachine::Base.new start_state: :timing_out
|
5
|
-
action = proc { @fired = true }
|
6
|
+
action = proc { @fired = true; @count = @count + 1 }
|
6
7
|
@state_machine.when :timing_out do |state|
|
7
8
|
@transition = state.transition_to(:timed_out, after: 0.5, action: action).first
|
8
|
-
state.transition_to :
|
9
|
+
state.transition_to :cancelled, on: :cancel
|
9
10
|
end
|
10
11
|
end
|
11
12
|
|
@@ -24,7 +25,7 @@ describe StateMachine::TimedTransition do
|
|
24
25
|
@fired.should == false
|
25
26
|
end
|
26
27
|
|
27
|
-
it "
|
28
|
+
it "executes at the given time if not cancelled" do
|
28
29
|
sleep 0.49
|
29
30
|
@state_machine.current_state.symbol.should == :timing_out
|
30
31
|
@fired.should == false
|
@@ -33,16 +34,25 @@ describe StateMachine::TimedTransition do
|
|
33
34
|
@fired.should == true
|
34
35
|
end
|
35
36
|
|
36
|
-
it "
|
37
|
+
it "is not executed if leaving the state before timeout" do
|
37
38
|
sleep 0.49
|
38
39
|
@fired.should == false
|
39
40
|
@other_queue.async do
|
40
41
|
@state_machine.event :cancel
|
41
42
|
end
|
42
43
|
sleep 0.02
|
43
|
-
@state_machine.current_state.symbol.should == :
|
44
|
+
@state_machine.current_state.symbol.should == :cancelled
|
44
45
|
@fired.should == false
|
45
46
|
end
|
47
|
+
|
48
|
+
it "does not repeat (regression test)" do
|
49
|
+
sleep 0.49
|
50
|
+
@state_machine.current_state.symbol.should == :timing_out
|
51
|
+
sleep 0.02
|
52
|
+
@state_machine.current_state.symbol.should == :timed_out
|
53
|
+
sleep 1.0
|
54
|
+
@count.should == 1
|
55
|
+
end
|
46
56
|
end
|
47
57
|
|
48
58
|
end
|
data/spec/transition_spec.rb
CHANGED
@@ -58,16 +58,16 @@ describe StateMachine::Transition do
|
|
58
58
|
|
59
59
|
describe "#unguarded_execute" do
|
60
60
|
it "should call its source state's exit method if not internal" do
|
61
|
-
exit_action_called = false
|
61
|
+
@exit_action_called = false
|
62
62
|
@state_machine.when(:awake) do |state|
|
63
63
|
state.on_exit do
|
64
|
-
exit_action_called = true
|
64
|
+
@exit_action_called = true
|
65
65
|
end
|
66
66
|
end
|
67
67
|
@state_machine.start!
|
68
|
-
exit_action_called.should == false
|
68
|
+
@exit_action_called.should == false
|
69
69
|
@transition.send :unguarded_execute
|
70
|
-
exit_action_called.should == true
|
70
|
+
@exit_action_called.should == true
|
71
71
|
end
|
72
72
|
|
73
73
|
it "should not call its source state's exit method if internal" do
|
@@ -85,16 +85,16 @@ describe StateMachine::Transition do
|
|
85
85
|
end
|
86
86
|
|
87
87
|
it "should call its destination state's enter method if not internal" do
|
88
|
-
entry_action_called = false
|
88
|
+
@entry_action_called = false
|
89
89
|
@state_machine.when(:tired) do |state|
|
90
90
|
state.on_entry do
|
91
|
-
entry_action_called = true
|
91
|
+
@entry_action_called = true
|
92
92
|
end
|
93
93
|
end
|
94
94
|
@state_machine.start!
|
95
|
-
entry_action_called.should == false
|
95
|
+
@entry_action_called.should == false
|
96
96
|
@transition.send :unguarded_execute
|
97
|
-
entry_action_called.should == true
|
97
|
+
@entry_action_called.should == true
|
98
98
|
end
|
99
99
|
|
100
100
|
it "should not call its destination state's enter method if internal" do
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: motion-state-machine
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.8.
|
4
|
+
version: 0.8.3
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,11 +9,11 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date:
|
12
|
+
date: 2013-10-03 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: rake
|
16
|
-
requirement:
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
17
|
none: false
|
18
18
|
requirements:
|
19
19
|
- - ! '>='
|
@@ -21,7 +21,12 @@ dependencies:
|
|
21
21
|
version: '0'
|
22
22
|
type: :development
|
23
23
|
prerelease: false
|
24
|
-
version_requirements:
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ! '>='
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: '0'
|
25
30
|
description: A finite state machine for RubyMotion with a flavor of Grand Central
|
26
31
|
Dispatch.
|
27
32
|
email:
|
@@ -62,21 +67,15 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
62
67
|
- - ! '>='
|
63
68
|
- !ruby/object:Gem::Version
|
64
69
|
version: '0'
|
65
|
-
segments:
|
66
|
-
- 0
|
67
|
-
hash: -1755037909543191418
|
68
70
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
69
71
|
none: false
|
70
72
|
requirements:
|
71
73
|
- - ! '>='
|
72
74
|
- !ruby/object:Gem::Version
|
73
75
|
version: '0'
|
74
|
-
segments:
|
75
|
-
- 0
|
76
|
-
hash: -1755037909543191418
|
77
76
|
requirements: []
|
78
77
|
rubyforge_project:
|
79
|
-
rubygems_version: 1.8.
|
78
|
+
rubygems_version: 1.8.25
|
80
79
|
signing_key:
|
81
80
|
specification_version: 3
|
82
81
|
summary: Comes with a nice syntax for state and transition definition. Supports triggering
|