mongo 1.10.0.rc0 → 1.10.0.rc1

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 (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
@@ -334,12 +334,13 @@ class ClientTest < Test::Unit::TestCase
334
334
  conn = standard_connection(:connect => false)
335
335
 
336
336
  admin_db = Object.new
337
- admin_db.expects(:command).returns({'ok' => 1, 'ismaster' => 1, 'maxWireVersion' => 1, 'minWireVersion' => 1})
337
+ admin_db.expects(:command).returns({'ok' => 1, 'ismaster' => 1, 'maxWireVersion' => 1, 'minWireVersion' => 1, 'maxWriteBatchSize' => 999})
338
338
  conn.expects(:[]).with('admin').returns(admin_db)
339
339
  conn.connect
340
340
 
341
341
  assert_equal 1, conn.max_wire_version
342
342
  assert_equal 1, conn.min_wire_version
343
+ assert_equal 999, conn.max_write_batch_size
343
344
  end
344
345
 
345
346
  def test_max_wire_version_and_min_wire_version_values_with_no_reported_values
@@ -352,6 +353,7 @@ class ClientTest < Test::Unit::TestCase
352
353
 
353
354
  assert_equal 0, conn.max_wire_version
354
355
  assert_equal 0, conn.min_wire_version
356
+ assert_equal Mongo::MongoClient::DEFAULT_MAX_WRITE_BATCH_SIZE, conn.max_write_batch_size
355
357
  end
356
358
 
357
359
  def test_wire_version_feature
@@ -96,7 +96,265 @@ class CollectionTest < Test::Unit::TestCase
96
96
  end
97
97
  end
98
98
 
99
+ if @@version >= '2.5.4'
100
+
101
+ def test_single_delete_write_command
102
+ @@test.drop
103
+ @@test.insert([{ :a => 1 }, { :a => 1 }])
104
+
105
+ command = {
106
+ 'delete' => @@test.name,
107
+ :deletes => [{ :q => { :a => 1 }, :limit => 1 }],
108
+ :writeConcern => { :w => 1 },
109
+ :ordered => false
110
+ }
111
+
112
+ result = @@db.command(command)
113
+ assert_equal 1, result['n']
114
+ assert_equal 1, result['ok']
115
+ assert_equal 1, @@test.count
116
+ end
117
+
118
+ def test_multi_ordered_delete_write_command
119
+ @@test.drop
120
+ @@test.insert([{ :a => 1 }, { :a => 1 }])
121
+
122
+ command = {
123
+ 'delete' => @@test.name,
124
+ :deletes => [{ :q => { :a => 1 }, :limit => 0 }],
125
+ :writeConcern => { :w => 1 },
126
+ :ordered => true
127
+ }
128
+
129
+ result = @@db.command(command)
130
+ assert_equal 2, result['n']
131
+ assert_equal 1, result['ok']
132
+ assert_equal 0, @@test.count
133
+ end
134
+
135
+ def test_multi_unordered_delete_write_command
136
+ @@test.drop
137
+ @@test.insert([{ :a => 1 }, { :a => 1 }])
138
+
139
+ command = {
140
+ 'delete' => @@test.name,
141
+ :deletes => [{ :q => { :a => 1 }, :limit => 0 }],
142
+ :writeConcern => { :w => 1 },
143
+ :ordered => false
144
+ }
145
+
146
+ result = @@db.command(command)
147
+ assert_equal 2, result['n']
148
+ assert_equal 1, result['ok']
149
+ assert_equal 0, @@test.count
150
+ end
151
+
152
+ def test_delete_write_command_with_no_concern
153
+ @@test.drop
154
+ @@test.insert([{ :a => 1 }, { :a => 1 }])
155
+
156
+ command = {
157
+ 'delete' => @@test.name,
158
+ :deletes => [{ :q => { :a => 1 }, :limit => 0 }],
159
+ :ordered => false
160
+ }
161
+
162
+ result = @@db.command(command)
163
+ assert_equal 2, result['n']
164
+ assert_equal 1, result['ok']
165
+ assert_equal 0, @@test.count
166
+ end
167
+
168
+ def test_delete_write_command_with_error
169
+ @@test.drop
170
+ @@test.insert([{ :a => 1 }, { :a => 1 }])
171
+
172
+ command = {
173
+ 'delete' => @@test.name,
174
+ :deletes => [{ :q => { '$set' => { :a => 1 }}, :limit => 0 }],
175
+ :writeConcern => { :w => 1 },
176
+ :ordered => false
177
+ }
178
+
179
+ assert_raise Mongo::OperationFailure do
180
+ @@db.command(command)
181
+ end
182
+ end
183
+
184
+ def test_single_insert_write_command
185
+ @@test.drop
186
+
187
+ command = {
188
+ 'insert' => @@test.name,
189
+ :documents => [{ :a => 1 }],
190
+ :writeConcern => { :w => 1 },
191
+ :ordered => false
192
+ }
193
+
194
+ result = @@db.command(command)
195
+ assert_equal 1, result['ok']
196
+ assert_equal 1, @@test.count
197
+ end
198
+
199
+ def test_multi_ordered_insert_write_command
200
+ @@test.drop
201
+
202
+ command = {
203
+ 'insert' => @@test.name,
204
+ :documents => [{ :a => 1 }, { :a => 2 }],
205
+ :writeConcern => { :w => 1 },
206
+ :ordered => true
207
+ }
208
+
209
+ result = @@db.command(command)
210
+ assert_equal 1, result['ok']
211
+ assert_equal 2, @@test.count
212
+ end
213
+
214
+ def test_multi_unordered_insert_write_command
215
+ @@test.drop
216
+
217
+ command = {
218
+ 'insert' => @@test.name,
219
+ :documents => [{ :a => 1 }, { :a => 2 }],
220
+ :writeConcern => { :w => 1 },
221
+ :ordered => false
222
+ }
223
+
224
+ result = @@db.command(command)
225
+ assert_equal 1, result['ok']
226
+ assert_equal 2, @@test.count
227
+ end
228
+
229
+ def test_insert_write_command_with_no_concern
230
+ @@test.drop
231
+
232
+ command = {
233
+ 'insert' => @@test.name,
234
+ :documents => [{ :a => 1 }, { :a => 2 }],
235
+ :ordered => false
236
+ }
237
+
238
+ result = @@db.command(command)
239
+ assert_equal 1, result['ok']
240
+ assert_equal 2, @@test.count
241
+ end
242
+
243
+ def test_insert_write_command_with_error
244
+ @@test.drop
245
+ @@test.ensure_index({ :a => 1 }, { :unique => true })
246
+
247
+ command = {
248
+ 'insert' => @@test.name,
249
+ :documents => [{ :a => 1 }, { :a => 1 }],
250
+ :writeConcern => { :w => 1 },
251
+ :ordered => false
252
+ }
253
+
254
+ assert_raise Mongo::OperationFailure do
255
+ @@db.command(command)
256
+ end
257
+ end
258
+
259
+ def test_single_update_write_command
260
+ @@test.drop
261
+ @@test.insert([{ :a => 1 }, { :a => 2 }])
262
+
263
+ command = {
264
+ 'update' => @@test.name,
265
+ :updates => [{ :q => { :a => 1 }, :u => { '$set' => { :a => 2 }}}],
266
+ :writeConcern => { :w => 1 }
267
+ }
268
+
269
+ result = @@db.command(command)
270
+ assert_equal 1, result['ok']
271
+ assert_equal 1, result['n']
272
+ assert_equal 2, @@test.find({ :a => 2 }).count
273
+ end
274
+
275
+ def test_multi_ordered_update_write_command
276
+ @@test.drop
277
+ @@test.insert([{ :a => 1 }, { :a => 3 }])
278
+
279
+ command = {
280
+ 'update' => @@test.name,
281
+ :updates => [
282
+ { :q => { :a => 1 }, :u => { '$set' => { :a => 2 }}},
283
+ { :q => { :a => 3 }, :u => { '$set' => { :a => 4 }}}
284
+ ],
285
+ :writeConcern => { :w => 1 },
286
+ :ordered => true
287
+ }
288
+
289
+ result = @@db.command(command)
290
+ assert_equal 1, result['ok']
291
+ assert_equal 2, result['n']
292
+ assert_equal 1, @@test.find({ :a => 2 }).count
293
+ assert_equal 1, @@test.find({ :a => 4 }).count
294
+ end
295
+
296
+ def test_multi_unordered_update_write_command
297
+ @@test.drop
298
+ @@test.insert([{ :a => 1 }, { :a => 3 }])
299
+
300
+ command = {
301
+ 'update' => @@test.name,
302
+ :updates => [
303
+ { :q => { :a => 1 }, :u => { '$set' => { :a => 2 }}},
304
+ { :q => { :a => 3 }, :u => { '$set' => { :a => 4 }}}
305
+ ],
306
+ :writeConcern => { :w => 1 },
307
+ :ordered => false
308
+ }
309
+
310
+ result = @@db.command(command)
311
+ assert_equal 1, result['ok']
312
+ assert_equal 2, result['n']
313
+ assert_equal 1, @@test.find({ :a => 2 }).count
314
+ assert_equal 1, @@test.find({ :a => 4 }).count
315
+ end
316
+
317
+ def test_update_write_command_with_no_concern
318
+ @@test.drop
319
+ @@test.insert([{ :a => 1 }, { :a => 3 }])
320
+
321
+ command = {
322
+ 'update' => @@test.name,
323
+ :updates => [
324
+ { :q => { :a => 1 }, :u => { '$set' => { :a => 2 }}},
325
+ { :q => { :a => 3 }, :u => { '$set' => { :a => 4 }}}
326
+ ],
327
+ :ordered => false
328
+ }
329
+
330
+ result = @@db.command(command)
331
+ assert_equal 1, result['ok']
332
+ assert_equal 2, result['n']
333
+ assert_equal 1, @@test.find({ :a => 2 }).count
334
+ assert_equal 1, @@test.find({ :a => 4 }).count
335
+ end
336
+
337
+ def test_update_write_command_with_error
338
+ @@test.drop
339
+ @@test.ensure_index({ :a => 1 }, { :unique => true })
340
+ @@test.insert([{ :a => 1 }, { :a => 2 }])
341
+
342
+ command = {
343
+ 'update' => @@test.name,
344
+ :updates => [
345
+ { :q => { :a => 2 }, :u => { '$set' => { :a => 1 }}}
346
+ ],
347
+ :ordered => false
348
+ }
349
+
350
+ assert_raise Mongo::OperationFailure do
351
+ @@db.command(command)
352
+ end
353
+ end
354
+ end
355
+
99
356
  if @@version >= '2.5.1'
357
+
100
358
  def test_aggregation_cursor
101
359
  [10, 1000].each do |size|
102
360
  @@test.drop
@@ -119,6 +377,16 @@ class CollectionTest < Test::Unit::TestCase
119
377
  @@test.drop
120
378
  end
121
379
 
380
+ def test_aggregation_array
381
+ @@test.drop
382
+ 100.times {|i| @@test.insert({ :_id => i }) }
383
+ agg = @@test.aggregate([{ :$project => {:_id => '$_id'}} ])
384
+
385
+ assert agg.kind_of?(Array)
386
+
387
+ @@test.drop
388
+ end
389
+
122
390
  def test_aggregation_cursor_invalid_ops
123
391
  cursor = @@test.aggregate([], :cursor => {})
124
392
  assert_raise(Mongo::InvalidOperation) { cursor.rewind! }
@@ -134,13 +402,6 @@ class CollectionTest < Test::Unit::TestCase
134
402
  end
135
403
 
136
404
  if @@version >= '2.5.3'
137
- def test_aggregation_allow_disk_usage
138
- @@db.expects(:command).with do |selector, opts|
139
- opts[:allowDiskUsage] == true
140
- end.returns({ 'ok' => 1 })
141
- @@test.aggregate([], :allowDiskUsage => true)
142
- end
143
-
144
405
  def test_aggregation_supports_explain
145
406
  @@db.expects(:command).with do |selector, opts|
146
407
  opts[:explain] == true
@@ -613,6 +874,26 @@ class CollectionTest < Test::Unit::TestCase
613
874
  end
614
875
  end
615
876
 
877
+ if @@version < "2.5.3"
878
+ def test_jnote_raises_exception
879
+ with_no_journaling(@@client) do
880
+ ex = assert_raise Mongo::OperationFailure do
881
+ @@test.insert({:foo => 1}, :j => true)
882
+ end
883
+ result = ex.result
884
+ assert_true result.has_key?("jnote")
885
+ end
886
+ end
887
+
888
+ def test_wnote_raises_exception
889
+ ex = assert_raise Mongo::OperationFailure do
890
+ @@test.insert({:foo => 1}, :w => 2)
891
+ end
892
+ result = ex.result
893
+ assert_true result.has_key?("wnote")
894
+ end
895
+ end
896
+
616
897
  def test_update
617
898
  id1 = @@test.save("x" => 5)
618
899
  @@test.update({}, {"$inc" => {"x" => 1}})
@@ -780,7 +1061,7 @@ class CollectionTest < Test::Unit::TestCase
780
1061
  end
781
1062
  end
782
1063
 
783
- def test_defualt_timeout
1064
+ def test_default_timeout
784
1065
  cursor = @@test.find
785
1066
  assert_equal true, cursor.timeout
786
1067
  end
@@ -804,6 +1085,28 @@ class CollectionTest < Test::Unit::TestCase
804
1085
  end
805
1086
  end
806
1087
 
1088
+ if @@version >= '2.5.5'
1089
+ def test_meta_field_projection
1090
+ @@test.save({ :t => 'spam eggs and spam'})
1091
+ @@test.save({ :t => 'spam'})
1092
+ @@test.save({ :t => 'egg sausage and bacon'})
1093
+
1094
+ @@test.ensure_index([[:t, 'text']])
1095
+ assert @@test.find_one({ :$text => { :$search => 'spam' }},
1096
+ { :fields => [:t, { :score => { :$meta => 'textScore' } }] })
1097
+ end
1098
+
1099
+ def test_sort_by_meta
1100
+ @@test.save({ :t => 'spam eggs and spam'})
1101
+ @@test.save({ :t => 'spam'})
1102
+ @@test.save({ :t => 'egg sausage and bacon'})
1103
+
1104
+ @@test.ensure_index([[:t, 'text']])
1105
+ assert @@test.find({ :$text => { :$search => 'spam' }}).sort([:score, { '$meta' => 'textScore' }])
1106
+ assert @@test.find({ :$text => { :$search => 'spam' }}).sort(:score => { '$meta' =>'textScore' })
1107
+ end
1108
+ end
1109
+
807
1110
  if @@version >= "1.5.1"
808
1111
  def test_fields_with_slice
809
1112
  @@test.save({:foo => [1, 2, 3, 4, 5, 6], :test => 'slice'})
@@ -1181,19 +1484,32 @@ class CollectionTest < Test::Unit::TestCase
1181
1484
  end
1182
1485
 
1183
1486
  if @@version >= '2.5.5'
1487
+ def test_aggregation_allow_disk_use
1488
+ @@db.expects(:command).with do |selector, opts|
1489
+ opts[:allowDiskUse] == true
1490
+ end.returns({ 'ok' => 1 })
1491
+ @@test.aggregate([], :allowDiskUse => true)
1492
+ end
1493
+
1184
1494
  def test_parallel_scan
1185
1495
  8000.times { |i| @@test.insert({ :_id => i }) }
1186
1496
 
1187
- n_docs = {}
1497
+ lock = Mutex.new
1498
+ doc_ids = Set.new
1188
1499
  threads = []
1189
1500
  cursors = @@test.parallel_scan(3)
1190
1501
  cursors.each_with_index do |cursor, i|
1191
1502
  threads << Thread.new do
1192
- n_docs[i] = cursor.to_a.size
1503
+ docs = cursor.to_a
1504
+ lock.synchronize do
1505
+ docs.each do |doc|
1506
+ doc_ids << doc['_id']
1507
+ end
1508
+ end
1193
1509
  end
1194
1510
  end
1195
1511
  threads.each(&:join)
1196
- assert_equal @@test.count, n_docs.values.inject(0) { |sum, n| sum + n }
1512
+ assert_equal 8000, doc_ids.count
1197
1513
  end
1198
1514
  end
1199
1515
 
@@ -1718,16 +2034,19 @@ end
1718
2034
  end
1719
2035
 
1720
2036
  should "generate indexes in the proper order" do
1721
- @collection.expects(:send_write) do |type, selector, documents, check_keys, opts, collection_name|
1722
- assert_equal 'b_1_a_1', selector[:name]
2037
+ key = BSON::OrderedHash['b', 1, 'a', 1]
2038
+ if @@version < '2.5.5'
2039
+ @collection.expects(:send_write) do |type, selector, documents, check_keys, opts, collection_name|
2040
+ assert_equal key, selector[:key]
2041
+ end
2042
+ else
2043
+ @collection.db.expects(:command) do |selector|
2044
+ assert_equal key, selector[:indexes].first[:key]
2045
+ end
1723
2046
  end
1724
2047
  @collection.create_index([['b', 1], ['a', 1]])
1725
2048
  end
1726
2049
 
1727
- should "allow multiple calls to create_index" do
1728
-
1729
- end
1730
-
1731
2050
  should "allow creation of multiple indexes" do
1732
2051
  assert @collection.create_index([['a', 1]])
1733
2052
  assert @collection.create_index([['a', 1]])
@@ -27,6 +27,34 @@ class ConversionsTest < Test::Unit::TestCase
27
27
  assert_equal({ "field1" => 1, "field2" => -1 }, params)
28
28
  end
29
29
 
30
+ def test_array_as_sort_parameters_with_array_of_key_and_hash
31
+ params = array_as_sort_parameters(["score", {"$meta" => "textScore"}])
32
+ assert_equal({"score" => {"$meta" => "textScore"}}, params)
33
+ end
34
+
35
+ def test_array_as_sort_parameters_with_array_of_key_and_hashes
36
+ params = array_as_sort_parameters([["field1", :asc],["score", {"$meta" => "textScore"}]])
37
+ assert_equal({"field1" => 1, "score" => {"$meta" => "textScore"}}, params)
38
+ end
39
+
40
+ def test_hash_as_sort_parameters_with_string
41
+ sort = BSON::OrderedHash["field", "asc"]
42
+ params = hash_as_sort_parameters(sort)
43
+ assert_equal({"field" => 1}, params)
44
+ end
45
+
46
+ def test_hash_as_sort_parameters_with_hash
47
+ sort = BSON::OrderedHash["score", {"$meta" => "textScore"}]
48
+ params = hash_as_sort_parameters(sort)
49
+ assert_equal({"score" => {"$meta" => "textScore"}}, params)
50
+ end
51
+
52
+ def test_hash_as_sort_parameters_with_hash_and_string
53
+ sort = BSON::OrderedHash["score", {"$meta" => "textScore"}, "field", "asc"]
54
+ params = hash_as_sort_parameters(sort)
55
+ assert_equal({ "score" => {"$meta" => "textScore"}, "field" => 1 }, params)
56
+ end
57
+
30
58
  def test_string_as_sort_parameters_with_string
31
59
  params = string_as_sort_parameters("field")
32
60
  assert_equal({ "field" => 1 }, params)
@@ -122,6 +150,10 @@ class ConversionsTest < Test::Unit::TestCase
122
150
  assert_equal(-1, sort_value(:DESC))
123
151
  end
124
152
 
153
+ def test_sort_value_when_value_is_hash
154
+ assert_equal({"$meta" => "textScore"}, sort_value("$meta" => "textScore"))
155
+ end
156
+
125
157
  def test_sort_value_when_value_is_invalid
126
158
  assert_raise Mongo::InvalidSortValueError do
127
159
  sort_value(2)