mongo 2.9.2 → 2.10.0.rc0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (227) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data.tar.gz.sig +0 -0
  4. data/lib/mongo.rb +1 -0
  5. data/lib/mongo/auth/user/view.rb +4 -4
  6. data/lib/mongo/bulk_write.rb +14 -8
  7. data/lib/mongo/bulk_write/result.rb +1 -1
  8. data/lib/mongo/bulk_write/result_combiner.rb +2 -2
  9. data/lib/mongo/bulk_write/transformable.rb +17 -9
  10. data/lib/mongo/client.rb +107 -16
  11. data/lib/mongo/cluster.rb +47 -25
  12. data/lib/mongo/cluster/topology/replica_set_no_primary.rb +1 -1
  13. data/lib/mongo/cluster_time.rb +139 -0
  14. data/lib/mongo/collection.rb +84 -25
  15. data/lib/mongo/collection/view.rb +7 -3
  16. data/lib/mongo/collection/view/aggregation.rb +4 -4
  17. data/lib/mongo/collection/view/builder/aggregation.rb +31 -6
  18. data/lib/mongo/collection/view/builder/find_command.rb +4 -1
  19. data/lib/mongo/collection/view/builder/map_reduce.rb +4 -1
  20. data/lib/mongo/collection/view/change_stream.rb +54 -66
  21. data/lib/mongo/collection/view/iterable.rb +2 -2
  22. data/lib/mongo/collection/view/map_reduce.rb +6 -4
  23. data/lib/mongo/collection/view/readable.rb +36 -16
  24. data/lib/mongo/collection/view/writable.rb +68 -22
  25. data/lib/mongo/cursor.rb +87 -20
  26. data/lib/mongo/database.rb +47 -43
  27. data/lib/mongo/database/view.rb +54 -11
  28. data/lib/mongo/error.rb +13 -4
  29. data/lib/mongo/error/invalid_write_concern.rb +2 -2
  30. data/lib/mongo/error/operation_failure.rb +65 -11
  31. data/lib/mongo/error/parser.rb +41 -8
  32. data/lib/mongo/grid/fs_bucket.rb +26 -6
  33. data/lib/mongo/grid/stream/read.rb +9 -2
  34. data/lib/mongo/grid/stream/write.rb +21 -5
  35. data/lib/mongo/index/view.rb +3 -3
  36. data/lib/mongo/lint.rb +10 -3
  37. data/lib/mongo/operation.rb +2 -0
  38. data/lib/mongo/operation/aggregate/result.rb +19 -6
  39. data/lib/mongo/operation/collections_info.rb +1 -1
  40. data/lib/mongo/operation/get_more/result.rb +9 -0
  41. data/lib/mongo/operation/list_collections/command.rb +1 -3
  42. data/lib/mongo/operation/list_collections/op_msg.rb +1 -2
  43. data/lib/mongo/operation/parallel_scan/command.rb +4 -1
  44. data/lib/mongo/operation/parallel_scan/op_msg.rb +4 -1
  45. data/lib/mongo/operation/result.rb +27 -4
  46. data/lib/mongo/operation/shared/executable.rb +19 -5
  47. data/lib/mongo/operation/shared/executable_no_validate.rb +1 -2
  48. data/lib/mongo/operation/shared/executable_transaction_label.rb +0 -9
  49. data/lib/mongo/operation/shared/polymorphic_result.rb +9 -1
  50. data/lib/mongo/operation/shared/result/aggregatable.rb +2 -2
  51. data/lib/mongo/operation/shared/sessions_supported.rb +42 -32
  52. data/lib/mongo/operation/shared/specifiable.rb +40 -0
  53. data/lib/mongo/operation/shared/unpinnable.rb +39 -0
  54. data/lib/mongo/operation/shared/write.rb +1 -1
  55. data/lib/mongo/protocol/update.rb +6 -2
  56. data/lib/mongo/retryable.rb +79 -39
  57. data/lib/mongo/server/connection.rb +10 -3
  58. data/lib/mongo/server/description.rb +25 -1
  59. data/lib/mongo/server/monitor/connection.rb +1 -1
  60. data/lib/mongo/server_selector.rb +10 -0
  61. data/lib/mongo/server_selector/selectable.rb +172 -32
  62. data/lib/mongo/session.rb +654 -581
  63. data/lib/mongo/session/session_pool.rb +1 -1
  64. data/lib/mongo/socket.rb +7 -28
  65. data/lib/mongo/socket/ssl.rb +26 -1
  66. data/lib/mongo/socket/tcp.rb +3 -0
  67. data/lib/mongo/socket/unix.rb +3 -0
  68. data/lib/mongo/uri.rb +112 -265
  69. data/lib/mongo/uri/srv_protocol.rb +4 -1
  70. data/lib/mongo/version.rb +1 -1
  71. data/lib/mongo/write_concern.rb +10 -29
  72. data/lib/mongo/write_concern/acknowledged.rb +12 -0
  73. data/lib/mongo/write_concern/base.rb +17 -13
  74. data/lib/mongo/write_concern/unacknowledged.rb +12 -0
  75. data/spec/atlas/atlas_connectivity_spec.rb +7 -37
  76. data/spec/atlas/operations_spec.rb +25 -0
  77. data/spec/integration/change_stream_examples_spec.rb +45 -31
  78. data/spec/integration/change_stream_spec.rb +305 -5
  79. data/spec/integration/client_spec.rb +44 -0
  80. data/spec/integration/command_monitoring_spec.rb +1 -0
  81. data/spec/integration/command_spec.rb +7 -1
  82. data/spec/integration/mmapv1_spec.rb +28 -0
  83. data/spec/integration/mongos_pinning_spec.rb +34 -0
  84. data/spec/integration/operation_failure_code_spec.rb +2 -2
  85. data/spec/integration/{read_concern.rb → read_concern_spec.rb} +7 -1
  86. data/spec/integration/read_preference_spec.rb +485 -0
  87. data/spec/integration/retryable_writes_spec.rb +8 -19
  88. data/spec/integration/sdam_error_handling_spec.rb +1 -1
  89. data/spec/integration/sdam_events_spec.rb +2 -2
  90. data/spec/integration/server_description_spec.rb +14 -17
  91. data/spec/integration/server_selector_spec.rb +7 -3
  92. data/spec/integration/server_spec.rb +48 -0
  93. data/spec/integration/ssl_uri_options_spec.rb +1 -1
  94. data/spec/integration/step_down_spec.rb +10 -4
  95. data/spec/integration/transactions_examples_spec.rb +11 -10
  96. data/spec/lite_spec_helper.rb +19 -16
  97. data/spec/mongo/auth/scram/negotiation_spec.rb +11 -8
  98. data/spec/mongo/bulk_write/ordered_combiner_spec.rb +6 -6
  99. data/spec/mongo/bulk_write/unordered_combiner_spec.rb +4 -4
  100. data/spec/mongo/bulk_write_spec.rb +12 -2
  101. data/spec/mongo/client_construction_spec.rb +160 -8
  102. data/spec/mongo/client_spec.rb +5 -4
  103. data/spec/mongo/cluster_spec.rb +6 -6
  104. data/spec/mongo/cluster_time_spec.rb +148 -0
  105. data/spec/mongo/collection/view/aggregation_spec.rb +34 -15
  106. data/spec/mongo/collection/view/change_stream_spec.rb +62 -3
  107. data/spec/mongo/collection/view/map_reduce_spec.rb +7 -5
  108. data/spec/mongo/collection/view/readable_spec.rb +4 -4
  109. data/spec/mongo/collection_spec.rb +331 -14
  110. data/spec/mongo/cursor_spec.rb +117 -5
  111. data/spec/mongo/database_spec.rb +240 -8
  112. data/spec/mongo/error/operation_failure_spec.rb +47 -1
  113. data/spec/mongo/error/parser_spec.rb +160 -23
  114. data/spec/mongo/operation/insert/bulk_spec.rb +2 -1
  115. data/spec/mongo/operation/result_spec.rb +27 -0
  116. data/spec/mongo/operation/update/bulk_spec.rb +1 -0
  117. data/spec/mongo/retryable_spec.rb +2 -0
  118. data/spec/mongo/server/app_metadata_spec.rb +2 -2
  119. data/spec/mongo/server/connection_spec.rb +13 -17
  120. data/spec/mongo/server/monitor/connection_spec.rb +13 -10
  121. data/spec/mongo/server_selector_spec.rb +34 -2
  122. data/spec/mongo/session/session_pool_spec.rb +14 -3
  123. data/spec/mongo/session_spec.rb +3 -3
  124. data/spec/mongo/session_transaction_spec.rb +4 -3
  125. data/spec/mongo/socket/ssl_spec.rb +19 -5
  126. data/spec/mongo/socket_spec.rb +1 -62
  127. data/spec/mongo/uri/srv_protocol_spec.rb +14 -20
  128. data/spec/mongo/uri_option_parsing_spec.rb +94 -8
  129. data/spec/mongo/uri_spec.rb +23 -10
  130. data/spec/mongo/write_concern_spec.rb +56 -3
  131. data/spec/spec_tests/change_streams_spec.rb +2 -1
  132. data/spec/spec_tests/cmap_spec.rb +1 -1
  133. data/spec/spec_tests/crud_spec.rb +12 -2
  134. data/spec/spec_tests/data/change_streams/change-streams-errors.yml +24 -1
  135. data/spec/spec_tests/data/change_streams/change-streams.yml +172 -3
  136. data/spec/spec_tests/data/command_monitoring/bulkWrite.yml +1 -1
  137. data/spec/spec_tests/data/command_monitoring/updateMany.yml +0 -2
  138. data/spec/spec_tests/data/command_monitoring/updateOne.yml +0 -5
  139. data/spec/spec_tests/data/crud/read/aggregate-out.yml +0 -6
  140. data/spec/spec_tests/data/crud/read/count-empty.yml +29 -0
  141. data/spec/spec_tests/data/crud/write/bulkWrite-arrayFilters.yml +1 -0
  142. data/spec/spec_tests/data/crud/write/bulkWrite-collation.yml +101 -0
  143. data/spec/spec_tests/data/crud/write/bulkWrite.yml +401 -0
  144. data/spec/spec_tests/data/crud/write/insertMany.yml +58 -2
  145. data/spec/spec_tests/data/crud/write/updateMany-arrayFilters.yml +3 -0
  146. data/spec/spec_tests/data/crud/write/updateOne-arrayFilters.yml +6 -1
  147. data/spec/spec_tests/data/crud_v2/aggregate-merge.yml +103 -0
  148. data/spec/spec_tests/data/crud_v2/aggregate-out-readConcern.yml +110 -0
  149. data/spec/spec_tests/data/crud_v2/bulkWrite-arrayFilters.yml +81 -0
  150. data/spec/spec_tests/data/crud_v2/db-aggregate.yml +38 -0
  151. data/spec/spec_tests/data/crud_v2/updateWithPipelines.yml +92 -0
  152. data/spec/spec_tests/data/retryable_writes/insertOne-serverErrors.yml +2 -2
  153. data/spec/spec_tests/data/transactions/abort.yml +3 -0
  154. data/spec/spec_tests/data/transactions/bulk.yml +3 -8
  155. data/spec/spec_tests/data/transactions/causal-consistency.yml +3 -8
  156. data/spec/spec_tests/data/transactions/commit.yml +3 -1
  157. data/spec/spec_tests/data/transactions/count.yml +3 -0
  158. data/spec/spec_tests/data/transactions/delete.yml +3 -0
  159. data/spec/spec_tests/data/transactions/error-labels.yml +4 -1
  160. data/spec/spec_tests/data/transactions/errors-client.yml +56 -0
  161. data/spec/spec_tests/data/transactions/errors.yml +3 -0
  162. data/spec/spec_tests/data/transactions/findOneAndDelete.yml +3 -0
  163. data/spec/spec_tests/data/transactions/findOneAndReplace.yml +3 -0
  164. data/spec/spec_tests/data/transactions/findOneAndUpdate.yml +3 -0
  165. data/spec/spec_tests/data/transactions/insert.yml +3 -0
  166. data/spec/spec_tests/data/transactions/isolation.yml +3 -0
  167. data/spec/spec_tests/data/transactions/mongos-pin-auto.yml +1671 -0
  168. data/spec/spec_tests/data/transactions/mongos-recovery-token.yml +347 -0
  169. data/spec/spec_tests/data/transactions/pin-mongos.yml +557 -0
  170. data/spec/spec_tests/data/transactions/read-concern.yml +3 -0
  171. data/spec/spec_tests/data/transactions/read-pref.yml +3 -0
  172. data/spec/spec_tests/data/transactions/reads.yml +3 -0
  173. data/spec/spec_tests/data/transactions/retryable-abort.yml +5 -2
  174. data/spec/spec_tests/data/transactions/retryable-commit.yml +4 -1
  175. data/spec/spec_tests/data/transactions/retryable-writes.yml +3 -0
  176. data/spec/spec_tests/data/transactions/run-command.yml +3 -0
  177. data/spec/spec_tests/data/transactions/transaction-options.yml +6 -0
  178. data/spec/spec_tests/data/transactions/update.yml +3 -8
  179. data/spec/spec_tests/data/transactions/write-concern.yml +348 -38
  180. data/spec/spec_tests/data/transactions_api/callback-aborts.yml +6 -0
  181. data/spec/spec_tests/data/transactions_api/callback-commits.yml +5 -0
  182. data/spec/spec_tests/data/transactions_api/callback-retry.yml +7 -2
  183. data/spec/spec_tests/data/transactions_api/commit-retry.yml +70 -15
  184. data/spec/spec_tests/data/transactions_api/commit-transienttransactionerror-4.2.yml +3 -0
  185. data/spec/spec_tests/data/transactions_api/commit-transienttransactionerror.yml +3 -0
  186. data/spec/spec_tests/data/transactions_api/commit-writeconcernerror.yml +59 -109
  187. data/spec/spec_tests/data/transactions_api/commit.yml +5 -0
  188. data/spec/spec_tests/data/transactions_api/transaction-options.yml +10 -0
  189. data/spec/spec_tests/retryable_reads_spec.rb +5 -2
  190. data/spec/spec_tests/retryable_writes_spec.rb +5 -2
  191. data/spec/spec_tests/sdam_monitoring_spec.rb +3 -3
  192. data/spec/spec_tests/sdam_spec.rb +2 -2
  193. data/spec/spec_tests/transactions_api_spec.rb +1 -67
  194. data/spec/spec_tests/transactions_spec.rb +2 -66
  195. data/spec/support/authorization.rb +4 -0
  196. data/spec/support/change_streams.rb +30 -10
  197. data/spec/support/change_streams/operation.rb +27 -0
  198. data/spec/support/client_registry.rb +44 -25
  199. data/spec/support/cluster_config.rb +25 -14
  200. data/spec/support/cluster_tools.rb +32 -10
  201. data/spec/support/command_monitoring.rb +1 -1
  202. data/spec/support/common_shortcuts.rb +30 -0
  203. data/spec/support/connection_string.rb +8 -3
  204. data/spec/support/constraints.rb +34 -0
  205. data/spec/support/crud.rb +31 -16
  206. data/spec/support/crud/context.rb +23 -0
  207. data/spec/support/crud/operation.rb +311 -14
  208. data/spec/support/crud/spec.rb +2 -1
  209. data/spec/support/crud/test.rb +24 -27
  210. data/spec/support/crud/test_base.rb +22 -0
  211. data/spec/support/crud/verifier.rb +15 -1
  212. data/spec/support/event_subscriber.rb +12 -0
  213. data/spec/support/sdam_formatter_integration.rb +12 -6
  214. data/spec/support/shared/server_selector.rb +10 -0
  215. data/spec/support/shared/session.rb +13 -12
  216. data/spec/support/spec_config.rb +32 -22
  217. data/spec/support/spec_setup.rb +2 -2
  218. data/spec/support/transactions.rb +87 -0
  219. data/spec/support/transactions/context.rb +33 -0
  220. data/spec/support/transactions/operation.rb +99 -349
  221. data/spec/support/transactions/spec.rb +1 -3
  222. data/spec/support/transactions/test.rb +110 -49
  223. data/spec/support/utils.rb +74 -1
  224. metadata +52 -10
  225. metadata.gz.sig +0 -0
  226. data/spec/support/crud/read.rb +0 -265
  227. data/spec/support/crud/write.rb +0 -284
@@ -1,14 +1,7 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  describe Mongo::Server::Monitor::Connection do
4
-
5
- before do
6
- ClientRegistry.instance.close_all_clients
7
- end
8
-
9
- let(:client) do
10
- authorized_client.with(options)
11
- end
4
+ clean_slate
12
5
 
13
6
  let(:address) do
14
7
  Mongo::Address.new(ClusterConfig.instance.primary_address, options)
@@ -19,7 +12,7 @@ describe Mongo::Server::Monitor::Connection do
19
12
  let(:cluster) do
20
13
  double('cluster').tap do |cl|
21
14
  allow(cl).to receive(:topology).and_return(topology)
22
- allow(cl).to receive(:app_metadata).and_return(Mongo::Server::Monitor::AppMetadata.new(authorized_client.cluster.options))
15
+ allow(cl).to receive(:app_metadata).and_return(Mongo::Server::Monitor::AppMetadata.new({}))
23
16
  allow(cl).to receive(:options).and_return({})
24
17
  end
25
18
  end
@@ -147,6 +140,16 @@ describe Mongo::Server::Monitor::Connection do
147
140
  connection.ismaster
148
141
  end
149
142
 
143
+ before do
144
+ # Since we set expectations on the connection, kill the
145
+ # background thread (but without disconnecting the connection).
146
+ # Note also that we need to have the connection connected in
147
+ # the first place, thus the scan! call here.
148
+ monitor.scan!
149
+ monitor.instance_variable_get('@thread').kill
150
+ monitor.instance_variable_get('@thread').join
151
+ end
152
+
150
153
  it 'retries ismaster and is successful' do
151
154
  expect(result).to be_a(Hash)
152
155
  expect(result['ok']).to eq(1.0)
@@ -154,7 +157,7 @@ describe Mongo::Server::Monitor::Connection do
154
157
 
155
158
  it 'logs the retry' do
156
159
  expect(Mongo::Logger.logger).to receive(:warn) do |msg|
157
- expect(msg).to match(/Retrying ismaster on #{connection.address}/)
160
+ expect(msg).to match(/Retrying ismaster in monitor for #{connection.address}/)
158
161
  end
159
162
  expect(result).to be_a(Hash)
160
163
  end
@@ -341,7 +341,7 @@ describe Mongo::ServerSelector do
341
341
  Mongo::Error::UnsupportedFeatures.new('Test UnsupportedFeatures')
342
342
  end
343
343
 
344
- let(:selector) { described_class.get(mode: :primary) }
344
+ let(:selector) { described_class.primary }
345
345
 
346
346
  it 'raises Error::UnsupportedFeatures' do
347
347
  expect(topology).to receive(:compatible?).and_return(false)
@@ -351,6 +351,38 @@ describe Mongo::ServerSelector do
351
351
  end.to raise_error(Mongo::Error::UnsupportedFeatures, 'Test UnsupportedFeatures')
352
352
  end
353
353
  end
354
+
355
+ context 'sharded topology' do
356
+
357
+ let(:cluster) do
358
+ double('cluster').tap do |c|
359
+ allow(c).to receive(:connected?).and_return(true)
360
+ allow(c).to receive(:summary)
361
+ allow(c).to receive(:topology).and_return(topology)
362
+ allow(c).to receive(:servers).and_return(servers)
363
+ allow(c).to receive(:addresses).and_return(servers.map(&:address))
364
+ allow(c).to receive(:replica_set?).and_return(false)
365
+ allow(c).to receive(:single?).and_return(false)
366
+ allow(c).to receive(:sharded?).and_return(true)
367
+ allow(c).to receive(:unknown?).and_return(false)
368
+ allow(c).to receive(:scan!)
369
+ allow(c).to receive(:options).and_return(local_threshold: 0.050)
370
+ allow(topology).to receive(:compatible?).and_return(true)
371
+ allow(topology).to receive(:single?).and_return(false)
372
+ end
373
+ end
374
+
375
+ context 'unknown and mongos' do
376
+ let(:mongos) { make_server(:mongos, address: Mongo::Address.new('localhost')) }
377
+ let(:unknown) { make_server(:unknown, address: Mongo::Address.new('localhost')) }
378
+ let(:servers) { [unknown, mongos] }
379
+ let(:selector) { described_class.primary }
380
+
381
+ it 'returns the mongos' do
382
+ expect(selector.select_server(cluster)).to eq(mongos)
383
+ end
384
+ end
385
+ end
354
386
  end
355
387
 
356
388
  shared_context 'a ServerSelector' do
@@ -378,7 +410,7 @@ describe Mongo::ServerSelector do
378
410
  end
379
411
 
380
412
  let(:read_pref) do
381
- described_class.get(mode: :primary)
413
+ described_class.primary
382
414
  end
383
415
 
384
416
  it 'raises a NoServerAvailable error' do
@@ -3,9 +3,15 @@ require 'spec_helper'
3
3
  describe Mongo::Session::SessionPool do
4
4
  min_server_fcv '3.6'
5
5
  require_topology :replica_set, :sharded
6
+ clean_slate_for_all
6
7
 
7
8
  let(:cluster) do
8
- authorized_client.cluster
9
+ authorized_client.cluster.tap do |cluster|
10
+ # Cluster time assertions can fail if there are background operations
11
+ # that cause cluster time to be updated. This also necessitates clean
12
+ # state requirement.
13
+ authorized_client.close(true)
14
+ end
9
15
  end
10
16
 
11
17
  describe '.create' do
@@ -156,7 +162,7 @@ describe Mongo::Session::SessionPool do
156
162
  end
157
163
 
158
164
  after do
159
- client.close
165
+ client.close(true)
160
166
  end
161
167
 
162
168
  context 'when the number of ids is not larger than 10,000' do
@@ -185,10 +191,15 @@ describe Mongo::Session::SessionPool do
185
191
  context 'when talking to a replica set or mongos' do
186
192
 
187
193
  it 'sends the endSessions command with all the session ids and cluster time' do
194
+ start_time = client.cluster.cluster_time
188
195
  end_sessions_command
196
+ end_time = client.cluster.cluster_time
189
197
  expect(end_sessions_command.command[:endSessions]).to include(BSON::Document.new(session_a.session_id))
190
198
  expect(end_sessions_command.command[:endSessions]).to include(BSON::Document.new(session_b.session_id))
191
- expect(end_sessions_command.command[:$clusterTime]).to eq(client.cluster.cluster_time)
199
+ # cluster time may have been advanced due to background operations
200
+ actual_cluster_time = Mongo::ClusterTime.new(end_sessions_command.command[:$clusterTime])
201
+ expect(actual_cluster_time).to be >= start_time
202
+ expect(actual_cluster_time).to be <= end_time
192
203
  end
193
204
  end
194
205
  end
@@ -80,7 +80,7 @@ describe Mongo::Session do
80
80
  context 'when the original cluster time is less than the new cluster time' do
81
81
 
82
82
  let(:original_cluster_time) do
83
- { 'clusterTime' => BSON::Timestamp.new(0, 1) }
83
+ Mongo::ClusterTime.new('clusterTime' => BSON::Timestamp.new(0, 1))
84
84
  end
85
85
 
86
86
  before do
@@ -96,7 +96,7 @@ describe Mongo::Session do
96
96
  context 'when the original cluster time is equal or greater than the new cluster time' do
97
97
 
98
98
  let(:original_cluster_time) do
99
- { 'clusterTime' => BSON::Timestamp.new(0, 6) }
99
+ Mongo::ClusterTime.new('clusterTime' => BSON::Timestamp.new(0, 6))
100
100
  end
101
101
 
102
102
  before do
@@ -232,7 +232,7 @@ describe Mongo::Session do
232
232
  end
233
233
 
234
234
  after do
235
- client.close
235
+ client.close(true)
236
236
  end
237
237
 
238
238
  it 'returns false' do
@@ -3,6 +3,7 @@ require 'spec_helper'
3
3
  class SessionTransactionSpecError < StandardError; end
4
4
 
5
5
  describe Mongo::Session do
6
+ require_wired_tiger
6
7
  min_server_fcv '4.0'
7
8
  require_topology :replica_set, :sharded
8
9
 
@@ -137,14 +138,14 @@ describe Mongo::Session do
137
138
  sleep 0.1
138
139
 
139
140
  exc = Mongo::Error::OperationFailure.new('timeout test')
140
- exc.send(:add_label, Mongo::Error::TRANSIENT_TRANSACTION_ERROR_LABEL)
141
+ exc.add_label('TransientTransactionError')
141
142
  raise exc
142
143
  end
143
144
  end.to raise_error(Mongo::Error::OperationFailure, 'timeout test')
144
145
  end
145
146
  end
146
147
 
147
- %w(UNKNOWN_TRANSACTION_COMMIT_RESULT_LABEL TRANSIENT_TRANSACTION_ERROR_LABEL).each do |label|
148
+ %w(UnknownTransactionCommitResult TransientTransactionError).each do |label|
148
149
  context "timeout with commit raising with #{label}" do
149
150
  max_example_run_time 7
150
151
 
@@ -169,7 +170,7 @@ describe Mongo::Session do
169
170
  end
170
171
 
171
172
  exc = Mongo::Error::OperationFailure.new('timeout test')
172
- exc.send(:add_label, Mongo::Error.const_get(label))
173
+ exc.add_label(label)
173
174
 
174
175
  expect(session).to receive(:commit_transaction).and_raise(exc).at_least(:once)
175
176
 
@@ -1,6 +1,8 @@
1
1
  require 'spec_helper'
2
2
 
3
- describe Mongo::Socket::SSL do
3
+ # this test performs direct network connections without retries.
4
+ # In case of intermittent network issues, retry the entire failing test.
5
+ describe Mongo::Socket::SSL, retry: 3 do
4
6
  require_tls
5
7
 
6
8
  let(:address) do
@@ -478,7 +480,7 @@ describe Mongo::Socket::SSL do
478
480
  end
479
481
 
480
482
  let(:connection) do
481
- Mongo::Server::Connection.new(server, options)
483
+ Mongo::Server::Connection.new(server, options.merge(socket_timeout: 2))
482
484
  end
483
485
 
484
486
  context 'as a file' do
@@ -509,7 +511,7 @@ describe Mongo::Socket::SSL do
509
511
  end
510
512
 
511
513
  let(:connection) do
512
- Mongo::Server::Connection.new(server, options)
514
+ Mongo::Server::Connection.new(server, options.merge(socket_timeout: 2))
513
515
  end
514
516
 
515
517
  context 'as a file' do
@@ -564,7 +566,7 @@ describe Mongo::Socket::SSL do
564
566
  end
565
567
 
566
568
  let(:connection) do
567
- Mongo::Server::Connection.new(server, options)
569
+ Mongo::Server::Connection.new(server, options.merge(socket_timeout: 2))
568
570
  end
569
571
 
570
572
  context 'as a path to a file' do
@@ -666,7 +668,7 @@ describe Mongo::Socket::SSL do
666
668
  end
667
669
 
668
670
  let(:connection) do
669
- Mongo::Server::Connection.new(server, options)
671
+ Mongo::Server::Connection.new(server, options.merge(socket_timeout: 2))
670
672
  end
671
673
 
672
674
  let(:options) do
@@ -729,6 +731,18 @@ describe Mongo::Socket::SSL do
729
731
  expect(socket).to be_alive
730
732
  end
731
733
  end
734
+
735
+ context 'when OpenSSL allows disabling renegotiation 'do
736
+ before do
737
+ unless OpenSSL::SSL.const_defined?(:OP_NO_RENEGOTIATION)
738
+ skip 'OpenSSL::SSL::OP_NO_RENEGOTIATION is not defined'
739
+ end
740
+ end
741
+
742
+ it 'disables TLS renegotiation' do
743
+ expect(socket.context.options & OpenSSL::SSL::OP_NO_RENEGOTIATION).to eq(OpenSSL::SSL::OP_NO_RENEGOTIATION)
744
+ end
745
+ end
732
746
  end
733
747
 
734
748
  describe '#readbyte' do
@@ -1,4 +1,4 @@
1
- require 'spec_helper'
1
+ require 'lite_spec_helper'
2
2
 
3
3
  describe Mongo::Socket do
4
4
 
@@ -51,65 +51,4 @@ describe Mongo::Socket do
51
51
  end.to raise_error(Mongo::Error::SocketError, 'OpenSSL::SSL::SSLError: Test error (for fake-address) (MongoDB may not be configured with SSL support)')
52
52
  end
53
53
  end
54
-
55
- describe '#read' do
56
- let(:target_host) do
57
- host = ClusterConfig.instance.primary_address_host
58
- # Take ipv4 address
59
- Socket.getaddrinfo(host, 0).detect { |ai| ai.first == 'AF_INET' }[3]
60
- end
61
-
62
- let(:socket) do
63
- Mongo::Socket::TCP.new(target_host, ClusterConfig.instance.primary_address_port, 1, Socket::PF_INET)
64
- end
65
-
66
- let(:raw_socket) { socket.instance_variable_get('@socket') }
67
-
68
- let(:wait_readable_class) do
69
- Class.new(Exception) do
70
- include IO::WaitReadable
71
- end
72
- end
73
-
74
- context 'timeout' do
75
-
76
- shared_examples_for 'times out' do
77
- it 'times out' do
78
- expect(socket).to receive(:timeout).at_least(:once).and_return(0.2)
79
- # When we raise WaitWritable, the socket object is ready for
80
- # writing which makes the read method invoke read_nonblock many times
81
- expect(raw_socket).to receive(:read_nonblock).at_least(:once) do |len, buf|
82
- sleep 0.01
83
- raise exception_class
84
- end
85
-
86
- expect do
87
- socket.read(10)
88
- end.to raise_error(Mongo::Error::SocketTimeoutError, /Took more than .* seconds to receive data \(for /)
89
- end
90
- end
91
-
92
- context 'with WaitReadable' do
93
-
94
- let(:exception_class) do
95
- Class.new(Exception) do
96
- include IO::WaitReadable
97
- end
98
- end
99
-
100
- it_behaves_like 'times out'
101
- end
102
-
103
- context 'with WaitWritable' do
104
-
105
- let(:exception_class) do
106
- Class.new(Exception) do
107
- include IO::WaitWritable
108
- end
109
- end
110
-
111
- it_behaves_like 'times out'
112
- end
113
- end
114
- end
115
54
  end
@@ -1,19 +1,13 @@
1
- require 'spec_helper'
1
+ require 'lite_spec_helper'
2
2
 
3
3
  describe Mongo::URI::SRVProtocol do
4
+ clean_slate_for_all
4
5
 
5
6
  let(:scheme) { 'mongodb+srv://' }
6
7
  let(:uri) { described_class.new(string) }
7
8
 
8
- before(:all) do
9
- # Since these tests assert on warnings being produced,
10
- # close clients to ensure background threads do not interfere with
11
- # their warnings.
12
- ClientRegistry.instance.close_all_clients
13
- end
14
-
15
9
  let(:client) do
16
- new_local_client(string, monitoring_io: false)
10
+ new_local_client_nmio(string)
17
11
  end
18
12
 
19
13
  describe 'invalid uris' do
@@ -364,11 +358,11 @@ describe Mongo::URI::SRVProtocol do
364
358
  let(:concern) { Mongo::Options::Redacted.new(:w => 1)}
365
359
 
366
360
  it 'sets the write concern options' do
367
- expect(uri.uri_options[:write]).to eq(concern)
361
+ expect(uri.uri_options[:write_concern]).to eq(concern)
368
362
  end
369
363
 
370
364
  it 'sets the options on a client created with the uri' do
371
- expect(client.options[:write]).to eq(concern)
365
+ expect(client.options[:write_concern]).to eq(concern)
372
366
  end
373
367
  end
374
368
 
@@ -377,11 +371,11 @@ describe Mongo::URI::SRVProtocol do
377
371
  let(:concern) { Mongo::Options::Redacted.new(:w => :majority) }
378
372
 
379
373
  it 'sets the write concern options' do
380
- expect(uri.uri_options[:write]).to eq(concern)
374
+ expect(uri.uri_options[:write_concern]).to eq(concern)
381
375
  end
382
376
 
383
377
  it 'sets the options on a client created with the uri' do
384
- expect(client.options[:write]).to eq(concern)
378
+ expect(client.options[:write_concern]).to eq(concern)
385
379
  end
386
380
  end
387
381
 
@@ -390,11 +384,11 @@ describe Mongo::URI::SRVProtocol do
390
384
  let(:concern) { Mongo::Options::Redacted.new(:j => true) }
391
385
 
392
386
  it 'sets the write concern options' do
393
- expect(uri.uri_options[:write]).to eq(concern)
387
+ expect(uri.uri_options[:write_concern]).to eq(concern)
394
388
  end
395
389
 
396
390
  it 'sets the options on a client created with the uri' do
397
- expect(client.options[:write]).to eq(concern)
391
+ expect(client.options[:write_concern]).to eq(concern)
398
392
  end
399
393
  end
400
394
 
@@ -403,11 +397,11 @@ describe Mongo::URI::SRVProtocol do
403
397
  let(:concern) { Mongo::Options::Redacted.new(:fsync => true) }
404
398
 
405
399
  it 'sets the write concern options' do
406
- expect(uri.uri_options[:write]).to eq(concern)
400
+ expect(uri.uri_options[:write_concern]).to eq(concern)
407
401
  end
408
402
 
409
403
  it 'sets the options on a client created with the uri' do
410
- expect(client.options[:write]).to eq(concern)
404
+ expect(client.options[:write_concern]).to eq(concern)
411
405
  end
412
406
  end
413
407
 
@@ -417,11 +411,11 @@ describe Mongo::URI::SRVProtocol do
417
411
  let(:concern) { Mongo::Options::Redacted.new(:w => 2, :wtimeout => timeout) }
418
412
 
419
413
  it 'sets the write concern options' do
420
- expect(uri.uri_options[:write]).to eq(concern)
414
+ expect(uri.uri_options[:write_concern]).to eq(concern)
421
415
  end
422
416
 
423
417
  it 'sets the options on a client created with the uri' do
424
- expect(client.options[:write]).to eq(concern)
418
+ expect(client.options[:write_concern]).to eq(concern)
425
419
  end
426
420
  end
427
421
  end
@@ -581,7 +575,7 @@ describe Mongo::URI::SRVProtocol do
581
575
  end
582
576
 
583
577
  context 'replica set option provided' do
584
- let(:rs_name) { TEST_SET }
578
+ let(:rs_name) { 'test-rs-name' }
585
579
  let(:options) { "replicaSet=#{rs_name}" }
586
580
 
587
581
  it 'sets the replica set option' do
@@ -129,6 +129,22 @@ describe Mongo::URI do
129
129
  expect(uri.uri_options[ruby_option]).to eq('foo')
130
130
  end
131
131
 
132
+ context 'it is escaped in URI' do
133
+ let(:string) { "mongodb://example.com/?#{uri_option}=foo%2f" }
134
+
135
+ it 'is unescaped' do
136
+ expect(uri.uri_options[ruby_option]).to eq('foo/')
137
+ end
138
+ end
139
+
140
+ context 'it is escaped twice in URI' do
141
+ let(:string) { "mongodb://example.com/?#{uri_option}=foo%252f" }
142
+
143
+ it 'is unescaped once' do
144
+ expect(uri.uri_options[ruby_option]).to eq('foo%2f')
145
+ end
146
+ end
147
+
132
148
  context 'value is a number' do
133
149
  let(:string) { "mongodb://example.com/?#{uri_option}=1" }
134
150
 
@@ -168,6 +184,17 @@ describe Mongo::URI do
168
184
  expect(uri.uri_options[:auth_mech]).to eq(:scram256)
169
185
  end
170
186
  end
187
+
188
+ context 'unrecognized value' do
189
+
190
+ let(:string) { 'mongodb://example.com/?authMechanism=foobar' }
191
+
192
+ it_behaves_like 'parses successfully'
193
+
194
+ it 'is mapped to auth mechanism' do
195
+ expect(uri.uri_options[:auth_mech]).to eq('foobar')
196
+ end
197
+ end
171
198
  end
172
199
 
173
200
  context 'authMechanismProperties' do
@@ -182,6 +209,30 @@ describe Mongo::URI do
182
209
  canonicalize_host_name: true,
183
210
  ))
184
211
  end
212
+
213
+ context 'canonicalize host name is false' do
214
+
215
+ let(:string) { 'mongodb://example.com/?authmechanismproperties=SERVICE_REALM:foo,CANONICALIZE_HOST_NAME:false' }
216
+
217
+ it 'parses correctly' do
218
+ expect(uri.uri_options[:auth_mech_properties]).to eq(BSON::Document.new(
219
+ service_realm: 'foo',
220
+ canonicalize_host_name: false,
221
+ ))
222
+ end
223
+ end
224
+
225
+ context 'canonicalize host name is true in mixed case' do
226
+
227
+ let(:string) { 'mongodb://example.com/?authmechanismproperties=SERVICE_REALM:foo,CANONICALIZE_HOST_NAME:TrUe' }
228
+
229
+ it 'parses correctly' do
230
+ expect(uri.uri_options[:auth_mech_properties]).to eq(BSON::Document.new(
231
+ service_realm: 'foo',
232
+ canonicalize_host_name: true,
233
+ ))
234
+ end
235
+ end
185
236
  end
186
237
 
187
238
  context 'authSource' do
@@ -190,6 +241,22 @@ describe Mongo::URI do
190
241
  let(:ruby_option) { :auth_source }
191
242
 
192
243
  it_behaves_like 'a string option'
244
+
245
+ context '$external' do
246
+ let(:string) { "mongodb://example.com/?#{uri_option}=$external" }
247
+
248
+ it 'is converted to ;external' do
249
+ expect(uri.uri_options[ruby_option]).to eq(:external)
250
+ end
251
+ end
252
+
253
+ context 'empty' do
254
+ let(:string) { "mongodb://example.com/?#{uri_option}=" }
255
+
256
+ it 'is mapped to the empty string' do
257
+ expect(uri.uri_options[ruby_option]).to eq('')
258
+ end
259
+ end
193
260
  end
194
261
 
195
262
  context 'compressors' do
@@ -236,7 +303,7 @@ describe Mongo::URI do
236
303
  it_behaves_like 'parses successfully'
237
304
 
238
305
  it 'is a boolean' do
239
- expect(uri.uri_options[:write]).to eq(BSON::Document.new(fsync: true))
306
+ expect(uri.uri_options[:write_concern]).to eq(BSON::Document.new(fsync: true))
240
307
  end
241
308
  end
242
309
 
@@ -255,7 +322,7 @@ describe Mongo::URI do
255
322
  it_behaves_like 'parses successfully'
256
323
 
257
324
  it 'is a boolean' do
258
- expect(uri.uri_options[:write]).to eq(BSON::Document.new(j: true))
325
+ expect(uri.uri_options[:write_concern]).to eq(BSON::Document.new(j: true))
259
326
  end
260
327
  end
261
328
 
@@ -319,8 +386,8 @@ describe Mongo::URI do
319
386
 
320
387
  it_behaves_like 'parses successfully'
321
388
 
322
- it 'is a string' do
323
- expect(uri.uri_options[:read_concern]).to eq(BSON::Document.new(level: 'snapshot'))
389
+ it 'is a symbol' do
390
+ expect(uri.uri_options[:read_concern]).to eq(BSON::Document.new(level: :snapshot))
324
391
  end
325
392
  end
326
393
 
@@ -333,6 +400,15 @@ describe Mongo::URI do
333
400
  it 'is a string' do
334
401
  expect(uri.uri_options[:read]).to eq(BSON::Document.new(mode: :nearest))
335
402
  end
403
+
404
+ context 'an unknown value' do
405
+
406
+ let(:string) { "mongodb://example.com/?readPreference=foobar" }
407
+
408
+ it 'is unchanged' do
409
+ expect(uri.uri_options[:read]).to eq(BSON::Document.new(mode: 'foobar'))
410
+ end
411
+ end
336
412
  end
337
413
 
338
414
  context 'readPreferenceTags' do
@@ -345,6 +421,16 @@ describe Mongo::URI do
345
421
  expect(uri.uri_options[:read]).to eq(BSON::Document.new(
346
422
  tag_sets: [{'dc' => 'ny', 'rack' => '1'}]))
347
423
  end
424
+
425
+ context 'with double escaped keys and values' do
426
+
427
+ let(:string) { "mongodb://example.com/?readPreferenceTags=dc%252f:ny,rack:1%252f" }
428
+
429
+ it 'unescapes once' do
430
+ expect(uri.uri_options[:read]).to eq(BSON::Document.new(
431
+ tag_sets: [{'dc%2f' => 'ny', 'rack' => '1%2f'}]))
432
+ end
433
+ end
348
434
  end
349
435
 
350
436
  context 'replicaSet' do
@@ -451,7 +537,7 @@ describe Mongo::URI do
451
537
  it_behaves_like 'parses successfully'
452
538
 
453
539
  it 'is an integer' do
454
- expect(uri.uri_options[:write]).to eq(BSON::Document.new(w: 1))
540
+ expect(uri.uri_options[:write_concern]).to eq(BSON::Document.new(w: 1))
455
541
  end
456
542
  end
457
543
 
@@ -461,7 +547,7 @@ describe Mongo::URI do
461
547
  it_behaves_like 'parses successfully'
462
548
 
463
549
  it 'is a string' do
464
- expect(uri.uri_options[:write]).to eq(BSON::Document.new(w: 'foo'))
550
+ expect(uri.uri_options[:write_concern]).to eq(BSON::Document.new(w: 'foo'))
465
551
  end
466
552
  end
467
553
 
@@ -471,7 +557,7 @@ describe Mongo::URI do
471
557
  it_behaves_like 'parses successfully'
472
558
 
473
559
  it 'is a symbol' do
474
- expect(uri.uri_options[:write]).to eq(BSON::Document.new(w: :majority))
560
+ expect(uri.uri_options[:write_concern]).to eq(BSON::Document.new(w: :majority))
475
561
  end
476
562
  end
477
563
  end
@@ -491,7 +577,7 @@ describe Mongo::URI do
491
577
  it_behaves_like 'parses successfully'
492
578
 
493
579
  it 'is a float' do
494
- expect(uri.uri_options[:write]).to eq(BSON::Document.new(wtimeout: 100))
580
+ expect(uri.uri_options[:write_concern]).to eq(BSON::Document.new(wtimeout: 100))
495
581
  end
496
582
  end
497
583