mongo 2.1.0.rc0 → 2.1.0

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 (110) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +5 -2
  3. data.tar.gz.sig +0 -0
  4. data/Rakefile +2 -2
  5. data/lib/mongo.rb +2 -1
  6. data/lib/mongo/address.rb +11 -5
  7. data/lib/mongo/address/ipv4.rb +6 -1
  8. data/lib/mongo/auth/cr/conversation.rb +1 -1
  9. data/lib/mongo/auth/ldap/conversation.rb +1 -1
  10. data/lib/mongo/auth/scram/conversation.rb +1 -1
  11. data/lib/mongo/auth/user/view.rb +2 -2
  12. data/lib/mongo/auth/x509/conversation.rb +1 -1
  13. data/lib/mongo/bulk_write.rb +12 -9
  14. data/lib/mongo/bulk_write/transformable.rb +20 -5
  15. data/lib/mongo/client.rb +11 -11
  16. data/lib/mongo/cluster.rb +2 -2
  17. data/lib/mongo/collection.rb +21 -8
  18. data/lib/mongo/collection/view.rb +1 -0
  19. data/lib/mongo/collection/view/aggregation.rb +11 -5
  20. data/lib/mongo/collection/view/iterable.rb +6 -2
  21. data/lib/mongo/collection/view/map_reduce.rb +39 -5
  22. data/lib/mongo/collection/view/readable.rb +35 -30
  23. data/lib/mongo/collection/view/writable.rb +26 -18
  24. data/lib/mongo/database.rb +12 -2
  25. data/lib/mongo/database/view.rb +4 -3
  26. data/lib/mongo/dbref.rb +4 -4
  27. data/lib/mongo/grid/fs_bucket.rb +8 -1
  28. data/lib/mongo/grid/stream/read.rb +1 -1
  29. data/lib/mongo/index.rb +5 -0
  30. data/lib/mongo/index/view.rb +2 -2
  31. data/lib/mongo/monitoring/command_log_subscriber.rb +9 -3
  32. data/lib/mongo/monitoring/event.rb +1 -0
  33. data/lib/mongo/monitoring/event/command_started.rb +2 -1
  34. data/lib/mongo/monitoring/event/command_succeeded.rb +6 -3
  35. data/lib/mongo/monitoring/event/secure.rb +58 -0
  36. data/lib/mongo/operation.rb +31 -1
  37. data/lib/mongo/operation/commands/collections_info.rb +2 -0
  38. data/lib/mongo/operation/commands/collections_info/result.rb +39 -0
  39. data/lib/mongo/operation/commands/list_indexes/result.rb +2 -1
  40. data/lib/mongo/operation/commands/map_reduce/result.rb +1 -1
  41. data/lib/mongo/operation/read/query.rb +2 -0
  42. data/lib/mongo/operation/read/query/result.rb +40 -0
  43. data/lib/mongo/operation/result.rb +13 -1
  44. data/lib/mongo/operation/write/bulk/delete.rb +2 -2
  45. data/lib/mongo/operation/write/bulk/update.rb +3 -3
  46. data/lib/mongo/operation/write/delete.rb +2 -2
  47. data/lib/mongo/operation/write/update.rb +9 -4
  48. data/lib/mongo/options.rb +1 -0
  49. data/lib/mongo/options/redacted.rb +156 -0
  50. data/lib/mongo/protocol/insert.rb +25 -6
  51. data/lib/mongo/protocol/query.rb +45 -31
  52. data/lib/mongo/protocol/reply.rb +29 -6
  53. data/lib/mongo/protocol/serializers.rb +1 -1
  54. data/lib/mongo/retryable.rb +83 -0
  55. data/lib/mongo/server.rb +16 -3
  56. data/lib/mongo/server/connectable.rb +21 -3
  57. data/lib/mongo/server/connection.rb +38 -4
  58. data/lib/mongo/server/connection_pool.rb +12 -0
  59. data/lib/mongo/server/connection_pool/queue.rb +15 -0
  60. data/lib/mongo/server/monitor/connection.rb +2 -2
  61. data/lib/mongo/server_selector.rb +5 -0
  62. data/lib/mongo/server_selector/selectable.rb +16 -9
  63. data/lib/mongo/socket.rb +6 -2
  64. data/lib/mongo/uri.rb +1 -1
  65. data/lib/mongo/version.rb +1 -1
  66. data/spec/mongo/bulk_write/ordered_combiner_spec.rb +11 -11
  67. data/spec/mongo/bulk_write/unordered_combiner_spec.rb +10 -10
  68. data/spec/mongo/client_spec.rb +101 -18
  69. data/spec/mongo/collection_spec.rb +44 -0
  70. data/spec/mongo/connection_string_spec.rb +36 -58
  71. data/spec/mongo/database_spec.rb +20 -0
  72. data/spec/mongo/grid/fs_bucket_spec.rb +1 -1
  73. data/spec/mongo/grid/stream/write_spec.rb +2 -2
  74. data/spec/mongo/monitoring/event/command_started_spec.rb +26 -0
  75. data/spec/mongo/monitoring/event/command_succeeded_spec.rb +26 -0
  76. data/spec/mongo/monitoring/event/secure_spec.rb +57 -0
  77. data/spec/mongo/operation/commands/aggregate_spec.rb +0 -16
  78. data/spec/mongo/operation/commands/command_spec.rb +0 -18
  79. data/spec/mongo/operation/kill_cursors_spec.rb +0 -16
  80. data/spec/mongo/operation/read/get_more_spec.rb +0 -16
  81. data/spec/mongo/operation/read/query_spec.rb +19 -16
  82. data/spec/mongo/operation/write/bulk/delete_spec.rb +16 -16
  83. data/spec/mongo/operation/write/bulk/update_spec.rb +6 -6
  84. data/spec/mongo/operation/write/command/delete_spec.rb +0 -16
  85. data/spec/mongo/operation/write/command/insert_spec.rb +0 -16
  86. data/spec/mongo/operation/write/command/update_spec.rb +0 -16
  87. data/spec/mongo/operation/write/delete_spec.rb +3 -3
  88. data/spec/mongo/operation/write/update_spec.rb +6 -6
  89. data/spec/mongo/options/redacted_spec.rb +350 -0
  90. data/spec/mongo/protocol/query_spec.rb +15 -1
  91. data/spec/mongo/retryable_spec.rb +147 -0
  92. data/spec/mongo/server/connection_pool/queue_spec.rb +16 -0
  93. data/spec/mongo/server/connection_pool_spec.rb +32 -0
  94. data/spec/mongo/server/connection_spec.rb +37 -0
  95. data/spec/mongo/server_discovery_and_monitoring_spec.rb +24 -59
  96. data/spec/mongo/server_selection_rtt_spec.rb +37 -57
  97. data/spec/mongo/server_selection_spec.rb +2 -0
  98. data/spec/mongo/server_selector/nearest_spec.rb +1 -0
  99. data/spec/mongo/server_selector/primary_preferred_spec.rb +1 -0
  100. data/spec/mongo/server_selector/primary_spec.rb +8 -2
  101. data/spec/mongo/server_selector/secondary_preferred_spec.rb +1 -0
  102. data/spec/mongo/server_selector/secondary_spec.rb +1 -0
  103. data/spec/mongo/server_spec.rb +68 -1
  104. data/spec/mongo/socket/ssl_spec.rb +29 -5
  105. data/spec/mongo/uri_spec.rb +20 -20
  106. data/spec/support/crud.rb +7 -1
  107. data/spec/support/matchers.rb +1 -1
  108. data/spec/support/shared/server_selector.rb +58 -2
  109. metadata +20 -5
  110. metadata.gz.sig +0 -0
@@ -54,6 +54,18 @@ module Mongo
54
54
  queue.dequeue
55
55
  end
56
56
 
57
+ # Disconnect the connection pool.
58
+ #
59
+ # @example Disconnect the connection pool.
60
+ # pool.disconnect!
61
+ #
62
+ # @return [ true ] true.
63
+ #
64
+ # @since 2.1.0
65
+ def disconnect!
66
+ queue.disconnect!
67
+ end
68
+
57
69
  # Create the new connection pool.
58
70
  #
59
71
  # @example Create the new connection pool.
@@ -63,6 +63,21 @@ module Mongo
63
63
  end
64
64
  end
65
65
 
66
+ # Disconnect all connections in the queue.
67
+ #
68
+ # @example Disconnect all connections.
69
+ # queue.disconnect!
70
+ #
71
+ # @return [ true ] Always true.
72
+ #
73
+ # @since 2.1.0
74
+ def disconnect!
75
+ mutex.synchronize do
76
+ queue.each{ |connection| connection.disconnect! }
77
+ true
78
+ end
79
+ end
80
+
66
81
  # Enqueue a connection in the queue.
67
82
  #
68
83
  # @example Enqueue a connection.
@@ -36,7 +36,7 @@ module Mongo
36
36
  def connect!
37
37
  unless socket
38
38
  @socket = address.socket(timeout, ssl_options)
39
- @socket.connect!
39
+ socket.connect!
40
40
  end
41
41
  true
42
42
  end
@@ -96,7 +96,7 @@ module Mongo
96
96
  def initialize(address, options = {})
97
97
  @address = address
98
98
  @options = options.freeze
99
- @ssl_options = options.reject { |k, v| !k.to_s.start_with?('ssl') }
99
+ @ssl_options = options.reject { |k, v| !k.to_s.start_with?(SSL) }
100
100
  @socket = nil
101
101
  @pid = Process.pid
102
102
  end
@@ -38,6 +38,11 @@ module Mongo
38
38
  # @since 2.0.0
39
39
  SERVER_SELECTION_TIMEOUT = 30.freeze
40
40
 
41
+ # Primary read preference.
42
+ #
43
+ # @since 2.1.0
44
+ PRIMARY = Options::Redacted.new(mode: :primary).freeze
45
+
41
46
  # Hash lookup for the selector classes based off the symbols
42
47
  # provided in configuration.
43
48
  #
@@ -61,10 +61,10 @@ module Mongo
61
61
  #
62
62
  # @since 2.0.0
63
63
  def initialize(options = {})
64
+ @options = (options || {}).freeze
64
65
  tag_sets = options[:tag_sets] || []
65
66
  validate_tag_sets!(tag_sets)
66
- @tag_sets = tag_sets
67
- @options = options
67
+ @tag_sets = tag_sets.freeze
68
68
  end
69
69
 
70
70
  # Select a server from eligible candidates.
@@ -80,14 +80,11 @@ module Mongo
80
80
  def select_server(cluster)
81
81
  deadline = Time.now + server_selection_timeout
82
82
  while (deadline - Time.now) > 0
83
- if cluster.single?
84
- servers = cluster.servers
85
- elsif cluster.sharded?
86
- servers = near_servers(cluster.servers)
87
- else
88
- servers = select(cluster.servers)
83
+ servers = candidates(cluster)
84
+ if servers && !servers.compact.empty?
85
+ server = servers.first
86
+ return server if server.connectable?
89
87
  end
90
- return servers.first if servers && !servers.compact.empty?
91
88
  cluster.scan!
92
89
  end
93
90
  raise Error::NoServerAvailable.new(self)
@@ -120,6 +117,16 @@ module Mongo
120
117
 
121
118
  private
122
119
 
120
+ def candidates(cluster)
121
+ if cluster.single?
122
+ cluster.servers
123
+ elsif cluster.sharded?
124
+ near_servers(cluster.servers)
125
+ else
126
+ select(cluster.servers)
127
+ end
128
+ end
129
+
123
130
  # Select the primary from a list of provided candidates.
124
131
  #
125
132
  # @param [ Array ] candidates List of candidate servers to select the
@@ -54,7 +54,7 @@ module Mongo
54
54
  #
55
55
  # @return [ true, false ] If the socket is alive.
56
56
  #
57
- # @since 2.0.0
57
+ # @deprecated Use #connectable? on the connection instead.
58
58
  def alive?
59
59
  sock_arr = [ @socket ]
60
60
  if Kernel::select(sock_arr, nil, sock_arr, 0)
@@ -172,10 +172,14 @@ module Mongo
172
172
  @socket.read(length) || String.new
173
173
  end
174
174
 
175
+ def unix_socket?(sock)
176
+ defined?(UNIXSocket) && sock.is_a?(UNIXSocket)
177
+ end
178
+
175
179
  def set_socket_options(sock)
176
180
  sock.set_encoding(BSON::BINARY)
177
181
 
178
- unless sock.is_a?(UNIXSocket) && BSON::Environment.jruby?
182
+ unless unix_socket?(sock) && BSON::Environment.jruby?
179
183
  encoded_timeout = [ timeout, 0 ].pack(TIMEOUT_PACK)
180
184
  sock.setsockopt(SOL_SOCKET, SO_RCVTIMEO, encoded_timeout)
181
185
  sock.setsockopt(SOL_SOCKET, SO_SNDTIMEO, encoded_timeout)
@@ -268,7 +268,7 @@ module Mongo
268
268
 
269
269
  def parse_db_opts!(string)
270
270
  auth_db, d, uri_opts = string.partition(URI_OPTS_DELIM)
271
- @uri_options = parse_uri_options!(uri_opts)
271
+ @uri_options = Options::Redacted.new(parse_uri_options!(uri_opts))
272
272
  @database = parse_database!(auth_db)
273
273
  end
274
274
 
@@ -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.1.0.rc0'.freeze
20
+ VERSION = '2.1.0'.freeze
21
21
  end
@@ -24,8 +24,8 @@ describe Mongo::BulkWrite::OrderedCombiner do
24
24
  [
25
25
  {
26
26
  delete_one: [
27
- { q: { _id: 0 }, limit: 1 },
28
- { q: { _id: 1 }, limit: 1 }
27
+ { 'q' => { _id: 0 }, 'limit' => 1 },
28
+ { 'q' => { _id: 1 }, 'limit' => 1 }
29
29
  ]
30
30
  }
31
31
  ]
@@ -66,8 +66,8 @@ describe Mongo::BulkWrite::OrderedCombiner do
66
66
  [
67
67
  {
68
68
  delete_many: [
69
- { q: { _id: 0 }, limit: 0 },
70
- { q: { _id: 1 }, limit: 0 }
69
+ { 'q' => { _id: 0 }, 'limit' => 0 },
70
+ { 'q' => { _id: 1 }, 'limit' => 0 }
71
71
  ]
72
72
  }
73
73
  ]
@@ -137,8 +137,8 @@ describe Mongo::BulkWrite::OrderedCombiner do
137
137
  [
138
138
  {
139
139
  replace_one: [
140
- { q: { _id: 0 }, u: { name: 'test' }, multi: false, upsert: false },
141
- { q: { _id: 1 }, u: { name: 'test' }, multi: false, upsert: false }
140
+ { 'q' => { _id: 0 }, 'u' => { name: 'test' }, 'multi' => false, 'upsert' => false },
141
+ { 'q' => { _id: 1 }, 'u' => { name: 'test' }, 'multi' => false, 'upsert' => false }
142
142
  ]
143
143
  }
144
144
  ]
@@ -179,8 +179,8 @@ describe Mongo::BulkWrite::OrderedCombiner do
179
179
  [
180
180
  {
181
181
  update_one: [
182
- { q: { _id: 0 }, u: { '$set' => { name: 'test' }}, multi: false, upsert: false },
183
- { q: { _id: 1 }, u: { '$set' => { name: 'test' }}, multi: false, upsert: false }
182
+ { 'q' => { _id: 0 }, 'u' => { '$set' => { name: 'test' }}, 'multi' => false, 'upsert' => false },
183
+ { 'q' => { _id: 1 }, 'u' => { '$set' => { name: 'test' }}, 'multi' => false, 'upsert' => false }
184
184
  ]
185
185
  }
186
186
  ]
@@ -221,8 +221,8 @@ describe Mongo::BulkWrite::OrderedCombiner do
221
221
  [
222
222
  {
223
223
  update_many: [
224
- { q: { _id: 0 }, u: { '$set' => { name: 'test' }}, multi: true, upsert: false },
225
- { q: { _id: 1 }, u: { '$set' => { name: 'test' }}, multi: true, upsert: false }
224
+ { 'q' => { _id: 0 }, 'u' => { '$set' => { name: 'test' }}, 'multi' => true, 'upsert' => false },
225
+ { 'q' => { _id: 1 }, 'u' => { '$set' => { name: 'test' }}, 'multi' => true, 'upsert' => false }
226
226
  ]
227
227
  }
228
228
  ]
@@ -261,7 +261,7 @@ describe Mongo::BulkWrite::OrderedCombiner do
261
261
  expect(combiner.combine).to eq(
262
262
  [
263
263
  { insert_one: [{ _id: 0 }]},
264
- { delete_one: [{ q: { _id: 0 }, limit: 1 }]},
264
+ { delete_one: [{ 'q' => { _id: 0 }, 'limit' => 1 }]},
265
265
  { insert_one: [{ _id: 1 }]}
266
266
  ]
267
267
  )
@@ -24,8 +24,8 @@ describe Mongo::BulkWrite::UnorderedCombiner do
24
24
  [
25
25
  {
26
26
  delete_one: [
27
- { q: { _id: 0 }, limit: 1 },
28
- { q: { _id: 1 }, limit: 1 }
27
+ { 'q' => { _id: 0 }, 'limit' => 1 },
28
+ { 'q' => { _id: 1 }, 'limit' => 1 }
29
29
  ]
30
30
  }
31
31
  ]
@@ -66,8 +66,8 @@ describe Mongo::BulkWrite::UnorderedCombiner do
66
66
  [
67
67
  {
68
68
  delete_many: [
69
- { q: { _id: 0 }, limit: 0 },
70
- { q: { _id: 1 }, limit: 0 }
69
+ { 'q' => { _id: 0 }, 'limit' => 0 },
70
+ { 'q' => { _id: 1 }, 'limit' => 0 }
71
71
  ]
72
72
  }
73
73
  ]
@@ -137,8 +137,8 @@ describe Mongo::BulkWrite::UnorderedCombiner do
137
137
  [
138
138
  {
139
139
  update_one: [
140
- { q: { _id: 0 }, u: { '$set' => { name: 'test' }}, multi: false, upsert: false },
141
- { q: { _id: 1 }, u: { '$set' => { name: 'test' }}, multi: false, upsert: false }
140
+ { 'q' => { _id: 0 }, 'u' => { '$set' => { name: 'test' }}, 'multi' => false, 'upsert' => false },
141
+ { 'q' => { _id: 1 }, 'u' => { '$set' => { name: 'test' }}, 'multi' => false, 'upsert' => false }
142
142
  ]
143
143
  }
144
144
  ]
@@ -179,8 +179,8 @@ describe Mongo::BulkWrite::UnorderedCombiner do
179
179
  [
180
180
  {
181
181
  update_many: [
182
- { q: { _id: 0 }, u: { '$set' => { name: 'test' }}, multi: true, upsert: false },
183
- { q: { _id: 1 }, u: { '$set' => { name: 'test' }}, multi: true, upsert: false }
182
+ { 'q' => { _id: 0 }, 'u' => { '$set' => { name: 'test' }}, 'multi' => true, 'upsert' => false },
183
+ { 'q' => { _id: 1 }, 'u' => { '$set' => { name: 'test' }}, 'multi' => true, 'upsert' => false }
184
184
  ]
185
185
  }
186
186
  ]
@@ -227,8 +227,8 @@ describe Mongo::BulkWrite::UnorderedCombiner do
227
227
  },
228
228
  {
229
229
  delete_one: [
230
- { q: { _id: 0 }, limit: 1 },
231
- { q: { _id: 1 }, limit: 1 }
230
+ { 'q' => { _id: 0 }, 'limit' => 1 },
231
+ { 'q' => { _id: 1 }, 'limit' => 1 }
232
232
  ]
233
233
  }
234
234
  ]
@@ -167,16 +167,20 @@ describe Mongo::Client do
167
167
  ['127.0.0.1:27017'],
168
168
  :read => { :mode => :primary },
169
169
  :local_threshold_ms => 10,
170
- :server_selection_timeout_ms => 10000,
170
+ :server_selection_timeout => 10000,
171
171
  :database => TEST_DB
172
172
  )
173
173
  end
174
174
 
175
+ let(:options) do
176
+ Mongo::Options::Redacted.new(:read => { :mode => :primary },
177
+ :local_threshold_ms => 10,
178
+ :server_selection_timeout => 10000,
179
+ :database => TEST_DB)
180
+ end
181
+
175
182
  let(:expected) do
176
- [client.cluster, { :read => { :mode => :primary },
177
- :local_threshold_ms => 10,
178
- :server_selection_timeout_ms => 10000,
179
- :database => TEST_DB }].hash
183
+ [client.cluster, options].hash
180
184
  end
181
185
 
182
186
  it 'returns a hash of the cluster and options' do
@@ -199,6 +203,23 @@ describe Mongo::Client do
199
203
  "<Mongo::Client:0x#{client.object_id} cluster=127.0.0.1:27017"
200
204
  )
201
205
  end
206
+
207
+ context 'when there is sensitive data in the options' do
208
+
209
+ let(:client) do
210
+ described_class.new(
211
+ ['127.0.0.1:27017'],
212
+ :read => { :mode => :primary },
213
+ :database => TEST_DB,
214
+ :password => 'some_password',
215
+ :user => 'emily'
216
+ )
217
+ end
218
+
219
+ it 'does not print out sensitive data' do
220
+ expect(client.inspect).not_to match('some_password')
221
+ end
222
+ end
202
223
  end
203
224
 
204
225
  describe '#initialize' do
@@ -291,8 +312,12 @@ describe Mongo::Client do
291
312
  described_class.new(uri)
292
313
  end
293
314
 
315
+ let(:expected_options) do
316
+ Mongo::Options::Redacted.new(:write => { :w => 3 }, :database => 'testdb')
317
+ end
318
+
294
319
  it 'sets the options' do
295
- expect(client.options).to eq(:write => { :w => 3 }, :database => 'testdb')
320
+ expect(client.options).to eq(expected_options)
296
321
  end
297
322
  end
298
323
 
@@ -306,8 +331,12 @@ describe Mongo::Client do
306
331
  described_class.new(uri, :write => { :w => 3 })
307
332
  end
308
333
 
334
+ let(:expected_options) do
335
+ Mongo::Options::Redacted.new(:write => { :w => 3 }, :database => 'testdb')
336
+ end
337
+
309
338
  it 'sets the options' do
310
- expect(client.options).to eq(:write => { :w => 3 }, :database => 'testdb')
339
+ expect(client.options).to eq(expected_options)
311
340
  end
312
341
  end
313
342
 
@@ -321,8 +350,12 @@ describe Mongo::Client do
321
350
  described_class.new(uri, :write => { :w => 4 })
322
351
  end
323
352
 
353
+ let(:expected_options) do
354
+ Mongo::Options::Redacted.new(:write => { :w => 4 }, :database => 'testdb')
355
+ end
356
+
324
357
  it 'allows explicit options to take preference' do
325
- expect(client.options).to eq(:write => { :w => 4 }, :database => 'testdb')
358
+ expect(client.options).to eq(expected_options)
326
359
  end
327
360
  end
328
361
 
@@ -348,7 +381,8 @@ describe Mongo::Client do
348
381
  let(:client) do
349
382
  described_class.new(['127.0.0.1:27017'],
350
383
  :database => TEST_DB,
351
- :read => mode)
384
+ :read => mode,
385
+ :server_selection_timeout => 2)
352
386
  end
353
387
 
354
388
  let(:preference) do
@@ -366,7 +400,7 @@ describe Mongo::Client do
366
400
  end
367
401
 
368
402
  it 'passes the options to the read preference' do
369
- expect(preference.options[:database]).to eq(TEST_DB)
403
+ expect(preference.options[:server_selection_timeout]).to eq(2)
370
404
  end
371
405
  end
372
406
 
@@ -424,6 +458,33 @@ describe Mongo::Client do
424
458
  expect(preference).to be_a(Mongo::ServerSelector::Primary)
425
459
  end
426
460
  end
461
+
462
+ context 'when the read preference is printed' do
463
+
464
+ let(:client) do
465
+ described_class.new([ DEFAULT_ADDRESS ], options)
466
+ end
467
+
468
+ let(:options) do
469
+ { user: 'Emily', password: 'sensitive_data', server_selection_timeout: 0.1 }
470
+ end
471
+
472
+ before do
473
+ allow(client.database.cluster).to receive(:single?).and_return(false)
474
+ end
475
+
476
+ let(:error) do
477
+ begin
478
+ client.database.command(ping: 1)
479
+ rescue => e
480
+ e
481
+ end
482
+ end
483
+
484
+ it 'redacts sensitive client options' do
485
+ expect(error.message).not_to match(options[:password])
486
+ end
487
+ end
427
488
  end
428
489
 
429
490
  describe '#use' do
@@ -497,20 +558,28 @@ describe Mongo::Client do
497
558
  client.with(:read => { :mode => :primary })
498
559
  end
499
560
 
561
+ let(:new_options) do
562
+ Mongo::Options::Redacted.new(:read => { :mode => :primary },
563
+ :write => { :w => 1 },
564
+ :database => TEST_DB)
565
+ end
566
+
567
+ let(:original_options) do
568
+ Mongo::Options::Redacted.new(:read => { :mode => :secondary },
569
+ :write => { :w => 1 },
570
+ :database => TEST_DB)
571
+ end
572
+
500
573
  it 'returns a new client' do
501
574
  expect(new_client).not_to equal(client)
502
575
  end
503
576
 
504
577
  it 'replaces the existing options' do
505
- expect(new_client.options).to eq({
506
- :read => { :mode => :primary }, :write => { :w => 1 }, :database => TEST_DB
507
- })
578
+ expect(new_client.options).to eq(new_options)
508
579
  end
509
580
 
510
581
  it 'does not modify the original client' do
511
- expect(client.options).to eq({
512
- :read => { :mode => :secondary }, :write => { :w => 1 }, :database => TEST_DB
513
- })
582
+ expect(client.options).to eq(original_options)
514
583
  end
515
584
 
516
585
  it 'keeps the same cluster' do
@@ -579,7 +648,7 @@ describe Mongo::Client do
579
648
  end
580
649
 
581
650
  it 'returns a acknowledged write concern' do
582
- expect(concern.get_last_error).to eq(:getlasterror => 1, :j => true)
651
+ expect(concern.get_last_error).to eq(:getlasterror => 1, 'j' => true)
583
652
  end
584
653
  end
585
654
 
@@ -656,7 +725,21 @@ describe Mongo::Client do
656
725
 
657
726
  it 'reconnects the cluster and returns true' do
658
727
  expect(client.reconnect).to be(true)
659
- sleep(2)
728
+ end
729
+ end
730
+
731
+ describe '#dup' do
732
+
733
+ let(:client) do
734
+ described_class.new(
735
+ ['127.0.0.1:27017'],
736
+ :read => { :mode => :primary },
737
+ :database => TEST_DB
738
+ )
739
+ end
740
+
741
+ it 'creates a client with Redacted options' do
742
+ expect(client.dup.options).to be_a(Mongo::Options::Redacted)
660
743
  end
661
744
  end
662
745
  end