mongo 2.9.2 → 2.10.0.rc0

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 (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