connection_pool 2.1.3 → 2.2.4

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,3 +1,3 @@
1
1
  class ConnectionPool
2
- VERSION = "2.1.3"
2
+ VERSION = "2.2.4"
3
3
  end
@@ -0,0 +1,51 @@
1
+ class ConnectionPool
2
+ class Wrapper < ::BasicObject
3
+ METHODS = [:with, :pool_shutdown, :wrapped_pool]
4
+
5
+ def initialize(options = {}, &block)
6
+ @pool = options.fetch(:pool) { ::ConnectionPool.new(options, &block) }
7
+ end
8
+
9
+ def wrapped_pool
10
+ @pool
11
+ end
12
+
13
+ def with(&block)
14
+ @pool.with(&block)
15
+ end
16
+
17
+ def pool_shutdown(&block)
18
+ @pool.shutdown(&block)
19
+ end
20
+
21
+ def pool_size
22
+ @pool.size
23
+ end
24
+
25
+ def pool_available
26
+ @pool.available
27
+ end
28
+
29
+ def respond_to?(id, *args)
30
+ METHODS.include?(id) || with { |c| c.respond_to?(id, *args) }
31
+ end
32
+
33
+ # rubocop:disable Style/MethodMissingSuper
34
+ # rubocop:disable Style/MissingRespondToMissing
35
+ if ::RUBY_VERSION >= "2.7.0"
36
+ def method_missing(name, *args, **kwargs, &block)
37
+ with do |connection|
38
+ connection.send(name, *args, **kwargs, &block)
39
+ end
40
+ end
41
+ else
42
+ def method_missing(name, *args, &block)
43
+ with do |connection|
44
+ connection.send(name, *args, &block)
45
+ end
46
+ end
47
+ end
48
+ # rubocop:enable Style/MethodMissingSuper
49
+ # rubocop:enable Style/MissingRespondToMissing
50
+ end
51
+ end
data/test/helper.rb CHANGED
@@ -1,8 +1,8 @@
1
- gem 'minitest'
1
+ gem "minitest"
2
2
 
3
- require 'minitest/pride'
4
- require 'minitest/autorun'
3
+ require "minitest/pride"
4
+ require "minitest/autorun"
5
5
 
6
6
  $VERBOSE = 1
7
7
 
8
- require_relative '../lib/connection_pool'
8
+ require_relative "../lib/connection_pool"
@@ -1,15 +1,16 @@
1
- require_relative 'helper'
1
+ require_relative "helper"
2
2
 
3
3
  class TestConnectionPool < Minitest::Test
4
-
5
4
  class NetworkConnection
5
+ SLEEP_TIME = 0.1
6
+
6
7
  def initialize
7
8
  @x = 0
8
9
  end
9
10
 
10
- def do_something
11
- @x += 1
12
- sleep 0.05
11
+ def do_something(*_args, increment: 1)
12
+ @x += increment
13
+ sleep SLEEP_TIME
13
14
  @x
14
15
  end
15
16
 
@@ -19,7 +20,7 @@ class TestConnectionPool < Minitest::Test
19
20
 
20
21
  def do_something_with_block
21
22
  @x += yield
22
- sleep 0.05
23
+ sleep SLEEP_TIME
23
24
  @x
24
25
  end
25
26
 
@@ -41,12 +42,12 @@ class TestConnectionPool < Minitest::Test
41
42
  end
42
43
 
43
44
  def use_pool(pool, size)
44
- Array.new(size) do
45
+ Array.new(size) {
45
46
  Thread.new do
46
- pool.with do sleep end
47
+ pool.with { sleep }
47
48
  end
48
- end.each do |thread|
49
- Thread.pass until thread.status == 'sleep'
49
+ }.each do |thread|
50
+ Thread.pass until thread.status == "sleep"
50
51
  end
51
52
  end
52
53
 
@@ -58,33 +59,38 @@ class TestConnectionPool < Minitest::Test
58
59
  end
59
60
 
60
61
  def test_basic_multithreaded_usage
61
- pool = ConnectionPool.new(:size => 5) { NetworkConnection.new }
62
+ pool_size = 5
63
+ pool = ConnectionPool.new(size: pool_size) { NetworkConnection.new }
64
+
65
+ start = Time.new
66
+
67
+ generations = 3
62
68
 
63
- threads = Array.new(15) do
69
+ result = Array.new(pool_size * generations) {
64
70
  Thread.new do
65
71
  pool.with do |net|
66
72
  net.do_something
67
73
  end
68
74
  end
69
- end
75
+ }.map(&:value)
76
+
77
+ finish = Time.new
78
+
79
+ assert_equal((1..generations).cycle(pool_size).sort, result.sort)
70
80
 
71
- a = Time.now
72
- result = threads.map(&:value)
73
- b = Time.now
74
- assert_operator((b - a), :>, 0.125)
75
- assert_equal([1,2,3].cycle(5).sort, result.sort)
81
+ assert_operator(finish - start, :>, generations * NetworkConnection::SLEEP_TIME)
76
82
  end
77
83
 
78
84
  def test_timeout
79
- pool = ConnectionPool.new(:timeout => 0, :size => 1) { NetworkConnection.new }
80
- thread = Thread.new do
85
+ pool = ConnectionPool.new(timeout: 0, size: 1) { NetworkConnection.new }
86
+ thread = Thread.new {
81
87
  pool.with do |net|
82
88
  net.do_something
83
89
  sleep 0.01
84
90
  end
85
- end
91
+ }
86
92
 
87
- Thread.pass while thread.status == 'run'
93
+ Thread.pass while thread.status == "run"
88
94
 
89
95
  assert_raises Timeout::Error do
90
96
  pool.with { |net| net.do_something }
@@ -98,79 +104,132 @@ class TestConnectionPool < Minitest::Test
98
104
  end
99
105
 
100
106
  def test_with
101
- pool = ConnectionPool.new(:timeout => 0, :size => 1) { Object.new }
107
+ pool = ConnectionPool.new(timeout: 0, size: 1) { Object.new }
102
108
 
103
109
  pool.with do
104
- assert_raises Timeout::Error do
105
- Thread.new { pool.checkout }.join
106
- end
110
+ Thread.new {
111
+ assert_raises Timeout::Error do
112
+ pool.checkout
113
+ end
114
+ }.join
107
115
  end
108
116
 
109
117
  assert Thread.new { pool.checkout }.join
110
118
  end
111
119
 
112
- def test_with_with_dangerous_timeouts
113
- case RUBY_ENGINE.to_sym
114
- when :jruby
115
- skip('JRuby GC dislikes this test')
116
- when :ruby
117
- if RUBY_VERSION == '2.0.0' && RUBY_PATCHLEVEL == 598
118
- skip("#{RUBY_VERSION}p#{RUBY_PATCHLEVEL} GC dislikes this test")
120
+ def test_then
121
+ pool = ConnectionPool.new { Object.new }
122
+
123
+ assert_equal pool.method(:then), pool.method(:with)
124
+ end
125
+
126
+ def test_with_timeout
127
+ pool = ConnectionPool.new(timeout: 0, size: 1) { Object.new }
128
+
129
+ assert_raises Timeout::Error do
130
+ Timeout.timeout(0.01) do
131
+ pool.with do |obj|
132
+ assert_equal 0, pool.available
133
+ sleep 0.015
134
+ end
119
135
  end
120
136
  end
137
+ assert_equal 1, pool.available
138
+ end
121
139
 
122
- marker_class = Class.new
123
- pool = ConnectionPool.new(:timeout => 0, :size => 1) { marker_class.new }
140
+ def test_invalid_size
141
+ assert_raises ArgumentError, TypeError do
142
+ ConnectionPool.new(timeout: 0, size: nil) { Object.new }
143
+ end
144
+ assert_raises ArgumentError, TypeError do
145
+ ConnectionPool.new(timeout: 0, size: "") { Object.new }
146
+ end
147
+ end
124
148
 
125
- # no "connections" allocated yet
126
- assert_equal [], ObjectSpace.each_object(marker_class).to_a
149
+ def test_handle_interrupt_ensures_checkin
150
+ pool = ConnectionPool.new(timeout: 0, size: 1) { Object.new }
151
+ def pool.checkout(options)
152
+ sleep 0.015
153
+ super
154
+ end
127
155
 
128
- checkin_time = 0.05
156
+ did_something = false
129
157
 
130
- assert_raises Timeout::Error do
131
- Timeout.timeout(checkin_time) do
132
- pool.with do
133
- # a "connection" has been allocated
134
- refute_equal [], ObjectSpace.each_object(marker_class).to_a
135
- sleep 2 * checkin_time
158
+ action = lambda do
159
+ Timeout.timeout(0.01) do
160
+ pool.with do |obj|
161
+ did_something = true
162
+ # Timeout::Error will be triggered by any non-trivial Ruby code
163
+ # executed here since it couldn't be raised during checkout.
164
+ # It looks like setting the local variable above does not trigger
165
+ # the Timeout check in MRI 2.2.1.
166
+ obj.tap { obj.hash }
136
167
  end
137
168
  end
138
169
  end
139
170
 
140
- GC.start
171
+ if RUBY_ENGINE == "ruby"
172
+ # These asserts rely on the Ruby implementation reaching `did_something =
173
+ # true` before the interrupt is detected by the thread. Interrupt
174
+ # detection timing is implementation-specific in practice, with JRuby,
175
+ # Rubinius, and TruffleRuby all having different interrupt timings to MRI.
176
+ # In fact they generally detect interrupts more quickly than MRI, so they
177
+ # may not reach `did_something = true` before detecting the interrupt.
178
+
179
+ assert_raises Timeout::Error, &action
180
+
181
+ assert did_something
182
+ else
183
+ action.call
184
+ end
185
+
186
+ assert_equal 1, pool.available
187
+ end
188
+
189
+ def test_explicit_return
190
+ pool = ConnectionPool.new(timeout: 0, size: 1) {
191
+ mock = Minitest::Mock.new
192
+ def mock.disconnect!
193
+ raise "should not disconnect upon explicit return"
194
+ end
195
+ mock
196
+ }
141
197
 
142
- # no dangling references to this "connection" remain
143
- assert_equal [], ObjectSpace.each_object(marker_class).to_a
198
+ pool.with do |conn|
199
+ return true
200
+ end
144
201
  end
145
202
 
146
203
  def test_with_timeout_override
147
- pool = ConnectionPool.new(:timeout => 0, :size => 1) { NetworkConnection.new }
204
+ pool = ConnectionPool.new(timeout: 0, size: 1) { NetworkConnection.new }
148
205
 
149
- t = Thread.new do
206
+ t = Thread.new {
150
207
  pool.with do |net|
151
208
  net.do_something
152
209
  sleep 0.01
153
210
  end
154
- end
211
+ }
155
212
 
156
- Thread.pass while t.status == 'run'
213
+ Thread.pass while t.status == "run"
157
214
 
158
215
  assert_raises Timeout::Error do
159
216
  pool.with { |net| net.do_something }
160
217
  end
161
218
 
162
- pool.with(:timeout => 0.1) do |conn|
219
+ pool.with(timeout: 2 * NetworkConnection::SLEEP_TIME) do |conn|
163
220
  refute_nil conn
164
221
  end
165
222
  end
166
223
 
167
224
  def test_checkin
168
- pool = ConnectionPool.new(:timeout => 0, :size => 1) { NetworkConnection.new }
225
+ pool = ConnectionPool.new(timeout: 0, size: 1) { NetworkConnection.new }
169
226
  conn = pool.checkout
170
227
 
171
- assert_raises Timeout::Error do
172
- Thread.new { pool.checkout }.join
173
- end
228
+ Thread.new {
229
+ assert_raises Timeout::Error do
230
+ pool.checkout
231
+ end
232
+ }.join
174
233
 
175
234
  pool.checkin
176
235
 
@@ -178,22 +237,19 @@ class TestConnectionPool < Minitest::Test
178
237
  end
179
238
 
180
239
  def test_returns_value
181
- pool = ConnectionPool.new(:timeout => 0, :size => 1) { Object.new }
182
- assert_equal 1, pool.with {|o| 1 }
240
+ pool = ConnectionPool.new(timeout: 0, size: 1) { Object.new }
241
+ assert_equal 1, pool.with { |o| 1 }
183
242
  end
184
243
 
185
244
  def test_checkin_never_checkout
186
- pool = ConnectionPool.new(:timeout => 0, :size => 1) { Object.new }
245
+ pool = ConnectionPool.new(timeout: 0, size: 1) { Object.new }
187
246
 
188
- e = assert_raises ConnectionPool::Error do
189
- pool.checkin
190
- end
191
-
192
- assert_equal 'no connections are checked out', e.message
247
+ e = assert_raises(ConnectionPool::Error) { pool.checkin }
248
+ assert_equal "no connections are checked out", e.message
193
249
  end
194
250
 
195
251
  def test_checkin_no_current_checkout
196
- pool = ConnectionPool.new(:timeout => 0, :size => 1) { Object.new }
252
+ pool = ConnectionPool.new(timeout: 0, size: 1) { Object.new }
197
253
 
198
254
  pool.checkout
199
255
  pool.checkin
@@ -204,18 +260,18 @@ class TestConnectionPool < Minitest::Test
204
260
  end
205
261
 
206
262
  def test_checkin_twice
207
- pool = ConnectionPool.new(:timeout => 0, :size => 1) { Object.new }
263
+ pool = ConnectionPool.new(timeout: 0, size: 1) { Object.new }
208
264
 
209
265
  pool.checkout
210
266
  pool.checkout
211
267
 
212
268
  pool.checkin
213
269
 
214
- assert_raises Timeout::Error do
215
- Thread.new do
270
+ Thread.new {
271
+ assert_raises Timeout::Error do
216
272
  pool.checkout
217
- end.join
218
- end
273
+ end
274
+ }.join
219
275
 
220
276
  pool.checkin
221
277
 
@@ -223,7 +279,7 @@ class TestConnectionPool < Minitest::Test
223
279
  end
224
280
 
225
281
  def test_checkout
226
- pool = ConnectionPool.new(:size => 1) { NetworkConnection.new }
282
+ pool = ConnectionPool.new(size: 1) { NetworkConnection.new }
227
283
 
228
284
  conn = pool.checkout
229
285
 
@@ -233,18 +289,18 @@ class TestConnectionPool < Minitest::Test
233
289
  end
234
290
 
235
291
  def test_checkout_multithread
236
- pool = ConnectionPool.new(:size => 2) { NetworkConnection.new }
292
+ pool = ConnectionPool.new(size: 2) { NetworkConnection.new }
237
293
  conn = pool.checkout
238
294
 
239
- t = Thread.new do
295
+ t = Thread.new {
240
296
  pool.checkout
241
- end
297
+ }
242
298
 
243
299
  refute_same conn, t.value
244
300
  end
245
301
 
246
302
  def test_checkout_timeout
247
- pool = ConnectionPool.new(:timeout => 0, :size => 0) { Object.new }
303
+ pool = ConnectionPool.new(timeout: 0, size: 0) { Object.new }
248
304
 
249
305
  assert_raises Timeout::Error do
250
306
  pool.checkout
@@ -252,34 +308,35 @@ class TestConnectionPool < Minitest::Test
252
308
  end
253
309
 
254
310
  def test_checkout_timeout_override
255
- pool = ConnectionPool.new(:timeout => 0, :size => 1) { NetworkConnection.new }
311
+ pool = ConnectionPool.new(timeout: 0, size: 1) { NetworkConnection.new }
256
312
 
257
- thread = Thread.new do
313
+ thread = Thread.new {
258
314
  pool.with do |net|
259
315
  net.do_something
260
316
  sleep 0.01
261
317
  end
262
- end
318
+ }
263
319
 
264
- Thread.pass while thread.status == 'run'
320
+ Thread.pass while thread.status == "run"
265
321
 
266
322
  assert_raises Timeout::Error do
267
323
  pool.checkout
268
324
  end
269
325
 
270
- assert pool.checkout :timeout => 0.1
326
+ assert pool.checkout timeout: 2 * NetworkConnection::SLEEP_TIME
271
327
  end
272
328
 
273
329
  def test_passthru
274
- pool = ConnectionPool.wrap(:timeout => 0.1, :size => 1) { NetworkConnection.new }
330
+ pool = ConnectionPool.wrap(timeout: 2 * NetworkConnection::SLEEP_TIME, size: 1) { NetworkConnection.new }
275
331
  assert_equal 1, pool.do_something
276
332
  assert_equal 2, pool.do_something
277
333
  assert_equal 5, pool.do_something_with_block { 3 }
278
334
  assert_equal 6, pool.with { |net| net.fast }
335
+ assert_equal 8, pool.do_something(increment: 2)
279
336
  end
280
337
 
281
338
  def test_passthru_respond_to
282
- pool = ConnectionPool.wrap(:timeout => 0.1, :size => 1) { NetworkConnection.new }
339
+ pool = ConnectionPool.wrap(timeout: 2 * NetworkConnection::SLEEP_TIME, size: 1) { NetworkConnection.new }
283
340
  assert pool.respond_to?(:with)
284
341
  assert pool.respond_to?(:do_something)
285
342
  assert pool.respond_to?(:do_magic)
@@ -287,67 +344,67 @@ class TestConnectionPool < Minitest::Test
287
344
  end
288
345
 
289
346
  def test_return_value
290
- pool = ConnectionPool.new(:timeout => 0.1, :size => 1) { NetworkConnection.new }
291
- result = pool.with do |net|
347
+ pool = ConnectionPool.new(timeout: 2 * NetworkConnection::SLEEP_TIME, size: 1) { NetworkConnection.new }
348
+ result = pool.with { |net|
292
349
  net.fast
293
- end
350
+ }
294
351
  assert_equal 1, result
295
352
  end
296
353
 
297
354
  def test_heavy_threading
298
- pool = ConnectionPool.new(:timeout => 0.5, :size => 3) { NetworkConnection.new }
355
+ pool = ConnectionPool.new(timeout: 0.5, size: 3) { NetworkConnection.new }
299
356
 
300
- threads = Array.new(20) do
357
+ threads = Array.new(20) {
301
358
  Thread.new do
302
359
  pool.with do |net|
303
360
  sleep 0.01
304
361
  end
305
362
  end
306
- end
363
+ }
307
364
 
308
365
  threads.map { |thread| thread.join }
309
366
  end
310
367
 
311
368
  def test_reuses_objects_when_pool_not_saturated
312
- pool = ConnectionPool.new(:size => 5) { NetworkConnection.new }
369
+ pool = ConnectionPool.new(size: 5) { NetworkConnection.new }
313
370
 
314
- ids = 10.times.map do
371
+ ids = 10.times.map {
315
372
  pool.with { |c| c.object_id }
316
- end
373
+ }
317
374
 
318
375
  assert_equal 1, ids.uniq.size
319
376
  end
320
377
 
321
378
  def test_nested_checkout
322
379
  recorder = Recorder.new
323
- pool = ConnectionPool.new(:size => 1) { recorder }
380
+ pool = ConnectionPool.new(size: 1) { recorder }
324
381
  pool.with do |r_outer|
325
- @other = Thread.new do |t|
382
+ @other = Thread.new { |t|
326
383
  pool.with do |r_other|
327
- r_other.do_work('other')
384
+ r_other.do_work("other")
328
385
  end
329
- end
386
+ }
330
387
 
331
388
  pool.with do |r_inner|
332
- r_inner.do_work('inner')
389
+ r_inner.do_work("inner")
333
390
  end
334
391
 
335
392
  Thread.pass
336
393
 
337
- r_outer.do_work('outer')
394
+ r_outer.do_work("outer")
338
395
  end
339
396
 
340
397
  @other.join
341
398
 
342
- assert_equal ['inner', 'outer', 'other'], recorder.calls
399
+ assert_equal ["inner", "outer", "other"], recorder.calls
343
400
  end
344
401
 
345
402
  def test_shutdown_is_executed_for_all_connections
346
403
  recorders = []
347
404
 
348
- pool = ConnectionPool.new(:size => 3) do
405
+ pool = ConnectionPool.new(size: 3) {
349
406
  Recorder.new.tap { |r| recorders << r }
350
- end
407
+ }
351
408
 
352
409
  threads = use_pool pool, 3
353
410
 
@@ -361,9 +418,9 @@ class TestConnectionPool < Minitest::Test
361
418
  end
362
419
 
363
420
  def test_raises_error_after_shutting_down
364
- pool = ConnectionPool.new(:size => 1) { true }
421
+ pool = ConnectionPool.new(size: 1) { true }
365
422
 
366
- pool.shutdown { }
423
+ pool.shutdown {}
367
424
 
368
425
  assert_raises ConnectionPool::PoolShuttingDownError do
369
426
  pool.checkout
@@ -373,9 +430,9 @@ class TestConnectionPool < Minitest::Test
373
430
  def test_runs_shutdown_block_asynchronously_if_connection_was_in_use
374
431
  recorders = []
375
432
 
376
- pool = ConnectionPool.new(:size => 3) do
433
+ pool = ConnectionPool.new(size: 3) {
377
434
  Recorder.new.tap { |r| recorders << r }
378
- end
435
+ }
379
436
 
380
437
  threads = use_pool pool, 2
381
438
 
@@ -395,7 +452,7 @@ class TestConnectionPool < Minitest::Test
395
452
  end
396
453
 
397
454
  def test_raises_an_error_if_shutdown_is_called_without_a_block
398
- pool = ConnectionPool.new(:size => 1) { }
455
+ pool = ConnectionPool.new(size: 1) {}
399
456
 
400
457
  assert_raises ArgumentError do
401
458
  pool.shutdown
@@ -405,9 +462,9 @@ class TestConnectionPool < Minitest::Test
405
462
  def test_shutdown_is_executed_for_all_connections_in_wrapped_pool
406
463
  recorders = []
407
464
 
408
- wrapper = ConnectionPool::Wrapper.new(:size => 3) do
465
+ wrapper = ConnectionPool::Wrapper.new(size: 3) {
409
466
  Recorder.new.tap { |r| recorders << r }
410
- end
467
+ }
411
468
 
412
469
  threads = use_pool wrapper, 3
413
470
 
@@ -420,6 +477,11 @@ class TestConnectionPool < Minitest::Test
420
477
  assert_equal [["shutdown"]] * 3, recorders.map { |r| r.calls }
421
478
  end
422
479
 
480
+ def test_wrapper_wrapped_pool
481
+ wrapper = ConnectionPool::Wrapper.new { NetworkConnection.new }
482
+ assert_equal ConnectionPool, wrapper.wrapped_pool.class
483
+ end
484
+
423
485
  def test_wrapper_method_missing
424
486
  wrapper = ConnectionPool::Wrapper.new { NetworkConnection.new }
425
487
 
@@ -436,17 +498,17 @@ class TestConnectionPool < Minitest::Test
436
498
  end
437
499
 
438
500
  def test_wrapper_with
439
- wrapper = ConnectionPool::Wrapper.new(:timeout => 0, :size => 1) { Object.new }
501
+ wrapper = ConnectionPool::Wrapper.new(timeout: 0, size: 1) { Object.new }
440
502
 
441
503
  wrapper.with do
442
- assert_raises Timeout::Error do
443
- Thread.new do
444
- wrapper.with { flunk 'connection checked out :(' }
445
- end.join
446
- end
504
+ Thread.new {
505
+ assert_raises Timeout::Error do
506
+ wrapper.with { flunk "connection checked out :(" }
507
+ end
508
+ }.join
447
509
  end
448
510
 
449
- assert Thread.new { wrapper.with { } }.join
511
+ assert Thread.new { wrapper.with {} }.join
450
512
  end
451
513
 
452
514
  class ConnWithEval
@@ -461,4 +523,38 @@ class TestConnectionPool < Minitest::Test
461
523
  assert_equal "eval'ed 1", wrapper.eval(1)
462
524
  end
463
525
 
526
+ def test_wrapper_with_connection_pool
527
+ recorder = Recorder.new
528
+ pool = ConnectionPool.new(size: 1) { recorder }
529
+ wrapper = ConnectionPool::Wrapper.new(pool: pool)
530
+
531
+ pool.with { |r| r.do_work("with") }
532
+ wrapper.do_work("wrapped")
533
+
534
+ assert_equal ["with", "wrapped"], recorder.calls
535
+ end
536
+
537
+ def test_stats_without_active_connection
538
+ pool = ConnectionPool.new(size: 2) { NetworkConnection.new }
539
+
540
+ assert_equal(2, pool.size)
541
+ assert_equal(2, pool.available)
542
+ end
543
+
544
+ def test_stats_with_active_connection
545
+ pool = ConnectionPool.new(size: 2) { NetworkConnection.new }
546
+
547
+ pool.with do
548
+ assert_equal(1, pool.available)
549
+ end
550
+ end
551
+
552
+ def test_stats_with_string_size
553
+ pool = ConnectionPool.new(size: "2") { NetworkConnection.new }
554
+
555
+ pool.with do
556
+ assert_equal(2, pool.size)
557
+ assert_equal(1, pool.available)
558
+ end
559
+ end
464
560
  end