mongo 2.20.1 → 2.21.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 (246) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +3 -0
  3. data/Rakefile +2 -2
  4. data/lib/mongo/address.rb +22 -3
  5. data/lib/mongo/auth/aws/credentials_retriever.rb +70 -17
  6. data/lib/mongo/auth/base.rb +1 -1
  7. data/lib/mongo/bulk_write.rb +35 -2
  8. data/lib/mongo/client.rb +38 -6
  9. data/lib/mongo/client_encryption.rb +6 -3
  10. data/lib/mongo/cluster/reapers/cursor_reaper.rb +6 -1
  11. data/lib/mongo/cluster/sdam_flow.rb +20 -7
  12. data/lib/mongo/cluster.rb +14 -4
  13. data/lib/mongo/collection/helpers.rb +1 -1
  14. data/lib/mongo/collection/view/aggregation/behavior.rb +131 -0
  15. data/lib/mongo/collection/view/aggregation.rb +33 -99
  16. data/lib/mongo/collection/view/builder/aggregation.rb +1 -7
  17. data/lib/mongo/collection/view/change_stream.rb +80 -27
  18. data/lib/mongo/collection/view/iterable.rb +76 -60
  19. data/lib/mongo/collection/view/map_reduce.rb +25 -8
  20. data/lib/mongo/collection/view/readable.rb +79 -30
  21. data/lib/mongo/collection/view/writable.rb +109 -48
  22. data/lib/mongo/collection/view.rb +43 -3
  23. data/lib/mongo/collection.rb +158 -23
  24. data/lib/mongo/crypt/auto_encrypter.rb +4 -6
  25. data/lib/mongo/crypt/binding.rb +4 -4
  26. data/lib/mongo/crypt/context.rb +20 -14
  27. data/lib/mongo/crypt/encryption_io.rb +56 -26
  28. data/lib/mongo/crypt/explicit_encrypter.rb +49 -20
  29. data/lib/mongo/crypt/explicit_encryption_context.rb +17 -11
  30. data/lib/mongo/crypt/kms/azure/credentials_retriever.rb +22 -6
  31. data/lib/mongo/crypt/kms/gcp/credentials_retriever.rb +29 -4
  32. data/lib/mongo/csot_timeout_holder.rb +119 -0
  33. data/lib/mongo/cursor/kill_spec.rb +5 -2
  34. data/lib/mongo/cursor/nontailable.rb +27 -0
  35. data/lib/mongo/cursor.rb +86 -24
  36. data/lib/mongo/cursor_host.rb +82 -0
  37. data/lib/mongo/database/view.rb +81 -14
  38. data/lib/mongo/database.rb +88 -18
  39. data/lib/mongo/error/operation_failure.rb +209 -204
  40. data/lib/mongo/error/server_timeout_error.rb +12 -0
  41. data/lib/mongo/error/socket_timeout_error.rb +3 -1
  42. data/lib/mongo/error/timeout_error.rb +23 -0
  43. data/lib/mongo/error.rb +2 -0
  44. data/lib/mongo/grid/fs_bucket.rb +45 -12
  45. data/lib/mongo/grid/stream/read.rb +15 -1
  46. data/lib/mongo/grid/stream/write.rb +21 -4
  47. data/lib/mongo/index/view.rb +77 -16
  48. data/lib/mongo/operation/context.rb +40 -2
  49. data/lib/mongo/operation/create_search_indexes/op_msg.rb +2 -2
  50. data/lib/mongo/operation/delete/op_msg.rb +2 -1
  51. data/lib/mongo/operation/drop_search_index/op_msg.rb +2 -2
  52. data/lib/mongo/operation/find/op_msg.rb +45 -0
  53. data/lib/mongo/operation/get_more/op_msg.rb +33 -0
  54. data/lib/mongo/operation/insert/op_msg.rb +3 -2
  55. data/lib/mongo/operation/insert/result.rb +4 -2
  56. data/lib/mongo/operation/list_collections/result.rb +1 -1
  57. data/lib/mongo/operation/map_reduce/result.rb +1 -1
  58. data/lib/mongo/operation/op_msg_base.rb +3 -1
  59. data/lib/mongo/operation/result.rb +26 -5
  60. data/lib/mongo/operation/shared/executable.rb +12 -1
  61. data/lib/mongo/operation/shared/op_msg_executable.rb +4 -1
  62. data/lib/mongo/operation/shared/response_handling.rb +3 -3
  63. data/lib/mongo/operation/shared/sessions_supported.rb +1 -1
  64. data/lib/mongo/operation/shared/timed.rb +52 -0
  65. data/lib/mongo/operation/shared/write.rb +4 -1
  66. data/lib/mongo/operation/update/op_msg.rb +2 -1
  67. data/lib/mongo/operation/update_search_index/op_msg.rb +2 -2
  68. data/lib/mongo/operation.rb +1 -0
  69. data/lib/mongo/protocol/message.rb +1 -4
  70. data/lib/mongo/protocol/msg.rb +2 -2
  71. data/lib/mongo/retryable/read_worker.rb +69 -29
  72. data/lib/mongo/retryable/write_worker.rb +49 -18
  73. data/lib/mongo/retryable.rb +8 -2
  74. data/lib/mongo/server/connection.rb +11 -5
  75. data/lib/mongo/server/connection_base.rb +22 -2
  76. data/lib/mongo/server/connection_pool.rb +32 -14
  77. data/lib/mongo/server/description/features.rb +1 -1
  78. data/lib/mongo/server/description.rb +18 -5
  79. data/lib/mongo/server/monitor.rb +7 -4
  80. data/lib/mongo/server/pending_connection.rb +7 -3
  81. data/lib/mongo/server/{round_trip_time_averager.rb → round_trip_time_calculator.rb} +25 -7
  82. data/lib/mongo/server.rb +11 -6
  83. data/lib/mongo/server_selector/base.rb +25 -9
  84. data/lib/mongo/session.rb +78 -9
  85. data/lib/mongo/socket/ssl.rb +109 -17
  86. data/lib/mongo/socket/tcp.rb +40 -6
  87. data/lib/mongo/socket.rb +154 -25
  88. data/lib/mongo/uri/options_mapper.rb +1 -0
  89. data/lib/mongo/version.rb +1 -1
  90. data/lib/mongo.rb +1 -0
  91. data/spec/atlas/atlas_connectivity_spec.rb +4 -0
  92. data/spec/atlas/operations_spec.rb +4 -0
  93. data/spec/integration/client_side_encryption/auto_encryption_mongocryptd_spawn_spec.rb +2 -1
  94. data/spec/integration/client_side_encryption/auto_encryption_spec.rb +494 -487
  95. data/spec/integration/client_side_encryption/on_demand_aws_credentials_spec.rb +1 -1
  96. data/spec/integration/client_side_encryption/range_explicit_encryption_prose_spec.rb +66 -22
  97. data/spec/integration/client_side_operations_timeout/encryption_prose_spec.rb +131 -0
  98. data/spec/integration/connection_pool_populator_spec.rb +2 -0
  99. data/spec/integration/cursor_pinning_spec.rb +15 -60
  100. data/spec/integration/cursor_reaping_spec.rb +1 -1
  101. data/spec/integration/docs_examples_spec.rb +1 -1
  102. data/spec/integration/operation_failure_code_spec.rb +1 -1
  103. data/spec/integration/operation_failure_message_spec.rb +3 -3
  104. data/spec/integration/retryable_errors_spec.rb +2 -2
  105. data/spec/integration/sdam_error_handling_spec.rb +2 -1
  106. data/spec/integration/search_indexes_prose_spec.rb +4 -0
  107. data/spec/integration/server_spec.rb +4 -3
  108. data/spec/integration/transactions_api_examples_spec.rb +2 -0
  109. data/spec/kerberos/kerberos_spec.rb +4 -0
  110. data/spec/lite_spec_helper.rb +3 -1
  111. data/spec/mongo/auth/user/view_spec.rb +1 -1
  112. data/spec/mongo/caching_cursor_spec.rb +1 -1
  113. data/spec/mongo/client_encryption_spec.rb +1 -0
  114. data/spec/mongo/client_spec.rb +158 -4
  115. data/spec/mongo/collection/view/aggregation_spec.rb +14 -39
  116. data/spec/mongo/collection/view/change_stream_spec.rb +3 -3
  117. data/spec/mongo/collection_spec.rb +5 -6
  118. data/spec/mongo/crypt/auto_encrypter_spec.rb +14 -12
  119. data/spec/mongo/crypt/data_key_context_spec.rb +3 -1
  120. data/spec/mongo/crypt/explicit_encryption_context_spec.rb +2 -2
  121. data/spec/mongo/crypt/handle_spec.rb +1 -1
  122. data/spec/mongo/cursor_spec.rb +26 -9
  123. data/spec/mongo/error/operation_failure_heavy_spec.rb +2 -2
  124. data/spec/mongo/operation/context_spec.rb +79 -0
  125. data/spec/mongo/operation/create/op_msg_spec.rb +106 -110
  126. data/spec/mongo/operation/delete/op_msg_spec.rb +6 -5
  127. data/spec/mongo/operation/find/op_msg_spec.rb +66 -0
  128. data/spec/mongo/operation/get_more/op_msg_spec.rb +65 -0
  129. data/spec/mongo/operation/insert/op_msg_spec.rb +128 -131
  130. data/spec/mongo/operation/shared/csot/examples.rb +113 -0
  131. data/spec/mongo/query_cache_spec.rb +243 -225
  132. data/spec/mongo/retryable_spec.rb +1 -0
  133. data/spec/mongo/server/round_trip_time_calculator_spec.rb +120 -0
  134. data/spec/mongo/socket/ssl_spec.rb +0 -10
  135. data/spec/runners/change_streams/test.rb +2 -2
  136. data/spec/runners/crud/operation.rb +1 -1
  137. data/spec/runners/crud/verifier.rb +3 -1
  138. data/spec/runners/transactions/operation.rb +4 -6
  139. data/spec/runners/unified/ambiguous_operations.rb +13 -0
  140. data/spec/runners/unified/assertions.rb +4 -0
  141. data/spec/runners/unified/change_stream_operations.rb +14 -24
  142. data/spec/runners/unified/crud_operations.rb +82 -59
  143. data/spec/runners/unified/ddl_operations.rb +38 -7
  144. data/spec/runners/unified/grid_fs_operations.rb +37 -2
  145. data/spec/runners/unified/support_operations.rb +43 -4
  146. data/spec/runners/unified/test.rb +22 -10
  147. data/spec/runners/unified.rb +1 -1
  148. data/spec/solo/clean_exit_spec.rb +2 -0
  149. data/spec/spec_tests/client_side_operations_timeout_spec.rb +15 -0
  150. data/spec/spec_tests/data/change_streams_unified/change-streams-clusterTime.yml +3 -1
  151. data/spec/spec_tests/data/change_streams_unified/change-streams-disambiguatedPaths.yml +3 -1
  152. data/spec/spec_tests/data/change_streams_unified/change-streams-errors.yml +3 -1
  153. data/spec/spec_tests/data/change_streams_unified/change-streams-pre_and_post_images.yml +1 -1
  154. data/spec/spec_tests/data/change_streams_unified/change-streams-resume-allowlist.yml +1 -1
  155. data/spec/spec_tests/data/change_streams_unified/change-streams-resume-errorLabels.yml +1 -1
  156. data/spec/spec_tests/data/change_streams_unified/change-streams-showExpandedEvents.yml +1 -1
  157. data/spec/spec_tests/data/client_side_encryption/badQueries.yml +2 -1
  158. data/spec/spec_tests/data/client_side_encryption/timeoutMS.yml +67 -0
  159. data/spec/spec_tests/data/client_side_operations_timeout/bulkWrite.yml +87 -0
  160. data/spec/spec_tests/data/client_side_operations_timeout/change-streams.yml +358 -0
  161. data/spec/spec_tests/data/client_side_operations_timeout/close-cursors.yml +129 -0
  162. data/spec/spec_tests/data/client_side_operations_timeout/command-execution.yml +250 -0
  163. data/spec/spec_tests/data/client_side_operations_timeout/convenient-transactions.yml +113 -0
  164. data/spec/spec_tests/data/client_side_operations_timeout/cursors.yml +70 -0
  165. data/spec/spec_tests/data/client_side_operations_timeout/deprecated-options.yml +3982 -0
  166. data/spec/spec_tests/data/client_side_operations_timeout/error-transformations.yml +96 -0
  167. data/spec/spec_tests/data/client_side_operations_timeout/global-timeoutMS.yml +3236 -0
  168. data/spec/spec_tests/data/client_side_operations_timeout/gridfs-advanced.yml +207 -0
  169. data/spec/spec_tests/data/client_side_operations_timeout/gridfs-delete.yml +152 -0
  170. data/spec/spec_tests/data/client_side_operations_timeout/gridfs-download.yml +182 -0
  171. data/spec/spec_tests/data/client_side_operations_timeout/gridfs-find.yml +100 -0
  172. data/spec/spec_tests/data/client_side_operations_timeout/gridfs-upload.yml +249 -0
  173. data/spec/spec_tests/data/client_side_operations_timeout/legacy-timeouts.yml +204 -0
  174. data/spec/spec_tests/data/client_side_operations_timeout/non-tailable-cursors.yml +307 -0
  175. data/spec/spec_tests/data/client_side_operations_timeout/override-collection-timeoutMS.yml +1877 -0
  176. data/spec/spec_tests/data/client_side_operations_timeout/override-operation-timeoutMS.yml +1918 -0
  177. data/spec/spec_tests/data/client_side_operations_timeout/retryability-legacy-timeouts.yml +1676 -0
  178. data/spec/spec_tests/data/client_side_operations_timeout/retryability-timeoutMS.yml +2824 -0
  179. data/spec/spec_tests/data/client_side_operations_timeout/sessions-inherit-timeoutMS.yml +168 -0
  180. data/spec/spec_tests/data/client_side_operations_timeout/sessions-override-operation-timeoutMS.yml +171 -0
  181. data/spec/spec_tests/data/client_side_operations_timeout/sessions-override-timeoutMS.yml +168 -0
  182. data/spec/spec_tests/data/client_side_operations_timeout/tailable-awaitData.yml +247 -0
  183. data/spec/spec_tests/data/client_side_operations_timeout/tailable-non-awaitData.yml +181 -0
  184. data/spec/spec_tests/data/crud_unified/aggregate-write-readPreference.yml +4 -0
  185. data/spec/spec_tests/data/crud_unified/db-aggregate-write-readPreference.yml +4 -0
  186. data/spec/spec_tests/data/crud_unified/find-test-all-options.yml +29 -0
  187. data/spec/spec_tests/server_selection_rtt_spec.rb +6 -6
  188. data/spec/support/certificates/atlas-ocsp-ca.crt +81 -83
  189. data/spec/support/certificates/atlas-ocsp.crt +107 -107
  190. data/spec/support/cluster_tools.rb +3 -3
  191. data/spec/support/common_shortcuts.rb +2 -2
  192. data/spec/support/crypt/encrypted_fields/range-encryptedFields-Date.json +1 -1
  193. data/spec/support/crypt/encrypted_fields/range-encryptedFields-DecimalNoPrecision.json +1 -1
  194. data/spec/support/crypt/encrypted_fields/range-encryptedFields-DecimalPrecision.json +1 -1
  195. data/spec/support/crypt/encrypted_fields/range-encryptedFields-DoubleNoPrecision.json +1 -1
  196. data/spec/support/crypt/encrypted_fields/range-encryptedFields-DoublePrecision.json +1 -1
  197. data/spec/support/crypt/encrypted_fields/range-encryptedFields-Int.json +1 -1
  198. data/spec/support/crypt/encrypted_fields/range-encryptedFields-Long.json +1 -1
  199. data/spec/support/shared/session.rb +2 -2
  200. data/spec/support/spec_setup.rb +2 -2
  201. data/spec/support/utils.rb +3 -1
  202. metadata +78 -91
  203. data/spec/mongo/server/round_trip_time_averager_spec.rb +0 -48
  204. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Date-Aggregate.yml +0 -242
  205. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Date-Correctness.yml +0 -423
  206. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Date-Delete.yml +0 -183
  207. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Date-FindOneAndUpdate.yml +0 -240
  208. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Date-InsertFind.yml +0 -236
  209. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Date-Update.yml +0 -253
  210. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Decimal-Aggregate.yml +0 -1688
  211. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Decimal-Correctness.yml +0 -294
  212. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Decimal-Delete.yml +0 -906
  213. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Decimal-FindOneAndUpdate.yml +0 -1685
  214. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Decimal-InsertFind.yml +0 -1681
  215. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Decimal-Update.yml +0 -1698
  216. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-DecimalPrecision-Aggregate.yml +0 -330
  217. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-DecimalPrecision-Correctness.yml +0 -425
  218. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-DecimalPrecision-Delete.yml +0 -227
  219. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-DecimalPrecision-FindOneAndUpdate.yml +0 -328
  220. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-DecimalPrecision-InsertFind.yml +0 -320
  221. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-DecimalPrecision-Update.yml +0 -337
  222. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Double-Aggregate.yml +0 -914
  223. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Double-Correctness.yml +0 -293
  224. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Double-Delete.yml +0 -519
  225. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Double-FindOneAndUpdate.yml +0 -912
  226. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Double-InsertFind.yml +0 -908
  227. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Double-Update.yml +0 -925
  228. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-DoublePrecision-Aggregate.yml +0 -326
  229. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-DoublePrecision-Correctness.yml +0 -425
  230. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-DoublePrecision-Delete.yml +0 -225
  231. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-DoublePrecision-FindOneAndUpdate.yml +0 -324
  232. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-DoublePrecision-InsertFind.yml +0 -320
  233. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-DoublePrecision-Update.yml +0 -339
  234. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Int-Aggregate.yml +0 -242
  235. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Int-Correctness.yml +0 -424
  236. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Int-Delete.yml +0 -183
  237. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Int-FindOneAndUpdate.yml +0 -240
  238. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Int-InsertFind.yml +0 -236
  239. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Int-Update.yml +0 -255
  240. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Long-Aggregate.yml +0 -242
  241. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Long-Correctness.yml +0 -423
  242. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Long-Delete.yml +0 -183
  243. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Long-FindOneAndUpdate.yml +0 -240
  244. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Long-InsertFind.yml +0 -236
  245. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Long-Update.yml +0 -255
  246. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-WrongType.yml +0 -44
@@ -2,8 +2,12 @@
2
2
  # rubocop:todo all
3
3
 
4
4
  require 'spec_helper'
5
+ require_relative '../shared/csot/examples'
5
6
 
6
7
  describe Mongo::Operation::Insert::OpMsg do
8
+ include CSOT::Examples
9
+
10
+ let(:context) { Mongo::Operation::Context.new }
7
11
 
8
12
  let(:documents) { [{ :_id => 1, :foo => 1 }] }
9
13
  let(:session) { nil }
@@ -104,193 +108,186 @@ describe Mongo::Operation::Insert::OpMsg do
104
108
  # https://jira.mongodb.org/browse/RUBY-2224
105
109
  require_no_linting
106
110
 
107
- context 'when the server supports OP_MSG' do
108
- min_server_fcv '3.6'
111
+ let(:documents) do
112
+ [ { foo: 1 }, { bar: 2 }]
113
+ end
114
+
115
+ let(:global_args) do
116
+ {
117
+ insert: TEST_COLL,
118
+ ordered: true,
119
+ writeConcern: write_concern.options,
120
+ '$db' => SpecConfig.instance.test_db,
121
+ lsid: session.session_id
122
+ }
123
+ end
124
+
125
+ let!(:expected_payload_1) do
126
+ Mongo::Protocol::Msg::Section1.new('documents', op.documents)
127
+ end
109
128
 
110
- let(:documents) do
111
- [ { foo: 1 }, { bar: 2 }]
129
+ let(:session) do
130
+ Mongo::Session.new(nil, authorized_client, implicit: true).tap do |session|
131
+ allow(session).to receive(:session_id).and_return(42)
112
132
  end
133
+ end
113
134
 
114
- let(:global_args) do
115
- {
116
- insert: TEST_COLL,
117
- ordered: true,
118
- writeConcern: write_concern.options,
119
- '$db' => SpecConfig.instance.test_db,
120
- lsid: session.session_id
121
- }
135
+ context 'when the topology is replica set or sharded' do
136
+ require_topology :replica_set, :sharded
137
+
138
+ let(:expected_global_args) do
139
+ global_args.merge(Mongo::Operation::CLUSTER_TIME => authorized_client.cluster.cluster_time)
140
+ end
141
+
142
+ it 'creates the correct OP_MSG message' do
143
+ authorized_client.command(ping:1)
144
+ RSpec::Mocks.with_temporary_scope do
145
+ expect(Mongo::Protocol::Msg).to receive(:new).with([],
146
+ {},
147
+ expected_global_args,
148
+ expected_payload_1)
149
+ op.send(:message, connection)
150
+ end
122
151
  end
152
+ end
153
+
154
+ context 'when the topology is standalone' do
155
+ require_topology :single
123
156
 
124
- let!(:expected_payload_1) do
125
- Mongo::Protocol::Msg::Section1.new('documents', op.documents)
157
+ let(:expected_global_args) do
158
+ global_args
126
159
  end
127
160
 
128
- let(:session) do
129
- Mongo::Session.new(nil, authorized_client, implicit: true).tap do |session|
130
- allow(session).to receive(:session_id).and_return(42)
161
+ it 'creates the correct OP_MSG message' do
162
+ RSpec::Mocks.with_temporary_scope do
163
+ authorized_client.command(ping:1)
164
+ expect(Mongo::Protocol::Msg).to receive(:new).with([],
165
+ {},
166
+ expected_global_args,
167
+ expected_payload_1)
168
+ op.send(:message, connection)
131
169
  end
132
170
  end
133
171
 
134
- context 'when the topology is replica set or sharded' do
135
- min_server_fcv '3.6'
136
- require_topology :replica_set, :sharded
172
+ context 'when an implicit session is created and the topology is then updated and the server does not support sessions' do
173
+ # Mocks on features are incompatible with linting
174
+ require_no_linting
137
175
 
138
176
  let(:expected_global_args) do
139
- global_args.merge(Mongo::Operation::CLUSTER_TIME => authorized_client.cluster.cluster_time)
177
+ global_args.dup.tap do |args|
178
+ args.delete(:lsid)
179
+ end
180
+ end
181
+
182
+ before do
183
+ session.implicit?.should be true
140
184
  end
141
185
 
142
186
  it 'creates the correct OP_MSG message' do
143
- authorized_client.command(ping:1)
144
187
  RSpec::Mocks.with_temporary_scope do
188
+ expect(connection.features).to receive(:sessions_enabled?).and_return(false)
189
+
190
+ expect(expected_global_args).not_to have_key(:lsid)
145
191
  expect(Mongo::Protocol::Msg).to receive(:new).with([],
146
- {},
147
- expected_global_args,
148
- expected_payload_1)
192
+ {},
193
+ expected_global_args,
194
+ expected_payload_1)
149
195
  op.send(:message, connection)
150
196
  end
151
197
  end
152
198
  end
199
+ end
153
200
 
154
- context 'when the topology is standalone' do
155
- min_server_fcv '3.6'
156
- require_topology :single
201
+ context 'when the write concern is 0' do
157
202
 
158
- let(:expected_global_args) do
159
- global_args
160
- end
203
+ let(:write_concern) do
204
+ Mongo::WriteConcern.get(w: 0)
205
+ end
161
206
 
162
- it 'creates the correct OP_MSG message' do
163
- RSpec::Mocks.with_temporary_scope do
164
- authorized_client.command(ping:1)
165
- expect(Mongo::Protocol::Msg).to receive(:new).with([],
166
- {},
167
- expected_global_args,
168
- expected_payload_1)
169
- op.send(:message, connection)
207
+ context 'when the session is implicit' do
208
+
209
+ let(:session) do
210
+ Mongo::Session.new(nil, authorized_client, implicit: true).tap do |session|
211
+ allow(session).to receive(:session_id).and_return(42)
212
+ session.should be_implicit
170
213
  end
171
214
  end
172
215
 
173
- context 'when an implicit session is created and the topology is then updated and the server does not support sessions' do
174
- # Mocks on features are incompatible with linting
175
- require_no_linting
216
+ context 'when the topology is replica set or sharded' do
217
+ require_topology :replica_set, :sharded
176
218
 
177
219
  let(:expected_global_args) do
178
220
  global_args.dup.tap do |args|
179
221
  args.delete(:lsid)
222
+ args.merge!(Mongo::Operation::CLUSTER_TIME => authorized_client.cluster.cluster_time)
180
223
  end
181
224
  end
182
225
 
183
- before do
184
- session.implicit?.should be true
185
- end
186
-
187
- it 'creates the correct OP_MSG message' do
226
+ it 'does not send a session id in the command' do
227
+ authorized_client.command(ping:1)
188
228
  RSpec::Mocks.with_temporary_scope do
189
- expect(connection.features).to receive(:sessions_enabled?).and_return(false)
190
-
191
- expect(expected_global_args).not_to have_key(:lsid)
192
- expect(Mongo::Protocol::Msg).to receive(:new).with([],
193
- {},
194
- expected_global_args,
195
- expected_payload_1)
229
+ expect(Mongo::Protocol::Msg).to receive(:new).with([:more_to_come],
230
+ {},
231
+ expected_global_args,
232
+ expected_payload_1)
196
233
  op.send(:message, connection)
197
234
  end
198
235
  end
199
236
  end
200
- end
201
237
 
202
- context 'when the write concern is 0' do
203
-
204
- let(:write_concern) do
205
- Mongo::WriteConcern.get(w: 0)
206
- end
238
+ context 'when the topology is standalone' do
239
+ require_topology :single
207
240
 
208
- context 'when the session is implicit' do
209
-
210
- let(:session) do
211
- Mongo::Session.new(nil, authorized_client, implicit: true).tap do |session|
212
- allow(session).to receive(:session_id).and_return(42)
213
- session.should be_implicit
214
- end
215
- end
216
-
217
- context 'when the topology is replica set or sharded' do
218
- min_server_fcv '3.6'
219
- require_topology :replica_set, :sharded
220
-
221
- let(:expected_global_args) do
222
- global_args.dup.tap do |args|
223
- args.delete(:lsid)
224
- args.merge!(Mongo::Operation::CLUSTER_TIME => authorized_client.cluster.cluster_time)
225
- end
226
- end
227
-
228
- it 'does not send a session id in the command' do
229
- authorized_client.command(ping:1)
230
- RSpec::Mocks.with_temporary_scope do
231
- expect(Mongo::Protocol::Msg).to receive(:new).with([:more_to_come],
232
- {},
233
- expected_global_args,
234
- expected_payload_1)
235
- op.send(:message, connection)
236
- end
241
+ let(:expected_global_args) do
242
+ global_args.dup.tap do |args|
243
+ args.delete(:lsid)
237
244
  end
238
245
  end
239
246
 
240
- context 'when the topology is standalone' do
241
- min_server_fcv '3.6'
242
- require_topology :single
243
-
244
- let(:expected_global_args) do
245
- global_args.dup.tap do |args|
246
- args.delete(:lsid)
247
- end
248
- end
249
-
250
- it 'creates the correct OP_MSG message' do
251
- authorized_client.command(ping:1)
252
- RSpec::Mocks.with_temporary_scope do
253
- expect(Mongo::Protocol::Msg).to receive(:new).with([:more_to_come],
254
- {},
255
- expected_global_args,
256
- expected_payload_1)
257
- op.send(:message, connection)
258
- end
247
+ it 'creates the correct OP_MSG message' do
248
+ authorized_client.command(ping:1)
249
+ RSpec::Mocks.with_temporary_scope do
250
+ expect(Mongo::Protocol::Msg).to receive(:new).with([:more_to_come],
251
+ {},
252
+ expected_global_args,
253
+ expected_payload_1)
254
+ op.send(:message, connection)
259
255
  end
260
256
  end
261
257
  end
258
+ end
262
259
 
263
- context 'when the session is explicit' do
264
- min_server_fcv '3.6'
265
- require_topology :replica_set, :sharded
260
+ context 'when the session is explicit' do
261
+ require_topology :replica_set, :sharded
266
262
 
267
- let(:session) do
268
- authorized_client.start_session
269
- end
263
+ let(:session) do
264
+ authorized_client.start_session
265
+ end
270
266
 
271
- before do
272
- session.should_not be_implicit
273
- end
267
+ before do
268
+ session.should_not be_implicit
269
+ end
274
270
 
275
- let(:expected_global_args) do
276
- global_args.dup.tap do |args|
277
- args.delete(:lsid)
278
- args.merge!(Mongo::Operation::CLUSTER_TIME => authorized_client.cluster.cluster_time)
279
- end
271
+ let(:expected_global_args) do
272
+ global_args.dup.tap do |args|
273
+ args.delete(:lsid)
274
+ args.merge!(Mongo::Operation::CLUSTER_TIME => authorized_client.cluster.cluster_time)
280
275
  end
276
+ end
281
277
 
282
- it 'does not send a session id in the command' do
283
- authorized_client.command(ping:1)
284
- RSpec::Mocks.with_temporary_scope do
285
- expect(Mongo::Protocol::Msg).to receive(:new).with([:more_to_come],
286
- {},
287
- expected_global_args,
288
- expected_payload_1)
289
- op.send(:message, connection)
290
- end
278
+ it 'does not send a session id in the command' do
279
+ authorized_client.command(ping:1)
280
+ RSpec::Mocks.with_temporary_scope do
281
+ expect(Mongo::Protocol::Msg).to receive(:new).with([:more_to_come],
282
+ {},
283
+ expected_global_args,
284
+ expected_payload_1)
285
+ op.send(:message, connection)
291
286
  end
292
287
  end
293
288
  end
294
289
  end
295
290
  end
291
+
292
+ it_behaves_like 'a CSOT-compliant OpMsg subclass'
296
293
  end
@@ -0,0 +1,113 @@
1
+ # frozen_string_literal: true
2
+ # rubocop:todo all
3
+
4
+ module CSOT
5
+ module Examples
6
+ # expects the following values to be available:
7
+ # `op` -- an instance of an OpMsgBase subclass
8
+ def self.included(example_context)
9
+ example_context.shared_examples 'mock CSOT environment' do
10
+ # Linting freaks out because of the doubles used in these specs.
11
+ require_no_linting
12
+
13
+ let(:message) { op.send(:message, connection) }
14
+
15
+ let(:body) { message.documents.first }
16
+
17
+ let(:cursor_type) { nil }
18
+ let(:timeout_mode) { nil }
19
+ let(:remaining_timeout_sec) { nil }
20
+ let(:minimum_round_trip_time) { 0 }
21
+ let(:view_options) { {} }
22
+ let(:max_await_time_ms) { nil }
23
+
24
+ let(:view) do
25
+ instance_double(Mongo::Collection::View).tap do |view|
26
+ allow(view).to receive(:cursor_type).and_return(cursor_type)
27
+ allow(view).to receive(:timeout_mode).and_return(timeout_mode)
28
+ allow(view).to receive(:options).and_return(view_options)
29
+ allow(view).to receive(:max_await_time_ms).and_return(max_await_time_ms)
30
+ end
31
+ end
32
+
33
+ let(:context) do
34
+ Mongo::Operation::Context.new(view: view).tap do |context|
35
+ allow(context).to receive(:remaining_timeout_sec).and_return(remaining_timeout_sec)
36
+ allow(context).to receive(:timeout?).and_return(!remaining_timeout_sec.nil?)
37
+ end
38
+ end
39
+
40
+ let(:server) do
41
+ instance_double(Mongo::Server).tap do |server|
42
+ allow(server).to receive(:minimum_round_trip_time).and_return(minimum_round_trip_time)
43
+ end
44
+ end
45
+
46
+ let(:address) { Mongo::Address.new('127.0.0.1') }
47
+
48
+ let(:description) do
49
+ Mongo::Server::Description.new(
50
+ address, { Mongo::Operation::Result::OK => 1 }
51
+ )
52
+ end
53
+
54
+ let(:features) do
55
+ Mongo::Server::Description::Features.new(
56
+ Mongo::Server::Description::Features::DRIVER_WIRE_VERSIONS,
57
+ address
58
+ )
59
+ end
60
+
61
+ let(:connection) do
62
+ instance_double(Mongo::Server::Connection).tap do |conn|
63
+ allow(conn).to receive(:server).and_return(server)
64
+ allow(conn).to receive(:description).and_return(description)
65
+ allow(conn).to receive(:features).and_return(features)
66
+ end
67
+ end
68
+
69
+ before do
70
+ # context is normally set when calling `execute` on the operation,
71
+ # but since we're not doing that, we have to tell the operation
72
+ # what the context is.
73
+ op.context = context
74
+ end
75
+ end
76
+
77
+ example_context.shared_examples 'a CSOT-compliant OpMsg subclass' do
78
+ include_examples 'mock CSOT environment'
79
+
80
+ context 'when no timeout_ms set' do
81
+ it 'does not set maxTimeMS' do
82
+ expect(body.key?(:maxTimeMS)).to be false
83
+ end
84
+ end
85
+
86
+ context 'when there is enough time to send the message' do
87
+ # Ten seconds remaining
88
+ let(:remaining_timeout_sec) { 10 }
89
+
90
+ # One second RTT
91
+ let(:minimum_round_trip_time) { 1 }
92
+
93
+ it 'sets the maxTimeMS' do
94
+ # Nine seconds
95
+ expect(body[:maxTimeMS]).to eq(9_000)
96
+ end
97
+ end
98
+
99
+ context 'when there is not enough time to send the message' do
100
+ # Ten seconds remaining
101
+ let(:remaining_timeout_sec) { 0.1 }
102
+
103
+ # One second RTT
104
+ let(:minimum_round_trip_time) { 1 }
105
+
106
+ it 'fails with an exception' do
107
+ expect { message }.to raise_error(Mongo::Error::TimeoutError)
108
+ end
109
+ end
110
+ end
111
+ end
112
+ end
113
+ end