actiontimer 0.1.1 → 0.2.1
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG +13 -0
- data/README.rdoc +13 -4
- data/actiontimer.gemspec +3 -2
- data/lib/actiontimer.rb +4 -1
- data/lib/actiontimer/Action.rb +25 -7
- data/lib/actiontimer/Timer.rb +53 -27
- data/tests/cases/action.rb +128 -0
- data/tests/cases/timer.rb +85 -0
- data/tests/run_tests.rb +145 -140
- metadata +25 -15
- data/test +0 -11
data/CHANGELOG
CHANGED
@@ -1,5 +1,18 @@
|
|
1
1
|
= CHANGELOG
|
2
2
|
|
3
|
+
== 0.2.1
|
4
|
+
* Use simple monitor
|
5
|
+
* Add support for rounding sleep time within a delta
|
6
|
+
* Raise unexpected exception to creator thread after shutting down
|
7
|
+
* Fix arity checks for < 1.9 versions
|
8
|
+
|
9
|
+
== 0.2.0
|
10
|
+
* hashed arguments for Timer#add and Action#new
|
11
|
+
* Timer#mass_add replaced with Timer#register for single and arrays of Actions
|
12
|
+
* Timer#registered? added to see if an Action is registered with the timer
|
13
|
+
* Timer#actions to see Actions registered with the timer
|
14
|
+
* Action#timer= to allow Actions to be moved
|
15
|
+
|
3
16
|
== 0.1.1
|
4
17
|
* fix for float calculations
|
5
18
|
* downcased gem name
|
data/README.rdoc
CHANGED
@@ -16,6 +16,15 @@ ActionTimer is a helper for timed events. It allows for single and recurring act
|
|
16
16
|
|
17
17
|
{rip}[http://hellorip.com/about.html] makes it easy to install directly from a github repository.
|
18
18
|
|
19
|
+
=== Testing
|
20
|
+
|
21
|
+
ActionTimer is currently tested on:
|
22
|
+
|
23
|
+
* Ruby 1.8.6-p383
|
24
|
+
* Ruby 1.8.7-p248
|
25
|
+
* Ruby 1.9.1-p376
|
26
|
+
* JRuby 1.4.0
|
27
|
+
|
19
28
|
=== Using the timer:
|
20
29
|
|
21
30
|
==== Simple example:
|
@@ -92,10 +101,10 @@ What if you want to add multiple actions at one time? We can do this:
|
|
92
101
|
timer = ActionTimer::Timer.new
|
93
102
|
result = 0
|
94
103
|
actions = []
|
95
|
-
actions << ActionTimer::Action.new(
|
96
|
-
actions << ActionTimer::Action.new(
|
97
|
-
actions << ActionTimer::Action.new(
|
98
|
-
timer.
|
104
|
+
actions << ActionTimer::Action.new(timer, 0.1){ result += 1}
|
105
|
+
actions << ActionTimer::Action.new(timer, 0.2){ result += 1}
|
106
|
+
actions << ActionTimer::Action.new(timer, 0.3){ result += 1}
|
107
|
+
timer.register(actions)
|
99
108
|
sleep(0.41)
|
100
109
|
p result
|
101
110
|
|
data/actiontimer.gemspec
CHANGED
@@ -2,7 +2,7 @@ spec = Gem::Specification.new do |s|
|
|
2
2
|
s.name = 'actiontimer'
|
3
3
|
s.author = 'spox'
|
4
4
|
s.email = 'spox@modspox.com'
|
5
|
-
s.version = '0.
|
5
|
+
s.version = '0.2.1'
|
6
6
|
s.summary = 'Simple timer for a complex world'
|
7
7
|
s.platform = Gem::Platform::RUBY
|
8
8
|
s.has_rdoc = true
|
@@ -10,7 +10,8 @@ spec = Gem::Specification.new do |s|
|
|
10
10
|
s.extra_rdoc_files = %w(README.rdoc LICENSE CHANGELOG)
|
11
11
|
s.files = Dir['**/*']
|
12
12
|
s.require_paths = %w(lib)
|
13
|
-
s.add_dependency '
|
13
|
+
s.add_dependency 'actionpool', '~> 0.2.3'
|
14
|
+
s.add_dependency 'splib', '~> 1.4'
|
14
15
|
s.required_ruby_version = '>= 1.8.6'
|
15
16
|
s.homepage = 'http://github.com/spox/actiontimer'
|
16
17
|
s.description = 'ActionTimer is a simple timer for recurring actions. It supports single and recurring actions with an easy to use API.'
|
data/lib/actiontimer.rb
CHANGED
data/lib/actiontimer/Action.rb
CHANGED
@@ -2,21 +2,36 @@ module ActionTimer
|
|
2
2
|
class Action
|
3
3
|
|
4
4
|
attr_accessor :owner
|
5
|
+
attr_accessor :timer
|
5
6
|
|
6
7
|
# timer:: Timer this action resides within
|
7
8
|
# period:: amount of time between runs
|
8
9
|
# once:: only run this action once
|
9
10
|
# data:: data to pass to block
|
10
11
|
# block:: block to be executed
|
11
|
-
def initialize(
|
12
|
-
|
12
|
+
def initialize(hash, &block)
|
13
|
+
raise ArgumentError.new('Period must be supplied') unless hash[:period]
|
14
|
+
raise ArgumentError.new('Block must be provided') unless block_given?
|
15
|
+
raise ArgumentError.new('Block must accept data value') if hash[:data] && block.arity == 0
|
16
|
+
if((block.arity > 0 || block.arity < -1) && (!hash.has_key?(:data) || hash[:data].nil?))
|
17
|
+
raise ArgumentError.new('Data must be supplied for block')
|
18
|
+
end
|
19
|
+
args = {:once => false, :data => nil, :owner => nil}.merge(hash)
|
20
|
+
@period = args[:period].to_f
|
13
21
|
@block = block
|
14
|
-
@data = data
|
15
|
-
@once = once
|
16
|
-
@timer = timer
|
22
|
+
@data = args[:data]
|
23
|
+
@once = args[:once]
|
24
|
+
@timer = args[:timer]
|
17
25
|
@completed = false
|
18
26
|
@wait_remaining = @period
|
19
|
-
@owner =
|
27
|
+
@owner = args[:owner]
|
28
|
+
end
|
29
|
+
|
30
|
+
# t:: ActionTimer::Timer
|
31
|
+
# Set timer for action to be associated with
|
32
|
+
def timer=(t)
|
33
|
+
raise ArgumentError.new('Expecting an ActionTimer::Timer') unless t.is_a?(ActionTimer::Timer)
|
34
|
+
@timer = t
|
20
35
|
end
|
21
36
|
|
22
37
|
# o:: Object that added this action
|
@@ -30,6 +45,8 @@ module ActionTimer
|
|
30
45
|
# amount:: amount of time that has passed
|
31
46
|
# Decrement remaining wait time by given amount
|
32
47
|
def tick(amount)
|
48
|
+
amount = amount.to_f
|
49
|
+
amount = 0 if amount < 0
|
33
50
|
@wait_remaining = @wait_remaining - amount if @wait_remaining > 0
|
34
51
|
@wait_remaining = 0 if @wait_remaining < 0
|
35
52
|
@completed = true if @once && @wait_remaining <= 0
|
@@ -45,7 +62,8 @@ module ActionTimer
|
|
45
62
|
def reset_period(new_time)
|
46
63
|
@period = new_time.to_f
|
47
64
|
@wait_remaining = @period
|
48
|
-
@
|
65
|
+
@completed = false
|
66
|
+
@timer.wakeup unless @timer.nil?
|
49
67
|
end
|
50
68
|
|
51
69
|
# Action is ready to be destroyed
|
data/lib/actiontimer/Timer.rb
CHANGED
@@ -8,10 +8,12 @@ module ActionTimer
|
|
8
8
|
# Argument hash: {:pool, :logger, :auto_start}
|
9
9
|
def initialize(args={}, extra=nil)
|
10
10
|
auto_start = true
|
11
|
+
@delta = nil
|
11
12
|
if(args.is_a?(Hash))
|
12
13
|
@pool = args[:pool] ? args[:pool] : ActionPool::Pool.new
|
13
14
|
@logger = args[:logger] && args[:logger].is_a?(Logger) ? args[:logger] : Logger.new(nil)
|
14
15
|
auto_start = args.has_key?(:auto_start) ? args[:auto_start] : true
|
16
|
+
@delta = args[:delta] ? args[:delta].to_f : nil
|
15
17
|
else
|
16
18
|
@pool = args.is_a?(ActionPool::Pool) ? args : ActionPool::Pool.new
|
17
19
|
@logger = extra && extra.is_a?(Logger) ? extra : Logger.new(nil)
|
@@ -20,17 +22,21 @@ module ActionTimer
|
|
20
22
|
@new_actions = []
|
21
23
|
@timer_thread = nil
|
22
24
|
@stop_timer = false
|
23
|
-
@add_lock =
|
24
|
-
@awake_lock =
|
25
|
+
@add_lock = Splib::Monitor.new
|
26
|
+
@awake_lock = Splib::Monitor.new
|
27
|
+
@sleeper = Splib::Monitor.new
|
28
|
+
@respond_to = Thread.current
|
25
29
|
start if auto_start
|
26
30
|
end
|
27
31
|
|
28
32
|
# Forcibly wakes the timer early
|
29
33
|
def wakeup
|
30
34
|
raise NotRunning.new unless running?
|
31
|
-
|
32
|
-
|
33
|
-
|
35
|
+
if(@sleeper.waiters > 0)
|
36
|
+
@sleeper.signal
|
37
|
+
else
|
38
|
+
@timer_thread.wakeup if @timer_thread.alive? && @timer_thread.stop?
|
39
|
+
end
|
34
40
|
end
|
35
41
|
|
36
42
|
# period:: amount of time between runs
|
@@ -39,22 +45,30 @@ module ActionTimer
|
|
39
45
|
# owner:: owner of Action
|
40
46
|
# func:: block to be executed
|
41
47
|
# Add a new action to block
|
42
|
-
def add(
|
43
|
-
|
44
|
-
|
48
|
+
def add(hash, &func)
|
49
|
+
raise ArgumentError.new('Expecting hash of arguments') unless hash.is_a?(Hash)
|
50
|
+
raise ArgumentError.new('A period must be provided for timed action') unless hash[:period]
|
51
|
+
raise ArgumentError.new('Block must be provided') unless block_given?
|
52
|
+
raise ArgumentError.new('Block must accept data value') if hash[:data] && func.arity == 0
|
53
|
+
args = {:once => false, :data => nil, :owner => nil}.merge(hash)
|
54
|
+
action = Action.new(args.merge(:timer => self), &func)
|
45
55
|
@add_lock.synchronize{ @new_actions << action }
|
46
56
|
wakeup if running?
|
47
|
-
|
57
|
+
action
|
48
58
|
end
|
49
59
|
|
50
|
-
# actions:: Array of actions
|
51
|
-
# Add multiple Actions to the timer at once
|
52
|
-
def
|
53
|
-
|
54
|
-
|
55
|
-
|
60
|
+
# actions:: Array of actions or single ActionTimer::Action
|
61
|
+
# Add single or multiple Actions to the timer at once
|
62
|
+
def register(action)
|
63
|
+
if(action.is_a?(Array))
|
64
|
+
if(action.find{|x|x.is_a?(Action)}.nil?)
|
65
|
+
raise ArgumentError.new('Array contains non ActionTimer::Action objects')
|
66
|
+
end
|
67
|
+
else
|
68
|
+
raise ArgumentError.new('Expecting an ActionTimer::Action object') unless action.is_a?(Action)
|
69
|
+
action = [action]
|
56
70
|
end
|
57
|
-
@add_lock.synchronize{ @new_actions = @new_actions +
|
71
|
+
@add_lock.synchronize{ @new_actions = @new_actions + action }
|
58
72
|
wakeup if running?
|
59
73
|
end
|
60
74
|
|
@@ -76,19 +90,24 @@ module ActionTimer
|
|
76
90
|
to_sleep = get_min_sleep
|
77
91
|
if((to_sleep.nil? || to_sleep > 0) && @new_actions.empty?)
|
78
92
|
@awake_lock.unlock if @awake_lock.locked?
|
79
|
-
|
93
|
+
start = Time.now.to_f
|
94
|
+
to_sleep.nil? ? @sleeper.wait : sleep(to_sleep)
|
95
|
+
actual_sleep = Time.now.to_f - start
|
96
|
+
if(@delta && to_sleep && actual_sleep.within_delta?(:expected => to_sleep, :delta => @delta))
|
97
|
+
actual_sleep = to_sleep
|
98
|
+
end
|
80
99
|
@awake_lock.lock
|
81
100
|
else
|
82
101
|
actual_sleep = 0
|
83
102
|
end
|
84
|
-
actual_sleep = to_sleep if actual_sleep <= 0
|
85
103
|
tick(actual_sleep)
|
86
104
|
add_waiting_actions
|
87
105
|
end
|
88
106
|
rescue Object => boom
|
89
107
|
@timer_thread = nil
|
90
108
|
clean_actions
|
91
|
-
@logger.fatal("Timer encountered an unexpected error: #{boom}\n#{boom.backtrace.join("\n")}")
|
109
|
+
@logger.fatal("Timer encountered an unexpected error and is shutting down: #{boom}\n#{boom.backtrace.join("\n")}")
|
110
|
+
@respond_to.raise boom
|
92
111
|
end
|
93
112
|
end
|
94
113
|
end
|
@@ -125,23 +144,30 @@ module ActionTimer
|
|
125
144
|
else
|
126
145
|
@actions.each{|a| @actions.delete(a) if a.owner == owner}
|
127
146
|
end
|
128
|
-
wakeup
|
147
|
+
wakeup if running?
|
129
148
|
end
|
130
149
|
|
131
150
|
# Is timer currently running?
|
132
151
|
def running?
|
133
|
-
|
152
|
+
!@timer_thread.nil?
|
153
|
+
end
|
154
|
+
|
155
|
+
# action:: ActionTimer::Action
|
156
|
+
# Is action currently in timer
|
157
|
+
def registered?(action)
|
158
|
+
@actions.include?(action)
|
159
|
+
end
|
160
|
+
|
161
|
+
# Actions registered with the timer
|
162
|
+
def actions
|
163
|
+
@actions.dup
|
134
164
|
end
|
135
165
|
|
136
166
|
private
|
137
167
|
|
138
168
|
def get_min_sleep
|
139
|
-
min = @actions.
|
140
|
-
|
141
|
-
@actions.each{|a|@actions.delete(a) if a.remaining == 0} # kill stuck actions
|
142
|
-
min = get_min_sleep
|
143
|
-
end
|
144
|
-
return min
|
169
|
+
min = @actions.min{|a,b|a.remaining <=> b.remaining}
|
170
|
+
min.remaining if min
|
145
171
|
end
|
146
172
|
|
147
173
|
def add_waiting_actions
|
@@ -0,0 +1,128 @@
|
|
1
|
+
require 'test/unit'
|
2
|
+
require 'actiontimer'
|
3
|
+
|
4
|
+
class ActionTests < Test::Unit::TestCase
|
5
|
+
def setup
|
6
|
+
@timer = ActionTimer::Timer.new
|
7
|
+
end
|
8
|
+
def teardown
|
9
|
+
end
|
10
|
+
|
11
|
+
def test_create
|
12
|
+
assert_raise(ArgumentError) do
|
13
|
+
action = ActionTimer::Action.new(:timer => @timer){true}
|
14
|
+
end
|
15
|
+
assert_raise(ArgumentError) do
|
16
|
+
action = ActionTimer::Action.new(:timer => @timer, :period => 1){|x|true}
|
17
|
+
end
|
18
|
+
assert_raise(ArgumentError) do
|
19
|
+
action = ActionTimer::Action.new(:timer => @timer, :period => 1, :data => 1)
|
20
|
+
end
|
21
|
+
if(RUBY_VERSION > "1.9.0")
|
22
|
+
assert_raise(ArgumentError) do
|
23
|
+
action = ActionTimer::Action.new(:timer => @timer, :period => 1, :data => 1){true}
|
24
|
+
end
|
25
|
+
end
|
26
|
+
assert_kind_of(ActionTimer::Action, ActionTimer::Action.new(:timer => @timer, :period => 1){true})
|
27
|
+
assert_kind_of(ActionTimer::Action, ActionTimer::Action.new(:timer => @timer, :period => 1, :once => true){true})
|
28
|
+
assert_kind_of(ActionTimer::Action, ActionTimer::Action.new(:timer => @timer, :period => 1, :once => false){true})
|
29
|
+
end
|
30
|
+
|
31
|
+
def test_timer
|
32
|
+
mytimer = ActionTimer::Timer.new
|
33
|
+
action = ActionTimer::Action.new(:timer => @timer, :period => 1){true}
|
34
|
+
assert_equal(@timer, action.timer)
|
35
|
+
action.timer = mytimer
|
36
|
+
assert_equal(mytimer, action.timer)
|
37
|
+
end
|
38
|
+
|
39
|
+
def test_owner
|
40
|
+
object = Object.new
|
41
|
+
action = ActionTimer::Action.new(:timer => @timer, :period => 1, :owner => object){true}
|
42
|
+
assert_equal(object, action.owner)
|
43
|
+
other_object = Object.new
|
44
|
+
action.owner = other_object
|
45
|
+
assert_equal(other_object, action.owner)
|
46
|
+
action.owner = object
|
47
|
+
assert_equal(object, action.owner)
|
48
|
+
end
|
49
|
+
|
50
|
+
def test_tick
|
51
|
+
action = ActionTimer::Action.new(:timer => @timer, :period => 2){true}
|
52
|
+
action.tick(1)
|
53
|
+
assert_equal(1, action.remaining)
|
54
|
+
action.tick(0.1)
|
55
|
+
assert_equal(0.9, action.remaining)
|
56
|
+
action.tick(0.11)
|
57
|
+
assert_equal(0.79, action.remaining)
|
58
|
+
end
|
59
|
+
|
60
|
+
def test_reset_period
|
61
|
+
action = ActionTimer::Action.new(:timer => @timer, :period => 2){true}
|
62
|
+
action.tick(1)
|
63
|
+
assert_equal(1, action.remaining)
|
64
|
+
action.reset_period(3)
|
65
|
+
assert_equal(3, action.remaining)
|
66
|
+
action.tick(3)
|
67
|
+
assert_equal(0, action.remaining)
|
68
|
+
assert(!action.is_complete?)
|
69
|
+
end
|
70
|
+
|
71
|
+
def test_complete
|
72
|
+
action = ActionTimer::Action.new(:timer => @timer, :period => 2, :once => true){true}
|
73
|
+
action.tick(2)
|
74
|
+
assert_equal(0, action.remaining)
|
75
|
+
assert(action.is_complete?)
|
76
|
+
end
|
77
|
+
|
78
|
+
def test_schedule
|
79
|
+
action = ActionTimer::Action.new(:timer => @timer, :period => 2){true}
|
80
|
+
action.tick(1)
|
81
|
+
assert_equal(1, action.remaining)
|
82
|
+
assert_equal(action, action.schedule)
|
83
|
+
assert_equal(2, action.remaining)
|
84
|
+
end
|
85
|
+
|
86
|
+
def test_due
|
87
|
+
action = ActionTimer::Action.new(:timer => @timer, :period => 2){true}
|
88
|
+
assert(!action.due?)
|
89
|
+
action.tick(2)
|
90
|
+
assert(action.due?)
|
91
|
+
end
|
92
|
+
|
93
|
+
def test_run_noargs
|
94
|
+
a = false
|
95
|
+
action = ActionTimer::Action.new(:timer => @timer, :period => 2){ a = true }
|
96
|
+
assert(!a)
|
97
|
+
action.run
|
98
|
+
assert(a)
|
99
|
+
end
|
100
|
+
|
101
|
+
def test_run_args
|
102
|
+
a = []
|
103
|
+
action = ActionTimer::Action.new(:timer => @timer, :period => 2, :data => [1,2,[3]]) do |b,c,d|
|
104
|
+
a << b
|
105
|
+
a << c
|
106
|
+
a << d
|
107
|
+
end
|
108
|
+
action.run
|
109
|
+
assert_kind_of(Array, a.pop)
|
110
|
+
assert_equal(2, a.pop)
|
111
|
+
assert_equal(1, a.pop)
|
112
|
+
assert(a.empty?)
|
113
|
+
action = ActionTimer::Action.new(:timer => @timer, :period => 2, :data => [1,2,[3]]) do |*b|
|
114
|
+
a = b
|
115
|
+
end
|
116
|
+
action.run
|
117
|
+
assert_kind_of(Array, a)
|
118
|
+
assert_kind_of(Array, a.pop)
|
119
|
+
assert_equal(2, a.pop)
|
120
|
+
assert_equal(1, a.pop)
|
121
|
+
assert(a.empty?)
|
122
|
+
action = ActionTimer::Action.new(:timer => @timer, :period => 2, :data => :foo) do |b|
|
123
|
+
a = b
|
124
|
+
end
|
125
|
+
action.run
|
126
|
+
assert_equal(:foo, a)
|
127
|
+
end
|
128
|
+
end
|
@@ -0,0 +1,85 @@
|
|
1
|
+
require 'test/unit'
|
2
|
+
require 'actiontimer'
|
3
|
+
|
4
|
+
class TimerTests < Test::Unit::TestCase
|
5
|
+
def setup
|
6
|
+
@timer = ActionTimer::Timer.new
|
7
|
+
end
|
8
|
+
|
9
|
+
def teardown
|
10
|
+
end
|
11
|
+
|
12
|
+
def test_add_bad
|
13
|
+
assert_raise(ArgumentError) do
|
14
|
+
@timer.add{true}
|
15
|
+
end
|
16
|
+
assert_raise(ArgumentError) do
|
17
|
+
@timer.add(1){true}
|
18
|
+
end
|
19
|
+
assert_raise(ArgumentError) do
|
20
|
+
@timer.add(:period => 1)
|
21
|
+
end
|
22
|
+
if(RUBY_VERSION > "1.9.0")
|
23
|
+
assert_raise(ArgumentError) do
|
24
|
+
@timer.add(:period => 1, :data => 2){true}
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def test_add
|
30
|
+
output = []
|
31
|
+
action = @timer.add(:period => 0.1){true}
|
32
|
+
assert_kind_of(ActionTimer::Action, action)
|
33
|
+
sleep(0.01)
|
34
|
+
assert_equal(1, @timer.actions.size)
|
35
|
+
assert(@timer.registered?(action))
|
36
|
+
@timer.add(:period => 0.1, :once => true, :data => :foo){|x| output << x }
|
37
|
+
sleep(0.01)
|
38
|
+
assert_equal(2, @timer.actions.size)
|
39
|
+
sleep(0.14)
|
40
|
+
assert_equal(:foo, output.pop)
|
41
|
+
assert_equal(1, @timer.actions.size)
|
42
|
+
end
|
43
|
+
|
44
|
+
def test_register
|
45
|
+
output = []
|
46
|
+
action = ActionTimer::Action.new(:period => 0.01){output << :action}
|
47
|
+
@timer.register(action)
|
48
|
+
sleep(0.113)
|
49
|
+
@timer.pause
|
50
|
+
assert_equal(10, output.size)
|
51
|
+
assert_equal(1, @timer.actions.size)
|
52
|
+
assert(@timer.registered?(action))
|
53
|
+
@timer.clear
|
54
|
+
assert(@timer.actions.empty?)
|
55
|
+
@timer.start
|
56
|
+
output.clear
|
57
|
+
actions = [action]
|
58
|
+
actions << ActionTimer::Action.new(:period => 0.02){output << :fubar}
|
59
|
+
@timer.register(actions)
|
60
|
+
sleep(0.051)
|
61
|
+
@timer.pause
|
62
|
+
assert_equal(7, output.size)
|
63
|
+
assert(output.include?(:fubar))
|
64
|
+
assert_equal(2, @timer.actions.size)
|
65
|
+
actions.each{|x| assert(@timer.registered?(x)) }
|
66
|
+
end
|
67
|
+
|
68
|
+
def test_remove
|
69
|
+
output = []
|
70
|
+
action = ActionTimer::Action.new(:period => 0.01){output << :action}
|
71
|
+
@timer.register(action)
|
72
|
+
sleep(0.029)
|
73
|
+
@timer.remove(action)
|
74
|
+
assert_equal(2, output.size)
|
75
|
+
assert(@timer.actions.empty?)
|
76
|
+
output.clear
|
77
|
+
assert(output.empty?)
|
78
|
+
action = @timer.add(:period => 0.01){output << :action}
|
79
|
+
sleep(0.021)
|
80
|
+
@timer.remove(action)
|
81
|
+
assert(!@timer.registered?(action))
|
82
|
+
assert(2, output.size)
|
83
|
+
end
|
84
|
+
|
85
|
+
end
|
data/tests/run_tests.rb
CHANGED
@@ -3,143 +3,148 @@ $LOAD_PATH.unshift(File.expand_path("#{__FILE__}/../../lib"))
|
|
3
3
|
require 'test/unit'
|
4
4
|
require 'actiontimer'
|
5
5
|
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
6
|
+
Dir.new("#{File.dirname(__FILE__)}/cases").each{|f|
|
7
|
+
require "#{File.dirname(__FILE__)}/cases/#{f}" if f[-2..f.size] == 'rb'
|
8
|
+
}
|
9
|
+
#
|
10
|
+
#
|
11
|
+
# class TimerTests < Test::Unit::TestCase
|
12
|
+
# def setup
|
13
|
+
# @timer = ActionTimer::Timer.new
|
14
|
+
# end
|
15
|
+
#
|
16
|
+
# # Simple test of basic repetitive action
|
17
|
+
# def test_basic
|
18
|
+
# result = 0
|
19
|
+
# @timer.add(2){ result += 1 }
|
20
|
+
# sleep(5)
|
21
|
+
# assert_equal(2, result)
|
22
|
+
# end
|
23
|
+
#
|
24
|
+
# # Check the the running? method properly reports
|
25
|
+
# def test_running
|
26
|
+
# @timer.add(1){ 1 + 1}
|
27
|
+
# assert(@timer.running?)
|
28
|
+
# @timer.pause
|
29
|
+
# assert(!@timer.running?)
|
30
|
+
# @timer.start
|
31
|
+
# assert(@timer.running?)
|
32
|
+
# @timer.stop
|
33
|
+
# assert(!@timer.running?)
|
34
|
+
# end
|
35
|
+
#
|
36
|
+
# # Check that a value 0 < t < 1 works
|
37
|
+
# # as expected
|
38
|
+
# def test_float
|
39
|
+
# result = 0
|
40
|
+
# @timer.add(0.1){ result += 1 }
|
41
|
+
# sleep(1.01)
|
42
|
+
# assert_equal(10, result)
|
43
|
+
# end
|
44
|
+
#
|
45
|
+
# # Check that a single iterative action is only
|
46
|
+
# # completed once
|
47
|
+
# def test_once
|
48
|
+
# result = 0
|
49
|
+
# @timer.add(1, true){ result += 1 }
|
50
|
+
# sleep(3)
|
51
|
+
# assert_equal(1, result)
|
52
|
+
# end
|
53
|
+
#
|
54
|
+
# # Check that timer can be paused and restarted
|
55
|
+
# # without registered actions being effected
|
56
|
+
# def test_pause
|
57
|
+
# result = 0
|
58
|
+
# @timer.add(1){ result += 1 }
|
59
|
+
# sleep(3.1)
|
60
|
+
# @timer.pause
|
61
|
+
# sleep(2)
|
62
|
+
# @timer.start
|
63
|
+
# sleep(2)
|
64
|
+
# assert_equal(5, result)
|
65
|
+
# end
|
66
|
+
#
|
67
|
+
# # Check that data can be passed to the block
|
68
|
+
# # properly when created
|
69
|
+
# def test_data
|
70
|
+
# result = 0
|
71
|
+
# @timer.add(1, true, 3){|a| result = a}
|
72
|
+
# sleep(2)
|
73
|
+
# assert_equal(3, result)
|
74
|
+
# @timer.add(1, true, [3,4,['foobar']]){|a,b,c| result = [b,a,c]}
|
75
|
+
# sleep(2)
|
76
|
+
# assert_equal(4, result[0])
|
77
|
+
# assert_equal(3, result[1])
|
78
|
+
# assert(result[2].is_a?(Array))
|
79
|
+
# end
|
80
|
+
#
|
81
|
+
# # Check that the timer's auto starting mechanism
|
82
|
+
# # can be disabled
|
83
|
+
# def test_auto_start
|
84
|
+
# timer = ActionTimer::Timer.new(:auto_start => false)
|
85
|
+
# timer.add(1){ 1+1 }
|
86
|
+
# assert(!timer.running?)
|
87
|
+
# timer.start
|
88
|
+
# assert(timer.running?)
|
89
|
+
# end
|
90
|
+
#
|
91
|
+
# # Check that the actions can be cleared out of the
|
92
|
+
# # timer and the timer is still left in a "running"
|
93
|
+
# # state.
|
94
|
+
# def test_clear
|
95
|
+
# result = 0
|
96
|
+
# @timer.add(1){ result += 1 }
|
97
|
+
# sleep(3)
|
98
|
+
# @timer.clear
|
99
|
+
# sleep(2)
|
100
|
+
# assert_equal(2, result)
|
101
|
+
# assert(@timer.running?)
|
102
|
+
# end
|
103
|
+
#
|
104
|
+
# # Check that the timer throws an exception when it
|
105
|
+
# # is instructed to wakeup while not running
|
106
|
+
# def test_wakeup
|
107
|
+
# @timer.stop
|
108
|
+
# assert_raise(ActionTimer::NotRunning){ @timer.wakeup }
|
109
|
+
# end
|
110
|
+
#
|
111
|
+
# # Check that the timer throws an exception when it
|
112
|
+
# # is instructed to start but is already running
|
113
|
+
# def test_start
|
114
|
+
# assert_raise(ActionTimer::AlreadyRunning){ @timer.start }
|
115
|
+
# end
|
116
|
+
#
|
117
|
+
# # Check that multiple actions can be added at once
|
118
|
+
# def test_mass_add
|
119
|
+
# result = 0
|
120
|
+
# actions = []
|
121
|
+
# actions << ActionTimer::Action.new(@timer, 1){ result += 1}
|
122
|
+
# actions << ActionTimer::Action.new(@timer, 3){ result += 1}
|
123
|
+
# actions << ActionTimer::Action.new(@timer, 5){ result += 1}
|
124
|
+
# @timer.mass_add(actions)
|
125
|
+
# sleep(5.3)
|
126
|
+
# assert_equal(7, result)
|
127
|
+
# end
|
128
|
+
#
|
129
|
+
# # Check that an action can be properly removed from
|
130
|
+
# # the timer
|
131
|
+
# def test_remove
|
132
|
+
# result = 0
|
133
|
+
# action = @timer.add(1){result += 1}
|
134
|
+
# sleep(2.1)
|
135
|
+
# @timer.remove(action)
|
136
|
+
# sleep(2)
|
137
|
+
# assert_equal(2, result)
|
138
|
+
# end
|
139
|
+
#
|
140
|
+
# # Check that an action's period can be dynamically
|
141
|
+
# # reset
|
142
|
+
# def test_action_reset
|
143
|
+
# result = 0
|
144
|
+
# action = @timer.add(1){ result += 1}
|
145
|
+
# sleep(2.1)
|
146
|
+
# action.reset_period(3)
|
147
|
+
# sleep(3.1)
|
148
|
+
# assert_equal(result, 3)
|
149
|
+
# end
|
150
|
+
# end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: actiontimer
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- spox
|
@@ -9,18 +9,28 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date: 2010-01-
|
12
|
+
date: 2010-01-13 00:00:00 -08:00
|
13
13
|
default_executable:
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
|
-
name:
|
16
|
+
name: actionpool
|
17
17
|
type: :runtime
|
18
18
|
version_requirement:
|
19
19
|
version_requirements: !ruby/object:Gem::Requirement
|
20
20
|
requirements:
|
21
|
-
- -
|
21
|
+
- - ~>
|
22
22
|
- !ruby/object:Gem::Version
|
23
|
-
version:
|
23
|
+
version: 0.2.3
|
24
|
+
version:
|
25
|
+
- !ruby/object:Gem::Dependency
|
26
|
+
name: splib
|
27
|
+
type: :runtime
|
28
|
+
version_requirement:
|
29
|
+
version_requirements: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ~>
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: "1.4"
|
24
34
|
version:
|
25
35
|
description: ActionTimer is a simple timer for recurring actions. It supports single and recurring actions with an easy to use API.
|
26
36
|
email: spox@modspox.com
|
@@ -33,21 +43,21 @@ extra_rdoc_files:
|
|
33
43
|
- LICENSE
|
34
44
|
- CHANGELOG
|
35
45
|
files:
|
36
|
-
-
|
37
|
-
-
|
38
|
-
-
|
46
|
+
- actiontimer.gemspec
|
47
|
+
- tests/cases/timer.rb
|
48
|
+
- tests/cases/action.rb
|
49
|
+
- tests/run_tests.rb
|
50
|
+
- lib/actiontimer.rb
|
39
51
|
- lib/actiontimer/Timer.rb
|
40
52
|
- lib/actiontimer/Action.rb
|
41
|
-
- lib/actiontimer.rb
|
42
|
-
- test
|
43
|
-
- tests
|
44
|
-
- tests/run_tests.rb
|
53
|
+
- lib/actiontimer/Exceptions.rb
|
45
54
|
- CHANGELOG
|
46
55
|
- LICENSE
|
47
56
|
- README.rdoc
|
48
|
-
- actiontimer.gemspec
|
49
57
|
has_rdoc: true
|
50
58
|
homepage: http://github.com/spox/actiontimer
|
59
|
+
licenses: []
|
60
|
+
|
51
61
|
post_install_message:
|
52
62
|
rdoc_options:
|
53
63
|
- --title
|
@@ -73,9 +83,9 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
73
83
|
requirements: []
|
74
84
|
|
75
85
|
rubyforge_project:
|
76
|
-
rubygems_version: 1.3.
|
86
|
+
rubygems_version: 1.3.5
|
77
87
|
signing_key:
|
78
|
-
specification_version:
|
88
|
+
specification_version: 3
|
79
89
|
summary: Simple timer for a complex world
|
80
90
|
test_files: []
|
81
91
|
|
data/test
DELETED
@@ -1,11 +0,0 @@
|
|
1
|
-
require 'actiontimer'
|
2
|
-
timer = ActionTimer::Timer.new
|
3
|
-
result = 0
|
4
|
-
actions = []
|
5
|
-
actions << ActionTimer::Action.new(@timer, 0.1){ result += 1}
|
6
|
-
actions << ActionTimer::Action.new(@timer, 0.2){ result += 1}
|
7
|
-
actions << ActionTimer::Action.new(@timer, 0.3){ result += 1}
|
8
|
-
timer.mass_add(actions)
|
9
|
-
sleep(0.41)
|
10
|
-
p result
|
11
|
-
|