1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
|
require "cases/helper"
require "models/project"
require "timeout"
class PooledConnectionsTest < ActiveRecord::TestCase
self.use_transactional_fixtures = false
def setup
@per_test_teardown = []
@connection = ActiveRecord::Base.remove_connection
end
def teardown
ActiveRecord::Base.clear_all_connections!
ActiveRecord::Base.establish_connection(@connection)
@per_test_teardown.each {|td| td.call }
end
def checkout_connections
ActiveRecord::Base.establish_connection(@connection.merge({:pool => 2, :wait_timeout => 0.3}))
@connections = []
@timed_out = 0
4.times do
Thread.new do
begin
@connections << ActiveRecord::Base.connection_pool.checkout
rescue ActiveRecord::ConnectionTimeoutError
@timed_out += 1
end
end.join
end
end
# Will deadlock due to lack of Monitor timeouts in 1.9
if RUBY_VERSION < '1.9'
def test_pooled_connection_checkout
checkout_connections
assert_equal 2, @connections.length
assert_equal 2, @timed_out
end
end
def checkout_checkin_connections(pool_size, threads)
ActiveRecord::Base.establish_connection(@connection.merge({:pool => pool_size, :wait_timeout => 0.5}))
@connection_count = 0
@timed_out = 0
threads.times do
Thread.new do
begin
conn = ActiveRecord::Base.connection_pool.checkout
sleep 0.1
ActiveRecord::Base.connection_pool.checkin conn
@connection_count += 1
rescue ActiveRecord::ConnectionTimeoutError
@timed_out += 1
end
end.join
end
end
def test_pooled_connection_checkin_one
checkout_checkin_connections 1, 2
assert_equal 2, @connection_count
assert_equal 0, @timed_out
assert_equal 1, ActiveRecord::Base.connection_pool.connections.size
end
def test_pooled_connection_checkin_two
checkout_checkin_connections 2, 3
assert_equal 3, @connection_count
assert_equal 0, @timed_out
assert_equal 1, ActiveRecord::Base.connection_pool.connections.size
end
def test_pooled_connection_checkout_existing_first
ActiveRecord::Base.establish_connection(@connection.merge({:pool => 1}))
conn_pool = ActiveRecord::Base.connection_pool
conn = conn_pool.checkout
conn_pool.checkin(conn)
conn = conn_pool.checkout
assert ActiveRecord::ConnectionAdapters::AbstractAdapter === conn
conn_pool.checkin(conn)
end
def test_not_connected_defined_connection_returns_false
ActiveRecord::Base.establish_connection(@connection)
assert ! ActiveRecord::Base.connected?
end
def test_undefined_connection_returns_false
old_handler = ActiveRecord::Base.connection_handler
ActiveRecord::Base.connection_handler = ActiveRecord::ConnectionAdapters::ConnectionHandler.new
assert ! ActiveRecord::Base.connected?
ensure
ActiveRecord::Base.connection_handler = old_handler
end
def test_connection_config
ActiveRecord::Base.establish_connection(@connection)
assert_equal @connection, ActiveRecord::Base.connection_config
end
def test_with_connection_nesting_safety
ActiveRecord::Base.establish_connection(@connection.merge({:pool => 1, :wait_timeout => 0.1}))
before_count = Project.count
add_record('one')
ActiveRecord::Base.connection.transaction do
add_record('two')
# Have another thread try to screw up the transaction
Thread.new do
ActiveRecord::Base.connection.rollback_db_transaction
ActiveRecord::Base.connection_pool.release_connection
end
add_record('three')
end
after_count = Project.count
assert_equal 3, after_count - before_count
end
def test_connection_pool_callbacks
checked_out, checked_in = false, false
ActiveRecord::ConnectionAdapters::AbstractAdapter.class_eval do
set_callback(:checkout, :after) { checked_out = true }
set_callback(:checkin, :before) { checked_in = true }
end
@per_test_teardown << proc do
ActiveRecord::ConnectionAdapters::AbstractAdapter.class_eval do
reset_callbacks :checkout
reset_callbacks :checkin
end
end
checkout_checkin_connections 1, 1
assert checked_out
assert checked_in
end
private
def add_record(name)
ActiveRecord::Base.connection_pool.with_connection { Project.create! :name => name }
end
end unless current_adapter?(:FrontBase) || in_memory_db?
|