mongo 1.8.4 → 1.8.5

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 (51) hide show
  1. checksums.yaml +6 -14
  2. checksums.yaml.gz.sig +0 -0
  3. data.tar.gz.sig +0 -0
  4. data/README.md +2 -0
  5. data/VERSION +1 -1
  6. data/lib/mongo.rb +11 -9
  7. data/lib/mongo/collection.rb +26 -19
  8. data/lib/mongo/cursor.rb +7 -2
  9. data/lib/mongo/db.rb +1 -1
  10. data/lib/mongo/mongo_client.rb +1 -1
  11. data/lib/mongo/mongo_replica_set_client.rb +2 -3
  12. data/lib/mongo/mongo_sharded_client.rb +1 -2
  13. data/lib/mongo/util/node.rb +12 -14
  14. data/lib/mongo/util/pool.rb +1 -1
  15. data/lib/mongo/util/pool_manager.rb +13 -15
  16. data/lib/mongo/util/sharding_pool_manager.rb +5 -2
  17. data/lib/mongo/util/support.rb +14 -0
  18. data/mongo.gemspec +7 -3
  19. data/test/functional/authentication_test.rb +21 -0
  20. data/test/functional/collection_test.rb +0 -1
  21. data/test/functional/connection_test.rb +1 -1
  22. data/test/functional/db_test.rb +1 -56
  23. data/test/functional/support_test.rb +30 -0
  24. data/test/replica_set/authentication_test.rb +23 -0
  25. data/test/replica_set/max_values_test.rb +61 -0
  26. data/test/sharded_cluster/basic_test.rb +18 -0
  27. data/test/shared/authentication.rb +49 -0
  28. data/test/tools/mongo_config.rb +21 -26
  29. data/test/unit/node_test.rb +3 -0
  30. data/test/unit/pool_manager_test.rb +3 -1
  31. data/test/unit/read_test.rb +4 -0
  32. data/test/unit/sharding_pool_manager_test.rb +88 -0
  33. metadata +38 -69
  34. metadata.gz.sig +0 -0
  35. data/test/auxillary/1.4_feature_test.rb +0 -165
  36. data/test/auxillary/authentication_test.rb +0 -74
  37. data/test/auxillary/autoreconnect_test.rb +0 -39
  38. data/test/auxillary/fork_test.rb +0 -28
  39. data/test/auxillary/pool_reuse_test.rb +0 -65
  40. data/test/auxillary/repl_set_auth_test.rb +0 -69
  41. data/test/auxillary/slave_connection_test.rb +0 -37
  42. data/test/auxillary/threaded_authentication_test.rb +0 -99
  43. data/test/bson/binary_test.rb +0 -13
  44. data/test/bson/bson_test.rb +0 -762
  45. data/test/bson/byte_buffer_test.rb +0 -215
  46. data/test/bson/hash_with_indifferent_access_test.rb +0 -48
  47. data/test/bson/json_test.rb +0 -16
  48. data/test/bson/object_id_test.rb +0 -153
  49. data/test/bson/ordered_hash_test.rb +0 -247
  50. data/test/bson/timestamp_test.rb +0 -51
  51. data/test/tools/auth_repl_set_manager.rb +0 -14
@@ -1272,7 +1272,6 @@ end
1272
1272
  should "create a geoHaystack index" do
1273
1273
  @geo.save({ "_id" => 100, "pos" => { "long" => 126.9, "lat" => 35.2 }, "type" => "restaurant"})
1274
1274
  @geo.create_index([['pos', Mongo::GEOHAYSTACK], ['type', Mongo::ASCENDING]], :bucket_size => 1)
1275
- puts @geo.index_information['loc_geoHaystack_type_1']
1276
1275
  end
1277
1276
 
1278
1277
  should "create a geo 2dsphere index" do
@@ -309,7 +309,7 @@ class TestConnection < Test::Unit::TestCase
309
309
  conn.expects(:[]).with('admin').returns(admin_db)
310
310
 
311
311
  conn.connect
312
- assert_equal Mongo::DEFAULT_MAX_MESSAGE_SIZE, conn.max_message_size
312
+ assert_equal Mongo::DEFAULT_MAX_BSON_SIZE * Mongo::MESSAGE_SIZE_FACTOR, conn.max_message_size
313
313
  end
314
314
 
315
315
  def test_connection_activity
@@ -131,47 +131,6 @@ class DBTest < Test::Unit::TestCase
131
131
  end
132
132
  end
133
133
 
134
- def test_authenticate
135
- @@db.add_user('spongebob', 'squarepants')
136
- assert_raise Mongo::AuthenticationError do
137
- assert !@@db.authenticate('nobody', 'nopassword')
138
- end
139
- assert_raise Mongo::AuthenticationError do
140
- assert !@@db.authenticate('spongebob' , 'squareliederhosen')
141
- end
142
- assert @@db.authenticate('spongebob', 'squarepants')
143
- @@db.logout
144
- @@db.remove_user('spongebob')
145
- end
146
-
147
- def test_authenticate_with_special_characters
148
- assert @@db.add_user('foo:bar', '@foo')
149
- assert @@db.authenticate('foo:bar', '@foo')
150
- @@db.logout
151
- @@db.remove_user('foo:bar')
152
- end
153
-
154
- def test_authenticate_read_only
155
- @@db.add_user('joebob', 'user', true) # read-only user
156
- assert @@db.authenticate('joebob', 'user')
157
- @@db.logout
158
- @@db.remove_user('joebob')
159
- end
160
-
161
- def test_authenticate_with_connection_uri
162
- @@db.add_user('spongebob', 'squarepants')
163
- assert Mongo::MongoClient.from_uri("mongodb://spongebob:squarepants@#{host_port}/#{@@db.name}")
164
-
165
- assert_raise Mongo::AuthenticationError do
166
- client = Mongo::MongoClient.from_uri("mongodb://wrong:info@#{host_port}/#{@@db.name}")
167
- client['test']['foo'].find_one
168
- end
169
- end
170
-
171
- def test_logout
172
- assert @@db.logout
173
- end
174
-
175
134
  def test_command
176
135
  assert_raise OperationFailure do
177
136
  @@db.command({:non_command => 1}, :check_response => true)
@@ -249,25 +208,11 @@ class DBTest < Test::Unit::TestCase
249
208
  db.collection('users').remove
250
209
  end
251
210
 
252
- def test_user_management
253
- @@db.add_user("bob", "secret")
254
- assert @@db.authenticate("bob", "secret")
255
- @@db.logout
256
- assert @@db.remove_user("bob")
257
- assert_raise Mongo::AuthenticationError do
258
- @@db.authenticate("bob", "secret")
259
- end
260
- end
261
-
262
- def test_remove_non_existant_user
263
- assert !@@db.remove_user("joe")
264
- end
265
-
266
211
  def test_stored_function_management
267
212
  @@db.add_stored_function("sum", "function (x, y) { return x + y; }")
268
213
  assert_equal @@db.eval("return sum(2,3);"), 5
269
214
  assert @@db.remove_stored_function("sum")
270
- assert_raise OperationFailure do
215
+ assert_raise OperationFailure do
271
216
  @@db.eval("return sum(2,3);")
272
217
  end
273
218
  end
@@ -15,4 +15,34 @@ class SupportTest < Test::Unit::TestCase
15
15
  assert !Support.ok?('ok' => 'str')
16
16
  assert !Support.ok?('ok' => false)
17
17
  end
18
+
19
+ def test_array_of_pairs
20
+ hps = [["localhost", 27017], ["localhost", 27018], ["localhost", 27019]]
21
+ assert_equal [["localhost", 27017], ["localhost", 27018], ["localhost", 27019]], Support.normalize_seeds(hps)
22
+ end
23
+
24
+ def test_array_of_strings
25
+ hps = ["localhost:27017", "localhost:27018", "localhost:27019"]
26
+ assert_equal [["localhost", 27017], ["localhost", 27018], ["localhost", 27019]], Support.normalize_seeds(hps)
27
+ end
28
+
29
+ def test_single_string_with_host_port
30
+ hps = "localhost:27017"
31
+ assert_equal ["localhost", 27017], Support.normalize_seeds(hps)
32
+ end
33
+
34
+ def test_single_string_missing_port
35
+ hps = "localhost"
36
+ assert_equal ["localhost", 27017], Support.normalize_seeds(hps)
37
+ end
38
+
39
+ def test_single_element_array_missing_port
40
+ hps = ["localhost"]
41
+ assert_equal ["localhost", 27017], Support.normalize_seeds(hps)
42
+ end
43
+
44
+ def test_pair_doesnt_get_converted
45
+ hps = ["localhost", 27017]
46
+ assert_equal ["localhost", 27017], Support.normalize_seeds(hps)
47
+ end
18
48
  end
@@ -0,0 +1,23 @@
1
+ require 'test_helper'
2
+ require 'shared/authentication'
3
+
4
+ class ReplicaSetAuthenticationTest < Test::Unit::TestCase
5
+ include Mongo
6
+ include AuthenticationTests
7
+
8
+ def setup
9
+ ensure_cluster(:rs)
10
+ @client = MongoReplicaSetClient.new(@rs.repl_set_seeds, :name => @rs.repl_set_name, :connect_timeout => 60)
11
+ @db = @client[MONGO_TEST_DB]
12
+ end
13
+
14
+ def teardown
15
+ @db['system.users'].remove
16
+ end
17
+
18
+ def test_authenticate_with_connection_uri
19
+ @db.add_user('eunice', 'uritest')
20
+ assert MongoReplicaSetClient.from_uri(
21
+ "mongodb://eunice:uritest@#{@rs.repl_set_seeds.join(',')}/#{@db.name}?replicaSet=#{@rs.repl_set_name}")
22
+ end
23
+ end
@@ -0,0 +1,61 @@
1
+ require 'test_helper'
2
+
3
+ class MaxValuesTest < Test::Unit::TestCase
4
+
5
+ include Mongo
6
+
7
+ def setup
8
+ ensure_cluster(:rs)
9
+ @client = MongoReplicaSetClient.new(@rs.repl_set_seeds, :name => @rs.repl_set_name)
10
+ end
11
+
12
+ def test_initial_max_sizes
13
+ assert @client.max_message_size
14
+ assert @client.max_bson_size
15
+ end
16
+
17
+ def test_updated_max_sizes_after_node_config_change
18
+ # stub max sizes for one member
19
+ @client.local_manager.members.each_with_index do |m, i|
20
+ if i % 2 == 0
21
+ m.stubs(:config).returns({'maxMessageSizeBytes' => 1024 * MESSAGE_SIZE_FACTOR, 'maxBsonObjectSize' => 1024})
22
+ m.set_config
23
+ end
24
+ end
25
+
26
+ assert_equal 1024, @client.max_bson_size
27
+ assert_equal 1024 * MESSAGE_SIZE_FACTOR, @client.max_message_size
28
+ end
29
+
30
+ def test_neither_max_sizes_in_config
31
+ @client.local_manager.members.each do |m|
32
+ m.stubs(:config).returns({})
33
+ m.set_config
34
+ end
35
+
36
+ assert_equal DEFAULT_MAX_BSON_SIZE, @client.max_bson_size
37
+ assert_equal DEFAULT_MAX_BSON_SIZE * MESSAGE_SIZE_FACTOR, @client.max_message_size
38
+ end
39
+
40
+ def test_only_bson_size_in_config
41
+ @client.local_manager.members.each do |m|
42
+ m.stubs(:config).returns({'maxBsonObjectSize' => 1024})
43
+ m.set_config
44
+ end
45
+ assert_equal 1024, @client.max_bson_size
46
+ assert_equal 1024 * MESSAGE_SIZE_FACTOR, @client.max_message_size
47
+ end
48
+
49
+ def test_both_sizes_in_config
50
+ @client.local_manager.members.each do |m|
51
+ m.stubs(:config).returns({'maxMessageSizeBytes' => 1024 * 2 * MESSAGE_SIZE_FACTOR,
52
+ 'maxBsonObjectSize' => 1024})
53
+ m.set_config
54
+ end
55
+
56
+ assert_equal 1024, @client.max_bson_size
57
+ assert_equal 1024 * 2 * MESSAGE_SIZE_FACTOR, @client.max_message_size
58
+ end
59
+
60
+ end
61
+
@@ -89,6 +89,24 @@ class BasicTest < Test::Unit::TestCase
89
89
  @client.close
90
90
  end
91
91
 
92
+ def test_mongos_failover
93
+ @client = MongoShardedClient.new(@seeds, :refresh_interval => 5, :refresh_mode => :sync)
94
+ assert @client.connected?
95
+ # do a find to pin a pool
96
+ @client['MONGO_TEST_DB']['test'].find_one
97
+ original_primary = @client.manager.primary
98
+ # stop the pinned member
99
+ @sc.member_by_name("#{original_primary[0]}:#{original_primary[1]}").stop
100
+ # assert that the client fails over to the next available mongos
101
+ assert_nothing_raised do
102
+ @client['MONGO_TEST_DB']['test'].find_one
103
+ end
104
+
105
+ assert_not_equal original_primary, @client.manager.primary
106
+ assert @client.connected?
107
+ @client.close
108
+ end
109
+
92
110
  def test_all_down
93
111
  @client = MongoShardedClient.new(@seeds)
94
112
  assert @client.connected?
@@ -0,0 +1,49 @@
1
+ module AuthenticationTests
2
+ def test_add_user
3
+ @db.add_user('bob','user')
4
+ assert @db['system.users'].find_one({:user => 'bob'})
5
+ end
6
+
7
+ def test_remove_user
8
+ @db.remove_user('bob')
9
+ assert_nil @db['system.users'].find_one({:user => 'bob'})
10
+ end
11
+
12
+ def test_remove_non_existent_user
13
+ assert_equal @db.remove_user('joe'), false
14
+ end
15
+
16
+ def test_authenticate
17
+ @db.add_user('peggy', 'user')
18
+ assert @db.authenticate('peggy', 'user')
19
+ @db.remove_user('peggy')
20
+ @db.logout
21
+ end
22
+
23
+ def test_authenticate_non_existent_user
24
+ assert_raise Mongo::AuthenticationError do
25
+ @db.authenticate('frank', 'thetank')
26
+ end
27
+ end
28
+
29
+ def test_logout
30
+ @db.add_user('peggy', 'user')
31
+ assert @db.authenticate('peggy', 'user')
32
+ assert @db.logout
33
+ @db.remove_user('peggy')
34
+ end
35
+
36
+ def test_authenticate_with_special_characters
37
+ assert @db.add_user('foo:bar','@foo')
38
+ assert @db.authenticate('foo:bar','@foo')
39
+ @db.remove_user('foo:bar')
40
+ @db.logout
41
+ end
42
+
43
+ def test_authenticate_read_only
44
+ @db.add_user('randy', 'readonly', true)
45
+ assert @db.authenticate('randy', 'readonly')
46
+ @db.remove_user('randy')
47
+ @db.logout
48
+ end
49
+ end
@@ -24,7 +24,7 @@ end
24
24
  #
25
25
  module Mongo
26
26
  class Config
27
- DEFAULT_BASE_OPTS = { :host => 'localhost', :dbpath => 'data', :logpath => 'data/log'}
27
+ DEFAULT_BASE_OPTS = { :host => 'localhost', :dbpath => 'data', :logpath => 'data/log' }
28
28
  DEFAULT_REPLICA_SET = DEFAULT_BASE_OPTS.merge( :replicas => 3, :arbiters => 0 )
29
29
  DEFAULT_SHARDED_SIMPLE = DEFAULT_BASE_OPTS.merge( :shards => 2, :configs => 1, :routers => 4 )
30
30
  DEFAULT_SHARDED_REPLICA = DEFAULT_SHARDED_SIMPLE.merge( :replicas => 3, :arbiters => 0)
@@ -80,51 +80,46 @@ module Mongo
80
80
  end
81
81
 
82
82
  def self.make_mongo(kind, opts)
83
- dbpath = opts[:dbpath]
84
- port = self.get_available_port
85
- path = "#{dbpath}/#{kind}-#{port}"
83
+ dbpath = opts[:dbpath]
84
+ port = self.get_available_port
85
+ path = "#{dbpath}/#{kind}-#{port}"
86
86
  logpath = "#{path}/#{kind}.log"
87
87
 
88
- {
89
- :host => opts[:host],
90
- :port => port,
91
- :logpath => logpath,
92
- :logappend => true
93
- }
88
+ { :host => opts[:host],
89
+ :port => port,
90
+ :logpath => logpath,
91
+ :logappend => true }
94
92
  end
95
93
 
96
94
  def self.make_mongod(kind, opts)
97
95
  params = make_mongo('mongods', opts)
98
96
 
99
97
  mongod = ENV['MONGOD'] || 'mongod'
100
- path = File.dirname(params[:logpath])
98
+ path = File.dirname(params[:logpath])
101
99
 
102
100
  noprealloc = opts[:noprealloc] || true
103
101
  smallfiles = opts[:smallfiles] || true
104
102
  quiet = opts[:quiet] || true
105
103
  fast_sync = opts[:fastsync] || false
106
-
107
- params.merge(
108
- :command => mongod,
109
- :dbpath => path,
110
- :smallfiles => smallfiles,
111
- :noprealloc => noprealloc,
112
- :quiet => quiet,
113
- :fastsync => fast_sync
114
- )
104
+ auth = opts[:auth] || true
105
+
106
+ params.merge(:command => mongod,
107
+ :dbpath => path,
108
+ :smallfiles => smallfiles,
109
+ :noprealloc => noprealloc,
110
+ :quiet => quiet,
111
+ :fastsync => fast_sync)
115
112
  end
116
113
 
117
114
  def self.make_replica(opts, count)
118
- params = make_mongod('replicas', opts)
115
+ params = make_mongod('replicas', opts)
119
116
 
120
117
  replSet = opts[:replSet] || 'ruby-driver-test'
121
118
  oplog_size = opts[:oplog_size] || 5
122
119
 
123
- params.merge(
124
- :_id => count,
125
- :replSet => replSet,
126
- :oplogSize => oplog_size
127
- )
120
+ params.merge(:_id => count,
121
+ :replSet => replSet,
122
+ :oplogSize => oplog_size)
128
123
  end
129
124
 
130
125
  def self.make_config(opts)
@@ -4,6 +4,9 @@ class NodeTest < Test::Unit::TestCase
4
4
 
5
5
  def setup
6
6
  @client = stub()
7
+ manager = mock('pool_manager')
8
+ manager.stubs(:update_max_sizes)
9
+ @client.stubs(:local_manager).returns(manager)
7
10
  end
8
11
 
9
12
  should "refuse to connect to node without 'hosts' key" do
@@ -52,6 +52,7 @@ class PoolManagerTest < Test::Unit::TestCase
52
52
 
53
53
  seeds = [['localhost', 27017]]
54
54
  manager = Mongo::PoolManager.new(@client, seeds)
55
+ @client.stubs(:local_manager).returns(manager)
55
56
  manager.connect
56
57
 
57
58
  assert_equal ['localhost', 27017], manager.primary
@@ -77,7 +78,8 @@ class PoolManagerTest < Test::Unit::TestCase
77
78
  )
78
79
 
79
80
  seeds = [['localhost', 27017]]
80
- manager = Mongo::PoolManager.new(@client, seeds)
81
+ manager = PoolManager.new(@client, seeds)
82
+ @client.stubs(:local_manager).returns(manager)
81
83
  manager.connect
82
84
 
83
85
  assert_equal ['localhost', 27018], manager.primary
@@ -106,6 +106,8 @@ class ReadTest < Test::Unit::TestCase
106
106
  sock = new_mock_socket
107
107
  read_pool = stub(:checkin => true)
108
108
  @client.stubs(:read_pool).returns(read_pool)
109
+ local_manager = PoolManager.new(@client, @client.seeds)
110
+ @client.stubs(:local_manager).returns(local_manager)
109
111
  primary_pool = stub(:checkin => true)
110
112
  sock.stubs(:pool).returns(primary_pool)
111
113
  @client.stubs(:primary_pool).returns(primary_pool)
@@ -120,6 +122,8 @@ class ReadTest < Test::Unit::TestCase
120
122
  should "allow override default value on query" do
121
123
  @cursor = @col.find({:a => 1}, :read => :primary)
122
124
  sock = new_mock_socket
125
+ local_manager = PoolManager.new(@client, @client.seeds)
126
+ @client.stubs(:local_manager).returns(local_manager)
123
127
  primary_pool = stub(:checkin => true)
124
128
  sock.stubs(:pool).returns(primary_pool)
125
129
  @client.stubs(:primary_pool).returns(primary_pool)
@@ -0,0 +1,88 @@
1
+ require 'test_helper'
2
+ include Mongo
3
+
4
+ class ShardingPoolManagerTest < Test::Unit::TestCase
5
+
6
+ context "Initialization: " do
7
+
8
+ setup do
9
+ TCPSocket.stubs(:new).returns(new_mock_socket)
10
+ @db = new_mock_db
11
+
12
+ @client = stub("MongoShardedClient")
13
+ @client.stubs(:connect_timeout).returns(5)
14
+ @client.stubs(:op_timeout).returns(5)
15
+ @client.stubs(:pool_size).returns(2)
16
+ @client.stubs(:pool_timeout).returns(100)
17
+ @client.stubs(:socket_class).returns(TCPSocket)
18
+ @client.stubs(:mongos?).returns(true)
19
+ @client.stubs(:[]).returns(@db)
20
+
21
+ @client.stubs(:replica_set_name).returns(nil)
22
+ @client.stubs(:log)
23
+ @arbiters = ['localhost:27020']
24
+ @hosts = [
25
+ 'localhost:27017',
26
+ 'localhost:27018',
27
+ 'localhost:27019'
28
+ ]
29
+
30
+ @ismaster = {
31
+ 'hosts' => @hosts,
32
+ 'arbiters' => @arbiters,
33
+ 'maxMessageSizeBytes' => 1024 * 2.5,
34
+ 'maxBsonObjectSize' => 1024
35
+ }
36
+ end
37
+
38
+ should "populate pools correctly" do
39
+
40
+ @db.stubs(:command).returns(
41
+ # First call to get a socket.
42
+ @ismaster.merge({'ismaster' => true}),
43
+
44
+ # Subsequent calls to configure pools.
45
+ @ismaster.merge({'ismaster' => true}),
46
+ @ismaster.merge({'secondary' => true, 'maxMessageSizeBytes' => 700}),
47
+ @ismaster.merge({'secondary' => true, 'maxBsonObjectSize' => 500}),
48
+ @ismaster.merge({'arbiterOnly' => true})
49
+ )
50
+
51
+ seed = ['localhost:27017']
52
+ manager = Mongo::ShardingPoolManager.new(@client, seed)
53
+ @client.stubs(:local_manager).returns(manager)
54
+ manager.connect
55
+
56
+ formatted_seed = ['localhost', 27017]
57
+
58
+ assert manager.seeds.include? formatted_seed
59
+ assert_equal 500, manager.max_bson_size
60
+ assert_equal 700 , manager.max_message_size
61
+ end
62
+
63
+ should "maintain seed format when checking connection health" do
64
+
65
+ @db.stubs(:command).returns(
66
+ # First call to get a socket.
67
+ @ismaster.merge({'ismaster' => true}),
68
+
69
+ # Subsequent calls to configure pools.
70
+ @ismaster.merge({'ismaster' => true}),
71
+ @ismaster.merge({'secondary' => true, 'maxMessageSizeBytes' => 700}),
72
+ @ismaster.merge({'secondary' => true, 'maxBsonObjectSize' => 500}),
73
+ @ismaster.merge({'arbiterOnly' => true})
74
+ )
75
+
76
+ config_db = new_mock_db
77
+ mongos_coll = mock('collection')
78
+ mongos_coll.stubs(:find).returns(@hosts.map{|h| {'_id' => h}})
79
+ config_db.stubs(:[]).with('mongos').returns(mongos_coll)
80
+ @client.stubs(:[]).with('config').returns(config_db)
81
+
82
+ manager = Mongo::ShardingPoolManager.new(@client, @hosts)
83
+ manager.check_connection_health
84
+
85
+ assert manager.seeds.all? {|s| s.is_a?(Array) && s[0].is_a?(String) && s[1].is_a?(Integer)}
86
+ end
87
+ end
88
+ end