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
@@ -241,15 +241,15 @@ describe Mongo::Cluster do
241
241
  cluster.instance_variable_get(:@servers)
242
242
  end
243
243
 
244
- let(:cursor_reaper) do
245
- cluster.instance_variable_get(:@cursor_reaper)
244
+ let(:periodic_executor) do
245
+ cluster.instance_variable_get(:@periodic_executor)
246
246
  end
247
247
 
248
248
  before do
249
249
  known_servers.each do |server|
250
250
  expect(server).to receive(:disconnect!).and_call_original
251
251
  end
252
- expect(cursor_reaper).to receive(:stop!).and_call_original
252
+ expect(periodic_executor).to receive(:stop!).and_call_original
253
253
  end
254
254
 
255
255
  it 'disconnects each server and the cursor reaper and returns true' do
@@ -259,15 +259,15 @@ describe Mongo::Cluster do
259
259
 
260
260
  describe '#reconnect!' do
261
261
 
262
- let(:cursor_reaper) do
263
- cluster.instance_variable_get(:@cursor_reaper)
262
+ let(:periodic_executor) do
263
+ cluster.instance_variable_get(:@periodic_executor)
264
264
  end
265
265
 
266
266
  before do
267
267
  cluster.servers.each do |server|
268
268
  expect(server).to receive(:reconnect!).and_call_original
269
269
  end
270
- expect(cursor_reaper).to receive(:restart!).and_call_original
270
+ expect(periodic_executor).to receive(:restart!).and_call_original
271
271
  end
272
272
 
273
273
  it 'reconnects each server and the cursor reaper and returns true' do
@@ -580,8 +580,12 @@ describe Mongo::Cluster do
580
580
  client.command(ping: 1)
581
581
  end
582
582
 
583
+ let(:operation_with_session) do
584
+ client.command({ ping: 1 }, session: session)
585
+ end
586
+
583
587
  let(:second_operation) do
584
- client.command(ping: 1)
588
+ client.command({ ping: 1 }, session: session)
585
589
  end
586
590
 
587
591
  it_behaves_like 'an operation updating cluster time'
@@ -224,6 +224,40 @@ describe Mongo::Collection::View::Aggregation do
224
224
  expect(aggregation.explain).to_not be_empty
225
225
  end
226
226
 
227
+ context 'session id', if: test_sessions? do
228
+
229
+ let(:options) do
230
+ { session: session }
231
+ end
232
+
233
+ let(:client) do
234
+ authorized_client.with(heartbeat_frequency: 100).tap do |cl|
235
+ cl.subscribe(Mongo::Monitoring::COMMAND, subscriber)
236
+ end
237
+ end
238
+
239
+ let(:session) do
240
+ client.start_session
241
+ end
242
+
243
+ let(:subscriber) do
244
+ EventSubscriber.new
245
+ end
246
+
247
+ let(:view) do
248
+ Mongo::Collection::View.new(client[TEST_COLL], selector, view_options)
249
+ end
250
+
251
+ let(:command) do
252
+ aggregation.explain
253
+ subscriber.started_events.find { |c| c.command_name == 'aggregate'}.command
254
+ end
255
+
256
+ it 'sends the session id' do
257
+ expect(command['lsid']).to eq(session.session_id)
258
+ end
259
+ end
260
+
227
261
  context 'when a collation is specified' do
228
262
 
229
263
  before do
@@ -357,6 +391,17 @@ describe Mongo::Collection::View::Aggregation do
357
391
  end
358
392
  end
359
393
 
394
+ context 'when comment is an option' do
395
+
396
+ let(:options) do
397
+ { :comment => 'testing' }
398
+ end
399
+
400
+ it 'includes the option in the spec' do
401
+ expect(aggregation_spec[:selector][:comment]).to eq(options[:comment])
402
+ end
403
+ end
404
+
360
405
  context 'when batch_size is set' do
361
406
 
362
407
  context 'when batch_size is set on the view' do
@@ -498,7 +543,7 @@ describe Mongo::Collection::View::Aggregation do
498
543
  end
499
544
  end
500
545
 
501
- context 'when $out is in the pipeline', if: write_command_enabled? do
546
+ context 'when $out is in the pipeline' do
502
547
 
503
548
  let(:pipeline) do
504
549
  [{
@@ -475,6 +475,21 @@ describe Mongo::Collection::View::Builder::FindCommand do
475
475
  it 'applies the read concern of the collection' do
476
476
  expect(selector['readConcern']).to eq(BSON::Document.new(level: 'invalid'))
477
477
  end
478
+
479
+ context 'when explain is called for the find' do
480
+
481
+ let(:collection) do
482
+ authorized_collection.with(read_concern: { level: 'invalid' })
483
+ end
484
+
485
+ let(:view) do
486
+ Mongo::Collection::View.new(collection, {})
487
+ end
488
+
489
+ it 'applies the read concern of the collection' do
490
+ expect( builder.explain_specification[:selector][:explain][:readConcern]).to eq(BSON::Document.new(level: 'invalid'))
491
+ end
492
+ end
478
493
  end
479
494
 
480
495
  context 'when the collection does not have a read concern defined' do
@@ -35,7 +35,11 @@ describe Mongo::Collection::View::ChangeStream, if: test_change_streams? do
35
35
  end
36
36
 
37
37
  let(:command_selector) do
38
- change_stream.send(:aggregate_spec, double('session'))[:selector]
38
+ command_spec[:selector]
39
+ end
40
+
41
+ let(:command_spec) do
42
+ change_stream.send(:aggregate_spec, double('session'))
39
43
  end
40
44
 
41
45
  let(:cursor) do
@@ -137,8 +141,7 @@ describe Mongo::Collection::View::ChangeStream, if: test_change_streams? do
137
141
  end
138
142
 
139
143
  it 'sets the collation value to the provided document' do
140
- expect(error).to be_a(Mongo::Error::OperationFailure)
141
- expect(error.message).to include('Only default collation is allowed')
144
+ expect(command_selector['collation']).to eq(BSON::Document.new(options['collation']))
142
145
  end
143
146
  end
144
147
 
@@ -181,7 +184,7 @@ describe Mongo::Collection::View::ChangeStream, if: test_change_streams? do
181
184
  context 'when the other pipeline operators are supported' do
182
185
 
183
186
  let(:pipeline) do
184
- [ { '$project' => { '_id' => 0 }}]
187
+ [{ '$project' => { '_id' => 0 }}]
185
188
  end
186
189
 
187
190
  it 'uses the pipeline operators' do
@@ -192,21 +195,23 @@ describe Mongo::Collection::View::ChangeStream, if: test_change_streams? do
192
195
  context 'when the other pipeline operators are not supported' do
193
196
 
194
197
  let(:pipeline) do
195
- [ { '$unwind' => '$test' }]
198
+ [{ '$unwind' => '$test' }]
196
199
  end
197
200
 
198
201
  it 'sends the pipeline to the server without a custom error' do
199
- expect(change_stream).to be_a(Mongo::Collection::View::ChangeStream)
202
+ expect {
203
+ change_stream
204
+ }.to raise_exception(Mongo::Error::OperationFailure)
200
205
  end
201
206
 
202
- context 'when the operation fails', if: sessions_enabled? && test_change_streams? do
207
+ context 'when the operation fails', if: test_change_streams? do
203
208
 
204
209
  let!(:before_last_use) do
205
210
  session.instance_variable_get(:@server_session).last_use
206
211
  end
207
212
 
208
213
  let!(:before_operation_time) do
209
- (session.instance_variable_get(:@operation_time) || 0)
214
+ (session.operation_time || 0)
210
215
  end
211
216
 
212
217
  let(:pipeline) do
@@ -238,7 +243,7 @@ describe Mongo::Collection::View::ChangeStream, if: test_change_streams? do
238
243
  end
239
244
 
240
245
  it 'updates the operation time value' do
241
- expect(session.instance_variable_get(:@operation_time)).not_to eq(before_operation_time)
246
+ expect(session.operation_time).not_to eq(before_operation_time)
242
247
  end
243
248
  end
244
249
  end
@@ -286,7 +291,7 @@ describe Mongo::Collection::View::ChangeStream, if: test_change_streams? do
286
291
  end
287
292
 
288
293
  let!(:before_operation_time) do
289
- (session.instance_variable_get(:@operation_time) || 0)
294
+ (session.operation_time || 0)
290
295
  end
291
296
 
292
297
  let!(:operation_result) do
@@ -298,7 +303,7 @@ describe Mongo::Collection::View::ChangeStream, if: test_change_streams? do
298
303
  end
299
304
 
300
305
  it 'updates the operation time value' do
301
- expect(session.instance_variable_get(:@operation_time)).not_to eq(before_operation_time)
306
+ expect(session.operation_time).not_to eq(before_operation_time)
302
307
  end
303
308
 
304
309
  it 'does not close the session when the operation completes' do
@@ -416,7 +421,7 @@ describe Mongo::Collection::View::ChangeStream, if: test_change_streams? do
416
421
  context 'when the first response does not contain the resume token' do
417
422
 
418
423
  let(:pipeline) do
419
- [ { '$project' => { _id: 0 } }]
424
+ [{ '$project' => { _id: 0 } }]
420
425
  end
421
426
 
422
427
  before do
@@ -811,4 +816,66 @@ describe Mongo::Collection::View::ChangeStream, if: test_change_streams? do
811
816
  end
812
817
  end
813
818
  end
819
+
820
+ describe '#inspect' do
821
+
822
+ it 'includes the Ruby object_id in the formatted string' do
823
+ expect(change_stream.inspect).to include(change_stream.object_id.to_s)
824
+ end
825
+
826
+ context 'when resume_after is provided' do
827
+
828
+ let(:options) do
829
+ { resume_after: sample_resume_token }
830
+ end
831
+
832
+ it 'includes resume_after value in the formatted string' do
833
+ expect(change_stream.inspect).to include(sample_resume_token.to_s)
834
+ end
835
+ end
836
+
837
+ context 'when max_await_time_ms is provided' do
838
+
839
+ let(:options) do
840
+ { max_await_time_ms: 10 }
841
+ end
842
+
843
+ it 'includes the max_await_time value in the formatted string' do
844
+ expect(change_stream.inspect).to include({ max_await_time_ms: 10 }.to_s)
845
+ end
846
+ end
847
+
848
+ context 'when batch_size is provided' do
849
+
850
+ let(:options) do
851
+ { batch_size: 5 }
852
+ end
853
+
854
+ it 'includes the batch_size value in the formatted string' do
855
+ expect(change_stream.inspect).to include({ batch_size: 5 }.to_s)
856
+ end
857
+ end
858
+
859
+ context 'when collation is provided' do
860
+
861
+ let(:options) do
862
+ { 'collation' => { locale: 'en_US', strength: 2 } }
863
+ end
864
+
865
+ it 'includes the collation value in the formatted string' do
866
+ expect(change_stream.inspect).to include({ 'collation' => { locale: 'en_US', strength: 2 } }.to_s)
867
+ end
868
+ end
869
+
870
+ context 'when pipeline operators are provided' do
871
+
872
+ let(:pipeline) do
873
+ [{ '$project' => { '_id' => 0 }}]
874
+ end
875
+
876
+ it 'includes the filters in the formatted string' do
877
+ expect(change_stream.inspect).to include([{ '$project' => { '_id' => 0 }}].to_s)
878
+ end
879
+ end
880
+ end
814
881
  end
@@ -59,6 +59,44 @@ describe Mongo::Collection::View::MapReduce do
59
59
  described_class.new(view, map, reduce, options)
60
60
  end
61
61
 
62
+ describe '#map_function' do
63
+
64
+ it 'returns the map function' do
65
+ expect(map_reduce.map_function).to eq(map)
66
+ end
67
+ end
68
+
69
+ describe '#reduce_function' do
70
+
71
+ it 'returns the map function' do
72
+ expect(map_reduce.reduce_function).to eq(reduce)
73
+ end
74
+ end
75
+
76
+ describe '#map' do
77
+
78
+ let(:results) do
79
+ map_reduce.map do |document|
80
+ document
81
+ end
82
+ end
83
+
84
+ it 'calls the Enumerable method' do
85
+ expect(results).to eq(map_reduce.to_a)
86
+ end
87
+ end
88
+
89
+ describe '#reduce' do
90
+
91
+ let(:results) do
92
+ map_reduce.reduce(0) { |sum, doc| sum + doc['value']['population'] }
93
+ end
94
+
95
+ it 'calls the Enumerable method' do
96
+ expect(results).to eq(12000000)
97
+ end
98
+ end
99
+
62
100
  describe '#each' do
63
101
 
64
102
  context 'when no options are provided' do
@@ -72,7 +110,7 @@ describe Mongo::Collection::View::MapReduce do
72
110
 
73
111
  context 'when provided a session' do
74
112
 
75
- let(:view_options) do
113
+ let(:options) do
76
114
  { session: session }
77
115
  end
78
116
 
@@ -139,6 +177,21 @@ describe Mongo::Collection::View::MapReduce do
139
177
  authorized_client['output_collection'].delete_many
140
178
  end
141
179
 
180
+ context 'when #each is called without a block' do
181
+
182
+ let(:new_map_reduce) do
183
+ map_reduce.out(replace: 'output_collection')
184
+ end
185
+
186
+ before do
187
+ new_map_reduce.each
188
+ end
189
+
190
+ it 'executes the map reduce' do
191
+ expect(map_reduce.to_a).to eq(new_map_reduce.to_a)
192
+ end
193
+ end
194
+
142
195
  context 'when the option is to replace' do
143
196
 
144
197
  let(:new_map_reduce) do
@@ -157,7 +210,7 @@ describe Mongo::Collection::View::MapReduce do
157
210
 
158
211
  context 'when provided a session' do
159
212
 
160
- let(:view_options) do
213
+ let(:options) do
161
214
  { session: session }
162
215
  end
163
216
 
@@ -174,7 +227,7 @@ describe Mongo::Collection::View::MapReduce do
174
227
 
175
228
  context 'when the output collection is iterated' do
176
229
 
177
- let(:view_options) do
230
+ let(:options) do
178
231
  { session: session }
179
232
  end
180
233
 
@@ -205,7 +258,7 @@ describe Mongo::Collection::View::MapReduce do
205
258
  begin; client.use('another-db')[TEST_COLL].create; rescue; end
206
259
  end
207
260
 
208
- it 'uses the session when iterating over the output collection', if: sessions_enabled? do
261
+ it 'uses the session when iterating over the output collection', if: test_sessions? do
209
262
  new_map_reduce.to_a
210
263
  expect(find_command["lsid"]).to eq(BSON::Document.new(session.session_id))
211
264
  end
@@ -360,6 +413,69 @@ describe Mongo::Collection::View::MapReduce do
360
413
  end
361
414
  end
362
415
 
416
+ describe '#execute' do
417
+
418
+ context 'when output is to a collection' do
419
+
420
+ let(:options) do
421
+ { out: 'output_collection' }
422
+ end
423
+
424
+ let!(:result) do
425
+ map_reduce.execute
426
+ end
427
+
428
+ it 'executes the map reduce' do
429
+ expect(authorized_client['output_collection'].count).to eq(2)
430
+ end
431
+
432
+ it 'returns a result object' do
433
+ expect(result).to be_a(Mongo::Operation::Result)
434
+ end
435
+ end
436
+
437
+ context 'when there is no output' do
438
+
439
+ let(:result) do
440
+ map_reduce.execute
441
+ end
442
+
443
+ it 'executes the map reduce' do
444
+ expect(result.documents.size).to eq(2)
445
+ end
446
+
447
+ it 'returns a result object' do
448
+ expect(result).to be_a(Mongo::Operation::Result)
449
+ end
450
+ end
451
+
452
+ context 'when a session is provided' do
453
+
454
+ let(:session) do
455
+ authorized_client.start_session
456
+ end
457
+
458
+ let(:options) do
459
+ { session: session }
460
+ end
461
+
462
+ let(:operation) do
463
+ map_reduce.execute
464
+ end
465
+
466
+ let(:failed_operation) do
467
+ described_class.new(view, '$invalid', reduce, options).execute
468
+ end
469
+
470
+ let(:client) do
471
+ authorized_client
472
+ end
473
+
474
+ it_behaves_like 'an operation using a session'
475
+ it_behaves_like 'a failed operation using a session'
476
+ end
477
+ end
478
+
363
479
  describe '#finalize' do
364
480
 
365
481
  let(:finalize) do