mongo 2.5.0.beta → 2.5.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 (172) 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/address.rb +1 -1
  5. data/lib/mongo/address/unix.rb +1 -1
  6. data/lib/mongo/auth/user.rb +0 -5
  7. data/lib/mongo/auth/user/view.rb +4 -4
  8. data/lib/mongo/bulk_write.rb +60 -32
  9. data/lib/mongo/client.rb +44 -8
  10. data/lib/mongo/cluster.rb +14 -12
  11. data/lib/mongo/cluster/periodic_executor.rb +106 -0
  12. data/lib/mongo/cluster/{cursor_reaper.rb → reapers/cursor_reaper.rb} +5 -37
  13. data/lib/mongo/cluster/reapers/socket_reaper.rb +59 -0
  14. data/lib/mongo/collection.rb +9 -6
  15. data/lib/mongo/collection/view.rb +2 -2
  16. data/lib/mongo/collection/view/builder/aggregation.rb +2 -1
  17. data/lib/mongo/collection/view/builder/find_command.rb +1 -1
  18. data/lib/mongo/collection/view/change_stream.rb +14 -1
  19. data/lib/mongo/collection/view/map_reduce.rb +30 -13
  20. data/lib/mongo/collection/view/readable.rb +5 -5
  21. data/lib/mongo/collection/view/writable.rb +98 -51
  22. data/lib/mongo/error.rb +3 -0
  23. data/lib/mongo/error/invalid_txt_record.rb +27 -0
  24. data/lib/mongo/error/invalid_uri.rb +7 -6
  25. data/lib/mongo/error/mismatched_domain.rb +27 -0
  26. data/lib/mongo/error/no_srv_records.rb +26 -0
  27. data/lib/mongo/error/unsupported_features.rb +0 -18
  28. data/lib/mongo/index/view.rb +2 -2
  29. data/lib/mongo/operation.rb +1 -0
  30. data/lib/mongo/operation/causally_consistent.rb +33 -0
  31. data/lib/mongo/operation/commands.rb +2 -1
  32. data/lib/mongo/operation/commands/aggregate.rb +2 -7
  33. data/lib/mongo/operation/commands/count.rb +27 -0
  34. data/lib/mongo/operation/commands/distinct.rb +27 -0
  35. data/lib/mongo/operation/commands/find.rb +3 -1
  36. data/lib/mongo/operation/commands/map_reduce.rb +1 -0
  37. data/lib/mongo/operation/commands/parallel_scan.rb +1 -0
  38. data/lib/mongo/operation/specifiable.rb +12 -0
  39. data/lib/mongo/operation/uses_command_op_msg.rb +36 -5
  40. data/lib/mongo/operation/write.rb +0 -5
  41. data/lib/mongo/operation/write/bulk/bulkable.rb +4 -8
  42. data/lib/mongo/operation/write/bulk/mergable.rb +2 -0
  43. data/lib/mongo/operation/write/command/create_index.rb +19 -0
  44. data/lib/mongo/operation/write/command/create_user.rb +19 -0
  45. data/lib/mongo/operation/write/command/delete.rb +1 -2
  46. data/lib/mongo/operation/write/command/drop_index.rb +19 -0
  47. data/lib/mongo/operation/write/command/insert.rb +1 -2
  48. data/lib/mongo/operation/write/command/remove_user.rb +19 -0
  49. data/lib/mongo/operation/write/command/update.rb +1 -2
  50. data/lib/mongo/operation/write/command/update_user.rb +19 -0
  51. data/lib/mongo/operation/write/write_command_enabled.rb +1 -3
  52. data/lib/mongo/protocol/compressed.rb +2 -1
  53. data/lib/mongo/protocol/serializers.rb +6 -6
  54. data/lib/mongo/retryable.rb +48 -5
  55. data/lib/mongo/server.rb +15 -0
  56. data/lib/mongo/server/connection.rb +21 -1
  57. data/lib/mongo/server/connection_pool.rb +3 -0
  58. data/lib/mongo/server/connection_pool/queue.rb +50 -5
  59. data/lib/mongo/server/description.rb +11 -3
  60. data/lib/mongo/server/description/features.rb +26 -7
  61. data/lib/mongo/session.rb +133 -6
  62. data/lib/mongo/session/server_session.rb +30 -0
  63. data/lib/mongo/session/session_pool.rb +20 -20
  64. data/lib/mongo/uri.rb +88 -44
  65. data/lib/mongo/uri/srv_protocol.rb +158 -0
  66. data/lib/mongo/version.rb +1 -1
  67. data/lib/mongo/write_concern/normalizable.rb +12 -0
  68. data/mongo.gemspec +1 -2
  69. data/spec/mongo/address_spec.rb +12 -0
  70. data/spec/mongo/auth/user/view_spec.rb +1 -5
  71. data/spec/mongo/bulk_write_spec.rb +232 -401
  72. data/spec/mongo/change_stream_examples_spec.rb +150 -0
  73. data/spec/mongo/client_spec.rb +142 -2
  74. data/spec/mongo/cluster/cursor_reaper_spec.rb +0 -70
  75. data/spec/mongo/cluster/socket_reaper_spec.rb +32 -0
  76. data/spec/mongo/cluster_spec.rb +11 -7
  77. data/spec/mongo/collection/view/aggregation_spec.rb +46 -1
  78. data/spec/mongo/collection/view/builder/find_command_spec.rb +15 -0
  79. data/spec/mongo/collection/view/change_stream_spec.rb +79 -12
  80. data/spec/mongo/collection/view/map_reduce_spec.rb +120 -4
  81. data/spec/mongo/collection/view/readable_spec.rb +23 -5
  82. data/spec/mongo/collection_spec.rb +292 -102
  83. data/spec/mongo/command_monitoring_spec.rb +26 -32
  84. data/spec/mongo/crud_spec.rb +1 -1
  85. data/spec/mongo/cursor_spec.rb +2 -3
  86. data/spec/mongo/database_spec.rb +30 -14
  87. data/spec/mongo/dns_seedlist_discovery_spec.rb +94 -0
  88. data/spec/mongo/grid/fs_bucket_spec.rb +1 -1
  89. data/spec/mongo/grid/stream/write_spec.rb +1 -1
  90. data/spec/mongo/index/view_spec.rb +8 -46
  91. data/spec/mongo/operation/write/bulk/delete_spec.rb +2 -2
  92. data/spec/mongo/operation/write/bulk/insert_spec.rb +2 -10
  93. data/spec/mongo/operation/write/{create_index_spec.rb → command/create_index_spec.rb} +2 -6
  94. data/spec/mongo/operation/write/command/delete_spec.rb +35 -7
  95. data/spec/mongo/operation/write/{drop_index_spec.rb → command/drop_index_spec.rb} +1 -1
  96. data/spec/mongo/operation/write/command/insert_spec.rb +37 -6
  97. data/spec/mongo/operation/write/{remove_user_spec.rb → command/remove_user_spec.rb} +2 -6
  98. data/spec/mongo/operation/write/command/update_spec.rb +34 -7
  99. data/spec/mongo/operation/write/{update_user_spec.rb → command/update_user_spec.rb} +1 -1
  100. data/spec/mongo/operation/write/create_user_spec.rb +1 -1
  101. data/spec/mongo/operation/write/delete_spec.rb +1 -1
  102. data/spec/mongo/operation/write/insert_spec.rb +2 -10
  103. data/spec/mongo/operation/write/update_spec.rb +3 -15
  104. data/spec/mongo/retryable_spec.rb +1 -1
  105. data/spec/mongo/retryable_writes_spec.rb +815 -0
  106. data/spec/mongo/server/connection_pool/queue_spec.rb +35 -2
  107. data/spec/mongo/server/connection_pool_spec.rb +234 -1
  108. data/spec/mongo/server/connection_spec.rb +10 -6
  109. data/spec/mongo/server/description/features_spec.rb +51 -37
  110. data/spec/mongo/server/description_spec.rb +6 -3
  111. data/spec/mongo/server_spec.rb +87 -0
  112. data/spec/mongo/session/server_session_spec.rb +43 -0
  113. data/spec/mongo/session/session_pool_spec.rb +63 -27
  114. data/spec/mongo/session_spec.rb +247 -0
  115. data/spec/mongo/shell_examples_spec.rb +2 -2
  116. data/spec/mongo/uri/srv_protocol_spec.rb +933 -0
  117. data/spec/mongo/uri_spec.rb +42 -3
  118. data/spec/mongo/write_concern/acknowledged_spec.rb +11 -0
  119. data/spec/mongo/write_concern/unacknowledged_spec.rb +11 -0
  120. data/spec/spec_helper.rb +11 -25
  121. data/spec/support/authorization.rb +2 -1
  122. data/spec/support/connection_string.rb +8 -4
  123. data/spec/support/crud.rb +38 -24
  124. data/spec/support/crud/write.rb +30 -3
  125. data/spec/support/crud_tests/read/aggregate-out.yml +21 -0
  126. data/spec/support/crud_tests/write/bulkWrite-arrayFilters.yml +44 -0
  127. data/spec/support/crud_tests/write/findOneAndUpdate-arrayFilters.yml +1 -1
  128. data/spec/support/crud_tests/write/insertMany.yml +1 -3
  129. data/spec/support/crud_tests/write/replaceOne.yml +1 -1
  130. data/spec/support/crud_tests/write/updateMany-arrayFilters.yml +1 -1
  131. data/spec/support/crud_tests/write/updateOne-arrayFilters.yml +1 -1
  132. data/spec/support/dns_seedlist_discovery_tests/longer-parent-in-return.yml +11 -0
  133. data/spec/support/dns_seedlist_discovery_tests/misformatted-option.yml +5 -0
  134. data/spec/support/dns_seedlist_discovery_tests/no-results.yml +5 -0
  135. data/spec/support/dns_seedlist_discovery_tests/not-enough-parts.yml +5 -0
  136. data/spec/support/dns_seedlist_discovery_tests/one-result-default-port.yml +10 -0
  137. data/spec/support/dns_seedlist_discovery_tests/one-txt-record-multiple-strings.yml +10 -0
  138. data/spec/support/dns_seedlist_discovery_tests/one-txt-record.yml +11 -0
  139. data/spec/support/dns_seedlist_discovery_tests/parent-part-mismatch1.yml +5 -0
  140. data/spec/support/dns_seedlist_discovery_tests/parent-part-mismatch2.yml +5 -0
  141. data/spec/support/dns_seedlist_discovery_tests/parent-part-mismatch3.yml +5 -0
  142. data/spec/support/dns_seedlist_discovery_tests/parent-part-mismatch4.yml +5 -0
  143. data/spec/support/dns_seedlist_discovery_tests/parent-part-mismatch5.yml +5 -0
  144. data/spec/support/dns_seedlist_discovery_tests/returned-parent-too-short.yml +5 -0
  145. data/spec/support/dns_seedlist_discovery_tests/returned-parent-wrong.yml +5 -0
  146. data/spec/support/dns_seedlist_discovery_tests/two-results-default-port.yml +11 -0
  147. data/spec/support/dns_seedlist_discovery_tests/two-results-nonstandard-port.yml +11 -0
  148. data/spec/support/dns_seedlist_discovery_tests/two-txt-records.yml +5 -0
  149. data/spec/support/dns_seedlist_discovery_tests/txt-record-not-allowed-option.yml +5 -0
  150. data/spec/support/dns_seedlist_discovery_tests/txt-record-with-overridden-ssl-option.yml +11 -0
  151. data/spec/support/dns_seedlist_discovery_tests/txt-record-with-overridden-uri-option.yml +11 -0
  152. data/spec/support/dns_seedlist_discovery_tests/txt-record-with-unallowed-option.yml +5 -0
  153. data/spec/support/dns_seedlist_discovery_tests/uri-with-port.yml +5 -0
  154. data/spec/support/dns_seedlist_discovery_tests/uri-with-two-hosts.yml +5 -0
  155. data/spec/support/retryable_writes_tests/bulkWrite.yml +305 -0
  156. data/spec/support/retryable_writes_tests/deleteOne.yml +51 -0
  157. data/spec/support/retryable_writes_tests/findOneAndDelete.yml +52 -0
  158. data/spec/support/retryable_writes_tests/findOneAndReplace.yml +57 -0
  159. data/spec/support/retryable_writes_tests/findOneAndUpdate.yml +56 -0
  160. data/spec/support/retryable_writes_tests/insertMany.yml +72 -0
  161. data/spec/support/retryable_writes_tests/insertOne.yml +55 -0
  162. data/spec/support/retryable_writes_tests/replaceOne.yml +60 -0
  163. data/spec/support/retryable_writes_tests/updateOne.yml +120 -0
  164. data/spec/support/shared/session.rb +525 -24
  165. metadata +437 -350
  166. metadata.gz.sig +0 -0
  167. data/lib/mongo/operation/commands/user_query.rb +0 -72
  168. data/lib/mongo/operation/write/create_index.rb +0 -67
  169. data/lib/mongo/operation/write/create_user.rb +0 -50
  170. data/lib/mongo/operation/write/drop_index.rb +0 -63
  171. data/lib/mongo/operation/write/remove_user.rb +0 -48
  172. data/lib/mongo/operation/write/update_user.rb +0 -50
@@ -1,6 +1,45 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  describe Mongo::URI do
4
+
5
+ describe '.get' do
6
+
7
+ let(:uri) { described_class.get(string) }
8
+
9
+ context 'when the scheme is mongodb://' do
10
+
11
+ let(:string) do
12
+ 'mongodb://localhost:27017'
13
+ end
14
+
15
+ it 'returns a Mongo::URI object' do
16
+ expect(uri).to be_a(Mongo::URI)
17
+ end
18
+ end
19
+
20
+ context 'when the scheme is mongodb+srv://' do
21
+
22
+ let(:string) do
23
+ 'mongodb+srv://test5.test.build.10gen.cc'
24
+ end
25
+
26
+ it 'returns a Mongo::URI::SRVProtocol object' do
27
+ expect(uri).to be_a(Mongo::URI::SRVProtocol)
28
+ end
29
+ end
30
+
31
+ context 'when the scheme is invalid' do
32
+
33
+ let(:string) do
34
+ 'mongo://localhost:27017'
35
+ end
36
+
37
+ it 'raises an exception' do
38
+ expect { uri }.to raise_error(Mongo::Error::InvalidURI)
39
+ end
40
+ end
41
+ end
42
+
4
43
  let(:scheme) { 'mongodb://' }
5
44
  let(:uri) { described_class.new(string) }
6
45
 
@@ -263,7 +302,7 @@ describe Mongo::URI do
263
302
  let(:servers) { '%2Ftmp%2Fmongodb-27017.sock' }
264
303
 
265
304
  it 'returns an array with the parsed server' do
266
- expect(uri.servers).to eq([servers])
305
+ expect(uri.servers).to eq([URI.unescape(servers)])
267
306
  end
268
307
  end
269
308
 
@@ -301,11 +340,11 @@ describe Mongo::URI do
301
340
  expect(options[:database]).to eq(TEST_DB)
302
341
  end
303
342
 
304
- it 'includes the credentials in the options' do
343
+ it 'includes the user in the options' do
305
344
  expect(options[:user]).to eq(user)
306
345
  end
307
346
 
308
- it 'includes the options in the options' do
347
+ it 'includes the password in the options' do
309
348
  expect(options[:password]).to eq(password)
310
349
  end
311
350
  end
@@ -2,6 +2,17 @@ require 'spec_helper'
2
2
 
3
3
  describe Mongo::WriteConcern::Acknowledged do
4
4
 
5
+ describe '#acknowledged?' do
6
+
7
+ let(:concern) do
8
+ described_class.new(:w => :majority)
9
+ end
10
+
11
+ it 'returns true' do
12
+ expect(concern.acknowledged?).to be(true)
13
+ end
14
+ end
15
+
5
16
  describe '#get_last_error' do
6
17
 
7
18
  let(:get_last_error) do
@@ -12,4 +12,15 @@ describe Mongo::WriteConcern::Unacknowledged do
12
12
  expect(concern.get_last_error).to be_nil
13
13
  end
14
14
  end
15
+
16
+ describe '#acknowledged?' do
17
+
18
+ let(:concern) do
19
+ described_class.new(:w => 0)
20
+ end
21
+
22
+ it 'returns false' do
23
+ expect(concern.acknowledged?).to be(false)
24
+ end
25
+ end
15
26
  end
data/spec/spec_helper.rb CHANGED
@@ -7,8 +7,10 @@ SERVER_SELECTION_RTT_TESTS = Dir.glob("#{CURRENT_PATH}/support/server_selection/
7
7
  SERVER_SELECTION_TESTS = Dir.glob("#{CURRENT_PATH}/support/server_selection/selection/**/*.yml")
8
8
  MAX_STALENESS_TESTS = Dir.glob("#{CURRENT_PATH}/support/max_staleness/**/*.yml")
9
9
  CRUD_TESTS = Dir.glob("#{CURRENT_PATH}/support/crud_tests/**/*.yml")
10
+ RETRYABLE_WRITES_TESTS = Dir.glob("#{CURRENT_PATH}/support/retryable_writes_tests/**/*.yml")
10
11
  COMMAND_MONITORING_TESTS = Dir.glob("#{CURRENT_PATH}/support/command_monitoring/**/*.yml")
11
12
  CONNECTION_STRING_TESTS = Dir.glob("#{CURRENT_PATH}/support/connection_string_tests/*.yml")
13
+ DNS_SEEDLIST_DISCOVERY_TESTS = Dir.glob("#{CURRENT_PATH}/support/dns_seedlist_discovery_tests/*.yml")
12
14
  GRIDFS_TESTS = Dir.glob("#{CURRENT_PATH}/support/gridfs_tests/*.yml")
13
15
 
14
16
  if ENV['DRIVERS_TOOLS']
@@ -66,13 +68,6 @@ RSpec.configure do |config|
66
68
  # databases that will be used in the test suite.
67
69
  ADMIN_AUTHORIZED_TEST_CLIENT.database.users.create(TEST_USER)
68
70
  rescue Exception => e
69
- unless write_command_enabled?
70
- # If we are on versions less than 2.6, we need to create a user for
71
- # each database, since the users are not stored in the admin database
72
- # but in the system.users collection on the databases themselves. Also,
73
- # roles in versions lower than 2.6 can only be strings, not hashes.
74
- begin ADMIN_AUTHORIZED_TEST_CLIENT.database.users.create(TEST_READ_WRITE_USER); rescue; end
75
- end
76
71
  end
77
72
  end
78
73
  end
@@ -144,6 +139,15 @@ end
144
139
  alias :change_stream_enabled? :op_msg_enabled?
145
140
  alias :sessions_enabled? :op_msg_enabled?
146
141
 
142
+
143
+ # Whether sessions can be tested. Sessions are available on server versions 3.6
144
+ # and higher and when connected to a replica set or sharded cluster.
145
+ #
146
+ # @since 2.5.0
147
+ def test_sessions?
148
+ sessions_enabled? && (replica_set? || sharded?)
149
+ end
150
+
147
151
  # Whether change streams can be tested. Change streams are available on server versions 3.6
148
152
  # and higher and when connected to a replica set.
149
153
  #
@@ -180,15 +184,6 @@ def find_command_enabled?
180
184
  $find_command_enabled ||= $mongo_client.cluster.servers.first.features.find_command_enabled?
181
185
  end
182
186
 
183
- # For instances where behaviour is different on different versions, we need to
184
- # determine in the specs if we are 2.6 or higher.
185
- #
186
- # @since 2.0.0
187
- def write_command_enabled?
188
- $mongo_client ||= initialize_scanned_client!
189
- $write_command_enabled ||= $mongo_client.cluster.servers.first.features.write_command_enabled?
190
- end
191
-
192
187
  # For instances where behaviour is different on different versions, we need to
193
188
  # determine in the specs if we are 2.7 or higher.
194
189
  #
@@ -229,15 +224,6 @@ end
229
224
 
230
225
  alias :scram_sha_1_enabled? :list_command_enabled?
231
226
 
232
- # Depending on whether write commands are enabled, there are different documents that
233
- # are guaranteed to cause a delete failure.
234
- #
235
- # @since 2.0.0
236
- def failing_delete_doc
237
- write_command_enabled? ? { q: { '$set' => { a: 1 } }, limit: 0 } :
238
- { que: { field: 'test' } }
239
- end
240
-
241
227
  # Try running a command on the admin database to see if the mongod was started with auth.
242
228
  #
243
229
  # @since 2.2.0
@@ -86,7 +86,8 @@ BASE_OPTIONS = {
86
86
  heartbeat_frequency: 20,
87
87
  max_read_retries: 5,
88
88
  wait_queue_timeout: 2,
89
- connect_timeout: 3
89
+ connect_timeout: 3,
90
+ max_idle_time: 5
90
91
  }
91
92
 
92
93
  # Options for test suite clients.
@@ -156,12 +156,16 @@ module Mongo
156
156
  end
157
157
 
158
158
  def uri
159
- @uri ||= Mongo::URI.new(@spec['uri'])
159
+ @uri ||= Mongo::URI.get(@spec['uri'])
160
160
  end
161
161
 
162
162
  def auth
163
163
  @auth ||= Auth.new(@spec['auth']) if @spec['auth']
164
164
  end
165
+
166
+ def raise_error?
167
+ @spec['error']
168
+ end
165
169
  end
166
170
 
167
171
  class Host
@@ -218,9 +222,9 @@ module Mongo
218
222
  end
219
223
 
220
224
  def match?(opts)
221
- @options.keys.all? do |k|
222
- opts[MAPPINGS[k]] == @options[k] ||
223
- Mongo::URI::AUTH_MECH_MAP[@options[k]] == opts[MAPPINGS[k]]
225
+ @options.all? do |k, v|
226
+ opts[MAPPINGS[k.downcase]] == v ||
227
+ opts[MAPPINGS[k.downcase]] == Mongo::URI::AUTH_MECH_MAP[v]
224
228
  end
225
229
  end
226
230
  end
data/spec/support/crud.rb CHANGED
@@ -103,29 +103,13 @@ module Mongo
103
103
  private
104
104
 
105
105
  def upper_bound_satisfied?(client)
106
- if @max_server_version
107
- if @max_server_version < '2.6'
108
- !client.cluster.next_primary.features.write_command_enabled?
109
- end
110
- else
111
- true
112
- end
106
+ return true unless @max_server_version
107
+ client.database.command(buildInfo: 1).first['version'] <= @max_server_version
113
108
  end
114
109
 
115
110
  def lower_bound_satisfied?(client)
116
- if @min_server_version
117
- if @min_server_version >= '3.6'
118
- client.cluster.next_primary.features.array_filters_enabled?
119
- elsif @min_server_version >= '3.4'
120
- client.cluster.next_primary.features.collation_enabled?
121
- elsif @min_server_version >= '2.6'
122
- client.cluster.next_primary.features.write_command_enabled?
123
- else
124
- true
125
- end
126
- else
127
- true
128
- end
111
+ return true unless @min_server_version
112
+ @min_server_version <= client.database.command(buildInfo: 1).first['version']
129
113
  end
130
114
  end
131
115
 
@@ -141,6 +125,8 @@ module Mongo
141
125
  # @since 2.0.0
142
126
  attr_reader :description
143
127
 
128
+ FAIL_POINT_BASE_COMMAND = { configureFailPoint: "onPrimaryTransactionalWrite" }
129
+
144
130
  # Instantiate the new CRUDTest.
145
131
  #
146
132
  # @example Create the test.
@@ -153,6 +139,7 @@ module Mongo
153
139
  # @since 2.0.0
154
140
  def initialize(data, test)
155
141
  @data = data
142
+ @fail_point_command = FAIL_POINT_BASE_COMMAND.merge(test['failPoint']) if test['failPoint']
156
143
  @description = test['description']
157
144
  @operation = Operation.get(test['operation'])
158
145
  @outcome = test['outcome']
@@ -170,11 +157,27 @@ module Mongo
170
157
  #
171
158
  # @since 2.0.0
172
159
  def run(collection)
173
- @collection = collection
174
- @collection.insert_many(@data)
175
160
  @operation.execute(collection)
176
161
  end
177
162
 
163
+ def setup_test(collection)
164
+ clear_fail_point(collection)
165
+ @collection = collection
166
+ collection.delete_many
167
+ collection.insert_many(@data)
168
+ set_up_fail_point(collection)
169
+ end
170
+
171
+ def set_up_fail_point(collection)
172
+ collection.client.use(:admin).command(@fail_point_command) if @fail_point_command
173
+ end
174
+
175
+ def clear_fail_point(collection)
176
+ if @fail_point_command
177
+ collection.client.use(:admin).command(FAIL_POINT_BASE_COMMAND.merge(mode: "off"))
178
+ end
179
+ end
180
+
178
181
  # The expected result of running the test.
179
182
  #
180
183
  # @example Get the expected result of running the test.
@@ -241,6 +244,10 @@ module Mongo
241
244
  @outcome['collection']['data'] if @outcome['collection']
242
245
  end
243
246
 
247
+ def error?
248
+ !!@outcome['error']
249
+ end
250
+
244
251
  private
245
252
 
246
253
  def compare_result(expected, actual)
@@ -248,8 +255,9 @@ module Mongo
248
255
  when nil
249
256
  actual.nil?
250
257
  when Hash
251
- actual.all? do |k, v|
252
- expected[k] == v || handle_upserted_id(k, expected[k], v)
258
+ results = actual.instance_variable_get(:@results)
259
+ (results || actual).all? do |k, v|
260
+ expected[k] == v || handle_upserted_id(k, expected[k], v) || handle_inserted_ids(k, expected[k], v)
253
261
  end
254
262
  when Integer
255
263
  expected == actual
@@ -265,6 +273,12 @@ module Mongo
265
273
  end
266
274
  end
267
275
 
276
+ def handle_inserted_ids(field, expected, actual)
277
+ if field == 'insertedIds'
278
+ expected.values == actual
279
+ end
280
+ end
281
+
268
282
  def actual_collection_data
269
283
  if @outcome['collection']
270
284
  collection_name = @outcome['collection']['name'] || @collection.name
@@ -99,7 +99,15 @@ module Mongo
99
99
  private
100
100
 
101
101
  def bulk_write(collection)
102
- collection.bulk_write(requests, options)
102
+ result = collection.bulk_write(requests, options)
103
+ return_doc = {}
104
+ return_doc['deletedCount'] = result.deleted_count if result.deleted_count
105
+ return_doc['insertedIds'] = result.inserted_ids if result.inserted_ids
106
+ return_doc['upsertedId'] = result.upserted_id if upsert
107
+ return_doc['upsertedCount'] = result.upserted_count if result.upserted_count
108
+ return_doc['matchedCount'] = result.matched_count if result.matched_count
109
+ return_doc['modifiedCount'] = result.modified_count if result.modified_count
110
+ return_doc
103
111
  end
104
112
 
105
113
  def delete_many(collection)
@@ -211,17 +219,36 @@ module Mongo
211
219
  { insert_one: request['insertOne']['document'] }
212
220
  when 'updateOne' then
213
221
  update = request['updateOne']
214
- { update_one: { filter: update['filter'], update: update['update'] }}
222
+ { update_one: { filter: update['filter'], update: update['update'] } }
223
+ when 'name' then
224
+ bulk_request(request)
215
225
  end
216
226
  end
217
227
  end
218
228
 
229
+ def bulk_request(request)
230
+ op_name = OPERATIONS[request['name']]
231
+ op = { op_name => {} }
232
+ op[op_name].merge!(filter: request['arguments']['filter']) if request['arguments']['filter']
233
+ op[op_name].merge!(update: request['arguments']['update']) if request['arguments']['update']
234
+ op[op_name].merge!(upsert: request['arguments']['upsert']) if request['arguments']['upsert']
235
+ op[op_name].merge!(replacement: request['arguments']['replacement']) if request['arguments']['replacement']
236
+ op[op_name].merge!(array_filters: request['arguments']['arrayFilters']) if request['arguments']['arrayFilters']
237
+ op[op_name] = request['arguments']['document'] if request['arguments']['document']
238
+ op
239
+ end
240
+
219
241
  def upsert
220
242
  arguments['upsert']
221
243
  end
222
244
 
223
245
  def return_document
224
- :after if arguments['returnDocument']
246
+ case arguments['returnDocument']
247
+ when 'Before'
248
+ :before
249
+ when 'After'
250
+ :after
251
+ end
225
252
  end
226
253
 
227
254
  def update
@@ -26,3 +26,24 @@ tests:
26
26
  data:
27
27
  - {_id: 2, x: 22}
28
28
  - {_id: 3, x: 33}
29
+ -
30
+ description: "Aggregate with $out and batch size of 0"
31
+ operation:
32
+ name: aggregate
33
+ arguments:
34
+ pipeline:
35
+ - $sort: {x: 1}
36
+ - $match:
37
+ _id: {$gt: 1}
38
+ - $out: "other_test_collection"
39
+ batchSize: 0
40
+
41
+ outcome:
42
+ result:
43
+ - {_id: 2, x: 22}
44
+ - {_id: 3, x: 33}
45
+ collection:
46
+ name: "other_test_collection"
47
+ data:
48
+ - {_id: 2, x: 22}
49
+ - {_id: 3, x: 33}
@@ -0,0 +1,44 @@
1
+ data:
2
+ - {_id: 1, y: [{b: 3}, {b: 1}]}
3
+ - {_id: 2, y: [{b: 0}, {b: 1}]}
4
+
5
+ minServerVersion: '3.5.6'
6
+
7
+ tests:
8
+ -
9
+ description: "BulkWrite with arrayFilters"
10
+ operation:
11
+ name: "bulkWrite"
12
+ arguments:
13
+ requests:
14
+ -
15
+ # UpdateOne when one document matches arrayFilters
16
+ name: "updateOne"
17
+ arguments:
18
+ filter: {}
19
+ update:
20
+ $set: {"y.$[i].b": 2}
21
+ arrayFilters:
22
+ - {i.b: 3}
23
+ -
24
+ # UpdateMany when multiple documents match arrayFilters
25
+ name: "updateMany"
26
+ arguments:
27
+ filter: {}
28
+ update:
29
+ $set: {"y.$[i].b": 2}
30
+ arrayFilters:
31
+ - {i.b: 1}
32
+ options: { ordered: true }
33
+ outcome:
34
+ result:
35
+ deletedCount: 0
36
+ insertedIds: {}
37
+ matchedCount: 3
38
+ modifiedCount: 3
39
+ upsertedCount: 0
40
+ upsertedIds: {}
41
+ collection:
42
+ data:
43
+ - {_id: 1, y: [{b: 2}, {b: 2}]}
44
+ - {_id: 2, y: [{b: 0}, {b: 2}]}