2014-03-13 21:56:16 -04:00
|
|
|
require_relative 'helper'
|
2011-05-14 18:36:17 -04:00
|
|
|
|
2013-08-14 22:33:19 -04:00
|
|
|
class TestConnectionPool < Minitest::Test
|
|
|
|
|
2011-05-14 18:36:17 -04:00
|
|
|
class NetworkConnection
|
2015-04-16 21:24:00 -04:00
|
|
|
SLEEP_TIME = 0.1
|
2015-04-16 21:16:34 -04:00
|
|
|
|
2011-05-14 22:42:07 -04:00
|
|
|
def initialize
|
|
|
|
@x = 0
|
|
|
|
end
|
2012-12-18 11:41:59 -05:00
|
|
|
|
2011-05-14 18:36:17 -04:00
|
|
|
def do_something
|
2011-05-14 22:42:07 -04:00
|
|
|
@x += 1
|
2015-04-16 21:16:34 -04:00
|
|
|
sleep SLEEP_TIME
|
2011-05-14 22:42:07 -04:00
|
|
|
@x
|
|
|
|
end
|
2012-12-18 11:41:59 -05:00
|
|
|
|
2011-05-14 22:42:07 -04:00
|
|
|
def fast
|
|
|
|
@x += 1
|
2011-05-14 18:36:17 -04:00
|
|
|
end
|
2012-12-18 11:41:59 -05:00
|
|
|
|
2012-02-08 12:44:18 -05:00
|
|
|
def do_something_with_block
|
|
|
|
@x += yield
|
2015-04-16 21:16:34 -04:00
|
|
|
sleep SLEEP_TIME
|
2012-02-08 12:44:18 -05:00
|
|
|
@x
|
|
|
|
end
|
2012-12-18 11:41:59 -05:00
|
|
|
|
|
|
|
def respond_to?(method_id, *args)
|
|
|
|
method_id == :do_magic || super(method_id, *args)
|
|
|
|
end
|
2011-05-14 18:36:17 -04:00
|
|
|
end
|
|
|
|
|
2013-05-25 13:19:19 -04:00
|
|
|
class Recorder
|
|
|
|
def initialize
|
|
|
|
@calls = []
|
|
|
|
end
|
|
|
|
|
|
|
|
attr_reader :calls
|
|
|
|
|
|
|
|
def do_work(label)
|
|
|
|
@calls << label
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2014-03-13 22:12:05 -04:00
|
|
|
def use_pool(pool, size)
|
|
|
|
Array.new(size) do
|
2014-02-17 19:25:22 -05:00
|
|
|
Thread.new do
|
|
|
|
pool.with do sleep end
|
|
|
|
end
|
|
|
|
end.each do |thread|
|
|
|
|
Thread.pass until thread.status == 'sleep'
|
2015-01-17 18:32:50 -05:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
def kill_threads(threads)
|
|
|
|
threads.each do |thread|
|
2014-02-17 19:25:22 -05:00
|
|
|
thread.kill
|
2015-01-18 14:51:45 -05:00
|
|
|
thread.join
|
2014-02-17 19:25:22 -05:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2011-05-14 18:36:17 -04:00
|
|
|
def test_basic_multithreaded_usage
|
2015-04-16 21:16:34 -04:00
|
|
|
pool_size = 5
|
2015-09-06 16:57:30 -04:00
|
|
|
pool = ConnectionPool.new(size: pool_size) { NetworkConnection.new }
|
2015-04-16 21:16:34 -04:00
|
|
|
|
|
|
|
start = Time.new
|
|
|
|
|
|
|
|
generations = 3
|
2014-03-13 22:12:05 -04:00
|
|
|
|
2015-04-16 21:16:34 -04:00
|
|
|
result = Array.new(pool_size * generations) do
|
2014-03-13 22:12:05 -04:00
|
|
|
Thread.new do
|
2012-12-18 21:33:59 -05:00
|
|
|
pool.with do |net|
|
2011-05-14 18:36:17 -04:00
|
|
|
net.do_something
|
|
|
|
end
|
|
|
|
end
|
2015-04-16 21:16:34 -04:00
|
|
|
end.map(&:value)
|
|
|
|
|
|
|
|
finish = Time.new
|
|
|
|
|
|
|
|
assert_equal((1..generations).cycle(pool_size).sort, result.sort)
|
2011-09-25 22:23:35 -04:00
|
|
|
|
2015-04-16 21:16:34 -04:00
|
|
|
assert_operator(finish - start, :>, generations * NetworkConnection::SLEEP_TIME)
|
2011-05-14 18:36:17 -04:00
|
|
|
end
|
|
|
|
|
|
|
|
def test_timeout
|
2015-09-06 16:57:30 -04:00
|
|
|
pool = ConnectionPool.new(timeout: 0, size: 1) { NetworkConnection.new }
|
2014-02-14 19:32:35 -05:00
|
|
|
thread = Thread.new do
|
2011-05-14 18:36:17 -04:00
|
|
|
pool.with do |net|
|
|
|
|
net.do_something
|
2014-02-14 19:32:35 -05:00
|
|
|
sleep 0.01
|
2011-05-14 18:36:17 -04:00
|
|
|
end
|
|
|
|
end
|
2014-02-14 19:32:35 -05:00
|
|
|
|
|
|
|
Thread.pass while thread.status == 'run'
|
|
|
|
|
2011-05-14 18:36:17 -04:00
|
|
|
assert_raises Timeout::Error do
|
2012-03-14 09:07:43 -04:00
|
|
|
pool.with { |net| net.do_something }
|
2011-05-14 18:36:17 -04:00
|
|
|
end
|
2011-09-09 17:12:23 -04:00
|
|
|
|
2014-02-14 19:32:35 -05:00
|
|
|
thread.join
|
|
|
|
|
2011-09-09 17:12:23 -04:00
|
|
|
pool.with do |conn|
|
|
|
|
refute_nil conn
|
|
|
|
end
|
2011-05-14 18:36:17 -04:00
|
|
|
end
|
2014-02-05 20:25:58 -05:00
|
|
|
|
2014-02-14 18:14:09 -05:00
|
|
|
def test_with
|
2015-09-06 16:57:30 -04:00
|
|
|
pool = ConnectionPool.new(timeout: 0, size: 1) { Object.new }
|
2014-02-14 18:14:09 -05:00
|
|
|
|
|
|
|
pool.with do
|
|
|
|
assert_raises Timeout::Error do
|
|
|
|
Thread.new { pool.checkout }.join
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
assert Thread.new { pool.checkout }.join
|
|
|
|
end
|
|
|
|
|
2015-04-10 14:22:26 -04:00
|
|
|
def test_with_timeout
|
2015-09-06 16:57:30 -04:00
|
|
|
pool = ConnectionPool.new(timeout: 0, size: 1) { Object.new }
|
2015-04-10 14:22:26 -04:00
|
|
|
|
|
|
|
assert_raises Timeout::Error do
|
|
|
|
Timeout.timeout(0.01) do
|
|
|
|
pool.with do |obj|
|
|
|
|
assert_equal 0, pool.instance_variable_get(:@available).instance_variable_get(:@que).size
|
2015-04-10 15:46:44 -04:00
|
|
|
sleep 0.015
|
2015-04-10 14:22:26 -04:00
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
2015-04-10 15:00:29 -04:00
|
|
|
assert_equal 1, pool.instance_variable_get(:@available).instance_variable_get(:@que).size
|
|
|
|
end
|
|
|
|
|
|
|
|
def test_checkout_ignores_timeout
|
2015-04-10 16:03:37 -04:00
|
|
|
skip("Thread.handle_interrupt not available") unless Thread.respond_to?(:handle_interrupt)
|
|
|
|
|
2015-09-06 16:57:30 -04:00
|
|
|
pool = ConnectionPool.new(timeout: 0, size: 1) { Object.new }
|
2015-04-10 15:00:29 -04:00
|
|
|
def pool.checkout(options)
|
|
|
|
sleep 0.015
|
2015-04-10 15:46:44 -04:00
|
|
|
super
|
2015-04-10 15:00:29 -04:00
|
|
|
end
|
2015-04-10 14:22:26 -04:00
|
|
|
|
2015-04-10 15:00:29 -04:00
|
|
|
did_something = false
|
|
|
|
assert_raises Timeout::Error do
|
|
|
|
Timeout.timeout(0.01) do
|
|
|
|
pool.with do |obj|
|
|
|
|
did_something = true
|
2015-04-10 15:46:44 -04:00
|
|
|
# Timeout::Error will be triggered by any non-trivial Ruby code
|
|
|
|
# executed here since it couldn't be raised during checkout.
|
|
|
|
# It looks like setting the local variable above does not trigger
|
|
|
|
# the Timeout check in MRI 2.2.1.
|
|
|
|
obj.tap { obj.hash }
|
2015-04-10 15:00:29 -04:00
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
assert did_something
|
2015-04-10 14:22:26 -04:00
|
|
|
assert_equal 1, pool.instance_variable_get(:@available).instance_variable_get(:@que).size
|
|
|
|
end
|
|
|
|
|
2015-04-09 23:21:51 -04:00
|
|
|
def test_explicit_return
|
2015-09-06 16:57:30 -04:00
|
|
|
pool = ConnectionPool.new(timeout: 0, size: 1) do
|
2015-04-09 23:21:51 -04:00
|
|
|
mock = Minitest::Mock.new
|
|
|
|
def mock.disconnect!
|
|
|
|
raise "should not disconnect upon explicit return"
|
|
|
|
end
|
|
|
|
mock
|
|
|
|
end
|
|
|
|
|
|
|
|
pool.with do |conn|
|
|
|
|
return true
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2014-02-05 20:25:58 -05:00
|
|
|
def test_with_timeout_override
|
2015-09-06 16:57:30 -04:00
|
|
|
pool = ConnectionPool.new(timeout: 0, size: 1) { NetworkConnection.new }
|
2014-02-14 19:24:29 -05:00
|
|
|
|
|
|
|
t = Thread.new do
|
2013-09-23 23:28:50 -04:00
|
|
|
pool.with do |net|
|
|
|
|
net.do_something
|
2014-02-14 19:24:29 -05:00
|
|
|
sleep 0.01
|
2013-09-23 23:28:50 -04:00
|
|
|
end
|
|
|
|
end
|
2014-02-14 19:24:29 -05:00
|
|
|
|
|
|
|
Thread.pass while t.status == 'run'
|
|
|
|
|
2013-09-23 23:28:50 -04:00
|
|
|
assert_raises Timeout::Error do
|
|
|
|
pool.with { |net| net.do_something }
|
2014-02-05 20:25:58 -05:00
|
|
|
end
|
2014-02-14 19:24:29 -05:00
|
|
|
|
2015-09-06 16:57:30 -04:00
|
|
|
pool.with(timeout: 2 * NetworkConnection::SLEEP_TIME) do |conn|
|
2013-09-23 23:28:50 -04:00
|
|
|
refute_nil conn
|
2014-02-05 20:25:58 -05:00
|
|
|
end
|
2013-09-23 23:28:50 -04:00
|
|
|
end
|
2011-05-14 18:36:17 -04:00
|
|
|
|
2014-02-07 16:38:07 -05:00
|
|
|
def test_checkin
|
2015-09-06 16:57:30 -04:00
|
|
|
pool = ConnectionPool.new(timeout: 0, size: 1) { NetworkConnection.new }
|
2014-02-07 16:38:07 -05:00
|
|
|
conn = pool.checkout
|
|
|
|
|
|
|
|
assert_raises Timeout::Error do
|
2015-01-18 01:09:47 -05:00
|
|
|
Thread.new { pool.checkout }.join
|
2014-02-07 16:38:07 -05:00
|
|
|
end
|
|
|
|
|
|
|
|
pool.checkin
|
|
|
|
|
2015-01-18 01:09:47 -05:00
|
|
|
assert_same conn, Thread.new { pool.checkout }.value
|
2014-02-07 16:38:07 -05:00
|
|
|
end
|
|
|
|
|
2014-06-13 11:30:32 -04:00
|
|
|
def test_returns_value
|
2015-09-06 16:57:30 -04:00
|
|
|
pool = ConnectionPool.new(timeout: 0, size: 1) { Object.new }
|
2014-06-13 11:30:32 -04:00
|
|
|
assert_equal 1, pool.with {|o| 1 }
|
|
|
|
end
|
|
|
|
|
2014-02-14 19:10:58 -05:00
|
|
|
def test_checkin_never_checkout
|
2015-09-06 16:57:30 -04:00
|
|
|
pool = ConnectionPool.new(timeout: 0, size: 1) { Object.new }
|
2014-02-14 18:04:10 -05:00
|
|
|
|
2014-02-14 19:05:15 -05:00
|
|
|
e = assert_raises ConnectionPool::Error do
|
|
|
|
pool.checkin
|
2014-02-14 18:04:10 -05:00
|
|
|
end
|
2014-02-14 19:05:15 -05:00
|
|
|
|
|
|
|
assert_equal 'no connections are checked out', e.message
|
2014-02-14 18:04:10 -05:00
|
|
|
end
|
|
|
|
|
2014-02-14 19:10:58 -05:00
|
|
|
def test_checkin_no_current_checkout
|
2015-09-06 16:57:30 -04:00
|
|
|
pool = ConnectionPool.new(timeout: 0, size: 1) { Object.new }
|
2014-02-14 19:10:58 -05:00
|
|
|
|
|
|
|
pool.checkout
|
|
|
|
pool.checkin
|
|
|
|
|
|
|
|
assert_raises ConnectionPool::Error do
|
|
|
|
pool.checkin
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2014-02-14 18:07:35 -05:00
|
|
|
def test_checkin_twice
|
2015-09-06 16:57:30 -04:00
|
|
|
pool = ConnectionPool.new(timeout: 0, size: 1) { Object.new }
|
2014-02-14 18:07:35 -05:00
|
|
|
|
|
|
|
pool.checkout
|
|
|
|
pool.checkout
|
|
|
|
|
|
|
|
pool.checkin
|
|
|
|
|
|
|
|
assert_raises Timeout::Error do
|
|
|
|
Thread.new do
|
|
|
|
pool.checkout
|
|
|
|
end.join
|
|
|
|
end
|
|
|
|
|
|
|
|
pool.checkin
|
|
|
|
|
|
|
|
assert Thread.new { pool.checkout }.join
|
|
|
|
end
|
|
|
|
|
2014-02-07 17:05:29 -05:00
|
|
|
def test_checkout
|
2015-09-06 16:57:30 -04:00
|
|
|
pool = ConnectionPool.new(size: 1) { NetworkConnection.new }
|
2014-02-07 17:05:29 -05:00
|
|
|
|
|
|
|
conn = pool.checkout
|
|
|
|
|
|
|
|
assert_kind_of NetworkConnection, conn
|
|
|
|
|
|
|
|
assert_same conn, pool.checkout
|
|
|
|
end
|
|
|
|
|
2014-02-07 16:35:48 -05:00
|
|
|
def test_checkout_multithread
|
2015-09-06 16:57:30 -04:00
|
|
|
pool = ConnectionPool.new(size: 2) { NetworkConnection.new }
|
2014-02-07 16:35:48 -05:00
|
|
|
conn = pool.checkout
|
|
|
|
|
|
|
|
t = Thread.new do
|
|
|
|
pool.checkout
|
|
|
|
end
|
|
|
|
|
|
|
|
refute_same conn, t.value
|
|
|
|
end
|
|
|
|
|
2014-02-14 17:47:01 -05:00
|
|
|
def test_checkout_timeout
|
2015-09-06 16:57:30 -04:00
|
|
|
pool = ConnectionPool.new(timeout: 0, size: 0) { Object.new }
|
2014-02-14 17:47:01 -05:00
|
|
|
|
|
|
|
assert_raises Timeout::Error do
|
|
|
|
pool.checkout
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2013-09-24 00:47:01 -04:00
|
|
|
def test_checkout_timeout_override
|
2015-09-06 16:57:30 -04:00
|
|
|
pool = ConnectionPool.new(timeout: 0, size: 1) { NetworkConnection.new }
|
2014-02-14 19:26:05 -05:00
|
|
|
|
|
|
|
thread = Thread.new do
|
2013-09-24 00:47:01 -04:00
|
|
|
pool.with do |net|
|
|
|
|
net.do_something
|
2014-02-14 19:26:05 -05:00
|
|
|
sleep 0.01
|
2013-09-24 00:47:01 -04:00
|
|
|
end
|
2014-02-05 20:25:58 -05:00
|
|
|
end
|
2014-02-14 19:26:05 -05:00
|
|
|
|
|
|
|
Thread.pass while thread.status == 'run'
|
|
|
|
|
2013-09-24 00:47:01 -04:00
|
|
|
assert_raises Timeout::Error do
|
2014-02-05 20:25:58 -05:00
|
|
|
pool.checkout
|
2013-09-24 00:47:01 -04:00
|
|
|
end
|
2014-02-14 19:26:05 -05:00
|
|
|
|
2015-09-06 16:57:30 -04:00
|
|
|
assert pool.checkout timeout: 2 * NetworkConnection::SLEEP_TIME
|
2013-09-24 00:47:01 -04:00
|
|
|
end
|
2014-02-05 20:25:58 -05:00
|
|
|
|
2011-05-14 18:36:17 -04:00
|
|
|
def test_passthru
|
2015-09-06 16:57:30 -04:00
|
|
|
pool = ConnectionPool.wrap(timeout: 2 * NetworkConnection::SLEEP_TIME, size: 1) { NetworkConnection.new }
|
2011-05-14 22:42:07 -04:00
|
|
|
assert_equal 1, pool.do_something
|
|
|
|
assert_equal 2, pool.do_something
|
2012-02-08 12:44:18 -05:00
|
|
|
assert_equal 5, pool.do_something_with_block { 3 }
|
2012-03-14 11:36:40 -04:00
|
|
|
assert_equal 6, pool.with { |net| net.fast }
|
2012-12-18 11:50:12 -05:00
|
|
|
end
|
2012-12-18 11:41:59 -05:00
|
|
|
|
2012-12-18 11:50:12 -05:00
|
|
|
def test_passthru_respond_to
|
2015-09-06 16:57:30 -04:00
|
|
|
pool = ConnectionPool.wrap(timeout: 2 * NetworkConnection::SLEEP_TIME, size: 1) { NetworkConnection.new }
|
2012-12-18 11:41:59 -05:00
|
|
|
assert pool.respond_to?(:with)
|
|
|
|
assert pool.respond_to?(:do_something)
|
|
|
|
assert pool.respond_to?(:do_magic)
|
|
|
|
refute pool.respond_to?(:do_lots_of_magic)
|
2011-05-14 22:42:07 -04:00
|
|
|
end
|
|
|
|
|
|
|
|
def test_return_value
|
2015-09-06 16:57:30 -04:00
|
|
|
pool = ConnectionPool.new(timeout: 2 * NetworkConnection::SLEEP_TIME, size: 1) { NetworkConnection.new }
|
2012-12-18 21:33:59 -05:00
|
|
|
result = pool.with do |net|
|
2011-05-14 22:42:07 -04:00
|
|
|
net.fast
|
|
|
|
end
|
|
|
|
assert_equal 1, result
|
2011-05-14 18:36:17 -04:00
|
|
|
end
|
2011-09-13 00:01:38 -04:00
|
|
|
|
|
|
|
def test_heavy_threading
|
2015-09-06 16:57:30 -04:00
|
|
|
pool = ConnectionPool.new(timeout: 0.5, size: 3) { NetworkConnection.new }
|
2014-02-14 19:19:59 -05:00
|
|
|
|
2014-03-13 22:12:05 -04:00
|
|
|
threads = Array.new(20) do
|
2011-09-13 00:01:38 -04:00
|
|
|
Thread.new do
|
|
|
|
pool.with do |net|
|
2014-02-14 19:19:59 -05:00
|
|
|
sleep 0.01
|
2011-09-13 00:01:38 -04:00
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
2014-02-14 19:19:59 -05:00
|
|
|
|
|
|
|
threads.map { |thread| thread.join }
|
2011-09-13 00:01:38 -04:00
|
|
|
end
|
2012-06-18 09:10:05 -04:00
|
|
|
|
2012-12-18 12:05:13 -05:00
|
|
|
def test_reuses_objects_when_pool_not_saturated
|
2015-09-06 16:57:30 -04:00
|
|
|
pool = ConnectionPool.new(size: 5) { NetworkConnection.new }
|
2012-12-18 12:05:13 -05:00
|
|
|
|
|
|
|
ids = 10.times.map do
|
|
|
|
pool.with { |c| c.object_id }
|
|
|
|
end
|
|
|
|
|
|
|
|
assert_equal 1, ids.uniq.size
|
|
|
|
end
|
|
|
|
|
2012-06-18 09:10:05 -04:00
|
|
|
def test_nested_checkout
|
|
|
|
recorder = Recorder.new
|
2015-09-06 16:57:30 -04:00
|
|
|
pool = ConnectionPool.new(size: 1) { recorder }
|
2012-06-18 09:10:05 -04:00
|
|
|
pool.with do |r_outer|
|
|
|
|
@other = Thread.new do |t|
|
|
|
|
pool.with do |r_other|
|
|
|
|
r_other.do_work('other')
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
pool.with do |r_inner|
|
|
|
|
r_inner.do_work('inner')
|
|
|
|
end
|
|
|
|
|
2014-02-14 19:35:24 -05:00
|
|
|
Thread.pass
|
2012-06-18 09:10:05 -04:00
|
|
|
|
|
|
|
r_outer.do_work('outer')
|
|
|
|
end
|
|
|
|
|
|
|
|
@other.join
|
|
|
|
|
|
|
|
assert_equal ['inner', 'outer', 'other'], recorder.calls
|
|
|
|
end
|
2013-05-25 13:19:19 -04:00
|
|
|
|
|
|
|
def test_shutdown_is_executed_for_all_connections
|
|
|
|
recorders = []
|
|
|
|
|
2015-09-06 16:57:30 -04:00
|
|
|
pool = ConnectionPool.new(size: 3) do
|
2013-05-25 13:19:19 -04:00
|
|
|
Recorder.new.tap { |r| recorders << r }
|
|
|
|
end
|
|
|
|
|
2015-01-17 18:32:50 -05:00
|
|
|
threads = use_pool pool, 3
|
2014-02-17 19:25:22 -05:00
|
|
|
|
2013-05-25 13:19:19 -04:00
|
|
|
pool.shutdown do |recorder|
|
|
|
|
recorder.do_work("shutdown")
|
|
|
|
end
|
|
|
|
|
2015-01-17 18:32:50 -05:00
|
|
|
kill_threads(threads)
|
|
|
|
|
2013-05-25 13:19:19 -04:00
|
|
|
assert_equal [["shutdown"]] * 3, recorders.map { |r| r.calls }
|
|
|
|
end
|
|
|
|
|
|
|
|
def test_raises_error_after_shutting_down
|
2015-09-06 16:57:30 -04:00
|
|
|
pool = ConnectionPool.new(size: 1) { true }
|
2013-05-25 13:19:19 -04:00
|
|
|
|
|
|
|
pool.shutdown { }
|
|
|
|
|
|
|
|
assert_raises ConnectionPool::PoolShuttingDownError do
|
|
|
|
pool.checkout
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
def test_runs_shutdown_block_asynchronously_if_connection_was_in_use
|
|
|
|
recorders = []
|
|
|
|
|
2015-09-06 16:57:30 -04:00
|
|
|
pool = ConnectionPool.new(size: 3) do
|
2013-05-25 13:19:19 -04:00
|
|
|
Recorder.new.tap { |r| recorders << r }
|
|
|
|
end
|
|
|
|
|
2015-01-17 18:32:50 -05:00
|
|
|
threads = use_pool pool, 2
|
2014-02-17 19:25:22 -05:00
|
|
|
|
2013-05-25 13:19:19 -04:00
|
|
|
pool.checkout
|
|
|
|
|
|
|
|
pool.shutdown do |recorder|
|
|
|
|
recorder.do_work("shutdown")
|
|
|
|
end
|
|
|
|
|
2015-01-17 18:32:50 -05:00
|
|
|
kill_threads(threads)
|
|
|
|
|
2015-01-18 01:09:47 -05:00
|
|
|
assert_equal [["shutdown"], ["shutdown"], []], recorders.map { |r| r.calls }
|
2013-05-25 13:19:19 -04:00
|
|
|
|
|
|
|
pool.checkin
|
|
|
|
|
|
|
|
assert_equal [["shutdown"], ["shutdown"], ["shutdown"]], recorders.map { |r| r.calls }
|
|
|
|
end
|
|
|
|
|
|
|
|
def test_raises_an_error_if_shutdown_is_called_without_a_block
|
2015-09-06 16:57:30 -04:00
|
|
|
pool = ConnectionPool.new(size: 1) { }
|
2013-05-25 13:19:19 -04:00
|
|
|
|
|
|
|
assert_raises ArgumentError do
|
|
|
|
pool.shutdown
|
|
|
|
end
|
|
|
|
end
|
2013-06-14 19:41:09 -04:00
|
|
|
|
2013-06-15 13:39:32 -04:00
|
|
|
def test_shutdown_is_executed_for_all_connections_in_wrapped_pool
|
|
|
|
recorders = []
|
|
|
|
|
2015-09-06 16:57:30 -04:00
|
|
|
wrapper = ConnectionPool::Wrapper.new(size: 3) do
|
2013-06-15 13:39:32 -04:00
|
|
|
Recorder.new.tap { |r| recorders << r }
|
|
|
|
end
|
|
|
|
|
2015-01-17 18:32:50 -05:00
|
|
|
threads = use_pool wrapper, 3
|
2014-02-17 19:25:22 -05:00
|
|
|
|
2013-06-15 13:39:32 -04:00
|
|
|
wrapper.pool_shutdown do |recorder|
|
|
|
|
recorder.do_work("shutdown")
|
|
|
|
end
|
|
|
|
|
2015-01-17 18:32:50 -05:00
|
|
|
kill_threads(threads)
|
|
|
|
|
2013-06-15 13:39:32 -04:00
|
|
|
assert_equal [["shutdown"]] * 3, recorders.map { |r| r.calls }
|
2013-06-14 19:41:09 -04:00
|
|
|
end
|
2014-02-14 18:45:57 -05:00
|
|
|
|
2014-02-14 18:47:59 -05:00
|
|
|
def test_wrapper_method_missing
|
|
|
|
wrapper = ConnectionPool::Wrapper.new { NetworkConnection.new }
|
|
|
|
|
|
|
|
assert_equal 1, wrapper.fast
|
|
|
|
end
|
|
|
|
|
2014-02-14 18:45:57 -05:00
|
|
|
def test_wrapper_respond_to_eh
|
|
|
|
wrapper = ConnectionPool::Wrapper.new { NetworkConnection.new }
|
|
|
|
|
|
|
|
assert_respond_to wrapper, :with
|
|
|
|
|
|
|
|
assert_respond_to wrapper, :fast
|
|
|
|
refute_respond_to wrapper, :"nonexistent method"
|
|
|
|
end
|
2014-02-14 18:52:35 -05:00
|
|
|
|
|
|
|
def test_wrapper_with
|
2015-09-06 16:57:30 -04:00
|
|
|
wrapper = ConnectionPool::Wrapper.new(timeout: 0, size: 1) { Object.new }
|
2014-02-14 18:52:35 -05:00
|
|
|
|
|
|
|
wrapper.with do
|
|
|
|
assert_raises Timeout::Error do
|
|
|
|
Thread.new do
|
|
|
|
wrapper.with { flunk 'connection checked out :(' }
|
|
|
|
end.join
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
assert Thread.new { wrapper.with { } }.join
|
|
|
|
end
|
2014-03-13 22:02:21 -04:00
|
|
|
|
|
|
|
class ConnWithEval
|
|
|
|
def eval(arg)
|
|
|
|
"eval'ed #{arg}"
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
def test_wrapper_kernel_methods
|
|
|
|
wrapper = ConnectionPool::Wrapper.new(timeout: 0, size: 1) { ConnWithEval.new }
|
|
|
|
|
|
|
|
assert_equal "eval'ed 1", wrapper.eval(1)
|
|
|
|
end
|
2014-03-13 22:12:05 -04:00
|
|
|
|
2016-05-18 10:21:56 -04:00
|
|
|
def test_wrapper_with_connection_pool
|
|
|
|
recorder = Recorder.new
|
|
|
|
pool = ConnectionPool.new(size: 1) { recorder }
|
|
|
|
wrapper = ConnectionPool::Wrapper.new(pool: pool)
|
|
|
|
|
|
|
|
pool.with { |r| r.do_work('with') }
|
|
|
|
wrapper.do_work('wrapped')
|
|
|
|
|
|
|
|
assert_equal ['with', 'wrapped'], recorder.calls
|
|
|
|
end
|
2017-08-08 09:30:13 -04:00
|
|
|
|
|
|
|
def test_stats_without_active_connection
|
|
|
|
pool = ConnectionPool.new(size: 2) { NetworkConnection.new }
|
|
|
|
|
2017-08-08 13:52:49 -04:00
|
|
|
assert_equal(2, pool.size)
|
|
|
|
assert_equal(2, pool.available)
|
2017-08-08 09:30:13 -04:00
|
|
|
end
|
|
|
|
|
|
|
|
def test_stats_with_active_connection
|
|
|
|
pool = ConnectionPool.new(size: 2) { NetworkConnection.new }
|
|
|
|
|
|
|
|
pool.with do
|
2017-08-08 13:52:49 -04:00
|
|
|
assert_equal(1, pool.available)
|
2017-08-08 09:30:13 -04:00
|
|
|
end
|
|
|
|
end
|
2011-09-09 17:12:23 -04:00
|
|
|
end
|