exceptional_synchrony 1.0.1 → 1.1.1

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.
@@ -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