kbaum-mongo 0.18.3p

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (72) hide show
  1. data/LICENSE.txt +202 -0
  2. data/README.rdoc +339 -0
  3. data/Rakefile +138 -0
  4. data/bin/bson_benchmark.rb +59 -0
  5. data/bin/fail_if_no_c.rb +11 -0
  6. data/examples/admin.rb +42 -0
  7. data/examples/capped.rb +22 -0
  8. data/examples/cursor.rb +48 -0
  9. data/examples/gridfs.rb +88 -0
  10. data/examples/index_test.rb +126 -0
  11. data/examples/info.rb +31 -0
  12. data/examples/queries.rb +70 -0
  13. data/examples/simple.rb +24 -0
  14. data/examples/strict.rb +35 -0
  15. data/examples/types.rb +36 -0
  16. data/lib/mongo/collection.rb +609 -0
  17. data/lib/mongo/connection.rb +672 -0
  18. data/lib/mongo/cursor.rb +403 -0
  19. data/lib/mongo/db.rb +555 -0
  20. data/lib/mongo/exceptions.rb +66 -0
  21. data/lib/mongo/gridfs/chunk.rb +91 -0
  22. data/lib/mongo/gridfs/grid.rb +79 -0
  23. data/lib/mongo/gridfs/grid_file_system.rb +101 -0
  24. data/lib/mongo/gridfs/grid_io.rb +338 -0
  25. data/lib/mongo/gridfs/grid_store.rb +580 -0
  26. data/lib/mongo/gridfs.rb +25 -0
  27. data/lib/mongo/types/binary.rb +52 -0
  28. data/lib/mongo/types/code.rb +36 -0
  29. data/lib/mongo/types/dbref.rb +40 -0
  30. data/lib/mongo/types/min_max_keys.rb +58 -0
  31. data/lib/mongo/types/objectid.rb +180 -0
  32. data/lib/mongo/types/regexp_of_holding.rb +45 -0
  33. data/lib/mongo/util/bson_c.rb +18 -0
  34. data/lib/mongo/util/bson_ruby.rb +606 -0
  35. data/lib/mongo/util/byte_buffer.rb +222 -0
  36. data/lib/mongo/util/conversions.rb +87 -0
  37. data/lib/mongo/util/ordered_hash.rb +140 -0
  38. data/lib/mongo/util/server_version.rb +69 -0
  39. data/lib/mongo/util/support.rb +26 -0
  40. data/lib/mongo.rb +63 -0
  41. data/mongo-ruby-driver.gemspec +28 -0
  42. data/test/auxillary/autoreconnect_test.rb +42 -0
  43. data/test/binary_test.rb +15 -0
  44. data/test/bson_test.rb +427 -0
  45. data/test/byte_buffer_test.rb +81 -0
  46. data/test/chunk_test.rb +82 -0
  47. data/test/collection_test.rb +515 -0
  48. data/test/connection_test.rb +160 -0
  49. data/test/conversions_test.rb +120 -0
  50. data/test/cursor_test.rb +379 -0
  51. data/test/db_api_test.rb +780 -0
  52. data/test/db_connection_test.rb +16 -0
  53. data/test/db_test.rb +272 -0
  54. data/test/grid_file_system_test.rb +210 -0
  55. data/test/grid_io_test.rb +78 -0
  56. data/test/grid_store_test.rb +334 -0
  57. data/test/grid_test.rb +87 -0
  58. data/test/objectid_test.rb +125 -0
  59. data/test/ordered_hash_test.rb +172 -0
  60. data/test/replica/count_test.rb +34 -0
  61. data/test/replica/insert_test.rb +50 -0
  62. data/test/replica/pooled_insert_test.rb +54 -0
  63. data/test/replica/query_test.rb +39 -0
  64. data/test/slave_connection_test.rb +36 -0
  65. data/test/test_helper.rb +42 -0
  66. data/test/threading/test_threading_large_pool.rb +90 -0
  67. data/test/threading_test.rb +87 -0
  68. data/test/unit/collection_test.rb +61 -0
  69. data/test/unit/connection_test.rb +117 -0
  70. data/test/unit/cursor_test.rb +93 -0
  71. data/test/unit/db_test.rb +98 -0
  72. metadata +127 -0
@@ -0,0 +1,34 @@
1
+ $:.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
2
+ require 'mongo'
3
+ require 'test/unit'
4
+ require 'test/test_helper'
5
+
6
+ # NOTE: this test should be run only if a replica pair is running.
7
+ class ReplicaPairCountTest < Test::Unit::TestCase
8
+ include Mongo
9
+
10
+ def setup
11
+ @conn = Mongo::Connection.new({:left => ["localhost", 27017], :right => ["localhost", 27018]}, nil)
12
+ @db = @conn.db('mongo-ruby-test')
13
+ @db.drop_collection("test-pairs")
14
+ @coll = @db.collection("test-pairs")
15
+ end
16
+
17
+ def test_correct_count_after_insertion_reconnect
18
+ @coll.insert({:a => 20}, :safe => true)
19
+ assert_equal 1, @coll.count
20
+
21
+ # Sleep to allow resync
22
+ sleep(3)
23
+
24
+ puts "Please disconnect the current master."
25
+ gets
26
+
27
+ rescue_connection_failure do
28
+ @coll.insert({:a => 30}, :safe => true)
29
+ end
30
+ @coll.insert({:a => 40}, :safe => true)
31
+ assert_equal 3, @coll.count, "Second count failed"
32
+ end
33
+
34
+ end
@@ -0,0 +1,50 @@
1
+ $:.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
2
+ require 'mongo'
3
+ require 'test/unit'
4
+ require 'test/test_helper'
5
+
6
+ # NOTE: this test should be run only if a replica pair is running.
7
+ class ReplicaPairInsertTest < Test::Unit::TestCase
8
+ include Mongo
9
+
10
+ def setup
11
+ @conn = Mongo::Connection.new({:left => ["localhost", 27017], :right => ["localhost", 27018]}, nil)
12
+ @db = @conn.db('mongo-ruby-test')
13
+ @db.drop_collection("test-pairs")
14
+ @coll = @db.collection("test-pairs")
15
+ end
16
+
17
+ def test_insert
18
+ @coll.save({:a => 20}, :safe => true)
19
+ puts "Please disconnect the current master."
20
+ gets
21
+
22
+ rescue_connection_failure do
23
+ @coll.save({:a => 30}, :safe => true)
24
+ end
25
+
26
+ @coll.save({:a => 40}, :safe => true)
27
+ @coll.save({:a => 50}, :safe => true)
28
+ @coll.save({:a => 60}, :safe => true)
29
+ @coll.save({:a => 70}, :safe => true)
30
+
31
+ puts "Please reconnect the old master to make sure that the new master " +
32
+ "has synced with the previous master. Note: this may have happened already."
33
+ gets
34
+ results = []
35
+
36
+ rescue_connection_failure do
37
+ @coll.find.each {|r| results << r}
38
+ [20, 30, 40, 50, 60, 70].each do |a|
39
+ assert results.any? {|r| r['a'] == a}, "Could not find record for a => #{a}"
40
+ end
41
+ end
42
+
43
+ @coll.save({:a => 80}, :safe => true)
44
+ @coll.find.each {|r| results << r}
45
+ [20, 30, 40, 50, 60, 70, 80].each do |a|
46
+ assert results.any? {|r| r['a'] == a}, "Could not find record for a => #{a} on second find"
47
+ end
48
+ end
49
+
50
+ end
@@ -0,0 +1,54 @@
1
+ $:.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
2
+ require 'mongo'
3
+ require 'test/unit'
4
+ require 'test/test_helper'
5
+
6
+ # NOTE: this test should be run only if a replica pair is running.
7
+ class ReplicaPairPooledInsertTest < Test::Unit::TestCase
8
+ include Mongo
9
+
10
+ def setup
11
+ @conn = Mongo::Connection.new({:left => ["localhost", 27017], :right => ["localhost", 27018]}, nil, :pool_size => 10, :timeout => 5)
12
+ @db = @conn.db('mongo-ruby-test')
13
+ @db.drop_collection("test-pairs")
14
+ @coll = @db.collection("test-pairs")
15
+ end
16
+
17
+ def test_insert
18
+ expected_results = [-1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
19
+ @coll.save({:a => -1}, :safe => true)
20
+ puts "Please disconnect the current master."
21
+ gets
22
+
23
+ threads = []
24
+ 10.times do |i|
25
+ threads[i] = Thread.new do
26
+ rescue_connection_failure do
27
+ @coll.save({:a => i}, :safe => true)
28
+ end
29
+ end
30
+ end
31
+
32
+ puts "Please reconnect the old master to make sure that the new master " +
33
+ "has synced with the previous master. Note: this may have happened already." +
34
+ "Note also that when connection with multiple threads, you may need to wait a few seconds" +
35
+ "after restarting the old master so that all the data has had a chance to sync." +
36
+ "This is a case of eventual consistency."
37
+ gets
38
+ results = []
39
+
40
+ rescue_connection_failure do
41
+ @coll.find.each {|r| results << r}
42
+ expected_results.each do |a|
43
+ assert results.any? {|r| r['a'] == a}, "Could not find record for a => #{a}"
44
+ end
45
+ end
46
+
47
+ @coll.save({:a => 10}, :safe => true)
48
+ @coll.find.each {|r| results << r}
49
+ (expected_results + [10]).each do |a|
50
+ assert results.any? {|r| r['a'] == a}, "Could not find record for a => #{a} on second find"
51
+ end
52
+ end
53
+
54
+ end
@@ -0,0 +1,39 @@
1
+ $:.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
2
+ require 'mongo'
3
+ require 'test/unit'
4
+ require 'test/test_helper'
5
+
6
+ # NOTE: this test should be run only if a replica pair is running.
7
+ class ReplicaPairQueryTest < Test::Unit::TestCase
8
+ include Mongo
9
+
10
+ def setup
11
+ @conn = Mongo::Connection.new({:left => ["localhost", 27017], :right => ["localhost", 27018]}, nil)
12
+ @db = @conn.db('mongo-ruby-test')
13
+ @db.drop_collection("test-pairs")
14
+ @coll = @db.collection("test-pairs")
15
+ end
16
+
17
+ def test_query
18
+ @coll.save({:a => 20})
19
+ @coll.save({:a => 30})
20
+ @coll.save({:a => 40})
21
+ results = []
22
+ @coll.find.each {|r| results << r}
23
+ [20, 30, 40].each do |a|
24
+ assert results.any? {|r| r['a'] == a}, "Could not find record for a => #{a}"
25
+ end
26
+
27
+ puts "Please disconnect the current master."
28
+ gets
29
+
30
+ results = []
31
+ rescue_connection_failure do
32
+ @coll.find.each {|r| results << r}
33
+ [20, 30, 40].each do |a|
34
+ assert results.any? {|r| r['a'] == a}, "Could not find record for a => #{a}"
35
+ end
36
+ end
37
+ end
38
+
39
+ end
@@ -0,0 +1,36 @@
1
+ require 'test/test_helper'
2
+
3
+ # NOTE: these tests are run only if we can connect to a single MongoDB in slave mode.
4
+ class SlaveConnectionTest < Test::Unit::TestCase
5
+ include Mongo
6
+
7
+ def self.connect_to_slave
8
+ @@host = ENV['MONGO_RUBY_DRIVER_HOST'] || 'localhost'
9
+ @@port = ENV['MONGO_RUBY_DRIVER_PORT'] || Connection::DEFAULT_PORT
10
+ conn = Connection.new(@@host, @@port, :slave_ok => true)
11
+ cmd = conn['admin'].command(:ismaster => 1)
12
+ cmd['ok'] == 1 && cmd['ismaster'] != 1
13
+ end
14
+
15
+ if self.connect_to_slave
16
+ puts "Connected to slave; running slave tests."
17
+
18
+ def test_connect_to_slave
19
+ assert_raise Mongo::ConfigurationError do
20
+ @db = Connection.new(@@host, @@port, :slave_ok => false).db('ruby-mongo-demo')
21
+ end
22
+ end
23
+
24
+ def test_slave_ok_sent_to_queries
25
+ @db = Connection.new(@@host, @@port, :slave_ok => true).db('ruby-mongo-demo')
26
+ assert_equal true, @db.slave_ok?
27
+ end
28
+ else
29
+ puts "Not connected to slave; skipping slave connection tests."
30
+
31
+ def test_slave_ok_false_on_queries
32
+ @conn = Connection.new(@@host, @@port)
33
+ assert !@conn.slave_ok?
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,42 @@
1
+ $:.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
2
+ require 'rubygems' if ENV['C_EXT']
3
+ require 'mongo'
4
+ require 'test/unit'
5
+
6
+ begin
7
+ require 'rubygems'
8
+ require 'shoulda'
9
+ require 'mocha'
10
+ rescue LoadError
11
+ puts <<MSG
12
+
13
+ This test suite requires shoulda and mocha.
14
+ You can install them as follows:
15
+ gem install shoulda
16
+ gem install mocha
17
+
18
+ MSG
19
+ exit
20
+ end
21
+
22
+ require 'mongo_ext/cbson' if ENV['C_EXT']
23
+
24
+ # NOTE: most tests assume that MongoDB is running.
25
+ class Test::Unit::TestCase
26
+ include Mongo
27
+
28
+ # Generic code for rescuing connection failures and retrying operations.
29
+ # This could be combined with some timeout functionality.
30
+ def rescue_connection_failure
31
+ success = false
32
+ while !success
33
+ begin
34
+ yield
35
+ success = true
36
+ rescue Mongo::ConnectionFailure
37
+ puts "Rescuing"
38
+ sleep(1)
39
+ end
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,90 @@
1
+ require 'test/test_helper'
2
+
3
+ # Essentialy the same as test_threading.rb but with an expanded pool for
4
+ # testing multiple connections.
5
+ class TestThreadingLargePool < Test::Unit::TestCase
6
+
7
+ include Mongo
8
+
9
+ @@db = Connection.new('localhost', 27017, :pool_size => 50, :timeout => 60).db('ruby-mongo-test')
10
+ @@coll = @@db.collection('thread-test-collection')
11
+
12
+ def set_up_safe_data
13
+ @@db.drop_collection('duplicate')
14
+ @@db.drop_collection('unique')
15
+ @duplicate = @@db.collection('duplicate')
16
+ @unique = @@db.collection('unique')
17
+
18
+ @duplicate.insert("test" => "insert")
19
+ @duplicate.insert("test" => "update")
20
+ @unique.insert("test" => "insert")
21
+ @unique.insert("test" => "update")
22
+ @unique.create_index("test", true)
23
+ end
24
+
25
+ def test_safe_update
26
+ set_up_safe_data
27
+ threads = []
28
+ 300.times do |i|
29
+ threads[i] = Thread.new do
30
+ if i % 2 == 0
31
+ assert_raise Mongo::OperationFailure do
32
+ @unique.update({"test" => "insert"}, {"$set" => {"test" => "update"}}, :safe => true)
33
+ end
34
+ else
35
+ @duplicate.update({"test" => "insert"}, {"$set" => {"test" => "update"}}, :safe => true)
36
+ end
37
+ end
38
+ end
39
+
40
+ 300.times do |i|
41
+ threads[i].join
42
+ end
43
+ end
44
+
45
+ def test_safe_insert
46
+ set_up_safe_data
47
+ threads = []
48
+ 300.times do |i|
49
+ threads[i] = Thread.new do
50
+ if i % 2 == 0
51
+ assert_raise Mongo::OperationFailure do
52
+ @unique.insert({"test" => "insert"}, :safe => true)
53
+ end
54
+ else
55
+ @duplicate.insert({"test" => "insert"}, :safe => true)
56
+ end
57
+ end
58
+ end
59
+
60
+ 300.times do |i|
61
+ threads[i].join
62
+ end
63
+ end
64
+
65
+ def test_threading
66
+ @@coll.drop
67
+ @@coll = @@db.collection('thread-test-collection')
68
+
69
+ 1000.times do |i|
70
+ @@coll.insert("x" => i)
71
+ end
72
+
73
+ threads = []
74
+
75
+ 10.times do |i|
76
+ threads[i] = Thread.new do
77
+ sum = 0
78
+ @@coll.find().each do |document|
79
+ sum += document["x"]
80
+ end
81
+ assert_equal 499500, sum
82
+ end
83
+ end
84
+
85
+ 10.times do |i|
86
+ threads[i].join
87
+ end
88
+ end
89
+
90
+ end
@@ -0,0 +1,87 @@
1
+ require 'test/test_helper'
2
+
3
+ class TestThreading < Test::Unit::TestCase
4
+
5
+ include Mongo
6
+
7
+ @@db = Connection.new('localhost', 27017, :pool_size => 1, :timeout => 30).db('ruby-mongo-test')
8
+ @@coll = @@db.collection('thread-test-collection')
9
+
10
+ def set_up_safe_data
11
+ @@db.drop_collection('duplicate')
12
+ @@db.drop_collection('unique')
13
+ @duplicate = @@db.collection('duplicate')
14
+ @unique = @@db.collection('unique')
15
+
16
+ @duplicate.insert("test" => "insert")
17
+ @duplicate.insert("test" => "update")
18
+ @unique.insert("test" => "insert")
19
+ @unique.insert("test" => "update")
20
+ @unique.create_index("test", true)
21
+ end
22
+
23
+ def test_safe_update
24
+ set_up_safe_data
25
+ threads = []
26
+ 100.times do |i|
27
+ threads[i] = Thread.new do
28
+ if i % 2 == 0
29
+ assert_raise Mongo::OperationFailure do
30
+ @unique.update({"test" => "insert"}, {"$set" => {"test" => "update"}}, :safe => true)
31
+ end
32
+ else
33
+ @duplicate.update({"test" => "insert"}, {"$set" => {"test" => "update"}}, :safe => true)
34
+ end
35
+ end
36
+ end
37
+
38
+ 100.times do |i|
39
+ threads[i].join
40
+ end
41
+ end
42
+
43
+ def test_safe_insert
44
+ set_up_safe_data
45
+ threads = []
46
+ 100.times do |i|
47
+ threads[i] = Thread.new do
48
+ if i % 2 == 0
49
+ assert_raise Mongo::OperationFailure do
50
+ @unique.insert({"test" => "insert"}, :safe => true)
51
+ end
52
+ else
53
+ @duplicate.insert({"test" => "insert"}, :safe => true)
54
+ end
55
+ end
56
+ end
57
+
58
+ 100.times do |i|
59
+ threads[i].join
60
+ end
61
+ end
62
+
63
+ def test_threading
64
+ @@coll.drop
65
+ @@coll = @@db.collection('thread-test-collection')
66
+
67
+ 1000.times do |i|
68
+ @@coll.insert("x" => i)
69
+ end
70
+
71
+ threads = []
72
+
73
+ 10.times do |i|
74
+ threads[i] = Thread.new do
75
+ sum = 0
76
+ @@coll.find().each do |document|
77
+ sum += document["x"]
78
+ end
79
+ assert_equal 499500, sum
80
+ end
81
+ end
82
+
83
+ 10.times do |i|
84
+ threads[i].join
85
+ end
86
+ end
87
+ end
@@ -0,0 +1,61 @@
1
+ require 'test/test_helper'
2
+
3
+ class CollectionTest < Test::Unit::TestCase
4
+
5
+ context "Basic operations: " do
6
+ setup do
7
+ @logger = mock()
8
+ end
9
+
10
+ should "send update message" do
11
+ @conn = Connection.new('localhost', 27017, :logger => @logger, :connect => false)
12
+ @db = @conn['testing']
13
+ @coll = @db.collection('books')
14
+ @conn.expects(:send_message).with do |op, msg, log|
15
+ op == 2001 && log.include?("db.books.update")
16
+ end
17
+ @coll.update({}, {:title => 'Moby Dick'})
18
+ end
19
+
20
+ should "send insert message" do
21
+ @conn = Connection.new('localhost', 27017, :logger => @logger, :connect => false)
22
+ @db = @conn['testing']
23
+ @coll = @db.collection('books')
24
+ @conn.expects(:send_message).with do |op, msg, log|
25
+ op == 2002 && log.include?("db.books.insert")
26
+ end
27
+ @coll.insert({:title => 'Moby Dick'})
28
+ end
29
+
30
+ should "not log binary data" do
31
+ @conn = Connection.new('localhost', 27017, :logger => @logger, :connect => false)
32
+ @db = @conn['testing']
33
+ @coll = @db.collection('books')
34
+ data = Mongo::Binary.new(("BINARY " * 1000).unpack("c*"))
35
+ @conn.expects(:send_message).with do |op, msg, log|
36
+ op == 2002 && log.include?("Mongo::Binary")
37
+ end
38
+ @coll.insert({:data => data})
39
+ end
40
+
41
+ should "send safe update message" do
42
+ @conn = Connection.new('localhost', 27017, :logger => @logger, :connect => false)
43
+ @db = @conn['testing']
44
+ @coll = @db.collection('books')
45
+ @conn.expects(:send_message_with_safe_check).with do |op, msg, db_name, log|
46
+ op == 2001 && log.include?("db.books.update")
47
+ end
48
+ @coll.update({}, {:title => 'Moby Dick'}, :safe => true)
49
+ end
50
+
51
+ should "send safe insert message" do
52
+ @conn = Connection.new('localhost', 27017, :logger => @logger, :connect => false)
53
+ @db = @conn['testing']
54
+ @coll = @db.collection('books')
55
+ @conn.expects(:send_message_with_safe_check).with do |op, msg, db_name, log|
56
+ op == 2001 && log.include?("db.books.update")
57
+ end
58
+ @coll.update({}, {:title => 'Moby Dick'}, :safe => true)
59
+ end
60
+ end
61
+ end
@@ -0,0 +1,117 @@
1
+ require 'test/test_helper'
2
+ include Mongo
3
+
4
+ class ConnectionTest < Test::Unit::TestCase
5
+ context "Initialization: " do
6
+ setup do
7
+ def new_mock_socket
8
+ socket = Object.new
9
+ socket.stubs(:setsockopt).with(Socket::IPPROTO_TCP, Socket::TCP_NODELAY, 1)
10
+ socket
11
+ end
12
+
13
+ def new_mock_db
14
+ db = Object.new
15
+ end
16
+ end
17
+
18
+ context "given a single node" do
19
+ setup do
20
+ TCPSocket.stubs(:new).returns(new_mock_socket)
21
+ @conn = Connection.new('localhost', 27017, :connect => false)
22
+
23
+ admin_db = new_mock_db
24
+ admin_db.expects(:command).returns({'ok' => 1, 'ismaster' => 1})
25
+ @conn.expects(:[]).with('admin').returns(admin_db)
26
+ @conn.connect_to_master
27
+ end
28
+
29
+ should "set localhost and port to master" do
30
+ assert_equal 'localhost', @conn.host
31
+ assert_equal 27017, @conn.port
32
+ end
33
+
34
+ should "set connection pool to 1" do
35
+ assert_equal 1, @conn.size
36
+ end
37
+
38
+ should "default slave_ok to false" do
39
+ assert !@conn.slave_ok?
40
+ end
41
+ end
42
+
43
+ context "initializing a paired connection" do
44
+ should "require left and right nodes" do
45
+ assert_raise MongoArgumentError do
46
+ Connection.paired(['localhost', 27018], :connect => false)
47
+ end
48
+
49
+ assert_raise MongoArgumentError do
50
+ Connection.paired(['localhost', 27018], :connect => false)
51
+ end
52
+ end
53
+
54
+ should "store both nodes" do
55
+ @conn = Connection.paired([['localhost', 27017], ['localhost', 27018]], :connect => false)
56
+
57
+ assert_equal ['localhost', 27017], @conn.nodes[0]
58
+ assert_equal ['localhost', 27018], @conn.nodes[1]
59
+ end
60
+ end
61
+
62
+ context "initializing with a mongodb uri" do
63
+ should "parse a simple uri" do
64
+ @conn = Connection.from_uri("mongodb://localhost", :connect => false)
65
+ assert_equal ['localhost', 27017], @conn.nodes[0]
66
+ end
67
+
68
+ should "parse a uri specifying multiple nodes" do
69
+ @conn = Connection.from_uri("mongodb://localhost:27017,mydb.com:27018", :connect => false)
70
+ assert_equal ['localhost', 27017], @conn.nodes[0]
71
+ assert_equal ['mydb.com', 27018], @conn.nodes[1]
72
+ end
73
+
74
+ should "parse a uri specifying multiple nodes with auth" do
75
+ @conn = Connection.from_uri("mongodb://kyle:s3cr3t@localhost:27017/app,mickey:m0u5e@mydb.com:27018/dsny", :connect => false)
76
+ assert_equal ['localhost', 27017], @conn.nodes[0]
77
+ assert_equal ['mydb.com', 27018], @conn.nodes[1]
78
+ assert_equal ['kyle', 's3cr3t', 'app'], @conn.auths[0]
79
+ assert_equal ['mickey', 'm0u5e', 'dsny'], @conn.auths[1]
80
+ end
81
+
82
+ should "attempt to connect" do
83
+ TCPSocket.stubs(:new).returns(new_mock_socket)
84
+ @conn = Connection.from_uri("mongodb://localhost", :connect => false)
85
+
86
+ admin_db = new_mock_db
87
+ admin_db.expects(:command).returns({'ok' => 1, 'ismaster' => 1})
88
+ @conn.expects(:[]).with('admin').returns(admin_db)
89
+ @conn.connect_to_master
90
+ end
91
+
92
+ should "raise an error on invalid uris" do
93
+ assert_raise MongoArgumentError do
94
+ Connection.from_uri("mongo://localhost", :connect => false)
95
+ end
96
+
97
+ assert_raise MongoArgumentError do
98
+ Connection.from_uri("mongodb://localhost:abc", :connect => false)
99
+ end
100
+
101
+ assert_raise MongoArgumentError do
102
+ Connection.from_uri("mongodb://localhost:27017, my.db.com:27018, ", :connect => false)
103
+ end
104
+ end
105
+
106
+ should "require all of username, password, and database if any one is specified" do
107
+ assert_raise MongoArgumentError do
108
+ Connection.from_uri("mongodb://localhost/db", :connect => false)
109
+ end
110
+
111
+ assert_raise MongoArgumentError do
112
+ Connection.from_uri("mongodb://kyle:password@localhost", :connect => false)
113
+ end
114
+ end
115
+ end
116
+ end
117
+ end