mongo 1.10.0.rc0 → 1.10.0.rc1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (42) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data.tar.gz.sig +0 -0
  4. data/VERSION +1 -1
  5. data/lib/mongo/bulk_write_collection_view.rb +31 -3
  6. data/lib/mongo/collection.rb +69 -25
  7. data/lib/mongo/collection_writer.rb +3 -2
  8. data/lib/mongo/connection/node.rb +5 -0
  9. data/lib/mongo/cursor.rb +4 -1
  10. data/lib/mongo/db.rb +23 -41
  11. data/lib/mongo/functional.rb +2 -0
  12. data/lib/mongo/functional/authentication.rb +18 -3
  13. data/lib/mongo/functional/sasl_java.rb +48 -0
  14. data/lib/mongo/functional/uri_parser.rb +62 -50
  15. data/lib/mongo/mongo_client.rb +24 -9
  16. data/lib/mongo/mongo_replica_set_client.rb +16 -5
  17. data/lib/mongo/networking.rb +3 -3
  18. data/lib/mongo/utils/conversions.rb +2 -1
  19. data/test/functional/authentication_test.rb +6 -1
  20. data/test/functional/bulk_api_stress_test.rb +133 -0
  21. data/test/functional/bulk_write_collection_view_test.rb +573 -226
  22. data/test/functional/client_test.rb +3 -1
  23. data/test/functional/collection_test.rb +336 -17
  24. data/test/functional/conversions_test.rb +32 -0
  25. data/test/functional/cursor_test.rb +3 -3
  26. data/test/functional/db_api_test.rb +2 -2
  27. data/test/functional/db_test.rb +24 -0
  28. data/test/functional/uri_test.rb +49 -32
  29. data/test/helpers/test_unit.rb +8 -0
  30. data/test/replica_set/authentication_test.rb +5 -1
  31. data/test/replica_set/client_test.rb +5 -4
  32. data/test/replica_set/max_values_test.rb +6 -0
  33. data/test/shared/authentication/basic_auth_shared.rb +101 -30
  34. data/test/shared/authentication/bulk_api_auth_shared.rb +259 -0
  35. data/test/shared/authentication/gssapi_shared.rb +164 -0
  36. data/test/shared/ssl_shared.rb +49 -27
  37. data/test/unit/client_test.rb +4 -2
  38. data/test/unit/connection_test.rb +4 -2
  39. data/test/unit/cursor_test.rb +12 -0
  40. data/test/unit/db_test.rb +6 -0
  41. metadata +27 -20
  42. metadata.gz.sig +0 -0
@@ -103,7 +103,7 @@ class CursorTest < Test::Unit::TestCase
103
103
  end
104
104
  end
105
105
 
106
- def test_server_op_timeout_error
106
+ def test_max_time_ms_error
107
107
  cursor = @@coll.find
108
108
  cursor.stubs(:send_initial_query).returns(true)
109
109
 
@@ -117,10 +117,10 @@ class CursorTest < Test::Unit::TestCase
117
117
  end
118
118
  end
119
119
 
120
- def test_server_op_timeout
120
+ def test_max_time_ms
121
121
  with_forced_timeout(@@connection) do
122
122
  assert_raise ExecutionTimeout do
123
- cursor = @@coll.find.server_op_timeout(100)
123
+ cursor = @@coll.find.max_time_ms(100)
124
124
  cursor.to_a
125
125
  end
126
126
  end
@@ -325,11 +325,11 @@ class DBAPITest < Test::Unit::TestCase
325
325
  @@db.strict = true
326
326
 
327
327
  begin
328
- coll = @@db.create_collection('foobar', :capped => true, :size => 1024)
328
+ coll = @@db.create_collection('foobar', :capped => true, :size => 4096)
329
329
  options = coll.options
330
330
  assert_equal 'foobar', options['create'] if @@client.server_version < '2.5.5'
331
331
  assert_equal true, options['capped']
332
- assert_equal 1024, options['size']
332
+ assert_equal 4096, options['size']
333
333
  rescue => ex
334
334
  @@db.drop_collection('foobar')
335
335
  fail "did not expect exception \"#{ex.inspect}\""
@@ -260,6 +260,30 @@ class DBTest < Test::Unit::TestCase
260
260
  @@db.eval(function, 'hello', :nolock => true)
261
261
  end
262
262
 
263
+ if @@version >= '2.5.3'
264
+ def test_default_admin_roles
265
+ # admin user
266
+ db = Mongo::MongoClient.new()['admin']
267
+ db.logout
268
+ silently { db.add_user('admin', 'pass') }
269
+ db.authenticate('admin', 'pass')
270
+ info = db.command(:usersInfo => 'admin')['users'].first
271
+ assert_equal 'root', info['roles'].first['role']
272
+
273
+ # read-only admin user
274
+ silently { db.add_user('ro-admin', 'pass', true) }
275
+ db.logout
276
+ db.authenticate('ro-admin', 'pass')
277
+ info = db.command(:usersInfo => 'ro-admin')['users'].first
278
+ assert_equal 'readAnyDatabase', info['roles'].first['role']
279
+ db.logout
280
+
281
+ db.authenticate('admin', 'pass')
282
+ db.command(:dropAllUsersFromDatabase => 1)
283
+ db.logout
284
+ end
285
+ end
286
+
263
287
  if @@version >= "1.3.5"
264
288
  def test_db_stats
265
289
  stats = @@db.stats
@@ -31,39 +31,39 @@ class URITest < Test::Unit::TestCase
31
31
  assert_equal 27018, parser.nodes[0][1]
32
32
  end
33
33
 
34
- def test_ipv6_format
35
- parser = Mongo::URIParser.new('mongodb://[::1]:27018')
36
- assert_equal 1, parser.nodes.length
37
- assert_equal '::1', parser.nodes[0][0]
38
- assert_equal 27018, parser.nodes[0][1]
39
-
40
- parser = Mongo::URIParser.new('mongodb://[::1]')
41
- assert_equal 1, parser.nodes.length
42
- assert_equal '::1', parser.nodes[0][0]
43
- end
34
+ def test_ipv6_format
35
+ parser = Mongo::URIParser.new('mongodb://[::1]:27018')
36
+ assert_equal 1, parser.nodes.length
37
+ assert_equal '::1', parser.nodes[0][0]
38
+ assert_equal 27018, parser.nodes[0][1]
44
39
 
45
- def test_ipv6_format_multi
46
- parser = Mongo::URIParser.new('mongodb://[::1]:27017,[::1]:27018')
47
- assert_equal 2, parser.nodes.length
48
- assert_equal '::1', parser.nodes[0][0]
49
- assert_equal 27017, parser.nodes[0][1]
50
- assert_equal '::1', parser.nodes[1][0]
51
- assert_equal 27018, parser.nodes[1][1]
52
-
53
- parser = Mongo::URIParser.new('mongodb://[::1]:27017,localhost:27018')
54
- assert_equal 2, parser.nodes.length
55
- assert_equal '::1', parser.nodes[0][0]
56
- assert_equal 27017, parser.nodes[0][1]
57
- assert_equal 'localhost', parser.nodes[1][0]
58
- assert_equal 27018, parser.nodes[1][1]
59
-
60
- parser = Mongo::URIParser.new('mongodb://localhost:27017,[::1]:27018')
61
- assert_equal 2, parser.nodes.length
62
- assert_equal 'localhost', parser.nodes[0][0]
63
- assert_equal 27017, parser.nodes[0][1]
64
- assert_equal '::1', parser.nodes[1][0]
65
- assert_equal 27018, parser.nodes[1][1]
66
- end
40
+ parser = Mongo::URIParser.new('mongodb://[::1]')
41
+ assert_equal 1, parser.nodes.length
42
+ assert_equal '::1', parser.nodes[0][0]
43
+ end
44
+
45
+ def test_ipv6_format_multi
46
+ parser = Mongo::URIParser.new('mongodb://[::1]:27017,[::1]:27018')
47
+ assert_equal 2, parser.nodes.length
48
+ assert_equal '::1', parser.nodes[0][0]
49
+ assert_equal 27017, parser.nodes[0][1]
50
+ assert_equal '::1', parser.nodes[1][0]
51
+ assert_equal 27018, parser.nodes[1][1]
52
+
53
+ parser = Mongo::URIParser.new('mongodb://[::1]:27017,localhost:27018')
54
+ assert_equal 2, parser.nodes.length
55
+ assert_equal '::1', parser.nodes[0][0]
56
+ assert_equal 27017, parser.nodes[0][1]
57
+ assert_equal 'localhost', parser.nodes[1][0]
58
+ assert_equal 27018, parser.nodes[1][1]
59
+
60
+ parser = Mongo::URIParser.new('mongodb://localhost:27017,[::1]:27018')
61
+ assert_equal 2, parser.nodes.length
62
+ assert_equal 'localhost', parser.nodes[0][0]
63
+ assert_equal 27017, parser.nodes[0][1]
64
+ assert_equal '::1', parser.nodes[1][0]
65
+ assert_equal 27018, parser.nodes[1][1]
66
+ end
67
67
 
68
68
  def test_multiple_uris
69
69
  parser = Mongo::URIParser.new('mongodb://a.example.com:27018,b.example.com')
@@ -310,4 +310,21 @@ end
310
310
  Mongo::URIParser.new("mongodb://user@localhost/some_db?authMechanism=PLAIN")
311
311
  end
312
312
  end
313
+
314
+ def test_gssapi
315
+ uri = "mongodb://foo%2Fbar%40example.net@localhost?authMechanism=GSSAPI;"
316
+ parser = Mongo::URIParser.new(uri)
317
+ assert_equal 'GSSAPI', parser.auths.first[:mechanism]
318
+ assert_equal 'foo/bar@example.net', parser.auths.first[:username]
319
+
320
+
321
+ uri = "mongodb://foo%2Fbar%40example.net@localhost?authMechanism=GSSAPI;" +
322
+ "gssapiServiceName=mongodb;canonicalizeHostName=true"
323
+ parser = Mongo::URIParser.new(uri)
324
+ assert_equal 'GSSAPI', parser.auths.first[:mechanism]
325
+ assert_equal 'foo/bar@example.net', parser.auths.first[:username]
326
+ assert_equal 'mongodb', parser.auths.first[:extra][:gssapi_service_name]
327
+ assert_equal true, parser.auths.first[:extra][:canonicalize_host_name]
328
+ end
329
+
313
330
  end
@@ -233,6 +233,11 @@ class Test::Unit::TestCase
233
233
  end
234
234
  end
235
235
 
236
+ def with_auth(client, &block)
237
+ cmd_line_args = client['admin'].command({ :getCmdLineOpts => 1 })['parsed']
238
+ yield if cmd_line_args.include?('auth')
239
+ end
240
+
236
241
  def with_default_journaling(client, &block)
237
242
  cmd_line_args = client['admin'].command({ :getCmdLineOpts => 1 })['parsed']
238
243
  unless client.server_version < "2.0" || cmd_line_args.include?('nojournal')
@@ -298,6 +303,9 @@ class Test::Unit::TestCase
298
303
  with_write_operations(client, &block)
299
304
  end
300
305
 
306
+ def batch_commands?(wire_version)
307
+ wire_version >= Mongo::MongoClient::BATCH_COMMANDS
308
+ end
301
309
  end
302
310
 
303
311
  # Before and after hooks for the entire test run
@@ -15,17 +15,21 @@
15
15
  require 'test_helper'
16
16
  require 'shared/authentication/basic_auth_shared'
17
17
  require 'shared/authentication/sasl_plain_shared'
18
+ require 'shared/authentication/bulk_api_auth_shared'
19
+ require 'shared/authentication/gssapi_shared'
18
20
 
19
21
  class ReplicaSetAuthenticationTest < Test::Unit::TestCase
20
22
  include Mongo
21
23
  include BasicAuthTests
22
24
  include SASLPlainTests
25
+ include BulkAPIAuthTests
26
+ include GSSAPITests
23
27
 
24
28
  def setup
25
29
  ensure_cluster(:rs)
26
30
  @client = MongoReplicaSetClient.new(@rs.repl_set_seeds)
31
+ @version = @client.server_version
27
32
  @db = @client[TEST_DB]
28
33
  @host_info = @rs.repl_set_seeds.join(',')
29
- init_auth
30
34
  end
31
35
  end
@@ -329,12 +329,13 @@ class ReplicaSetClientTest < Test::Unit::TestCase
329
329
  def test_find_and_modify_with_secondary_read_preference
330
330
  @client = MongoReplicaSetClient.new @rs.repl_set_seeds
331
331
  collection = @client[TEST_DB].collection('test', :read => :secondary)
332
- collection << { :a => 1, :processed => false}
332
+ id = BSON::ObjectId.new
333
+ collection << { :a => id, :processed => false }
333
334
 
334
335
  collection.find_and_modify(
335
- :query => {},
336
- :update => {"$set" => {:processed => true}}
336
+ :query => { 'a' => id },
337
+ :update => { "$set" => { :processed => true }}
337
338
  )
338
- assert_equal collection.find_one({}, :fields => {:_id => 0}, :read => :primary), {'a' => 1, 'processed' => true}
339
+ assert_equal true, collection.find_one({ 'a' => id }, :read => :primary)['processed']
339
340
  end
340
341
  end
@@ -135,5 +135,11 @@ class MaxValuesTest < Test::Unit::TestCase
135
135
  assert_true @client.use_write_command?({:w => 1})
136
136
  assert_false @client.use_write_command?({:w => 0})
137
137
  end
138
+
139
+ def test_max_write_batch_size
140
+ assert_equal Mongo::MongoClient::DEFAULT_MAX_WRITE_BATCH_SIZE, @client.max_write_batch_size
141
+ @client.local_manager.primary_pool.node.stubs(:max_write_batch_size).returns(999)
142
+ assert_equal 999, @client.max_write_batch_size
143
+ end
138
144
  end
139
145
 
@@ -14,7 +14,7 @@
14
14
 
15
15
  module BasicAuthTests
16
16
 
17
- def init_auth
17
+ def init_auth_basic
18
18
  # enable authentication by creating and logging in as admin user
19
19
  @admin = @client['admin']
20
20
  @admin.add_user('admin', 'password', nil, :roles => ['readAnyDatabase',
@@ -28,7 +28,7 @@ module BasicAuthTests
28
28
  @db.add_user('admin', 'cleanup', nil, :roles => [])
29
29
  end
30
30
 
31
- def teardown
31
+ def teardown_basic
32
32
  remove_all_users(@db, 'admin', 'cleanup')
33
33
  remove_all_users(@admin, 'admin', 'password') if has_auth?(@admin.name)
34
34
  end
@@ -48,15 +48,21 @@ module BasicAuthTests
48
48
  end
49
49
 
50
50
  def test_add_remove_user
51
+ init_auth_basic
52
+
51
53
  # add user
52
54
  silently { @db.add_user('bob','user') }
53
55
  assert @db.authenticate('bob', 'user')
54
56
 
55
57
  # remove user
56
58
  assert @db.remove_user('bob')
59
+
60
+ teardown_basic
57
61
  end
58
62
 
59
63
  def test_update_user
64
+ init_auth_basic
65
+
60
66
  # add user
61
67
  silently { @db.add_user('bob', 'user') }
62
68
  assert @db.authenticate('bob', 'user')
@@ -68,9 +74,13 @@ module BasicAuthTests
68
74
  @db.authenticate('bob', 'user')
69
75
  end
70
76
  assert @db.authenticate('bob', 'updated')
77
+
78
+ teardown_basic
71
79
  end
72
80
 
73
81
  def test_remove_non_existent_user
82
+ init_auth_basic
83
+
74
84
  if @client.server_version < '2.5'
75
85
  assert_equal false, @db.remove_user('joe')
76
86
  else
@@ -78,37 +88,49 @@ module BasicAuthTests
78
88
  assert @db.remove_user('joe')
79
89
  end
80
90
  end
91
+ teardown_basic
81
92
  end
82
93
 
83
94
  def test_authenticate
95
+ init_auth_basic
84
96
  silently { @db.add_user('peggy', 'user') }
85
97
  assert @db.authenticate('peggy', 'user')
86
98
  @db.remove_user('peggy')
99
+ teardown_basic
87
100
  end
88
101
 
89
102
  def test_authenticate_non_existent_user
103
+ init_auth_basic
90
104
  assert_raise Mongo::AuthenticationError do
91
105
  @db.authenticate('frank', 'thetank')
92
106
  end
107
+ teardown_basic
93
108
  end
94
109
 
95
110
  def test_logout
111
+ init_auth_basic
96
112
  silently { @db.add_user('peggy', 'user') }
97
113
  assert @db.authenticate('peggy', 'user')
98
114
  assert @db.logout
115
+ teardown_basic
99
116
  end
100
117
 
101
118
  def test_authenticate_with_special_characters
119
+ init_auth_basic
102
120
  silently { assert @db.add_user('foo:bar','@foo') }
103
121
  assert @db.authenticate('foo:bar','@foo')
122
+ teardown_basic
104
123
  end
105
124
 
106
125
  def test_authenticate_read_only
126
+ init_auth_basic
107
127
  silently { @db.add_user('randy', 'readonly', true) }
108
128
  assert @db.authenticate('randy', 'readonly')
129
+ teardown_basic
109
130
  end
110
131
 
111
132
  def test_authenticate_with_connection_uri
133
+ init_auth_basic
112
134
  silently { @db.add_user('eunice', 'uritest') }
113
135
 
114
136
  uri = "mongodb://eunice:uritest@#{@host_info}/#{@db.name}"
@@ -122,9 +144,11 @@ module BasicAuthTests
122
144
  assert_equal @db.name, auth[:db_name]
123
145
  assert_equal 'eunice', auth[:username]
124
146
  assert_equal 'uritest', auth[:password]
147
+ teardown_basic
125
148
  end
126
149
 
127
150
  def test_socket_auths
151
+ init_auth_basic
128
152
  # setup
129
153
  db_a = @client[TEST_DB + '_a']
130
154
  silently { db_a.add_user('user_a', 'password') }
@@ -156,47 +180,70 @@ module BasicAuthTests
156
180
  remove_all_users(db_a, 'user_a', 'password')
157
181
  remove_all_users(db_b, 'user_b', 'password')
158
182
  remove_all_users(db_c, 'user_c', 'password')
183
+ teardown_basic
184
+ end
185
+
186
+ def test_default_roles_non_admin
187
+ return unless @client.server_version >= '2.5.3'
188
+ init_auth_basic
189
+ silently { @db.add_user('user', 'pass') }
190
+ silently { @db.authenticate('user', 'pass') }
191
+ info = @db.command(:usersInfo => 'user')['users'].first
192
+ assert_equal 'dbOwner', info['roles'].first['role']
193
+
194
+ # read-only
195
+ silently { @db.add_user('ro-user', 'pass', true) }
196
+ @db.logout
197
+ @db.authenticate('ro-user', 'pass')
198
+ info = @db.command(:usersInfo => 'ro-user')['users'].first
199
+ assert_equal 'read', info['roles'].first['role']
200
+ @db.logout
201
+ teardown_basic
159
202
  end
160
203
 
161
204
  def test_delegated_authentication
162
205
  return unless @client.server_version >= '2.4' && @client.server_version < '2.5'
206
+ with_auth(@client) do
207
+ init_auth_basic
208
+ # create user in test databases
209
+ accounts = @client[TEST_DB + '_accounts']
210
+ silently do
211
+ accounts.add_user('debbie', 'delegate')
212
+ @db.add_user('debbie', nil, nil, :roles => ['read'], :userSource => accounts.name)
213
+ end
214
+ @admin.logout
163
215
 
164
- # create user in test databases
165
- accounts = @client[TEST_DB + '_accounts']
166
- silently do
167
- accounts.add_user('debbie', 'delegate')
168
- @db.add_user('debbie', nil, nil, :roles => ['read'], :userSource => accounts.name)
169
- end
170
- @admin.logout
216
+ # validate that direct authentication is not allowed
217
+ assert_raise Mongo::AuthenticationError do
218
+ @db.authenticate('debbie', 'delegate')
219
+ end
171
220
 
172
- # validate that direct authentication is not allowed
173
- assert_raise Mongo::AuthenticationError do
174
- @db.authenticate('debbie', 'delegate')
175
- end
221
+ # validate delegated authentication
222
+ assert accounts.authenticate('debbie', 'delegate')
223
+ assert @db.collection_names
224
+ accounts.logout
225
+ assert_raise Mongo::OperationFailure do
226
+ @db.collection_names
227
+ end
176
228
 
177
- # validate delegated authentication
178
- assert accounts.authenticate('debbie', 'delegate')
179
- assert @db.collection_names
180
- accounts.logout
181
- assert_raise Mongo::OperationFailure do
182
- @db.collection_names
183
- end
229
+ # validate auth using source database
230
+ @db.authenticate('debbie', 'delegate', nil, accounts.name)
231
+ assert @db.collection_names
232
+ accounts.logout
233
+ assert_raise Mongo::OperationFailure do
234
+ @db.collection_names
235
+ end
184
236
 
185
- # validate auth using source database
186
- @db.authenticate('debbie', 'delegate', nil, accounts.name)
187
- assert @db.collection_names
188
- accounts.logout
189
- assert_raise Mongo::OperationFailure do
190
- @db.collection_names
237
+ # clean-up
238
+ @admin.authenticate('admin', 'password')
239
+ remove_all_users(accounts, 'debbie', 'delegate')
240
+ teardown_basic
191
241
  end
192
-
193
- # clean-up
194
- @admin.authenticate('admin', 'password')
195
- remove_all_users(accounts, 'debbie', 'delegate')
196
242
  end
197
243
 
198
244
  def test_non_admin_default_roles
199
245
  return if @client.server_version < '2.5'
246
+ init_auth_basic
200
247
 
201
248
  # add read-only user and verify that role is 'read'
202
249
  @db.add_user('randy', 'password', nil, :roles => ['read'])
@@ -210,6 +257,30 @@ module BasicAuthTests
210
257
  @db.authenticate('emily', 'password')
211
258
  users = @db.command(:usersInfo => 'emily')['users']
212
259
  assert_equal 'dbOwner', users.first['roles'].first['role']
260
+ teardown_basic
261
+ end
262
+
263
+ def test_update_user_to_read_only
264
+ with_auth(@client) do
265
+ init_auth_basic
266
+ silently { @db.add_user('emily', 'password') }
267
+ @admin.logout
268
+ @db.authenticate('emily', 'password')
269
+ @db['test'].insert({})
270
+ @db.logout
271
+
272
+ @admin.authenticate('admin', 'password')
273
+ silently { @db.add_user('emily', 'password', true) }
274
+ @admin.logout
275
+
276
+ silently { @db.authenticate('emily', 'password') }
277
+ assert_raise Mongo::OperationFailure do
278
+ @db['test'].insert({})
279
+ end
280
+ @db.logout
281
+ @admin.authenticate('admin', 'password')
282
+ teardown_basic
283
+ end
213
284
  end
214
285
 
215
286
  end