11require 'spec_helper'
22require_relative 'dereferenceable_shared'
33require_relative 'observable_shared'
4- require_relative 'runnable_shared'
54
65module Concurrent
76
@@ -13,30 +12,24 @@ module Concurrent
1312 Concurrent ::TimerTask . stub ( :warn )
1413 end
1514
16- after ( :each ) do
17- @subject = @subject . runner if @subject . respond_to? ( :runner )
18- @subject . kill unless @subject . nil?
19- @thread . kill unless @thread . nil?
20- sleep ( 0.1 )
21- end
22-
23- context :runnable do
24-
25- subject { TimerTask . new { nil } }
26-
27- it_should_behave_like :runnable
28- end
29-
3015 context :dereferenceable do
3116
17+ after ( :each ) do
18+ begin
19+ @subject . kill if @subject
20+ rescue Exception => ex
21+ # prevent exceptions with mocks in tests
22+ end
23+ end
24+
3225 def dereferenceable_subject ( value , opts = { } )
3326 opts = opts . merge ( execution_interval : 0.1 , run_now : true )
34- TimerTask . new ( opts ) { value } . execute . tap { sleep ( 0.1 ) }
27+ @subject = TimerTask . new ( opts ) { value } . execute . tap { sleep ( 0.1 ) }
3528 end
3629
3730 def dereferenceable_observable ( opts = { } )
3831 opts = opts . merge ( execution_interval : 0.1 , run_now : true )
39- TimerTask . new ( opts ) { 'value' }
32+ @subject = TimerTask . new ( opts ) { 'value' }
4033 end
4134
4235 def execute_dereferenceable ( subject )
@@ -48,9 +41,11 @@ def execute_dereferenceable(subject)
4841 end
4942
5043 context :observable do
51-
44+
5245 subject { TimerTask . new ( execution_interval : 0.1 ) { nil } }
53-
46+
47+ after ( :each ) { subject . kill }
48+
5449 def trigger_observable ( observable )
5550 observable . execute
5651 sleep ( 0.2 )
@@ -65,156 +60,148 @@ def trigger_observable(observable)
6560
6661 it 'raises an exception if no block given' do
6762 lambda {
68- @subject = Concurrent ::TimerTask . new
63+ Concurrent ::TimerTask . new
6964 } . should raise_error ( ArgumentError )
7065 end
7166
7267 it 'raises an exception if :execution_interval is not greater than zero' do
7368 lambda {
74- @subject = Concurrent ::TimerTask . new ( execution_interval : 0 ) { nil }
69+ Concurrent ::TimerTask . new ( execution_interval : 0 ) { nil }
7570 } . should raise_error ( ArgumentError )
7671 end
7772
7873 it 'raises an exception if :execution_interval is not an integer' do
7974 lambda {
80- @subject = Concurrent ::TimerTask . new ( execution_interval : 'one' ) { nil }
75+ Concurrent ::TimerTask . new ( execution_interval : 'one' ) { nil }
8176 } . should raise_error ( ArgumentError )
8277 end
8378
8479 it 'raises an exception if :timeout_interval is not greater than zero' do
8580 lambda {
86- @subject = Concurrent ::TimerTask . new ( timeout_interval : 0 ) { nil }
81+ Concurrent ::TimerTask . new ( timeout_interval : 0 ) { nil }
8782 } . should raise_error ( ArgumentError )
8883 end
8984
9085 it 'raises an exception if :timeout_interval is not an integer' do
9186 lambda {
92- @subject = Concurrent ::TimerTask . new ( timeout_interval : 'one' ) { nil }
87+ Concurrent ::TimerTask . new ( timeout_interval : 'one' ) { nil }
9388 } . should raise_error ( ArgumentError )
9489 end
9590
9691 it 'uses the default execution interval when no interval is given' do
97- @ subject = TimerTask . new { nil }
98- @ subject. execution_interval . should eq TimerTask ::EXECUTION_INTERVAL
92+ subject = TimerTask . new { nil }
93+ subject . execution_interval . should eq TimerTask ::EXECUTION_INTERVAL
9994 end
10095
10196 it 'uses the default timeout interval when no interval is given' do
102- @ subject = TimerTask . new { nil }
103- @ subject. timeout_interval . should eq TimerTask ::TIMEOUT_INTERVAL
97+ subject = TimerTask . new { nil }
98+ subject . timeout_interval . should eq TimerTask ::TIMEOUT_INTERVAL
10499 end
105100
106101 it 'uses the given execution interval' do
107- @ subject = TimerTask . new ( execution_interval : 5 ) { nil }
108- @ subject. execution_interval . should eq 5
102+ subject = TimerTask . new ( execution_interval : 5 ) { nil }
103+ subject . execution_interval . should eq 5
109104 end
110105
111106 it 'uses the given timeout interval' do
112- @ subject = TimerTask . new ( timeout_interval : 5 ) { nil }
113- @ subject. timeout_interval . should eq 5
107+ subject = TimerTask . new ( timeout_interval : 5 ) { nil }
108+ subject . timeout_interval . should eq 5
114109 end
115110 end
116111
117112 context '#kill' do
118113
119114 it 'returns true on success' do
120- task = TimerTask . new ( run_now : false ) { nil }
121- task . run!
115+ task = TimerTask . execute ( run_now : false ) { nil }
122116 sleep ( 0.1 )
123117 task . kill . should be_true
124118 end
125119 end
126120 end
127121
128- context 'created with TimerTask.run! ' do
122+ context 'arguments ' do
129123
130- context 'arguments' do
124+ it 'raises an exception if no block given' do
125+ lambda {
126+ Concurrent ::TimerTask . execute
127+ } . should raise_error
128+ end
131129
132- it 'raises an exception if no block given' do
133- lambda {
134- @subject = Concurrent ::TimerTask . run
135- } . should raise_error
136- end
130+ specify '#execution_interval is writeable' do
137131
138- it 'passes the block to the new TimerTask' do
139- @expected = false
140- block = proc { @expected = true }
141- @subject = TimerTask . run! ( run_now : true , &block )
142- sleep ( 0.1 )
143- @expected . should be_true
132+ latch = CountDownLatch . new ( 1 )
133+ subject = TimerTask . new ( execution_interval : 1 ) do |task |
134+ task . execution_interval = 3
135+ latch . count_down
144136 end
145137
146- it 'creates a new thread' do
147- thread = Thread . new { sleep ( 1 ) }
148- Thread . should_receive ( :new ) . with ( any_args ( ) ) . and_return ( thread )
149- @subject = TimerTask . run! { nil }
150- end
138+ subject . execution_interval . should == 1
139+ subject . execution_interval = 0.1
140+ subject . execution_interval . should == 0.1
151141
152- specify '#execution_interval is writeable' do
153- @subject = TimerTask . new ( execution_interval : 1 ) do |task |
154- task . execution_interval = 3
155- end
156- @subject . execution_interval . should == 1
157- @subject . execution_interval = 0.1
158- @subject . execution_interval . should == 0.1
159- @thread = Thread . new { @subject . run }
160- sleep ( 0.2 )
161- @subject . execution_interval . should == 3
162- end
142+ subject . execute
143+ latch . wait ( 0.2 )
163144
164- specify '# execution_interval is writeable' do
165- @ subject = TimerTask . new ( timeout_interval : 1 , execution_interval : 0.1 ) do | task |
166- task . timeout_interval = 3
167- end
168- @subject . timeout_interval . should == 1
169- @subject . timeout_interval = 2
170- @subject . timeout_interval . should == 2
171- @thread = Thread . new { @subject . run }
172- sleep ( 0.2 )
173- @subject . timeout_interval . should == 3
145+ subject . execution_interval . should == 3
146+ subject . kill
147+ end
148+
149+ specify '#execution_interval is writeable' do
150+
151+ latch = CountDownLatch . new ( 1 )
152+ subject = TimerTask . new ( timeout_interval : 1 , execution_interval : 0.1 ) do | task |
153+ task . timeout_interval = 3
154+ latch . count_down
174155 end
156+
157+ subject . timeout_interval . should == 1
158+ subject . timeout_interval = 2
159+ subject . timeout_interval . should == 2
160+
161+ subject . execute
162+ latch . wait ( 0.2 )
163+
164+ subject . timeout_interval . should == 3
165+ subject . kill
175166 end
176167 end
177168
178169 context 'execution' do
179170
180171 it 'runs the block immediately when the :run_now option is true' do
181- @expected = false
182- @ subject = TimerTask . run! ( execution : 500 , now : true ) { @expected = true }
183- sleep ( 0.1 )
184- @expected . should be_true
172+ latch = CountDownLatch . new ( 1 )
173+ subject = TimerTask . execute ( execution : 500 , now : true ) { latch . count_down }
174+ latch . wait ( 0.1 ) . should be_true
175+ subject . kill
185176 end
186177
187178 it 'waits for :execution_interval seconds when the :run_now option is false' do
188- @expected = false
189- @ subject = TimerTask . run! ( execution : 0.5 , now : false ) { @expected = true }
190- @expected . should be_false
191- sleep ( 1 )
192- @expected . should be_true
179+ latch = CountDownLatch . new ( 1 )
180+ subject = TimerTask . execute ( execution : 0.1 , now : false ) { latch . count_down }
181+ latch . count . should eq 1
182+ latch . wait ( 0.2 ) . should be_true
183+ subject . kill
193184 end
194185
195186 it 'waits for :execution_interval seconds when the :run_now option is not given' do
196- @expected = false
197- @subject = TimerTask . run! ( execution : 0.5 ) { @expected = true }
198- @expected . should be_false
199- sleep ( 1 )
200- @expected . should be_true
201- end
202-
203- it 'yields to the execution block' do
204- @expected = false
205- @subject = TimerTask . run! ( execution : 1 ) { @expected = true }
206- sleep ( 2 )
207- @expected . should be_true
187+ latch = CountDownLatch . new ( 1 )
188+ subject = TimerTask . execute ( execution : 0.1 , now : false ) { latch . count_down }
189+ latch . count . should eq 1
190+ latch . wait ( 0.2 ) . should be_true
191+ subject . kill
208192 end
209193
210194 it 'passes a "self" reference to the block as the sole argument' do
211- @expected = nil
212- @subject = TimerTask . new ( execution_interval : 1 , run_now : true ) do |task |
213- @expected = task
195+ expected = nil
196+ latch = CountDownLatch . new ( 1 )
197+ subject = TimerTask . new ( execution_interval : 1 , run_now : true ) do |task |
198+ expected = task
199+ latch . sount_down
214200 end
215- @thread = Thread . new { @subject . run }
216- sleep ( 0.2 )
217- @expected . should eq @subject
201+ subject . execute
202+ latch . wait ( 0.2 )
203+ expected . should eq subject
204+ subject . kill
218205 end
219206 end
220207
@@ -225,42 +212,45 @@ def trigger_observable(observable)
225212 attr_reader :time
226213 attr_reader :value
227214 attr_reader :ex
215+ attr_reader :latch
216+ define_method ( :initialize ) { @latch = CountDownLatch . new ( 1 ) }
228217 define_method ( :update ) do |time , value , ex |
229218 @time = time
230219 @value = value
231220 @ex = ex
221+ @latch . count_down
232222 end
233223 end . new
234224 end
235225
236226 it 'notifies all observers on success' do
237- task = TimerTask . new ( run_now : true ) { sleep ( 0.1 ) ; 42 }
238- task . add_observer ( observer )
239- Thread . new { task . run }
240- sleep ( 1 )
227+ subject = TimerTask . new ( execution : 0.1 ) { 42 }
228+ subject . add_observer ( observer )
229+ subject . execute
230+ observer . latch . wait ( 1 )
241231 observer . value . should == 42
242232 observer . ex . should be_nil
243- task . kill
233+ subject . kill
244234 end
245235
246236 it 'notifies all observers on timeout' do
247- task = TimerTask . new ( run_now : true , timeout : 1 ) { sleep }
248- task . add_observer ( observer )
249- Thread . new { task . run }
250- sleep ( 2 )
237+ subject = TimerTask . new ( execution : 0.1 , timeout : 0. 1) { sleep }
238+ subject . add_observer ( observer )
239+ subject . execute
240+ observer . latch . wait ( 1 )
251241 observer . value . should be_nil
252242 observer . ex . should be_a ( Concurrent ::TimeoutError )
253- task . kill
243+ subject . kill
254244 end
255245
256246 it 'notifies all observers on error' do
257- task = TimerTask . new ( run_now : true ) { sleep ( 0.1 ) ; raise ArgumentError }
258- task . add_observer ( observer )
259- Thread . new { task . run }
260- sleep ( 1 )
247+ subject = TimerTask . new ( execution : 0.1 ) { raise ArgumentError }
248+ subject . add_observer ( observer )
249+ subject . execute
250+ observer . latch . wait ( 1 )
261251 observer . value . should be_nil
262252 observer . ex . should be_a ( ArgumentError )
263- task . kill
253+ subject . kill
264254 end
265255 end
266256 end
0 commit comments