mongo 2.3.1 → 2.4.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 (170) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data.tar.gz.sig +2 -3
  4. data/lib/mongo/bulk_write.rb +8 -7
  5. data/lib/mongo/bulk_write/combineable.rb +4 -0
  6. data/lib/mongo/bulk_write/transformable.rb +17 -5
  7. data/lib/mongo/bulk_write/validatable.rb +1 -0
  8. data/lib/mongo/client.rb +3 -0
  9. data/lib/mongo/cluster.rb +8 -0
  10. data/lib/mongo/cluster/app_metadata.rb +135 -0
  11. data/lib/mongo/collection.rb +42 -10
  12. data/lib/mongo/collection/view.rb +15 -1
  13. data/lib/mongo/collection/view/aggregation.rb +5 -0
  14. data/lib/mongo/collection/view/builder/aggregation.rb +13 -3
  15. data/lib/mongo/collection/view/builder/find_command.rb +7 -21
  16. data/lib/mongo/collection/view/builder/map_reduce.rb +22 -5
  17. data/lib/mongo/collection/view/iterable.rb +1 -0
  18. data/lib/mongo/collection/view/map_reduce.rb +5 -0
  19. data/lib/mongo/collection/view/readable.rb +35 -14
  20. data/lib/mongo/collection/view/writable.rb +54 -23
  21. data/lib/mongo/cursor/builder/get_more_command.rb +2 -3
  22. data/lib/mongo/database.rb +10 -2
  23. data/lib/mongo/error.rb +2 -0
  24. data/lib/mongo/error/invalid_application_name.rb +38 -0
  25. data/lib/mongo/error/invalid_server_preference.rb +24 -3
  26. data/lib/mongo/error/unsupported_collation.rb +51 -0
  27. data/lib/mongo/index/view.rb +28 -15
  28. data/lib/mongo/operation.rb +6 -0
  29. data/lib/mongo/operation/commands.rb +3 -0
  30. data/lib/mongo/operation/commands/aggregate.rb +10 -10
  31. data/lib/mongo/operation/commands/create.rb +45 -0
  32. data/lib/mongo/operation/commands/drop.rb +45 -0
  33. data/lib/mongo/operation/commands/drop_database.rb +45 -0
  34. data/lib/mongo/operation/commands/map_reduce.rb +12 -1
  35. data/lib/mongo/operation/commands/parallel_scan.rb +1 -0
  36. data/lib/mongo/operation/read_preference.rb +9 -9
  37. data/lib/mongo/operation/specifiable.rb +34 -0
  38. data/lib/mongo/operation/takes_write_concern.rb +35 -0
  39. data/lib/mongo/operation/write/bulk/bulkable.rb +1 -1
  40. data/lib/mongo/operation/write/command/create_index.rb +6 -0
  41. data/lib/mongo/operation/write/command/drop_index.rb +6 -0
  42. data/lib/mongo/operation/write/command/insert.rb +1 -1
  43. data/lib/mongo/operation/write/command/update.rb +1 -0
  44. data/lib/mongo/operation/write/command/writable.rb +2 -2
  45. data/lib/mongo/operation/write/create_index.rb +2 -2
  46. data/lib/mongo/operation/write/create_user.rb +1 -1
  47. data/lib/mongo/operation/write/delete.rb +5 -1
  48. data/lib/mongo/operation/write/gle.rb +1 -1
  49. data/lib/mongo/operation/write/insert.rb +2 -2
  50. data/lib/mongo/operation/write/remove_user.rb +1 -1
  51. data/lib/mongo/operation/write/update.rb +5 -1
  52. data/lib/mongo/operation/write/update_user.rb +1 -1
  53. data/lib/mongo/operation/write/write_command_enabled.rb +10 -2
  54. data/lib/mongo/protocol/insert.rb +1 -2
  55. data/lib/mongo/protocol/query.rb +3 -7
  56. data/lib/mongo/server.rb +8 -3
  57. data/lib/mongo/server/connection.rb +17 -11
  58. data/lib/mongo/server/description.rb +22 -0
  59. data/lib/mongo/server/description/features.rb +2 -0
  60. data/lib/mongo/server/monitor.rb +5 -0
  61. data/lib/mongo/server/monitor/connection.rb +11 -0
  62. data/lib/mongo/server_selector/nearest.rb +9 -6
  63. data/lib/mongo/server_selector/primary.rb +4 -0
  64. data/lib/mongo/server_selector/primary_preferred.rb +7 -1
  65. data/lib/mongo/server_selector/secondary.rb +5 -0
  66. data/lib/mongo/server_selector/secondary_preferred.rb +7 -2
  67. data/lib/mongo/server_selector/selectable.rb +57 -10
  68. data/lib/mongo/socket/ssl.rb +1 -0
  69. data/lib/mongo/uri.rb +4 -0
  70. data/lib/mongo/version.rb +1 -1
  71. data/lib/mongo/write_concern.rb +1 -0
  72. data/mongo.gemspec +1 -1
  73. data/spec/mongo/auth/cr_spec.rb +7 -1
  74. data/spec/mongo/auth/ldap_spec.rb +7 -1
  75. data/spec/mongo/auth/scram_spec.rb +7 -1
  76. data/spec/mongo/auth/x509_spec.rb +7 -1
  77. data/spec/mongo/bulk_write_spec.rb +598 -5
  78. data/spec/mongo/client_spec.rb +47 -1
  79. data/spec/mongo/cluster/app_metadata_spec.rb +104 -0
  80. data/spec/mongo/cluster/topology/replica_set_spec.rb +14 -8
  81. data/spec/mongo/cluster/topology/sharded_spec.rb +9 -3
  82. data/spec/mongo/cluster/topology/single_spec.rb +10 -4
  83. data/spec/mongo/cluster_spec.rb +29 -0
  84. data/spec/mongo/collection/view/aggregation_spec.rb +139 -0
  85. data/spec/mongo/collection/view/builder/find_command_spec.rb +6 -243
  86. data/spec/mongo/collection/view/map_reduce_spec.rb +104 -0
  87. data/spec/mongo/collection/view/readable_spec.rb +83 -0
  88. data/spec/mongo/collection/view/writable_spec.rb +447 -1
  89. data/spec/mongo/collection/view_spec.rb +57 -0
  90. data/spec/mongo/collection_spec.rb +926 -101
  91. data/spec/mongo/crud_spec.rb +4 -5
  92. data/spec/mongo/database_spec.rb +99 -1
  93. data/spec/mongo/index/view_spec.rb +360 -31
  94. data/spec/mongo/max_staleness_spec.rb +108 -0
  95. data/spec/mongo/operation/read_preference_spec.rb +8 -8
  96. data/spec/mongo/operation/write/command/delete_spec.rb +1 -1
  97. data/spec/mongo/operation/write/command/insert_spec.rb +1 -1
  98. data/spec/mongo/operation/write/command/update_spec.rb +1 -1
  99. data/spec/mongo/server/connection_pool_spec.rb +3 -1
  100. data/spec/mongo/server/connection_spec.rb +17 -7
  101. data/spec/mongo/server/description/features_spec.rb +50 -0
  102. data/spec/mongo/server/description_spec.rb +9 -3
  103. data/spec/mongo/server_selection_spec.rb +5 -3
  104. data/spec/mongo/server_selector/nearest_spec.rb +73 -0
  105. data/spec/mongo/server_selector/primary_preferred_spec.rb +73 -0
  106. data/spec/mongo/server_selector/primary_spec.rb +36 -0
  107. data/spec/mongo/server_selector/secondary_preferred_spec.rb +73 -0
  108. data/spec/mongo/server_selector/secondary_spec.rb +73 -0
  109. data/spec/mongo/server_selector_spec.rb +53 -0
  110. data/spec/mongo/server_spec.rb +3 -1
  111. data/spec/mongo/uri_spec.rb +54 -0
  112. data/spec/mongo/write_concern_spec.rb +18 -0
  113. data/spec/spec_helper.rb +10 -0
  114. data/spec/support/authorization.rb +8 -1
  115. data/spec/support/crud.rb +15 -0
  116. data/spec/support/crud/read.rb +27 -19
  117. data/spec/support/crud/write.rb +28 -3
  118. data/spec/support/crud_tests/read/aggregate.yml +15 -3
  119. data/spec/support/crud_tests/read/count.yml +14 -3
  120. data/spec/support/crud_tests/read/distinct.yml +13 -1
  121. data/spec/support/crud_tests/read/find.yml +12 -2
  122. data/spec/support/crud_tests/write/deleteMany.yml +22 -1
  123. data/spec/support/crud_tests/write/deleteOne.yml +20 -1
  124. data/spec/support/crud_tests/write/findOneAndDelete.yml +27 -2
  125. data/spec/support/crud_tests/write/findOneAndReplace.yml +43 -14
  126. data/spec/support/crud_tests/write/findOneAndUpdate.yml +50 -8
  127. data/spec/support/crud_tests/write/replaceOne.yml +34 -10
  128. data/spec/support/crud_tests/write/updateMany.yml +42 -11
  129. data/spec/support/crud_tests/write/updateOne.yml +32 -7
  130. data/spec/support/max_staleness/ReplicaSetNoPrimary/DefaultNoMaxStaleness.yml +26 -0
  131. data/spec/support/max_staleness/ReplicaSetNoPrimary/Incompatible.yml +25 -0
  132. data/spec/support/max_staleness/ReplicaSetNoPrimary/LastUpdateTime.yml +33 -0
  133. data/spec/support/max_staleness/ReplicaSetNoPrimary/Nearest.yml +33 -0
  134. data/spec/support/max_staleness/ReplicaSetNoPrimary/Nearest2.yml +33 -0
  135. data/spec/support/max_staleness/ReplicaSetNoPrimary/PrimaryPreferred.yml +27 -0
  136. data/spec/support/max_staleness/ReplicaSetNoPrimary/PrimaryPreferred_tags.yml +36 -0
  137. data/spec/support/max_staleness/ReplicaSetNoPrimary/Secondary.yml +51 -0
  138. data/spec/support/max_staleness/ReplicaSetNoPrimary/SecondaryPreferred.yml +26 -0
  139. data/spec/support/max_staleness/ReplicaSetNoPrimary/SecondaryPreferred_tags.yml +51 -0
  140. data/spec/support/max_staleness/ReplicaSetWithPrimary/DefaultNoMaxStaleness.yml +26 -0
  141. data/spec/support/max_staleness/ReplicaSetWithPrimary/Incompatible.yml +25 -0
  142. data/spec/support/max_staleness/ReplicaSetWithPrimary/LastUpdateTime.yml +35 -0
  143. data/spec/support/max_staleness/ReplicaSetWithPrimary/MaxStalenessTooSmall.yml +25 -0
  144. data/spec/support/max_staleness/ReplicaSetWithPrimary/MaxStalenessWithModePrimary.yml +23 -0
  145. data/spec/support/max_staleness/ReplicaSetWithPrimary/Nearest.yml +33 -0
  146. data/spec/support/max_staleness/ReplicaSetWithPrimary/Nearest2.yml +33 -0
  147. data/spec/support/max_staleness/ReplicaSetWithPrimary/Nearest_tags.yml +36 -0
  148. data/spec/support/max_staleness/ReplicaSetWithPrimary/PrimaryPreferred.yml +27 -0
  149. data/spec/support/max_staleness/ReplicaSetWithPrimary/PrimaryPreferred_incompatible.yml +27 -0
  150. data/spec/support/max_staleness/ReplicaSetWithPrimary/SecondaryPreferred.yml +26 -0
  151. data/spec/support/max_staleness/ReplicaSetWithPrimary/SecondaryPreferred_tags.yml +59 -0
  152. data/spec/support/max_staleness/ReplicaSetWithPrimary/SecondaryPreferred_tags2.yml +43 -0
  153. data/spec/support/max_staleness/ReplicaSetWithPrimary/Secondary_tags.yml +59 -0
  154. data/spec/support/max_staleness/ReplicaSetWithPrimary/Secondary_tags2.yml +43 -0
  155. data/spec/support/max_staleness/ReplicaSetWithPrimary/ShortHeartbeartShortMaxStaleness.yml +29 -0
  156. data/spec/support/max_staleness/ReplicaSetWithPrimary/ShortHeartbeartShortMaxStaleness2.yml +29 -0
  157. data/spec/support/max_staleness/ReplicaSetWithPrimary/ZeroMaxStaleness.yml +27 -0
  158. data/spec/support/max_staleness/Sharded/Incompatible.yml +25 -0
  159. data/spec/support/max_staleness/Sharded/SmallMaxStaleness.yml +20 -0
  160. data/spec/support/max_staleness/Single/Incompatible.yml +18 -0
  161. data/spec/support/max_staleness/Single/SmallMaxStaleness.yml +20 -0
  162. data/spec/support/server_selection.rb +25 -0
  163. data/spec/support/server_selection/selection/ReplicaSetNoPrimary/read/Nearest_multiple.yml +27 -0
  164. data/spec/support/server_selection/selection/ReplicaSetNoPrimary/read/Secondary_multi_tags.yml +31 -0
  165. data/spec/support/server_selection/selection/ReplicaSetNoPrimary/read/Secondary_multi_tags2.yml +31 -0
  166. data/spec/support/server_selection/selection/ReplicaSetWithPrimary/read/Nearest_multiple.yml +34 -0
  167. data/spec/support/server_selection/selection/ReplicaSetWithPrimary/read/SecondaryPreferred_tags.yml +28 -0
  168. data/spec/support/shared/server_selector.rb +4 -3
  169. metadata +91 -6
  170. metadata.gz.sig +0 -0
@@ -152,6 +152,63 @@ describe Mongo::Collection::View do
152
152
  view.close_query
153
153
  end
154
154
  end
155
+
156
+ describe 'collation' do
157
+
158
+ context 'when the view has a collation set' do
159
+
160
+ let(:options) do
161
+ { collation: { locale: 'en_US', strength: 2 } }
162
+ end
163
+
164
+ let(:filter) do
165
+ { name: 'BANG' }
166
+ end
167
+
168
+ before do
169
+ authorized_collection.insert_one(name: 'bang')
170
+ end
171
+
172
+ let(:result) do
173
+ view.limit(-1).first
174
+ end
175
+
176
+ context 'when the server selected supports collations', if: collation_enabled? do
177
+
178
+ it 'applies the collation' do
179
+ expect(result['name']).to eq('bang')
180
+ end
181
+ end
182
+
183
+ context 'when the server selected does not support collations', unless: collation_enabled? do
184
+
185
+ it 'raises an exception' do
186
+ expect {
187
+ result
188
+ }.to raise_exception(Mongo::Error::UnsupportedCollation)
189
+ end
190
+ end
191
+ end
192
+
193
+ context 'when the view does not have a collation set' do
194
+
195
+ let(:filter) do
196
+ { name: 'BANG' }
197
+ end
198
+
199
+ before do
200
+ authorized_collection.insert_one(name: 'bang')
201
+ end
202
+
203
+ let(:result) do
204
+ view.limit(-1).first
205
+ end
206
+
207
+ it 'does not apply the collation' do
208
+ expect(result).to be_nil
209
+ end
210
+ end
211
+ end
155
212
  end
156
213
 
157
214
  describe '#hash' do
@@ -4,17 +4,14 @@ describe Mongo::Collection do
4
4
 
5
5
  after do
6
6
  authorized_collection.delete_many
7
- collection_with_validator.drop()
8
7
  end
9
8
 
10
9
  let(:collection_invalid_write_concern) do
11
10
  authorized_collection.client.with(write: { w: (WRITE_CONCERN[:w] + 1) })[authorized_collection.name]
12
11
  end
12
+
13
13
  let(:collection_with_validator) do
14
- authorized_client[:validating,
15
- :validator => { :a => { '$exists' => true } }].tap do |c|
16
- c.create
17
- end
14
+ authorized_client[:validating]
18
15
  end
19
16
 
20
17
  describe '#==' do
@@ -416,6 +413,107 @@ describe Mongo::Collection do
416
413
  end
417
414
  end
418
415
  end
416
+
417
+ context 'when the collection has a write concern' do
418
+
419
+ after do
420
+ database[:specs].drop
421
+ end
422
+
423
+ let(:options) do
424
+ {
425
+ write: { w: WRITE_CONCERN[:w] + 1}
426
+ }
427
+ end
428
+
429
+ let(:collection) do
430
+ described_class.new(database, :specs, options)
431
+ end
432
+
433
+ context 'when the server supports write concern on the create command', if: replica_set? && collation_enabled? do
434
+
435
+ it 'applies the write concern' do
436
+ expect{
437
+ collection.create
438
+ }.to raise_exception(Mongo::Error::OperationFailure)
439
+ end
440
+ end
441
+
442
+ context 'when the server does not support write concern on the create command', unless: collation_enabled? do
443
+
444
+ it 'does not apply the write concern' do
445
+ expect(collection.create).to be_successful
446
+ end
447
+ end
448
+ end
449
+
450
+ context 'when the collection has a collation' do
451
+
452
+ shared_examples 'a collection command with a collation option' do
453
+
454
+ let!(:response) do
455
+ collection.create
456
+ end
457
+
458
+ let(:options) do
459
+ { :collation => { locale: 'fr' } }
460
+ end
461
+
462
+ let(:collection_info) do
463
+ database.list_collections.find { |i| i['name'] == 'specs' }
464
+ end
465
+
466
+ after do
467
+ collection.drop
468
+ end
469
+
470
+ context 'when the server supports collations', if: collation_enabled? do
471
+
472
+ it 'executes the command' do
473
+ expect(response).to be_successful
474
+ end
475
+
476
+ it 'sets the collection with a collation' do
477
+ expect(collection_info['options']['collation']['locale']).to eq('fr')
478
+ end
479
+
480
+ it 'creates the collection in the database' do
481
+ expect(database.collection_names).to include('specs')
482
+ end
483
+ end
484
+
485
+ context 'when the server does not support collations', unless: collation_enabled? do
486
+
487
+ it 'raises an error' do
488
+ expect {
489
+ response
490
+ }.to raise_exception(Mongo::Error::UnsupportedCollation)
491
+ end
492
+ end
493
+ end
494
+
495
+ context 'when instantiating a collection directly' do
496
+
497
+ let(:collection) do
498
+ described_class.new(database, :specs, options)
499
+ end
500
+
501
+ context 'when the server supports collation', if: collation_enabled? do
502
+ it_behaves_like 'a collection command with a collation option'
503
+ end
504
+ end
505
+
506
+ context 'when instantiating a collection through the database' do
507
+
508
+ let(:collection) do
509
+ authorized_client[:specs, options]
510
+ end
511
+
512
+ context 'when the server supports collation', if: collation_enabled? do
513
+ it_behaves_like 'a collection command with a collation option'
514
+ end
515
+ end
516
+ end
419
517
  end
420
518
  end
421
519
 
@@ -433,22 +531,58 @@ describe Mongo::Collection do
433
531
  collection.create
434
532
  end
435
533
 
436
- let!(:response) do
437
- collection.drop
438
- end
534
+ context 'when the collection does not have a write concern set' do
439
535
 
440
- it 'executes the command' do
441
- expect(response).to be_successful
442
- end
536
+ let!(:response) do
537
+ collection.drop
538
+ end
539
+
540
+ it 'executes the command' do
541
+ expect(response).to be_successful
542
+ end
543
+
544
+ it 'drops the collection from the database' do
545
+ expect(database.collection_names).to_not include('specs')
546
+ end
443
547
 
444
- it 'drops the collection from the database' do
445
- expect(database.collection_names).to_not include('specs')
548
+ context 'when the collection does not exist' do
549
+
550
+ it 'does not raise an error' do
551
+ expect(database['non-existent-coll'].drop).to be(false)
552
+ end
553
+ end
446
554
  end
447
555
 
448
- context 'when the collection does not exist' do
556
+ context 'when the collection has a write concern' do
557
+
558
+ let(:write_options) do
559
+ {
560
+ write: { w: WRITE_CONCERN[:w] + 1}
561
+ }
562
+ end
563
+
564
+ let(:collection_with_write_options) do
565
+ collection.with(write_options)
566
+ end
567
+
568
+ after do
569
+ collection.drop
570
+ end
571
+
572
+ context 'when the server supports write concern on the drop command', if: collation_enabled? do
573
+
574
+ it 'applies the write concern' do
575
+ expect{
576
+ collection_with_write_options.drop
577
+ }.to raise_exception(Mongo::Error::OperationFailure)
578
+ end
579
+ end
580
+
581
+ context 'when the server does not support write concern on the drop command', unless: collation_enabled? do
449
582
 
450
- it 'does not raise an error' do
451
- expect(database['non-existent-coll'].drop).to be(false)
583
+ it 'does not apply the write concern' do
584
+ expect(collection_with_write_options.drop).to be_successful
585
+ end
452
586
  end
453
587
  end
454
588
  end
@@ -496,10 +630,6 @@ describe Mongo::Collection do
496
630
  authorized_collection.insert_many([{ field: 'test1' }, { field: 'test2' }])
497
631
  end
498
632
 
499
- after do
500
- authorized_collection.delete_many
501
- end
502
-
503
633
  let(:view) do
504
634
  authorized_collection.find
505
635
  end
@@ -542,10 +672,6 @@ describe Mongo::Collection do
542
672
  authorized_collection.insert_one({ field => value })
543
673
  end
544
674
 
545
- after do
546
- authorized_collection.delete_many
547
- end
548
-
549
675
  it 'iterates over the documents' do
550
676
  view.each do |document|
551
677
  expect(document[field]).to eq(value)
@@ -605,8 +731,6 @@ describe Mongo::Collection do
605
731
  end
606
732
  end
607
733
 
608
- #limit
609
-
610
734
  context 'when provided :max_time_ms' do
611
735
 
612
736
  let(:options) do
@@ -687,16 +811,22 @@ describe Mongo::Collection do
687
811
  expect(view.modifiers[:$orderby]).to eq(options[:sort])
688
812
  end
689
813
  end
814
+
815
+ context 'when provided :collation' do
816
+
817
+ let(:options) do
818
+ { collation: { 'locale' => 'en_US' } }
819
+ end
820
+
821
+ it 'returns a view with :collation set' do
822
+ expect(view.options[:collation]).to eq(options[:collation])
823
+ end
824
+ end
690
825
  end
691
826
  end
692
827
 
693
828
  describe '#insert_many' do
694
829
 
695
- after do
696
- authorized_collection.delete_many
697
- collection_with_validator.delete_many
698
- end
699
-
700
830
  let(:result) do
701
831
  authorized_collection.insert_many([{ name: 'test1' }, { name: 'test2' }])
702
832
  end
@@ -781,6 +911,15 @@ describe Mongo::Collection do
781
911
 
782
912
  context 'when collection has a validator', if: find_command_enabled? do
783
913
 
914
+ around(:each) do |spec|
915
+ authorized_client[:validating,
916
+ :validator => { :a => { '$exists' => true } }].tap do |c|
917
+ c.create
918
+ end
919
+ spec.run
920
+ collection_with_validator.drop
921
+ end
922
+
784
923
  context 'when the document is valid' do
785
924
 
786
925
  let(:result) do
@@ -824,11 +963,6 @@ describe Mongo::Collection do
824
963
 
825
964
  describe '#insert_one' do
826
965
 
827
- after do
828
- authorized_collection.delete_many
829
- collection_with_validator.delete_many
830
- end
831
-
832
966
  let(:result) do
833
967
  authorized_collection.insert_one({ name: 'testing' })
834
968
  end
@@ -905,6 +1039,15 @@ describe Mongo::Collection do
905
1039
 
906
1040
  context 'when collection has a validator', if: find_command_enabled? do
907
1041
 
1042
+ around(:each) do |spec|
1043
+ authorized_client[:validating,
1044
+ :validator => { :a => { '$exists' => true } }].tap do |c|
1045
+ c.create
1046
+ end
1047
+ spec.run
1048
+ collection_with_validator.drop
1049
+ end
1050
+
908
1051
  context 'when the document is valid' do
909
1052
 
910
1053
  let(:result) do
@@ -1006,6 +1149,41 @@ describe Mongo::Collection do
1006
1149
  it 'sets the options on the Aggregation object' do
1007
1150
  expect(authorized_collection.aggregate([], options).options).to eq(options)
1008
1151
  end
1152
+
1153
+ context 'when collation is provided' do
1154
+
1155
+ before do
1156
+ authorized_collection.insert_many([ { name: 'bang' }, { name: 'bang' }])
1157
+ end
1158
+
1159
+ let(:pipeline) do
1160
+ [{ "$match" => { "name" => "BANG" } }]
1161
+ end
1162
+
1163
+ let(:options) do
1164
+ { collation: { locale: 'en_US', strength: 2 } }
1165
+ end
1166
+
1167
+ let(:result) do
1168
+ authorized_collection.aggregate(pipeline, options).collect { |doc| doc['name']}
1169
+ end
1170
+
1171
+ context 'when the server selected supports collations', if: collation_enabled? do
1172
+
1173
+ it 'applies the collation' do
1174
+ expect(result).to eq(['bang', 'bang'])
1175
+ end
1176
+ end
1177
+
1178
+ context 'when the server selected does not support collations', unless: collation_enabled? do
1179
+
1180
+ it 'raises an exception' do
1181
+ expect {
1182
+ result
1183
+ }.to raise_exception(Mongo::Error::UnsupportedCollation)
1184
+ end
1185
+ end
1186
+ end
1009
1187
  end
1010
1188
  end
1011
1189
 
@@ -1019,10 +1197,6 @@ describe Mongo::Collection do
1019
1197
  authorized_collection.insert_many(documents)
1020
1198
  end
1021
1199
 
1022
- after do
1023
- authorized_collection.delete_many
1024
- end
1025
-
1026
1200
  it 'returns an integer count' do
1027
1201
  expect(authorized_collection.count).to eq(10)
1028
1202
  end
@@ -1032,6 +1206,41 @@ describe Mongo::Collection do
1032
1206
  it 'passes the options to the count' do
1033
1207
  expect(authorized_collection.count({}, limit: 5)).to eq(5)
1034
1208
  end
1209
+
1210
+ context 'when a collation is specified' do
1211
+
1212
+ let(:selector) do
1213
+ { name: 'BANG' }
1214
+ end
1215
+
1216
+ let(:result) do
1217
+ authorized_collection.count(selector, options)
1218
+ end
1219
+
1220
+ before do
1221
+ authorized_collection.insert_one(name: 'bang')
1222
+ end
1223
+
1224
+ let(:options) do
1225
+ { collation: { locale: 'en_US', strength: 2 } }
1226
+ end
1227
+
1228
+ context 'when the server selected supports collations', if: collation_enabled? do
1229
+
1230
+ it 'applies the collation to the count' do
1231
+ expect(result).to eq(1)
1232
+ end
1233
+ end
1234
+
1235
+ context 'when the server selected does not support collations', unless: collation_enabled? do
1236
+
1237
+ it 'raises an exception' do
1238
+ expect {
1239
+ result
1240
+ }.to raise_exception(Mongo::Error::UnsupportedCollation)
1241
+ end
1242
+ end
1243
+ end
1035
1244
  end
1036
1245
  end
1037
1246
 
@@ -1045,10 +1254,6 @@ describe Mongo::Collection do
1045
1254
  authorized_collection.insert_many(documents)
1046
1255
  end
1047
1256
 
1048
- after do
1049
- authorized_collection.delete_many
1050
- end
1051
-
1052
1257
  it 'returns the distinct values' do
1053
1258
  expect(authorized_collection.distinct(:field).sort).to eq([ 'test1', 'test2', 'test3' ])
1054
1259
  end
@@ -1066,6 +1271,54 @@ describe Mongo::Collection do
1066
1271
  expect(authorized_collection.distinct(:field, {}, max_time_ms: 100).sort).to eq([ 'test1', 'test2', 'test3' ])
1067
1272
  end
1068
1273
  end
1274
+
1275
+ context 'when a collation is specified' do
1276
+
1277
+ let(:result) do
1278
+ authorized_collection.distinct(:name, {}, options)
1279
+ end
1280
+
1281
+ before do
1282
+ authorized_collection.insert_one(name: 'bang')
1283
+ authorized_collection.insert_one(name: 'BANG')
1284
+ end
1285
+
1286
+ let(:options) do
1287
+ { collation: { locale: 'en_US', strength: 2 } }
1288
+ end
1289
+
1290
+ context 'when the server selected supports collations', if: collation_enabled? do
1291
+
1292
+ it 'applies the collation to the distinct' do
1293
+ expect(result).to eq(['bang'])
1294
+ end
1295
+ end
1296
+
1297
+ context 'when the server selected does not support collations', unless: collation_enabled? do
1298
+
1299
+ it 'raises an exception' do
1300
+ expect {
1301
+ result
1302
+ }.to raise_exception(Mongo::Error::UnsupportedCollation)
1303
+ end
1304
+ end
1305
+ end
1306
+
1307
+ context 'when a collation is not specified' do
1308
+
1309
+ let(:result) do
1310
+ authorized_collection.distinct(:name)
1311
+ end
1312
+
1313
+ before do
1314
+ authorized_collection.insert_one(name: 'bang')
1315
+ authorized_collection.insert_one(name: 'BANG')
1316
+ end
1317
+
1318
+ it 'does not apply the collation to the distinct' do
1319
+ expect(result).to eq(['bang', 'BANG'])
1320
+ end
1321
+ end
1069
1322
  end
1070
1323
 
1071
1324
  describe '#delete_one' do
@@ -1084,10 +1337,6 @@ describe Mongo::Collection do
1084
1337
  ])
1085
1338
  end
1086
1339
 
1087
- after do
1088
- authorized_collection.delete_many
1089
- end
1090
-
1091
1340
  let(:response) do
1092
1341
  authorized_collection.delete_one(selector)
1093
1342
  end
@@ -1124,48 +1373,192 @@ describe Mongo::Collection do
1124
1373
  }.to raise_exception(Mongo::Error::OperationFailure)
1125
1374
  end
1126
1375
  end
1127
- end
1128
1376
 
1129
- describe '#delete_many' do
1377
+ context 'when a collation is provided' do
1130
1378
 
1131
- before do
1132
- authorized_collection.insert_many([{ field: 'test1' }, { field: 'test2' }])
1133
- end
1379
+ let(:selector) do
1380
+ { name: 'BANG' }
1381
+ end
1134
1382
 
1135
- after do
1136
- authorized_collection.delete_many
1137
- end
1383
+ let(:result) do
1384
+ authorized_collection.delete_one(selector, options)
1385
+ end
1138
1386
 
1139
- context 'when a selector was provided' do
1387
+ before do
1388
+ authorized_collection.insert_one(name: 'bang')
1389
+ end
1140
1390
 
1141
- let(:selector) do
1142
- { field: 'test1' }
1391
+ let(:options) do
1392
+ { collation: { locale: 'en_US', strength: 2 } }
1143
1393
  end
1144
1394
 
1145
- it 'deletes the matching documents in the collection' do
1146
- expect(authorized_collection.delete_many(selector).deleted_count).to eq(1)
1395
+ context 'when the server selected supports collations', if: collation_enabled? do
1396
+
1397
+ it 'applies the collation' do
1398
+ expect(result.written_count).to eq(1)
1399
+ expect(authorized_collection.find(name: 'bang').count).to eq(0)
1400
+ end
1401
+
1402
+ context 'when unacknowledged writes is used' do
1403
+
1404
+ let(:collection_with_unacknowledged_write_concern) do
1405
+ authorized_collection.with(write: { w: 0 })
1406
+ end
1407
+
1408
+ let(:result) do
1409
+ collection_with_unacknowledged_write_concern.delete_one(selector, options)
1410
+ end
1411
+
1412
+ it 'raises an exception' do
1413
+ expect {
1414
+ result
1415
+ }.to raise_exception(Mongo::Error::UnsupportedCollation)
1416
+ end
1417
+ end
1147
1418
  end
1148
- end
1149
1419
 
1150
- context 'when no selector was provided' do
1420
+ context 'when the server selected does not support collations', unless: collation_enabled? do
1151
1421
 
1152
- it 'deletes all the documents in the collection' do
1153
- expect(authorized_collection.delete_many.deleted_count).to eq(2)
1422
+ it 'raises an exception' do
1423
+ expect {
1424
+ result
1425
+ }.to raise_exception(Mongo::Error::UnsupportedCollation)
1426
+ end
1154
1427
  end
1155
1428
  end
1156
1429
 
1157
- context 'when the deletes fail', if: standalone? do
1430
+ context 'when collation is not specified' do
1431
+
1432
+ let(:selector) do
1433
+ { name: 'BANG' }
1434
+ end
1158
1435
 
1159
1436
  let(:result) do
1160
- collection_invalid_write_concern.delete_many
1437
+ authorized_collection.delete_one(selector)
1161
1438
  end
1162
1439
 
1163
- it 'raises an OperationFailure' do
1164
- expect {
1440
+ before do
1441
+ authorized_collection.insert_one(name: 'bang')
1442
+ end
1443
+
1444
+ it 'does not apply the collation' do
1445
+ expect(result.written_count).to eq(0)
1446
+ expect(authorized_collection.find(name: 'bang').count).to eq(1)
1447
+ end
1448
+ end
1449
+ end
1450
+
1451
+ describe '#delete_many' do
1452
+
1453
+ before do
1454
+ authorized_collection.insert_many([{ field: 'test1' }, { field: 'test2' }])
1455
+ end
1456
+
1457
+ context 'when a selector was provided' do
1458
+
1459
+ let(:selector) do
1460
+ { field: 'test1' }
1461
+ end
1462
+
1463
+ it 'deletes the matching documents in the collection' do
1464
+ expect(authorized_collection.delete_many(selector).deleted_count).to eq(1)
1465
+ end
1466
+ end
1467
+
1468
+ context 'when no selector was provided' do
1469
+
1470
+ it 'deletes all the documents in the collection' do
1471
+ expect(authorized_collection.delete_many.deleted_count).to eq(2)
1472
+ end
1473
+ end
1474
+
1475
+ context 'when the deletes fail', if: standalone? do
1476
+
1477
+ let(:result) do
1478
+ collection_invalid_write_concern.delete_many
1479
+ end
1480
+
1481
+ it 'raises an OperationFailure' do
1482
+ expect {
1165
1483
  result
1166
1484
  }.to raise_exception(Mongo::Error::OperationFailure)
1167
1485
  end
1168
1486
  end
1487
+
1488
+ context 'when a collation is specified' do
1489
+
1490
+ let(:selector) do
1491
+ { name: 'BANG' }
1492
+ end
1493
+
1494
+ let(:result) do
1495
+ authorized_collection.delete_many(selector, options)
1496
+ end
1497
+
1498
+ before do
1499
+ authorized_collection.insert_one(name: 'bang')
1500
+ authorized_collection.insert_one(name: 'bang')
1501
+ end
1502
+
1503
+ let(:options) do
1504
+ { collation: { locale: 'en_US', strength: 2 } }
1505
+ end
1506
+
1507
+ context 'when the server selected supports collations', if: collation_enabled? do
1508
+
1509
+ it 'applies the collation' do
1510
+ expect(result.written_count).to eq(2)
1511
+ expect(authorized_collection.find(name: 'bang').count).to eq(0)
1512
+ end
1513
+
1514
+ context 'when unacknowledged writes is used' do
1515
+
1516
+ let(:collection_with_unacknowledged_write_concern) do
1517
+ authorized_collection.with(write: { w: 0 })
1518
+ end
1519
+
1520
+ let(:result) do
1521
+ collection_with_unacknowledged_write_concern.delete_many(selector, options)
1522
+ end
1523
+
1524
+ it 'raises an exception' do
1525
+ expect {
1526
+ result
1527
+ }.to raise_exception(Mongo::Error::UnsupportedCollation)
1528
+ end
1529
+ end
1530
+ end
1531
+
1532
+ context 'when the server selected does not support collations', unless: collation_enabled? do
1533
+
1534
+ it 'raises an exception' do
1535
+ expect {
1536
+ result
1537
+ }.to raise_exception(Mongo::Error::UnsupportedCollation)
1538
+ end
1539
+ end
1540
+ end
1541
+
1542
+ context 'when a collation is not specified' do
1543
+
1544
+ let(:selector) do
1545
+ { name: 'BANG' }
1546
+ end
1547
+
1548
+ let(:result) do
1549
+ authorized_collection.delete_many(selector)
1550
+ end
1551
+
1552
+ before do
1553
+ authorized_collection.insert_one(name: 'bang')
1554
+ authorized_collection.insert_one(name: 'bang')
1555
+ end
1556
+
1557
+ it 'does not apply the collation' do
1558
+ expect(result.written_count).to eq(0)
1559
+ expect(authorized_collection.find(name: 'bang').count).to eq(2)
1560
+ end
1561
+ end
1169
1562
  end
1170
1563
 
1171
1564
  describe '#parallel_scan', unless: sharded? do
@@ -1262,6 +1655,37 @@ describe Mongo::Collection do
1262
1655
  }.to raise_exception(Mongo::Error::NoServerAvailable)
1263
1656
  end
1264
1657
  end
1658
+
1659
+ context 'when a max time ms value is provided', if: (!sharded? && write_command_enabled?) do
1660
+
1661
+ let(:result) do
1662
+ authorized_collection.parallel_scan(2, options)
1663
+ end
1664
+
1665
+ context 'when the read concern is valid' do
1666
+
1667
+ let(:options) do
1668
+ { max_time_ms: 2 }
1669
+ end
1670
+
1671
+ it 'sends the max time ms value' do
1672
+ expect { result }.to_not raise_error
1673
+ end
1674
+ end
1675
+
1676
+ context 'when the max time ms is not valid' do
1677
+
1678
+ let(:options) do
1679
+ { max_time_ms: 0.1 }
1680
+ end
1681
+
1682
+ it 'raises an exception' do
1683
+ expect {
1684
+ result
1685
+ }.to raise_error(Mongo::Error::OperationFailure)
1686
+ end
1687
+ end
1688
+ end
1265
1689
  end
1266
1690
 
1267
1691
  describe '#replace_one' do
@@ -1276,10 +1700,6 @@ describe Mongo::Collection do
1276
1700
  authorized_collection.insert_many([{ field: 'test1' }, { field: 'test1' }])
1277
1701
  end
1278
1702
 
1279
- after do
1280
- authorized_collection.delete_many
1281
- end
1282
-
1283
1703
  let!(:response) do
1284
1704
  authorized_collection.replace_one(selector, { field: 'testing' })
1285
1705
  end
@@ -1326,10 +1746,6 @@ describe Mongo::Collection do
1326
1746
  authorized_collection.find(field: 'test1').first
1327
1747
  end
1328
1748
 
1329
- after do
1330
- authorized_collection.delete_many
1331
- end
1332
-
1333
1749
  it 'reports that a document was written' do
1334
1750
  expect(response.written_count).to eq(1)
1335
1751
  end
@@ -1373,12 +1789,17 @@ describe Mongo::Collection do
1373
1789
 
1374
1790
  context 'when collection has a validator', if: find_command_enabled? do
1375
1791
 
1376
- before do
1377
- collection_with_validator.insert_one({ a: 1 })
1792
+ around(:each) do |spec|
1793
+ authorized_client[:validating,
1794
+ :validator => { :a => { '$exists' => true } }].tap do |c|
1795
+ c.create
1796
+ end
1797
+ spec.run
1798
+ collection_with_validator.drop
1378
1799
  end
1379
1800
 
1380
- after do
1381
- collection_with_validator.delete_many
1801
+ before do
1802
+ collection_with_validator.insert_one({ a: 1 })
1382
1803
  end
1383
1804
 
1384
1805
  context 'when the document is valid' do
@@ -1420,6 +1841,79 @@ describe Mongo::Collection do
1420
1841
  end
1421
1842
  end
1422
1843
  end
1844
+
1845
+ context 'when a collation is specified' do
1846
+
1847
+ let(:selector) do
1848
+ { name: 'BANG' }
1849
+ end
1850
+
1851
+ let(:result) do
1852
+ authorized_collection.replace_one(selector, { name: 'doink' }, options)
1853
+ end
1854
+
1855
+ before do
1856
+ authorized_collection.insert_one(name: 'bang')
1857
+ end
1858
+
1859
+ let(:options) do
1860
+ { collation: { locale: 'en_US', strength: 2 } }
1861
+ end
1862
+
1863
+ context 'when the server selected supports collations', if: collation_enabled? do
1864
+
1865
+ it 'applies the collation' do
1866
+ expect(result.written_count).to eq(1)
1867
+ expect(authorized_collection.find(name: 'doink').count).to eq(1)
1868
+ end
1869
+
1870
+ context 'when unacknowledged writes is used' do
1871
+
1872
+ let(:collection_with_unacknowledged_write_concern) do
1873
+ authorized_collection.with(write: { w: 0 })
1874
+ end
1875
+
1876
+ let(:result) do
1877
+ collection_with_unacknowledged_write_concern.replace_one(selector, { name: 'doink' }, options)
1878
+ end
1879
+
1880
+ it 'raises an exception' do
1881
+ expect {
1882
+ result
1883
+ }.to raise_exception(Mongo::Error::UnsupportedCollation)
1884
+ end
1885
+ end
1886
+ end
1887
+
1888
+ context 'when the server selected does not support collations', unless: collation_enabled? do
1889
+
1890
+ it 'raises an exception' do
1891
+ expect {
1892
+ result
1893
+ }.to raise_exception(Mongo::Error::UnsupportedCollation)
1894
+ end
1895
+ end
1896
+ end
1897
+
1898
+ context 'when a collation is not specified' do
1899
+
1900
+ let(:selector) do
1901
+ { name: 'BANG' }
1902
+ end
1903
+
1904
+ let(:result) do
1905
+ authorized_collection.replace_one(selector, { name: 'doink' })
1906
+ end
1907
+
1908
+ before do
1909
+ authorized_collection.insert_one(name: 'bang')
1910
+ end
1911
+
1912
+ it 'does not apply the collation' do
1913
+ expect(result.written_count).to eq(0)
1914
+ expect(authorized_collection.find(name: 'bang').count).to eq(1)
1915
+ end
1916
+ end
1423
1917
  end
1424
1918
 
1425
1919
  describe '#update_many' do
@@ -1428,10 +1922,6 @@ describe Mongo::Collection do
1428
1922
  { field: 'test' }
1429
1923
  end
1430
1924
 
1431
- after do
1432
- authorized_collection.delete_many
1433
- end
1434
-
1435
1925
  context 'when a selector was provided' do
1436
1926
 
1437
1927
  before do
@@ -1529,12 +2019,17 @@ describe Mongo::Collection do
1529
2019
 
1530
2020
  context 'when collection has a validator', if: find_command_enabled? do
1531
2021
 
1532
- before do
1533
- collection_with_validator.insert_many([{ a: 1 }, { a: 2 }])
2022
+ around(:each) do |spec|
2023
+ authorized_client[:validating,
2024
+ :validator => { :a => { '$exists' => true } }].tap do |c|
2025
+ c.create
2026
+ end
2027
+ spec.run
2028
+ collection_with_validator.drop
1534
2029
  end
1535
2030
 
1536
- after do
1537
- collection_with_validator.delete_many
2031
+ before do
2032
+ collection_with_validator.insert_many([{ a: 1 }, { a: 2 }])
1538
2033
  end
1539
2034
 
1540
2035
  context 'when the document is valid' do
@@ -1579,6 +2074,80 @@ describe Mongo::Collection do
1579
2074
  end
1580
2075
  end
1581
2076
  end
2077
+
2078
+ context 'when a collation is specified' do
2079
+
2080
+ let(:selector) do
2081
+ { name: 'BANG' }
2082
+ end
2083
+
2084
+ let(:result) do
2085
+ authorized_collection.update_many(selector, { '$set' => { other: 'doink' } }, options)
2086
+ end
2087
+
2088
+ before do
2089
+ authorized_collection.insert_one(name: 'bang')
2090
+ authorized_collection.insert_one(name: 'baNG')
2091
+ end
2092
+
2093
+ let(:options) do
2094
+ { collation: { locale: 'en_US', strength: 2 } }
2095
+ end
2096
+
2097
+ context 'when the server selected supports collations', if: collation_enabled? do
2098
+
2099
+ it 'applies the collation' do
2100
+ expect(result.written_count).to eq(2)
2101
+ expect(authorized_collection.find(other: 'doink').count).to eq(2)
2102
+ end
2103
+
2104
+ context 'when unacknowledged writes is used' do
2105
+
2106
+ let(:collection_with_unacknowledged_write_concern) do
2107
+ authorized_collection.with(write: { w: 0 })
2108
+ end
2109
+
2110
+ let(:result) do
2111
+ collection_with_unacknowledged_write_concern.update_many(selector, { '$set' => { other: 'doink' } }, options)
2112
+ end
2113
+
2114
+ it 'raises an exception' do
2115
+ expect {
2116
+ result
2117
+ }.to raise_exception(Mongo::Error::UnsupportedCollation)
2118
+ end
2119
+ end
2120
+ end
2121
+
2122
+ context 'when the server selected does not support collations', unless: collation_enabled? do
2123
+
2124
+ it 'raises an exception' do
2125
+ expect {
2126
+ result
2127
+ }.to raise_exception(Mongo::Error::UnsupportedCollation)
2128
+ end
2129
+ end
2130
+ end
2131
+
2132
+ context 'when collation is not specified' do
2133
+
2134
+ let(:selector) do
2135
+ {name: 'BANG'}
2136
+ end
2137
+
2138
+ let(:result) do
2139
+ authorized_collection.update_many(selector, { '$set' => {other: 'doink'} })
2140
+ end
2141
+
2142
+ before do
2143
+ authorized_collection.insert_one(name: 'bang')
2144
+ authorized_collection.insert_one(name: 'baNG')
2145
+ end
2146
+
2147
+ it 'does not apply the collation' do
2148
+ expect(result.written_count).to eq(0)
2149
+ end
2150
+ end
1582
2151
  end
1583
2152
 
1584
2153
  describe '#update_one' do
@@ -1684,12 +2253,17 @@ describe Mongo::Collection do
1684
2253
 
1685
2254
  context 'when collection has a validator', if: find_command_enabled? do
1686
2255
 
1687
- before do
1688
- collection_with_validator.insert_one({ a: 1 })
2256
+ around(:each) do |spec|
2257
+ authorized_client[:validating,
2258
+ :validator => { :a => { '$exists' => true } }].tap do |c|
2259
+ c.create
2260
+ end
2261
+ spec.run
2262
+ collection_with_validator.drop
1689
2263
  end
1690
2264
 
1691
- after do
1692
- collection_with_validator.delete_many
2265
+ before do
2266
+ collection_with_validator.insert_one({ a: 1 })
1693
2267
  end
1694
2268
 
1695
2269
  context 'when the document is valid' do
@@ -1734,6 +2308,78 @@ describe Mongo::Collection do
1734
2308
  end
1735
2309
  end
1736
2310
  end
2311
+
2312
+ context 'when there is a collation specified' do
2313
+
2314
+ let(:selector) do
2315
+ { name: 'BANG' }
2316
+ end
2317
+
2318
+ let(:result) do
2319
+ authorized_collection.update_one(selector, { '$set' => { other: 'doink' } }, options)
2320
+ end
2321
+
2322
+ before do
2323
+ authorized_collection.insert_one(name: 'bang')
2324
+ end
2325
+
2326
+ let(:options) do
2327
+ { collation: { locale: 'en_US', strength: 2 } }
2328
+ end
2329
+
2330
+ context 'when the server selected supports collations', if: collation_enabled? do
2331
+
2332
+ it 'applies the collation' do
2333
+ expect(result.written_count).to eq(1)
2334
+ expect(authorized_collection.find(other: 'doink').count).to eq(1)
2335
+ end
2336
+
2337
+ context 'when unacknowledged writes is used' do
2338
+
2339
+ let(:collection_with_unacknowledged_write_concern) do
2340
+ authorized_collection.with(write: { w: 0 })
2341
+ end
2342
+
2343
+ let(:result) do
2344
+ collection_with_unacknowledged_write_concern.update_one(selector, { '$set' => { other: 'doink' } }, options)
2345
+ end
2346
+
2347
+ it 'raises an exception' do
2348
+ expect {
2349
+ result
2350
+ }.to raise_exception(Mongo::Error::UnsupportedCollation)
2351
+ end
2352
+ end
2353
+ end
2354
+
2355
+ context 'when the server selected does not support collations', unless: collation_enabled? do
2356
+
2357
+ it 'raises an exception' do
2358
+ expect {
2359
+ result
2360
+ }.to raise_exception(Mongo::Error::UnsupportedCollation)
2361
+ end
2362
+ end
2363
+ end
2364
+
2365
+ context 'when a collation is not specified' do
2366
+
2367
+ let(:selector) do
2368
+ { name: 'BANG' }
2369
+ end
2370
+
2371
+ let(:result) do
2372
+ authorized_collection.update_one(selector, { '$set' => { other: 'doink' } })
2373
+ end
2374
+
2375
+ before do
2376
+ authorized_collection.insert_one(name: 'bang')
2377
+ end
2378
+
2379
+ it 'does not apply the collation' do
2380
+ expect(result.written_count).to eq(0)
2381
+ end
2382
+ end
1737
2383
  end
1738
2384
 
1739
2385
  describe '#find_one_and_delete' do
@@ -1855,6 +2501,61 @@ describe Mongo::Collection do
1855
2501
  }.to raise_error(Mongo::Error::OperationFailure)
1856
2502
  end
1857
2503
  end
2504
+
2505
+ context 'when collation is specified' do
2506
+
2507
+ let(:selector) do
2508
+ { name: 'BANG' }
2509
+ end
2510
+
2511
+ let(:result) do
2512
+ authorized_collection.find_one_and_delete(selector, options)
2513
+ end
2514
+
2515
+ before do
2516
+ authorized_collection.insert_one(name: 'bang')
2517
+ end
2518
+
2519
+ let(:options) do
2520
+ { collation: { locale: 'en_US', strength: 2 } }
2521
+ end
2522
+
2523
+ context 'when the server selected supports collations', if: collation_enabled? do
2524
+
2525
+ it 'applies the collation' do
2526
+ expect(result['name']).to eq('bang')
2527
+ expect(authorized_collection.find(name: 'bang').count).to eq(0)
2528
+ end
2529
+ end
2530
+
2531
+ context 'when the server selected does not support collations', unless: collation_enabled? do
2532
+
2533
+ it 'raises an exception' do
2534
+ expect {
2535
+ result
2536
+ }.to raise_exception(Mongo::Error::UnsupportedCollation)
2537
+ end
2538
+ end
2539
+ end
2540
+
2541
+ context 'when collation is not specified' do
2542
+
2543
+ let(:selector) do
2544
+ { name: 'BANG' }
2545
+ end
2546
+
2547
+ let(:result) do
2548
+ authorized_collection.find_one_and_delete(selector)
2549
+ end
2550
+
2551
+ before do
2552
+ authorized_collection.insert_one(name: 'bang')
2553
+ end
2554
+
2555
+ it 'does not apply the collation' do
2556
+ expect(result).to be_nil
2557
+ end
2558
+ end
1858
2559
  end
1859
2560
 
1860
2561
  describe '#find_one_and_update' do
@@ -2012,12 +2713,17 @@ describe Mongo::Collection do
2012
2713
 
2013
2714
  context 'when collection has a validator', if: find_command_enabled? do
2014
2715
 
2015
- before do
2016
- collection_with_validator.insert_one({ a: 1 })
2716
+ around(:each) do |spec|
2717
+ authorized_client[:validating,
2718
+ :validator => { :a => { '$exists' => true } }].tap do |c|
2719
+ c.create
2720
+ end
2721
+ spec.run
2722
+ collection_with_validator.drop
2017
2723
  end
2018
2724
 
2019
- after do
2020
- collection_with_validator.delete_many
2725
+ before do
2726
+ collection_with_validator.insert_one({ a: 1 })
2021
2727
  end
2022
2728
 
2023
2729
  context 'when the document is valid' do
@@ -2089,6 +2795,63 @@ describe Mongo::Collection do
2089
2795
  }.to raise_error(Mongo::Error::OperationFailure)
2090
2796
  end
2091
2797
  end
2798
+
2799
+ context 'when a collation is specified' do
2800
+
2801
+ let(:selector) do
2802
+ { name: 'BANG' }
2803
+ end
2804
+
2805
+ let(:result) do
2806
+ authorized_collection.find_one_and_update(selector,
2807
+ { '$set' => { other: 'doink' } },
2808
+ options)
2809
+ end
2810
+
2811
+ before do
2812
+ authorized_collection.insert_one(name: 'bang')
2813
+ end
2814
+
2815
+ let(:options) do
2816
+ { collation: { locale: 'en_US', strength: 2 } }
2817
+ end
2818
+
2819
+ context 'when the server selected supports collations', if: collation_enabled? do
2820
+
2821
+ it 'applies the collation' do
2822
+ expect(result['name']).to eq('bang')
2823
+ expect(authorized_collection.find({ name: 'bang' }, limit: -1).first['other']).to eq('doink')
2824
+ end
2825
+ end
2826
+
2827
+ context 'when the server selected does not support collations', unless: collation_enabled? do
2828
+
2829
+ it 'raises an exception' do
2830
+ expect {
2831
+ result
2832
+ }.to raise_exception(Mongo::Error::UnsupportedCollation)
2833
+ end
2834
+ end
2835
+ end
2836
+
2837
+ context 'when there is no collation specified' do
2838
+
2839
+ let(:selector) do
2840
+ { name: 'BANG' }
2841
+ end
2842
+
2843
+ let(:result) do
2844
+ authorized_collection.find_one_and_update(selector, { '$set' => { other: 'doink' } })
2845
+ end
2846
+
2847
+ before do
2848
+ authorized_collection.insert_one(name: 'bang')
2849
+ end
2850
+
2851
+ it 'does not apply the collation' do
2852
+ expect(result).to be_nil
2853
+ end
2854
+ end
2092
2855
  end
2093
2856
 
2094
2857
  describe '#find_one_and_replace' do
@@ -2220,12 +2983,17 @@ describe Mongo::Collection do
2220
2983
 
2221
2984
  context 'when collection has a validator', if: find_command_enabled? do
2222
2985
 
2223
- before do
2224
- collection_with_validator.insert_one({ a: 1 })
2986
+ around(:each) do |spec|
2987
+ authorized_client[:validating,
2988
+ :validator => { :a => { '$exists' => true } }].tap do |c|
2989
+ c.create
2990
+ end
2991
+ spec.run
2992
+ collection_with_validator.drop
2225
2993
  end
2226
2994
 
2227
- after do
2228
- collection_with_validator.delete_many
2995
+ before do
2996
+ collection_with_validator.insert_one({ a: 1 })
2229
2997
  end
2230
2998
 
2231
2999
  context 'when the document is valid' do
@@ -2297,5 +3065,62 @@ describe Mongo::Collection do
2297
3065
  }.to raise_error(Mongo::Error::OperationFailure)
2298
3066
  end
2299
3067
  end
3068
+
3069
+ context 'when collation is provided' do
3070
+
3071
+ let(:selector) do
3072
+ { name: 'BANG' }
3073
+ end
3074
+
3075
+ let(:result) do
3076
+ authorized_collection.find_one_and_replace(selector,
3077
+ { name: 'doink' },
3078
+ options)
3079
+ end
3080
+
3081
+ before do
3082
+ authorized_collection.insert_one(name: 'bang')
3083
+ end
3084
+
3085
+ let(:options) do
3086
+ { collation: { locale: 'en_US', strength: 2 } }
3087
+ end
3088
+
3089
+ context 'when the server selected supports collations', if: collation_enabled? do
3090
+
3091
+ it 'applies the collation' do
3092
+ expect(result['name']).to eq('bang')
3093
+ expect(authorized_collection.find(name: 'doink').count).to eq(1)
3094
+ end
3095
+ end
3096
+
3097
+ context 'when the server selected does not support collations', unless: collation_enabled? do
3098
+
3099
+ it 'raises an exception' do
3100
+ expect {
3101
+ result
3102
+ }.to raise_exception(Mongo::Error::UnsupportedCollation)
3103
+ end
3104
+ end
3105
+ end
3106
+
3107
+ context 'when collation is not specified' do
3108
+
3109
+ let(:selector) do
3110
+ { name: 'BANG' }
3111
+ end
3112
+
3113
+ let(:result) do
3114
+ authorized_collection.find_one_and_replace(selector, { name: 'doink' })
3115
+ end
3116
+
3117
+ before do
3118
+ authorized_collection.insert_one(name: 'bang')
3119
+ end
3120
+
3121
+ it 'does not apply the collation' do
3122
+ expect(result).to be_nil
3123
+ end
3124
+ end
2300
3125
  end
2301
3126
  end