mongo 2.4.0.rc0 → 2.4.0.rc1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (93) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data.tar.gz.sig +1 -2
  4. data/lib/mongo/bulk_write/validatable.rb +3 -1
  5. data/lib/mongo/client.rb +30 -3
  6. data/lib/mongo/cluster/app_metadata.rb +7 -2
  7. data/lib/mongo/collection.rb +3 -1
  8. data/lib/mongo/collection/view.rb +3 -1
  9. data/lib/mongo/collection/view/aggregation.rb +3 -1
  10. data/lib/mongo/collection/view/builder/find_command.rb +20 -5
  11. data/lib/mongo/collection/view/map_reduce.rb +3 -1
  12. data/lib/mongo/collection/view/writable.rb +12 -2
  13. data/lib/mongo/cursor/builder/get_more_command.rb +3 -2
  14. data/lib/mongo/error/closed_stream.rb +1 -1
  15. data/lib/mongo/error/invalid_server_preference.rb +1 -1
  16. data/lib/mongo/index/view.rb +3 -1
  17. data/lib/mongo/operation/write/bulk/mergable.rb +1 -1
  18. data/lib/mongo/operation/write/create_index.rb +1 -1
  19. data/lib/mongo/operation/write/delete.rb +1 -1
  20. data/lib/mongo/operation/write/update.rb +1 -1
  21. data/lib/mongo/protocol/delete.rb +4 -1
  22. data/lib/mongo/protocol/get_more.rb +4 -1
  23. data/lib/mongo/protocol/insert.rb +7 -3
  24. data/lib/mongo/protocol/kill_cursors.rb +4 -1
  25. data/lib/mongo/protocol/message.rb +5 -1
  26. data/lib/mongo/protocol/query.rb +11 -4
  27. data/lib/mongo/protocol/update.rb +4 -1
  28. data/lib/mongo/server/connectable.rb +8 -2
  29. data/lib/mongo/server/connection_pool.rb +3 -1
  30. data/lib/mongo/server/monitor.rb +1 -0
  31. data/lib/mongo/socket.rb +16 -8
  32. data/lib/mongo/socket/ssl.rb +24 -9
  33. data/lib/mongo/uri.rb +6 -6
  34. data/lib/mongo/version.rb +1 -1
  35. data/mongo.gemspec +1 -1
  36. data/spec/mongo/bulk_write_spec.rb +117 -0
  37. data/spec/mongo/collection/view/aggregation_spec.rb +26 -0
  38. data/spec/mongo/collection/view/builder/find_command_spec.rb +244 -2
  39. data/spec/mongo/collection/view/map_reduce_spec.rb +13 -0
  40. data/spec/mongo/collection/view/readable_spec.rb +26 -0
  41. data/spec/mongo/collection/view/writable_spec.rb +104 -0
  42. data/spec/mongo/collection/view_spec.rb +13 -0
  43. data/spec/mongo/collection_spec.rb +226 -7
  44. data/spec/mongo/crud_spec.rb +5 -5
  45. data/spec/mongo/index/view_spec.rb +53 -0
  46. data/spec/mongo/server/connection_spec.rb +45 -26
  47. data/spec/mongo/socket/ssl_spec.rb +358 -22
  48. data/spec/spec_helper.rb +4 -0
  49. data/spec/support/authorization.rb +3 -3
  50. data/spec/support/certificates/client_cert.pem +21 -0
  51. data/spec/support/certificates/client_key.pem +28 -0
  52. data/spec/support/certificates/client_key_encrypted.pem +30 -0
  53. data/spec/support/crud.rb +67 -22
  54. data/spec/support/crud/read.rb +18 -36
  55. data/spec/support/crud/write.rb +0 -44
  56. data/spec/support/crud_tests/read/aggregate-collation.yml +17 -0
  57. data/spec/support/crud_tests/read/aggregate-out.yml +28 -0
  58. data/spec/support/crud_tests/read/aggregate.yml +1 -35
  59. data/spec/support/crud_tests/read/count-collation.yml +15 -0
  60. data/spec/support/crud_tests/read/count.yml +3 -15
  61. data/spec/support/crud_tests/read/distinct-collation.yml +17 -0
  62. data/spec/support/crud_tests/read/distinct.yml +1 -14
  63. data/spec/support/crud_tests/read/find-collation.yml +15 -0
  64. data/spec/support/crud_tests/read/find.yml +1 -12
  65. data/spec/support/crud_tests/write/deleteMany-collation.yml +22 -0
  66. data/spec/support/crud_tests/write/deleteMany.yml +1 -23
  67. data/spec/support/crud_tests/write/deleteOne-collation.yml +22 -0
  68. data/spec/support/crud_tests/write/deleteOne.yml +1 -21
  69. data/spec/support/crud_tests/write/findOneAndDelete-collation.yml +23 -0
  70. data/spec/support/crud_tests/write/findOneAndDelete.yml +2 -28
  71. data/spec/support/crud_tests/write/findOneAndReplace-collation.yml +24 -0
  72. data/spec/support/crud_tests/write/findOneAndReplace-upsert.yml +47 -0
  73. data/spec/support/crud_tests/write/findOneAndReplace.yml +13 -53
  74. data/spec/support/crud_tests/write/findOneAndUpdate-collation.yml +27 -0
  75. data/spec/support/crud_tests/write/findOneAndUpdate.yml +8 -51
  76. data/spec/support/crud_tests/write/insertMany.yml +1 -2
  77. data/spec/support/crud_tests/write/insertOne.yml +1 -2
  78. data/spec/support/crud_tests/write/replaceOne-collation.yml +23 -0
  79. data/spec/support/crud_tests/write/replaceOne-upsert.yml +48 -0
  80. data/spec/support/crud_tests/write/replaceOne.yml +11 -45
  81. data/spec/support/crud_tests/write/updateMany-collation.yml +27 -0
  82. data/spec/support/crud_tests/write/updateMany.yml +10 -42
  83. data/spec/support/crud_tests/write/updateOne-collation.yml +24 -0
  84. data/spec/support/crud_tests/write/updateOne.yml +7 -33
  85. data/spec/support/sdam/rs/new_primary_new_setversion.yml +1 -1
  86. data/spec/support/sdam/rs/null_election_id.yml +1 -0
  87. data/spec/support/sdam/rs/primary_disconnect_electionid.yml +2 -3
  88. data/spec/support/sdam/rs/primary_disconnect_setversion.yml +1 -2
  89. data/spec/support/sdam/single/direct_connection_rsarbiter.yml +1 -1
  90. data/spec/support/sdam/single/direct_connection_rsprimary.yml +1 -1
  91. data/spec/support/sdam/single/direct_connection_rssecondary.yml +1 -1
  92. metadata +40 -4
  93. metadata.gz.sig +0 -0
@@ -59,6 +59,7 @@ module Mongo
59
59
  @update = update
60
60
  @flags = options[:flags] || []
61
61
  @upconverter = Upconverter.new(collection, selector, update, flags)
62
+ super
62
63
  end
63
64
 
64
65
  # Return the event payload for monitoring.
@@ -78,10 +79,12 @@ module Mongo
78
79
  }
79
80
  end
80
81
 
81
- private
82
+ protected
82
83
 
83
84
  attr_reader :upconverter
84
85
 
86
+ private
87
+
85
88
  # The operation code required to specify an Update message.
86
89
  # @return [Fixnum] the operation code.
87
90
  def op_code
@@ -28,6 +28,10 @@ module Mongo
28
28
  # The default time in seconds to timeout an operation executed on a socket.
29
29
  #
30
30
  # @since 2.0.0
31
+ #
32
+ # @deprecated Timeouts on Ruby sockets aren't effective so this default option is
33
+ # no longer used.
34
+ # Will be removed in driver version 3.0.
31
35
  TIMEOUT = 5.freeze
32
36
 
33
37
  # @return [ Mongo::Address ] address The address to connect to.
@@ -73,13 +77,15 @@ module Mongo
73
77
  #
74
78
  # @since 2.0.0
75
79
  def timeout
76
- @timeout ||= options[:socket_timeout] || TIMEOUT
80
+ @timeout ||= options[:socket_timeout]
77
81
  end
78
82
 
79
- private
83
+ protected
80
84
 
81
85
  attr_reader :socket
82
86
 
87
+ private
88
+
83
89
  def ssl_options
84
90
  @ssl_options[:ssl] == true ? @ssl_options : {}
85
91
  end
@@ -109,10 +109,12 @@ module Mongo
109
109
  checkin(connection) if connection
110
110
  end
111
111
 
112
- private
112
+ protected
113
113
 
114
114
  attr_reader :queue
115
115
 
116
+ private
117
+
116
118
  class << self
117
119
 
118
120
  # Get a connection pool for the provided server.
@@ -104,6 +104,7 @@ module Mongo
104
104
  @options = options.freeze
105
105
  @connection = Connection.new(address, options)
106
106
  @last_round_trip_time = nil
107
+ @last_scan = nil
107
108
  @mutex = Mutex.new
108
109
  end
109
110
 
@@ -162,14 +162,28 @@ module Mongo
162
162
  # @since 2.0.5
163
163
  def eof?
164
164
  @socket.eof?
165
- rescue IOError, SystemCallError => e
165
+ rescue IOError, SystemCallError => _
166
166
  true
167
167
  end
168
168
 
169
169
  private
170
170
 
171
171
  def read_from_socket(length)
172
- @socket.read(length) || String.new
172
+ data = String.new
173
+ deadline = (Time.now + timeout) if timeout
174
+ begin
175
+ while (data.length < length)
176
+ data << @socket.read_nonblock(length - data.length)
177
+ end
178
+ rescue IO::WaitReadable
179
+ select_timeout = (deadline - Time.now) if deadline
180
+ unless Kernel::select([@socket], nil, [@socket], select_timeout)
181
+ raise Timeout::Error.new("Took more than #{timeout} seconds to receive data.")
182
+ end
183
+ retry
184
+ end
185
+
186
+ data
173
187
  end
174
188
 
175
189
  def unix_socket?(sock)
@@ -178,12 +192,6 @@ module Mongo
178
192
 
179
193
  def set_socket_options(sock)
180
194
  sock.set_encoding(BSON::BINARY)
181
-
182
- unless unix_socket?(sock) && BSON::Environment.jruby?
183
- encoded_timeout = [ timeout, 0 ].pack(TIMEOUT_PACK)
184
- sock.setsockopt(SOL_SOCKET, SO_RCVTIMEO, encoded_timeout)
185
- sock.setsockopt(SOL_SOCKET, SO_SNDTIMEO, encoded_timeout)
186
- end
187
195
  end
188
196
 
189
197
  def handle_errors
@@ -116,22 +116,32 @@ module Mongo
116
116
 
117
117
  def create_context(options)
118
118
  context = OpenSSL::SSL::SSLContext.new
119
- set_cert(context, options) if options[:ssl_cert]
120
- set_key(context, options) if options[:ssl_key]
119
+ set_cert(context, options)
120
+ set_key(context, options)
121
121
  set_cert_verification(context, options) unless options[:ssl_verify] == false
122
122
  context
123
123
  end
124
124
 
125
125
  def set_cert(context, options)
126
- context.cert = OpenSSL::X509::Certificate.new(File.open(options[:ssl_cert]))
126
+ if options[:ssl_cert]
127
+ context.cert = OpenSSL::X509::Certificate.new(File.open(options[:ssl_cert]))
128
+ elsif options[:ssl_cert_string]
129
+ context.cert = OpenSSL::X509::Certificate.new(options[:ssl_cert_string])
130
+ elsif options[:ssl_cert_object]
131
+ context.cert = options[:ssl_cert_object]
132
+ end
127
133
  end
128
134
 
129
135
  def set_key(context, options)
130
- if options[:ssl_key_pass_phrase]
131
- context.key = OpenSSL::PKey::RSA.new(File.open(options[:ssl_key]),
132
- options[:ssl_key_pass_phrase])
133
- else
134
- context.key = OpenSSL::PKey::RSA.new(File.open(options[:ssl_key]))
136
+ passphrase = options[:ssl_key_pass_phrase]
137
+ if options[:ssl_key]
138
+ context.key = passphrase ? OpenSSL::PKey.read(File.open(options[:ssl_key]), passphrase) :
139
+ OpenSSL::PKey.read(File.open(options[:ssl_key]))
140
+ elsif options[:ssl_key_string]
141
+ context.key = passphrase ? OpenSSL::PKey.read(options[:ssl_key_string], passphrase) :
142
+ OpenSSL::PKey.read(options[:ssl_key_string])
143
+ elsif options[:ssl_key_object]
144
+ context.key = options[:ssl_key_object]
135
145
  end
136
146
  end
137
147
 
@@ -139,7 +149,12 @@ module Mongo
139
149
  context.verify_mode = OpenSSL::SSL::VERIFY_PEER
140
150
  cert_store = OpenSSL::X509::Store.new
141
151
  if options[:ssl_ca_cert]
142
- cert_store.add_file(options[:ssl_ca_cert])
152
+ cert_store.add_cert(OpenSSL::X509::Certificate.new(File.open(options[:ssl_ca_cert])))
153
+ elsif options[:ssl_ca_cert_string]
154
+ cert_store.add_cert(OpenSSL::X509::Certificate.new(options[:ssl_ca_cert_string]))
155
+ elsif options[:ssl_ca_cert_object]
156
+ raise TypeError("Option :ssl_ca_cert_object should be an array of OpenSSL::X509:Certificate objects") unless options[:ssl_ca_cert_object].is_a? Array
157
+ options[:ssl_ca_cert_object].each {|cert| cert_store.add_cert(cert)}
143
158
  else
144
159
  cert_store.set_default_paths
145
160
  end
@@ -193,7 +193,7 @@ module Mongo
193
193
  def initialize(string, options = {})
194
194
  @string = string
195
195
  @options = options
196
- empty, scheme, remaining = @string.partition(SCHEME)
196
+ _, scheme, remaining = @string.partition(SCHEME)
197
197
  raise_invalid_error!(INVALID_SCHEME) unless scheme == SCHEME
198
198
  setup!(remaining)
199
199
  end
@@ -248,7 +248,7 @@ module Mongo
248
248
  end
249
249
 
250
250
  def extract_db_opts!(string)
251
- db_opts, d, creds_hosts = string.reverse.partition(DATABASE_DELIM)
251
+ db_opts, _, creds_hosts = string.reverse.partition(DATABASE_DELIM)
252
252
  db_opts, creds_hosts = creds_hosts, db_opts if creds_hosts.empty?
253
253
  if db_opts.empty? && creds_hosts.include?(URI_OPTS_DELIM)
254
254
  raise_invalid_error!(INVALID_OPTS_DELIM)
@@ -264,13 +264,13 @@ module Mongo
264
264
  end
265
265
 
266
266
  def split_creds_hosts(string)
267
- hosts, d, creds = string.reverse.partition(AUTH_DELIM)
267
+ hosts, _, creds = string.reverse.partition(AUTH_DELIM)
268
268
  hosts, creds = creds, hosts if hosts.empty?
269
269
  [ hosts, creds ].map { |s| s.reverse }
270
270
  end
271
271
 
272
272
  def parse_db_opts!(string)
273
- auth_db, d, uri_opts = string.partition(URI_OPTS_DELIM)
273
+ auth_db, _, uri_opts = string.partition(URI_OPTS_DELIM)
274
274
  @uri_options = Options::Redacted.new(parse_uri_options!(uri_opts))
275
275
  @database = parse_database!(auth_db)
276
276
  end
@@ -324,7 +324,7 @@ module Mongo
324
324
  validate_port_string!(p)
325
325
  end
326
326
  elsif host.index(HOST_PORT_DELIM)
327
- h, d, p = host.partition(HOST_PORT_DELIM)
327
+ h, _, p = host.partition(HOST_PORT_DELIM)
328
328
  raise_invalid_error!(INVALID_HOST) unless h.size > 0
329
329
  validate_port_string!(p)
330
330
  elsif host =~ UNIX_SOCKET
@@ -339,7 +339,7 @@ module Mongo
339
339
  end
340
340
 
341
341
  def decode(value)
342
- ::URI.decode(value)
342
+ ::URI::DEFAULT_PARSER.unescape(value)
343
343
  end
344
344
 
345
345
  # Hash for storing map of URI option parameters to conversion strategies
@@ -17,5 +17,5 @@ module Mongo
17
17
  # The current version of the driver.
18
18
  #
19
19
  # @since 2.0.0
20
- VERSION = '2.4.0.rc0'.freeze
20
+ VERSION = '2.4.0.rc1'.freeze
21
21
  end
@@ -30,5 +30,5 @@ Gem::Specification.new do |s|
30
30
  s.has_rdoc = 'yard'
31
31
  s.bindir = 'bin'
32
32
 
33
- s.add_dependency 'bson', '~> 4.2.0.rc0'
33
+ s.add_dependency 'bson', '~> 4.2.0.rc1'
34
34
  end
@@ -243,6 +243,19 @@ describe Mongo::BulkWrite do
243
243
  bulk_write.execute
244
244
  }.to raise_exception(Mongo::Error::UnsupportedCollation)
245
245
  end
246
+
247
+ context 'when a String key is used' do
248
+
249
+ let(:requests) do
250
+ [{ delete_one: { filter: { name: 'BANG' }, 'collation' => collation } }]
251
+ end
252
+
253
+ it 'raises an exception' do
254
+ expect {
255
+ bulk_write.execute
256
+ }.to raise_exception(Mongo::Error::UnsupportedCollation)
257
+ end
258
+ end
246
259
  end
247
260
  end
248
261
 
@@ -371,6 +384,20 @@ describe Mongo::BulkWrite do
371
384
  bulk_write.execute
372
385
  }.to raise_exception(Mongo::Error::UnsupportedCollation)
373
386
  end
387
+
388
+ context 'when a String key is used' do
389
+
390
+ let(:requests) do
391
+ [{ delete_one: { filter: { name: 'BANG' }, 'collation' => collation }},
392
+ { delete_one: { filter: { name: 'DOINK' }, 'collation' => collation }}]
393
+ end
394
+
395
+ it 'raises an exception' do
396
+ expect {
397
+ bulk_write.execute
398
+ }.to raise_exception(Mongo::Error::UnsupportedCollation)
399
+ end
400
+ end
374
401
  end
375
402
  end
376
403
 
@@ -473,6 +500,19 @@ describe Mongo::BulkWrite do
473
500
  bulk_write.execute
474
501
  }.to raise_exception(Mongo::Error::UnsupportedCollation)
475
502
  end
503
+
504
+ context 'when a String key is used' do
505
+
506
+ let(:requests) do
507
+ [{ delete_many: { filter: { name: 'BANG' }, 'collation' => collation }}]
508
+ end
509
+
510
+ it 'raises an exception' do
511
+ expect {
512
+ bulk_write.execute
513
+ }.to raise_exception(Mongo::Error::UnsupportedCollation)
514
+ end
515
+ end
476
516
  end
477
517
  end
478
518
 
@@ -582,6 +622,20 @@ describe Mongo::BulkWrite do
582
622
  bulk_write.execute
583
623
  }.to raise_exception(Mongo::Error::UnsupportedCollation)
584
624
  end
625
+
626
+ context 'when a String key is used' do
627
+
628
+ let(:requests) do
629
+ [{ delete_many: { filter: { name: 'BANG' }, 'collation' => collation }},
630
+ { delete_many: { filter: { name: 'DOINK' }, 'collation' => collation }}]
631
+ end
632
+
633
+ it 'raises an exception' do
634
+ expect {
635
+ bulk_write.execute
636
+ }.to raise_exception(Mongo::Error::UnsupportedCollation)
637
+ end
638
+ end
585
639
  end
586
640
  end
587
641
 
@@ -698,6 +752,21 @@ describe Mongo::BulkWrite do
698
752
  bulk_write.execute
699
753
  }.to raise_exception(Mongo::Error::UnsupportedCollation)
700
754
  end
755
+
756
+ context 'when a String key is used' do
757
+
758
+ let(:requests) do
759
+ [{ replace_one: { filter: { name: 'BANG' },
760
+ replacement: { other: 'pong' },
761
+ 'collation' => collation }}]
762
+ end
763
+
764
+ it 'raises an exception' do
765
+ expect {
766
+ bulk_write.execute
767
+ }.to raise_exception(Mongo::Error::UnsupportedCollation)
768
+ end
769
+ end
701
770
  end
702
771
  end
703
772
 
@@ -936,6 +1005,21 @@ describe Mongo::BulkWrite do
936
1005
  bulk_write.execute
937
1006
  }.to raise_exception(Mongo::Error::UnsupportedCollation)
938
1007
  end
1008
+
1009
+ context 'when a String key is used' do
1010
+
1011
+ let(:requests) do
1012
+ [{ update_one: { filter: { name: 'BANG' },
1013
+ update: { "$set" => { name: 'pong' }},
1014
+ 'collation' => collation }}]
1015
+ end
1016
+
1017
+ it 'raises an exception' do
1018
+ expect {
1019
+ bulk_write.execute
1020
+ }.to raise_exception(Mongo::Error::UnsupportedCollation)
1021
+ end
1022
+ end
939
1023
  end
940
1024
  end
941
1025
 
@@ -1027,6 +1111,24 @@ describe Mongo::BulkWrite do
1027
1111
  bulk_write.execute
1028
1112
  }.to raise_exception(Mongo::Error::UnsupportedCollation)
1029
1113
  end
1114
+
1115
+ context 'when a String key is used' do
1116
+
1117
+ let(:requests) do
1118
+ [{ update_one: { filter: { name: 'BANG' },
1119
+ update: { "$set" => { name: 'pong' }},
1120
+ 'collation' => collation }},
1121
+ { update_one: { filter: { name: 'DOINK' },
1122
+ update: { "$set" => { name: 'pong' }},
1123
+ 'collation' => collation }}]
1124
+ end
1125
+
1126
+ it 'raises an exception' do
1127
+ expect {
1128
+ bulk_write.execute
1129
+ }.to raise_exception(Mongo::Error::UnsupportedCollation)
1130
+ end
1131
+ end
1030
1132
  end
1031
1133
  end
1032
1134
 
@@ -1314,6 +1416,21 @@ describe Mongo::BulkWrite do
1314
1416
  bulk_write.execute
1315
1417
  }.to raise_exception(Mongo::Error::UnsupportedCollation)
1316
1418
  end
1419
+
1420
+ context 'when a String key is used' do
1421
+
1422
+ let(:requests) do
1423
+ [{ update_many: { filter: { name: 'BANG' },
1424
+ update: { "$set" => { name: 'pong' }},
1425
+ 'collation' => collation }}]
1426
+ end
1427
+
1428
+ it 'raises an exception' do
1429
+ expect {
1430
+ bulk_write.execute
1431
+ }.to raise_exception(Mongo::Error::UnsupportedCollation)
1432
+ end
1433
+ end
1317
1434
  end
1318
1435
  end
1319
1436
 
@@ -235,6 +235,19 @@ describe Mongo::Collection::View::Aggregation do
235
235
  result
236
236
  }.to raise_exception(Mongo::Error::UnsupportedCollation)
237
237
  end
238
+
239
+ context 'when a String key is used' do
240
+
241
+ let(:options) do
242
+ { 'collation' => { locale: 'en_US', strength: 2 } }
243
+ end
244
+
245
+ it 'raises an exception' do
246
+ expect {
247
+ result
248
+ }.to raise_exception(Mongo::Error::UnsupportedCollation)
249
+ end
250
+ end
238
251
  end
239
252
  end
240
253
  end
@@ -419,6 +432,19 @@ describe Mongo::Collection::View::Aggregation do
419
432
  result
420
433
  }.to raise_exception(Mongo::Error::UnsupportedCollation)
421
434
  end
435
+
436
+ context 'when a String key is used' do
437
+
438
+ let(:options) do
439
+ { 'collation' => { locale: 'en_US', strength: 2 } }
440
+ end
441
+
442
+ it 'raises an exception' do
443
+ expect {
444
+ result
445
+ }.to raise_exception(Mongo::Error::UnsupportedCollation)
446
+ end
447
+ end
422
448
  end
423
449
  end
424
450