2009-11-23 20:20:05 +00:00
|
|
|
require 'test/test_helper'
|
|
|
|
|
|
|
|
class ConnectionTest < Test::Unit::TestCase
|
|
|
|
|
|
|
|
def new_mock_socket
|
|
|
|
socket = Object.new
|
|
|
|
socket.stubs(:setsockopt).with(Socket::IPPROTO_TCP, Socket::TCP_NODELAY, 1)
|
|
|
|
socket
|
|
|
|
end
|
|
|
|
|
|
|
|
def new_mock_db
|
|
|
|
db = Object.new
|
|
|
|
end
|
|
|
|
|
2009-11-24 19:23:43 +00:00
|
|
|
# Make a few methods public for these tests.
|
|
|
|
class Mongo::Connection
|
|
|
|
public :checkin, :checkout, :clear_stale_cached_connections!
|
|
|
|
end
|
|
|
|
|
2009-11-25 15:25:28 +00:00
|
|
|
context "Initialization: " do
|
2009-11-23 20:20:05 +00:00
|
|
|
|
2009-11-25 15:25:28 +00:00
|
|
|
context "given a single node" do
|
|
|
|
setup do
|
2009-11-23 21:03:33 +00:00
|
|
|
TCPSocket.stubs(:new).returns(new_mock_socket)
|
2009-12-02 21:43:30 +00:00
|
|
|
@conn = Connection.new('localhost', 27017, :connect => false)
|
2009-11-23 20:20:05 +00:00
|
|
|
|
|
|
|
admin_db = new_mock_db
|
|
|
|
admin_db.expects(:command).returns({'ok' => 1, 'ismaster' => 1})
|
|
|
|
@conn.expects(:[]).with('admin').returns(admin_db)
|
|
|
|
@conn.connect_to_master
|
|
|
|
end
|
|
|
|
|
2009-11-25 15:25:28 +00:00
|
|
|
should "set localhost and port to master" do
|
2009-11-23 20:20:05 +00:00
|
|
|
assert_equal 'localhost', @conn.host
|
|
|
|
assert_equal 27017, @conn.port
|
|
|
|
end
|
|
|
|
|
2009-11-25 15:25:28 +00:00
|
|
|
should "set connection pool to 1" do
|
2009-11-23 20:20:05 +00:00
|
|
|
assert_equal 1, @conn.size
|
|
|
|
end
|
|
|
|
|
2009-11-25 15:25:28 +00:00
|
|
|
should "default slave_ok to false" do
|
2009-11-23 20:20:05 +00:00
|
|
|
assert !@conn.slave_ok?
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2009-12-02 21:43:30 +00:00
|
|
|
context "with a nonstandard port" do
|
|
|
|
setup do
|
|
|
|
TCPSocket.stubs(:new).returns(new_mock_socket)
|
|
|
|
@conn = Connection.new('255.255.255.255', 2500, :connect => false)
|
|
|
|
admin_db = new_mock_db
|
|
|
|
admin_db.expects(:command).returns({'ok' => 1, 'ismaster' => 1})
|
|
|
|
@conn.expects(:[]).with('admin').returns(admin_db)
|
|
|
|
@conn.connect_to_master
|
|
|
|
end
|
|
|
|
|
|
|
|
should "set localhost and port correctly" do
|
|
|
|
assert_equal '255.255.255.255', @conn.host
|
|
|
|
assert_equal 2500, @conn.port
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2009-11-25 15:25:28 +00:00
|
|
|
context "Connection pooling: " do
|
|
|
|
setup do
|
2009-11-23 21:03:33 +00:00
|
|
|
TCPSocket.stubs(:new).returns(new_mock_socket)
|
2009-11-25 15:25:28 +00:00
|
|
|
@conn = Connection.new('localhost', 27107, :connect => false,
|
2009-11-23 20:20:05 +00:00
|
|
|
:pool_size => 3)
|
|
|
|
|
|
|
|
admin_db = new_mock_db
|
|
|
|
admin_db.expects(:command).returns({'ok' => 1, 'ismaster' => 1})
|
|
|
|
@conn.expects(:[]).with('admin').returns(admin_db)
|
|
|
|
@conn.connect_to_master
|
|
|
|
end
|
|
|
|
|
2009-11-25 15:25:28 +00:00
|
|
|
should "check out a new connection" do
|
2009-11-23 20:20:05 +00:00
|
|
|
socket = @conn.checkout
|
2009-11-25 15:35:06 +00:00
|
|
|
assert @conn.reserved_connections.keys.include?(Thread.current.object_id)
|
2009-11-23 20:20:05 +00:00
|
|
|
end
|
|
|
|
|
2009-11-25 15:25:28 +00:00
|
|
|
context "with multiple threads" do
|
|
|
|
setup do
|
2009-11-23 20:20:05 +00:00
|
|
|
@thread1 = Object.new
|
|
|
|
@thread2 = Object.new
|
|
|
|
@thread3 = Object.new
|
|
|
|
@thread4 = Object.new
|
2009-11-25 15:25:28 +00:00
|
|
|
|
2009-11-23 20:20:05 +00:00
|
|
|
Thread.stubs(:current).returns(@thread1)
|
|
|
|
@socket1 = @conn.checkout
|
|
|
|
Thread.stubs(:current).returns(@thread2)
|
|
|
|
@socket2 = @conn.checkout
|
|
|
|
Thread.stubs(:current).returns(@thread3)
|
|
|
|
@socket3 = @conn.checkout
|
|
|
|
end
|
|
|
|
|
2009-11-25 15:25:28 +00:00
|
|
|
should "add each thread to the reserved pool" do
|
2009-11-23 20:20:05 +00:00
|
|
|
assert @conn.reserved_connections.keys.include?(@thread1.object_id)
|
|
|
|
assert @conn.reserved_connections.keys.include?(@thread2.object_id)
|
|
|
|
assert @conn.reserved_connections.keys.include?(@thread3.object_id)
|
|
|
|
end
|
|
|
|
|
2009-11-25 15:25:28 +00:00
|
|
|
should "only add one socket per thread" do
|
2009-11-23 20:20:05 +00:00
|
|
|
@conn.reserved_connections.values do |socket|
|
|
|
|
assert [@socket1, @socket2, @socket3].include?(socket)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2009-11-25 15:25:28 +00:00
|
|
|
should "check out all sockets" do
|
2009-11-23 20:20:05 +00:00
|
|
|
assert_equal @conn.sockets.size, @conn.checked_out.size
|
|
|
|
@conn.sockets.each do |sock|
|
|
|
|
assert @conn.checked_out.include?(sock)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
should "raise an error if no more sockets can be checked out" do
|
|
|
|
# This can't be tested with mock threads.
|
|
|
|
# Will test in integration tests.
|
|
|
|
end
|
|
|
|
|
2009-11-25 15:25:28 +00:00
|
|
|
context "when releasing dead threads" do
|
|
|
|
setup do
|
2009-11-23 20:20:05 +00:00
|
|
|
@thread1.expects(:alive?).returns(false)
|
|
|
|
@thread2.expects(:alive?).returns(true)
|
|
|
|
@thread3.expects(:alive?).returns(true)
|
|
|
|
Thread.expects(:list).returns([@thread1, @thread2, @thread3])
|
|
|
|
@conn.clear_stale_cached_connections!
|
|
|
|
end
|
|
|
|
|
2009-11-25 15:25:28 +00:00
|
|
|
should "return connections for dead threads" do
|
2009-11-23 20:20:05 +00:00
|
|
|
assert !@conn.checked_out.include?(@socket1)
|
|
|
|
assert_nil @conn.reserved_connections[@thread1.object_id]
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
end
|
|
|
|
end
|
2009-11-25 15:25:28 +00:00
|
|
|
end
|
2009-11-23 20:20:05 +00:00
|
|
|
|