exceptional_synchrony 1.0.1 → 1.1.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,4 +1,5 @@
1
1
  require_relative '../test_helper'
2
+ require 'pry'
2
3
 
3
4
  describe ExceptionalSynchrony::CallbackExceptions do
4
5
  describe "ensure_callback" do
@@ -60,14 +61,14 @@ describe ExceptionalSynchrony::CallbackExceptions do
60
61
  deferrable = EM::DefaultDeferrable.new
61
62
  deferrable.succeed(12)
62
63
  result = ExceptionalSynchrony::CallbackExceptions.map_deferred_result(deferrable)
63
- result.must_equal 12
64
+ expect(result).must_equal(12)
64
65
  end
65
66
 
66
67
  it "should map success values to an array" do
67
68
  deferrable = EM::DefaultDeferrable.new
68
69
  deferrable.succeed(12, 13, 14)
69
70
  result = ExceptionalSynchrony::CallbackExceptions.map_deferred_result(deferrable)
70
- result.must_equal [12, 13, 14]
71
+ expect(result).must_equal([12, 13, 14])
71
72
  end
72
73
 
73
74
  it "should map success exception values to raise" do
@@ -77,7 +78,7 @@ describe ExceptionalSynchrony::CallbackExceptions do
77
78
  result = assert_raises(ArgumentError) do
78
79
  ExceptionalSynchrony::CallbackExceptions.map_deferred_result(deferrable)
79
80
  end
80
- result.must_equal exception
81
+ expect(result).must_equal(exception)
81
82
  end
82
83
  end
83
84
 
@@ -87,8 +88,18 @@ describe ExceptionalSynchrony::CallbackExceptions do
87
88
  deferrable.fail(first: "a", last: "b")
88
89
  result = assert_raises(ExceptionalSynchrony::CallbackExceptions::Failure) do
89
90
  ExceptionalSynchrony::CallbackExceptions.map_deferred_result(deferrable)
90
- end
91
- result.message.must_equal "{:first=>\"a\", :last=>\"b\"}"
91
+ end.message
92
+ expect(result).must_equal("RESULT = {:first=>\"a\", :last=>\"b\"}")
93
+ end
94
+
95
+ it "should truncate long failures" do
96
+ deferrable = EM::DefaultDeferrable.new
97
+ deferrable.fail('a'*75 + 'b'*75)
98
+ result = assert_raises(ExceptionalSynchrony::CallbackExceptions::Failure) do
99
+ ExceptionalSynchrony::CallbackExceptions.map_deferred_result(deferrable)
100
+ end.message
101
+ expected_message = "RESULT = \"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabbbbbbbbbbbbbbbb...TRUNC"
102
+ expect(result).must_equal(expected_message)
92
103
  end
93
104
 
94
105
  it "should map failure exceptions to raise" do
@@ -97,9 +108,9 @@ describe ExceptionalSynchrony::CallbackExceptions do
97
108
  deferrable.fail(exception)
98
109
  result = assert_raises(ExceptionalSynchrony::CallbackExceptions::Failure) do
99
110
  ExceptionalSynchrony::CallbackExceptions.map_deferred_result(deferrable)
100
- end
101
- result.message.must_match /ArgumentError/
102
- result.message.must_match /Wrong argument!/
111
+ end.message
112
+ expect(result).must_match(/ArgumentError/)
113
+ expect(result).must_match(/Wrong argument!/)
103
114
  end
104
115
 
105
116
  it "should map timeout failure to raise TimeoutError" do
@@ -114,6 +125,47 @@ describe ExceptionalSynchrony::CallbackExceptions do
114
125
  ExceptionalSynchrony::CallbackExceptions.map_deferred_result(deferrable)
115
126
  end
116
127
  end
128
+
129
+ it "should map Errno::ETIMEDOUT to TimeoutError" do
130
+ deferrable = EM::DefaultDeferrable.new
131
+
132
+ def deferrable.error
133
+ Errno::ETIMEDOUT
134
+ end
135
+
136
+ deferrable.fail(deferrable)
137
+ assert_raises(Timeout::Error) do
138
+ ExceptionalSynchrony::CallbackExceptions.map_deferred_result(deferrable)
139
+ end
140
+ end
141
+
142
+ it "should map other SystemCallError exceptions to Failures with the error in the message" do
143
+ deferrable = EM::DefaultDeferrable.new
144
+
145
+ def deferrable.error
146
+ Errno::ECONNREFUSED
147
+ end
148
+
149
+ deferrable.fail(deferrable)
150
+ result = assert_raises(ExceptionalSynchrony::CallbackExceptions::Failure) do
151
+ ExceptionalSynchrony::CallbackExceptions.map_deferred_result(deferrable)
152
+ end
153
+ expect(result.message).must_match(/\AERROR = Errno::ECONNREFUSED; RESULT = #<EventMachine::DefaultDeferrable/)
154
+ end
155
+
156
+ it "should map any other errors to Failure with the error in the message" do
157
+ deferrable = EM::DefaultDeferrable.new
158
+
159
+ def deferrable.error
160
+ ArgumentError.new("Some errror")
161
+ end
162
+
163
+ deferrable.fail(deferrable)
164
+ result = assert_raises(ExceptionalSynchrony::CallbackExceptions::Failure) do
165
+ ExceptionalSynchrony::CallbackExceptions.map_deferred_result(deferrable)
166
+ end
167
+ expect(result.message).must_match(/\AERROR = #<ArgumentError: Some errror>; RESULT = #<EventMachine::DefaultDeferrable/)
168
+ end
117
169
  end
118
170
 
119
171
  describe "no status" do
@@ -122,29 +174,29 @@ describe ExceptionalSynchrony::CallbackExceptions do
122
174
  result = assert_raises(ArgumentError) do
123
175
  ExceptionalSynchrony::CallbackExceptions.map_deferred_result(deferrable)
124
176
  end
125
- result.message.must_match /no deferred status set yet/i
177
+ expect(result.message).must_match(/no deferred status set yet/i)
126
178
  end
127
179
  end
128
180
  end
129
181
 
130
182
  describe "return_exception" do
131
183
  it "should return the value if no exception" do
132
- ExceptionalSynchrony::CallbackExceptions.return_exception do
184
+ expect(ExceptionalSynchrony::CallbackExceptions.return_exception do
133
185
  14
134
- end.must_equal 14
186
+ end).must_equal(14)
135
187
  end
136
188
 
137
189
  it "should yield its args" do
138
- ExceptionalSynchrony::CallbackExceptions.return_exception(0, 1) do |a, b|
190
+ expect(ExceptionalSynchrony::CallbackExceptions.return_exception(0, 1) do |a, b|
139
191
  assert_equal [0, 1], [a, b]
140
192
  14
141
- end.must_equal 14
193
+ end).must_equal(14)
142
194
  end
143
195
 
144
196
  it "should rescue any exception that was raised and return it" do
145
- ExceptionalSynchrony::CallbackExceptions.return_exception do
197
+ expect(ExceptionalSynchrony::CallbackExceptions.return_exception do
146
198
  raise ArgumentError, "An argument error occurred"
147
- end.inspect.must_equal ArgumentError.new("An argument error occurred").inspect
199
+ end.inspect).must_equal(ArgumentError.new("An argument error occurred").inspect)
148
200
  end
149
201
  end
150
202
  end
@@ -39,7 +39,45 @@ describe ExceptionalSynchrony::EventMachineProxy do
39
39
  ServerClass = Class.new
40
40
  mock(EventMachine).connect(ServerClass, 8080, :handler, :extra_arg).yields(:called)
41
41
  @em.connect(ServerClass, 8080, :handler, :extra_arg, &@block)
42
- @yielded_value.must_equal :called
42
+ expect(@yielded_value).must_equal(:called)
43
+ end
44
+
45
+ describe "#yield_to_reactor" do
46
+ it "should give control to other threads when the reactor is running" do
47
+ mock(@em).reactor_running? { true }
48
+ mock(EventMachine::Synchrony).sleep(0)
49
+ @em.yield_to_reactor
50
+ end
51
+
52
+ it "should be a no-op if the reactor is not running" do
53
+ mock(@em).reactor_running? { false }
54
+ stub(EventMachine::Synchrony).sleep(0) { raise "Should not sleep!" }
55
+ @em.yield_to_reactor
56
+ end
57
+ end
58
+
59
+ describe "#defer" do
60
+ it "should output its block's output when it doesn't raise an error" do
61
+ ExceptionHandling.logger = Logger.new(STDERR)
62
+
63
+ @em.run do
64
+ assert_equal 12, @em.defer("#defer success") { 12 }
65
+ @em.stop
66
+ end
67
+ end
68
+
69
+ it "should raise an error when its block raises an error" do
70
+ ExceptionHandling.logger = Logger.new(STDERR)
71
+
72
+ @em.run do
73
+ ex = assert_raises(ArgumentError) do
74
+ @em.defer("#defer raising an error") { raise ArgumentError, "!!!" }
75
+ end
76
+
77
+ assert_equal "!!!", ex.message
78
+ @em.stop
79
+ end
80
+ end
43
81
  end
44
82
 
45
83
  EXCEPTION = ArgumentError.new('in block')
@@ -50,19 +88,19 @@ describe ExceptionalSynchrony::EventMachineProxy do
50
88
  end
51
89
 
52
90
  it "add_timer" do
53
- mock(ExceptionHandling).log_error(EXCEPTION, "add_timer")
91
+ mock(ExceptionHandling).log_error(EXCEPTION, "add_timer", {})
54
92
  mock(EventMachine::Synchrony).add_timer(10) { |duration, *args| args.first.call }
55
93
  @em.add_timer(10) { raise EXCEPTION }
56
94
  end
57
95
 
58
96
  it "add_periodic_timer" do
59
- mock(ExceptionHandling).log_error(EXCEPTION, "add_periodic_timer")
97
+ mock(ExceptionHandling).log_error(EXCEPTION, "add_periodic_timer", {})
60
98
  mock(EventMachine::Synchrony).add_periodic_timer(10) { |duration, *args| args.first.call }
61
99
  @em.add_periodic_timer(10) { raise EXCEPTION }
62
100
  end
63
101
 
64
102
  it "next_tick" do
65
- mock(ExceptionHandling).log_error(EXCEPTION, "next_tick")
103
+ mock(ExceptionHandling).log_error(EXCEPTION, "next_tick", {})
66
104
  mock(EventMachine::Synchrony).next_tick { |*args| args.first.call }
67
105
  @em.next_tick { raise EXCEPTION }
68
106
  end
@@ -88,7 +126,7 @@ describe ExceptionalSynchrony::EventMachineProxy do
88
126
  proxy = ExceptionalSynchrony::EventMachineProxy.new(proxy_mock, nil)
89
127
 
90
128
  proxy.run(&@block)
91
- @yielded_value.must_equal synchrony ? :synchrony : :run
129
+ expect(@yielded_value).must_equal(synchrony ? :synchrony : :run)
92
130
  end
93
131
  end
94
132
  end
@@ -4,13 +4,13 @@ describe ExceptionalSynchrony::LimitedWorkQueue do
4
4
  end
5
5
 
6
6
  it "should raise an exception if created with a limit < 1" do
7
- assert_raises(ArgumentError) do
7
+ expect(assert_raises(ArgumentError) do
8
8
  ExceptionalSynchrony::LimitedWorkQueue.new(@em, 0)
9
- end.message.must_match /must be positive/
9
+ end.message).must_match(/must be positive/)
10
10
 
11
- assert_raises(ArgumentError) do
11
+ expect(assert_raises(ArgumentError) do
12
12
  ExceptionalSynchrony::LimitedWorkQueue.new(@em, -2)
13
- end.message.must_match /must be positive/
13
+ end.message).must_match(/must be positive/)
14
14
  end
15
15
 
16
16
  describe "when created" do
@@ -21,9 +21,9 @@ describe ExceptionalSynchrony::LimitedWorkQueue do
21
21
  it "should run non-blocking jobs immediately" do
22
22
  c = 0
23
23
  ExceptionalSynchrony::EMP.run_and_stop do
24
- @queue.add { c+=1 }
25
- @queue.add { c+=1 }
26
- @queue.add { c+=1 }
24
+ @queue.add! { c+=1 }
25
+ @queue.add! { c+=1 }
26
+ @queue.add! { c+=1 }
27
27
  end
28
28
  assert_equal 3, c
29
29
  end
@@ -46,9 +46,9 @@ describe ExceptionalSynchrony::LimitedWorkQueue do
46
46
  it "should allow objects to be queued instead of Procs" do
47
47
  c = 0
48
48
  ExceptionalSynchrony::EMP.run_and_stop do
49
- @queue.add(LWQTestProc.new { c+=1 })
50
- @queue.add(LWQTestProc.new { c+=1 })
51
- @queue.add(LWQTestProc.new { c+=1 })
49
+ @queue.add!(LWQTestProc.new { c+=1 })
50
+ @queue.add!(LWQTestProc.new { c+=1 })
51
+ @queue.add!(LWQTestProc.new { c+=1 })
52
52
  end
53
53
  assert_equal 3, c
54
54
  end
@@ -71,17 +71,17 @@ describe ExceptionalSynchrony::LimitedWorkQueue do
71
71
  end
72
72
 
73
73
  ExceptionalSynchrony::EMP.run_and_stop do
74
- @queue.add(job_proc)
74
+ @queue.add!(job_proc)
75
75
  end
76
76
  end
77
77
 
78
78
  it "should allow objects to merge themselves into the queue (canceling itself)" do
79
79
  c = 0
80
80
  ExceptionalSynchrony::EMP.run_and_stop do
81
- @queue.add(LWQTestProc.new { @em.sleep(0.001); c+=1 })
82
- @queue.add(LWQTestProc.new { @em.sleep(0.001); c+=2 })
83
- @queue.add(LWQTestProcWithMergeDrop.new(-> { c+=4 }) { @em.sleep(0.001); c+=8 })
84
- @queue.add(LWQTestProcWithMergeDrop.new(-> { c+=16 }) { @em.sleep(0.001); c+=32 }) # will get merged (by canceling self)
81
+ @queue.add!(LWQTestProc.new { @em.sleep(0.001); c+=1 })
82
+ @queue.add!(LWQTestProc.new { @em.sleep(0.001); c+=2 })
83
+ @queue.add!(LWQTestProcWithMergeDrop.new(-> { c+=4 }) { @em.sleep(0.001); c+=8 })
84
+ @queue.add!(LWQTestProcWithMergeDrop.new(-> { c+=16 }) { @em.sleep(0.001); c+=32 }) # will get merged (by canceling self)
85
85
  @em.sleep(0.050)
86
86
  end
87
87
  assert_equal 1+2+8+16, c
@@ -99,15 +99,35 @@ describe ExceptionalSynchrony::LimitedWorkQueue do
99
99
  it "should allow objects to merge themselves into the queue (canceling/replacing earlier)" do
100
100
  c = 0
101
101
  ExceptionalSynchrony::EMP.run_and_stop do
102
- @queue.add(LWQTestProc.new { @em.sleep(0.001); c+=1 })
103
- @queue.add(LWQTestProc.new { @em.sleep(0.001); c+=2 })
104
- @queue.add(LWQTestProcWithMergeReplace.new(-> { c+=4 }) { @em.sleep(0.001); c+=8 })
105
- @queue.add(LWQTestProcWithMergeReplace.new(-> { c+=16 }) { @em.sleep(0.001); c+=32 }) # will get merged with above (replacing above)
102
+ @queue.add!(LWQTestProc.new { @em.sleep(0.001); c+=1 })
103
+ @queue.add!(LWQTestProc.new { @em.sleep(0.001); c+=2 })
104
+ @queue.add!(LWQTestProcWithMergeReplace.new(-> { c+=4 }) { @em.sleep(0.001); c+=8 })
105
+ @queue.add!(LWQTestProcWithMergeReplace.new(-> { c+=16 }) { @em.sleep(0.001); c+=32 }) # will get merged with above (replacing above)
106
106
  @em.sleep(0.050)
107
107
  end
108
108
  assert_equal 1+2+4+32, c
109
109
  end
110
110
 
111
+ it "should ensure that the queue continues to function even when an exception is raised" do
112
+ mock(ExceptionHandling).log_error(anything, /LimitedWorkQueue encountered an exception/).twice
113
+ ExceptionalSynchrony::EMP.run_and_stop do
114
+ c = 0
115
+ last_start = nil; end_0 = nil; end_1 = nil
116
+ @queue.add! { c += 1; @em.sleep(0.001); end_0 = c+=1; raise "Boom" }
117
+ @queue.add! { c += 1; @em.sleep(0.001); end_1 = c+=1; raise "Boom" }
118
+ @queue.add! { last_start = c+= 1; @em.sleep(0.001); c+=1 }
119
+
120
+ 3.times do
121
+ @em.sleep(0.030)
122
+ break if c == 6
123
+ end
124
+
125
+ assert last_start && last_start > 3, "Unexpected value for last_start: #{last_start.inspect}"
126
+ assert [end_0, end_1].any? {|e| last_start > e }
127
+ assert_equal 6, c
128
+ end
129
+ end
130
+
111
131
  it "should run 2 blocking tasks in parallel and only start 3rd when one of the first 2 finishes" do
112
132
  stub_request(:get, "http://www.google.com/").
113
133
  to_return(:status => 200, :body => "1", :headers => {})
@@ -121,12 +141,12 @@ describe ExceptionalSynchrony::LimitedWorkQueue do
121
141
  ExceptionalSynchrony::EMP.run_and_stop do
122
142
  c = -1
123
143
  started2 = nil; ended0 = nil; ended1 = nil
124
- @queue.add { c+=1; @em.sleep(0.001); ExceptionalSynchrony::EMP.connection.new("http://www.google.com").get; ended0 = c+=1 }
125
- @queue.add { c+=1; @em.sleep(0.001); ExceptionalSynchrony::EMP.connection.new("http://www.cnn.com").get; ended1 = c+=1 }
126
- @queue.add { started2 = c+=1; ExceptionalSynchrony::EMP.connection.new("http://news.ycombinator.com").get; c+=1 }
144
+ @queue.add! { c+=1; @em.sleep(0.001); ExceptionalSynchrony::EMP.connection.new("http://www.google.com").get; ended0 = c+=1 }
145
+ @queue.add! { c+=1; @em.sleep(0.001); ExceptionalSynchrony::EMP.connection.new("http://www.cnn.com").get; ended1 = c+=1 }
146
+ @queue.add! { started2 = c+=1; ExceptionalSynchrony::EMP.connection.new("http://news.ycombinator.com").get; c+=1 }
127
147
 
128
148
  3.times do
129
- @em.sleep(0.005)
149
+ @em.sleep(0.030)
130
150
  break if c == 5
131
151
  end
132
152
 
@@ -135,5 +155,183 @@ describe ExceptionalSynchrony::LimitedWorkQueue do
135
155
  assert started2 > ended0 || started2 > ended1, [ended0, ended1, started2].inspect
136
156
  end
137
157
  end
158
+
159
+ describe '#paused?' do
160
+ it 'should return false when @paused is false' do
161
+ @queue.instance_variable_set(:@paused, false)
162
+ assert_equal false, @queue.paused?
163
+ end
164
+
165
+ it 'should return true when @paused is true' do
166
+ @queue.instance_variable_set(:@paused, false)
167
+ assert_equal false, @queue.paused?
168
+ end
169
+ end
170
+
171
+ describe '#pause!' do
172
+ it 'should set @paused to true if @paused is currently false' do
173
+ assert_equal false, @queue.instance_variable_get('@paused')
174
+ @queue.pause!
175
+ assert_equal true, @queue.instance_variable_get('@paused')
176
+ end
177
+
178
+ it 'should set @paused to true if @paused is currently true' do
179
+ @queue.instance_variable_set(:@paused, true)
180
+ assert_equal true, @queue.instance_variable_get('@paused')
181
+ @queue.pause!
182
+ assert_equal true, @queue.instance_variable_get('@paused')
183
+ end
184
+ end
185
+
186
+ describe '#unpause!' do
187
+ it 'should set @paused to false if @paused is currently false' do
188
+ assert_equal false, @queue.instance_variable_get('@paused')
189
+ @queue.unpause!
190
+ assert_equal false, @queue.instance_variable_get('@paused')
191
+ end
192
+
193
+ it 'should set @paused to false if @paused is currently true' do
194
+ @queue.instance_variable_set(:@paused, true)
195
+ assert_equal true, @queue.instance_variable_get('@paused')
196
+ @queue.unpause!
197
+ assert_equal false, @queue.instance_variable_get('@paused')
198
+ end
199
+ end
200
+
201
+ describe '#add!' do
202
+ it 'should run jobs added to the queue when paused? is false' do
203
+ assert_equal false, @queue.paused? # queue#paused is false be default
204
+ counter = 0
205
+ ExceptionalSynchrony::EMP.run_and_stop do
206
+ 3.times { @queue.add! { counter+=1 } }
207
+ end
208
+
209
+ assert_equal 0, @queue.instance_variable_get("@job_procs").size
210
+ assert_equal 3, counter
211
+ end
212
+
213
+ it 'should not run jobs added to the queue when paused? is true' do
214
+ @queue.pause!
215
+ assert_equal true, @queue.paused?
216
+ counter = 0
217
+ ExceptionalSynchrony::EMP.run_and_stop do
218
+ 3.times { @queue.add! { counter+=1 } }
219
+ end
220
+
221
+ mock(@queue).work!.never
222
+ assert_equal 3, @queue.instance_variable_get("@job_procs").size
223
+ assert_equal 0, counter
224
+ end
225
+
226
+ it 'should have a method alias to #add for callers using the previous #add method' do
227
+ assert_equal @queue.method(:add!), @queue.method(:add)
228
+ end
229
+ end
230
+
231
+ describe '#items' do
232
+ it 'should return job_procs array' do
233
+ assert_equal 0, @queue.items.size
234
+ job_procs = Array.new(3) { Proc.new { puts 'Hello World' } }
235
+ @queue.instance_variable_set(:@job_procs, job_procs)
236
+ assert_equal 3, @queue.items.size
237
+ end
238
+ end
239
+
240
+ describe '#work!' do
241
+ before do
242
+ @queue = ExceptionalSynchrony::LimitedWorkQueue.new(@em, 2)
243
+ end
244
+
245
+ it 'should run items in queue' do
246
+ counter = 0
247
+ job_procs = Array.new(3) { Proc.new { counter += 1} }
248
+ @queue.instance_variable_set(:@job_procs, job_procs)
249
+ mock.proxy(Fiber).new.with_any_args.times(3)
250
+ @queue.work!
251
+
252
+ assert_equal 0, @queue.instance_variable_get("@job_procs").size
253
+ assert_equal 3, counter
254
+ end
255
+
256
+ it 'should run items already in queue, even if queue is paused' do
257
+ @queue.pause!
258
+ counter = 4
259
+ job_procs = Array.new(3) { Proc.new { counter += 1} }
260
+ @queue.instance_variable_set(:@job_procs, job_procs)
261
+ assert_equal 3, @queue.instance_variable_get("@job_procs").size
262
+ mock.proxy(Fiber).new.with_any_args.times(3)
263
+
264
+ @queue.work!
265
+
266
+ assert_equal 7, counter
267
+ assert_equal 0, @queue.instance_variable_get("@job_procs").size
268
+ end
269
+
270
+ it 'should not run if queue_empty' do
271
+ stub(@queue).queue_empty? { true }
272
+ counter = 0
273
+ job_procs = Array.new(3) { Proc.new { counter += 1} }
274
+ @queue.instance_variable_set(:@job_procs, job_procs)
275
+ assert_equal 3, @queue.instance_variable_get("@job_procs").size
276
+ mock(Fiber).new.never
277
+
278
+ @queue.work!
279
+ assert_equal 0, counter
280
+ end
281
+
282
+ it 'should not run if workers are full' do
283
+ stub(@queue).workers_full? { true }
284
+ counter = 0
285
+ job_procs = Array.new(3) { Proc.new { counter += 1} }
286
+ @queue.instance_variable_set(:@job_procs, job_procs)
287
+
288
+ assert_equal 3, @queue.instance_variable_get("@job_procs").size
289
+ mock(Fiber).new.never
290
+
291
+ @queue.work!
292
+ assert_equal 0, counter
293
+ end
294
+ end
295
+
296
+ describe '#workers_full?' do
297
+ before do
298
+ @queue = ExceptionalSynchrony::LimitedWorkQueue.new(@em, 2) # limit the number of active workers to 2 max
299
+ end
300
+
301
+ it 'should return true if the number of current workers is greater than the queue\'s defined worker limit' do
302
+ @queue.instance_variable_set(:@worker_count, 20)
303
+ @queue.instance_variable_set(:@limit, 10)
304
+ assert_equal true, @queue.workers_full?
305
+ end
306
+
307
+ it 'should return true if the current number of workers is equal to the queue\'s defined worker limit' do
308
+ @queue.instance_variable_set(:@worker_count, 10)
309
+ @queue.instance_variable_set(:@limit, 10)
310
+ assert_equal true, @queue.workers_full?
311
+ end
312
+
313
+ it 'should return false if the current number of workers is less than the queue\'s defined worker limit' do
314
+ @queue.instance_variable_set(:@worker_count, 5)
315
+ @queue.instance_variable_set(:@limit, 10)
316
+ assert_equal false, @queue.workers_full?
317
+ end
318
+ end
319
+
320
+ describe '#queue_empty?' do
321
+ before do
322
+ @queue = ExceptionalSynchrony::LimitedWorkQueue.new(@em, 2)
323
+ end
324
+
325
+ it 'should return true if queue is empty' do
326
+ @queue.instance_variable_set(:@job_procs, [])
327
+ assert_equal true, @queue.queue_empty?
328
+ end
329
+
330
+ it 'should return false if queue is not empty' do
331
+ @queue.instance_variable_set(:@job_procs, [Proc.new { 'hello'}])
332
+ assert_equal false, @queue.queue_empty?
333
+ end
334
+ end
335
+
138
336
  end
139
337
  end
@@ -56,15 +56,15 @@ describe ExceptionalSynchrony::ParallelSync do
56
56
  stub_request(:get, "http://news.ycombinator.com/").
57
57
  to_return(:status => 200, :body => "3", :headers => {})
58
58
 
59
- assert_raises(NotImplementedError) do
59
+ expect(assert_raises(NotImplementedError) do
60
60
  ExceptionalSynchrony::EMP.run_and_stop do
61
- responses = ExceptionalSynchrony::ParallelSync.parallel(@em) do |parallel|
61
+ ExceptionalSynchrony::ParallelSync.parallel(@em) do |parallel|
62
62
  parallel.add { ExceptionalSynchrony::EMP.connection.new("http://www.google.com").get; raise NotImplementedError, "Not implemented!" }
63
63
  parallel.add { ExceptionalSynchrony::EMP.connection.new("http://www.cnn.com").get }
64
64
  parallel.add { ExceptionalSynchrony::EMP.connection.new("http://news.ycombinator.com").get }
65
65
  end
66
66
  end
67
- end.to_s.must_match(/Not implemented!/)
67
+ end.to_s).must_match(/Not implemented!/)
68
68
  end
69
69
 
70
70
  it "should pass several exceptions through and raise them on the other side" do
@@ -77,15 +77,15 @@ describe ExceptionalSynchrony::ParallelSync do
77
77
  stub_request(:get, "http://news.ycombinator.com/").
78
78
  to_return(:status => 200, :body => "3", :headers => {})
79
79
 
80
- assert_raises(NotImplementedError) do
80
+ expect(assert_raises(NotImplementedError) do
81
81
  ExceptionalSynchrony::EMP.run_and_stop do
82
- responses = ExceptionalSynchrony::ParallelSync.parallel(@em) do |parallel|
82
+ ExceptionalSynchrony::ParallelSync.parallel(@em) do |parallel|
83
83
  parallel.add { ExceptionalSynchrony::EMP.connection.new("http://www.google.com").get; raise NotImplementedError, "Not implemented!" }
84
84
  parallel.add { ExceptionalSynchrony::EMP.connection.new("http://www.cnn.com").get; raise LoadError, "A load error occurred" }
85
85
  parallel.add { ExceptionalSynchrony::EMP.connection.new("http://news.ycombinator.com").get; raise IndexError, "An index error occurred" }
86
86
  end
87
87
  end
88
- end.message.must_match(/Not implemented!.*LoadError: A load error occurred.*IndexError: An index error occurred/m)
88
+ end.message).must_match(/Not implemented!.*LoadError: A load error occurred.*IndexError: An index error occurred/m)
89
89
  end
90
90
 
91
91
  class TestProc