mongo 2.1.0.rc0 → 2.1.0

Sign up to get free protection for your applications and to get access to all the features.
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