require "cases/helper" module ActiveRecord module ConnectionAdapters class ConnectionPoolTest < ActiveRecord::TestCase attr_reader :pool def setup super # Keep a duplicate pool so we do not bother others @pool = ConnectionPool.new ActiveRecord::Base.connection_pool.spec if in_memory_db? # Separate connections to an in-memory database create an entirely new database, # with an empty schema etc, so we just stub out this schema on the fly. @pool.with_connection do |connection| connection.create_table :posts do |t| t.integer :cololumn end end end end def teardown super @pool.disconnect! end def active_connections(pool) pool.connections.find_all(&:in_use?) end def test_checkout_after_close connection = pool.connection assert connection.in_use? connection.close assert !connection.in_use? assert pool.connection.in_use? end def test_released_connection_moves_between_threads thread_conn = nil Thread.new { pool.with_connection do |conn| thread_conn = conn end }.join assert thread_conn Thread.new { pool.with_connection do |conn| assert_equal thread_conn, conn end }.join end def test_with_connection assert_equal 0, active_connections(pool).size main_thread = pool.connection assert_equal 1, active_connections(pool).size Thread.new { pool.with_connection do |conn| assert conn assert_equal 2, active_connections(pool).size end assert_equal 1, active_connections(pool).size }.join main_thread.close assert_equal 0, active_connections(pool).size end def test_active_connection_in_use assert !pool.active_connection? main_thread = pool.connection assert pool.active_connection? main_thread.close assert !pool.active_connection? end def test_full_pool_exception assert_raises(PoolFullError) do (@pool.size + 1).times do @pool.checkout end end end def test_full_pool_blocks cs = @pool.size.times.map { @pool.checkout } t = Thread.new { @pool.checkout } # make sure our thread is in the timeout section Thread.pass until t.status == "sleep" connection = cs.first connection.close assert_equal connection, t.join.value end def test_removing_releases_latch cs = @pool.size.times.map { @pool.checkout } t = Thread.new { @pool.checkout } # make sure our thread is in the timeout section Thread.pass until t.status == "sleep" connection = cs.first @pool.remove connection assert_respond_to t.join.value, :execute end def test_reap_and_active @pool.checkout @pool.checkout @pool.checkout @pool.timeout = 0 connections = @pool.connections.dup @pool.reap assert_equal connections.length, @pool.connections.length end def test_reap_inactive @pool.checkout @pool.checkout @pool.checkout @pool.timeout = 0 connections = @pool.connections.dup connections.each do |conn| conn.extend(Module.new { def active?; false; end; }) end @pool.reap assert_equal 0, @pool.connections.length ensure connections.each(&:close) end def test_remove_connection conn = @pool.checkout assert conn.in_use? length = @pool.connections.length @pool.remove conn assert conn.in_use? assert_equal(length - 1, @pool.connections.length) ensure conn.close end def test_remove_connection_for_thread conn = @pool.connection @pool.remove conn assert_not_equal(conn, @pool.connection) ensure conn.close if conn end def test_active_connection? assert !@pool.active_connection? assert @pool.connection assert @pool.active_connection? @pool.release_connection assert !@pool.active_connection? end def test_checkout_behaviour pool = ConnectionPool.new ActiveRecord::Base.connection_pool.spec connection = pool.connection assert_not_nil connection threads = [] 4.times do |i| threads << Thread.new(i) do |pool_count| connection = pool.connection assert_not_nil connection connection.close end end threads.each(&:join) Thread.new do assert pool.connection pool.connection.close end.join end def test_automatic_reconnect= pool = ConnectionPool.new ActiveRecord::Base.connection_pool.spec assert pool.automatic_reconnect assert pool.connection pool.disconnect! assert pool.connection pool.disconnect! pool.automatic_reconnect = false assert_raises(ConnectionNotEstablished) do pool.connection end assert_raises(ConnectionNotEstablished) do pool.with_connection end end def test_pool_sets_connection_visitor assert @pool.connection.visitor.is_a?(Arel::Visitors::ToSql) end end end end