mongo 2.3.1 → 2.4.0.rc0

Sign up to get free protection for your applications and to get access to all the features.
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