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
@@ -260,6 +260,17 @@ describe Mongo::Client do
260
260
  expect(client.cluster.logger).to_not eq(Mongo::Logger.logger)
261
261
  end
262
262
  end
263
+
264
+ context 'when providing a heartbeat_frequency' do
265
+
266
+ let(:client) do
267
+ described_class.new(['127.0.0.1:27017'], :heartbeat_frequency => 2)
268
+ end
269
+
270
+ it 'sets the heartbeat frequency' do
271
+ expect(client.cluster.options[:heartbeat_frequency]).to eq(client.options[:heartbeat_frequency])
272
+ end
273
+ end
263
274
  end
264
275
 
265
276
  context 'when providing a connection string' do
@@ -557,6 +568,41 @@ describe Mongo::Client do
557
568
  end
558
569
  end
559
570
 
571
+ context 'when the app_name is changed' do
572
+
573
+ let(:client) do
574
+ authorized_client
575
+ end
576
+
577
+ let!(:original_options) do
578
+ client.options
579
+ end
580
+
581
+ let(:new_options) do
582
+ { app_name: 'reports' }
583
+ end
584
+
585
+ let!(:new_client) do
586
+ authorized_client.with(new_options)
587
+ end
588
+
589
+ it 'returns a new client' do
590
+ expect(new_client).not_to equal(client)
591
+ end
592
+
593
+ it 'replaces the existing options' do
594
+ expect(new_client.options).to eq(client.options.merge(new_options))
595
+ end
596
+
597
+ it 'does not modify the original client' do
598
+ expect(client.options).to eq(original_options)
599
+ end
600
+
601
+ it 'does not keep the same cluster' do
602
+ expect(new_client.cluster).not_to be(client.cluster)
603
+ end
604
+ end
605
+
560
606
  context 'when the write concern is not changed' do
561
607
 
562
608
  let(:client) do
@@ -595,7 +641,7 @@ describe Mongo::Client do
595
641
  end
596
642
 
597
643
  it 'keeps the same cluster' do
598
- expect(new_client.cluster).to equal(client.cluster)
644
+ expect(new_client.cluster).to be(client.cluster)
599
645
  end
600
646
  end
601
647
 
@@ -0,0 +1,104 @@
1
+ require 'spec_helper'
2
+
3
+ describe Mongo::Cluster::AppMetadata do
4
+
5
+ let(:app_metadata) do
6
+ described_class.new(cluster)
7
+ end
8
+
9
+ let(:cluster) do
10
+ authorized_client.cluster
11
+ end
12
+
13
+ describe '#initialize' do
14
+
15
+ context 'when the cluster has an app name option set' do
16
+
17
+ let(:cluster) do
18
+ authorized_client.with(app_name: :reports).cluster
19
+ end
20
+
21
+ it 'sets the app name' do
22
+ expect(app_metadata.send(:full_client_document)[:application][:name]).to eq(:reports)
23
+ end
24
+
25
+ context 'when the app name exceeds the max length of 128' do
26
+
27
+ let(:cluster) do
28
+ authorized_client.with(app_name: "\u3042"*43).cluster
29
+ end
30
+
31
+ it 'raises an error' do
32
+ expect {
33
+ app_metadata.send(:validate!)
34
+ }.to raise_exception(Mongo::Error::InvalidApplicationName)
35
+ end
36
+ end
37
+ end
38
+
39
+ context 'when the cluster does not have an app name option set' do
40
+
41
+ it 'does not set the app name' do
42
+ expect(app_metadata.send(:full_client_document)[:application]).to be(nil)
43
+ end
44
+ end
45
+
46
+ context 'when the client document exceeds the max of 512 bytes' do
47
+
48
+ context 'when the os.type length is too long' do
49
+
50
+ before do
51
+ allow(app_metadata).to receive(:type).and_return('x'*500)
52
+ end
53
+
54
+ it 'truncates the document' do
55
+ expect(app_metadata.send(:ismaster_bytes)).to be_a(String)
56
+ end
57
+ end
58
+
59
+ context 'when the os.name length is too long' do
60
+
61
+ before do
62
+ allow(app_metadata).to receive(:name).and_return('x'*500)
63
+ end
64
+
65
+ it 'truncates the document' do
66
+ expect(app_metadata.send(:ismaster_bytes)).to be_a(String)
67
+ end
68
+ end
69
+
70
+ context 'when the os.architecture length is too long' do
71
+
72
+ before do
73
+ allow(app_metadata).to receive(:architecture).and_return('x'*500)
74
+ end
75
+
76
+ it 'truncates the document' do
77
+ expect(app_metadata.send(:ismaster_bytes)).to be_a(String)
78
+ end
79
+ end
80
+
81
+ context 'when the platform length is too long' do
82
+
83
+ before do
84
+ allow(app_metadata).to receive(:platform).and_return('x'*500)
85
+ end
86
+
87
+ it 'truncates the document to be just an ismaster command' do
88
+ expect(app_metadata.send(:ismaster_bytes)).to be_a(String)
89
+ end
90
+ end
91
+
92
+ context 'when the driver info is too long' do
93
+
94
+ before do
95
+ allow(app_metadata).to receive(:driver_doc).and_return('x'*500)
96
+ end
97
+
98
+ it 'truncates the document to be just an ismaster command' do
99
+ expect(app_metadata.ismaster_bytes.length).to eq(Mongo::Server::Monitor::Connection::ISMASTER_BYTES.length)
100
+ end
101
+ end
102
+ end
103
+ end
104
+ end
@@ -14,22 +14,28 @@ describe Mongo::Cluster::Topology::ReplicaSet do
14
14
  Mongo::Monitoring.new
15
15
  end
16
16
 
17
+ let(:cluster) do
18
+ double('cluster').tap do |cl|
19
+ allow(cl).to receive(:app_metadata).and_return(app_metadata)
20
+ end
21
+ end
22
+
17
23
  describe '#servers' do
18
24
 
19
25
  let(:mongos) do
20
- Mongo::Server.new(address, double('cluster'), monitoring, listeners, TEST_OPTIONS)
26
+ Mongo::Server.new(address, cluster, monitoring, listeners, TEST_OPTIONS)
21
27
  end
22
28
 
23
29
  let(:standalone) do
24
- Mongo::Server.new(address, double('cluster'), monitoring, listeners, TEST_OPTIONS)
30
+ Mongo::Server.new(address, cluster, monitoring, listeners, TEST_OPTIONS)
25
31
  end
26
32
 
27
33
  let(:replica_set) do
28
- Mongo::Server.new(address, double('cluster'), monitoring, listeners, TEST_OPTIONS)
34
+ Mongo::Server.new(address, cluster, monitoring, listeners, TEST_OPTIONS)
29
35
  end
30
36
 
31
37
  let(:replica_set_two) do
32
- Mongo::Server.new(address, double('cluster'), monitoring, listeners, TEST_OPTIONS)
38
+ Mongo::Server.new(address, cluster, monitoring, listeners, TEST_OPTIONS)
33
39
  end
34
40
 
35
41
  let(:mongos_description) do
@@ -110,11 +116,11 @@ describe Mongo::Cluster::Topology::ReplicaSet do
110
116
  describe '#add_hosts?' do
111
117
 
112
118
  let(:primary) do
113
- Mongo::Server.new(address, double('cluster'), monitoring, listeners, TEST_OPTIONS)
119
+ Mongo::Server.new(address, cluster, monitoring, listeners, TEST_OPTIONS)
114
120
  end
115
121
 
116
122
  let(:secondary) do
117
- Mongo::Server.new(address, double('cluster'), monitoring, listeners, TEST_OPTIONS)
123
+ Mongo::Server.new(address, cluster, monitoring, listeners, TEST_OPTIONS)
118
124
  end
119
125
 
120
126
  let(:primary_description) do
@@ -193,7 +199,7 @@ describe Mongo::Cluster::Topology::ReplicaSet do
193
199
  describe '#remove_hosts?' do
194
200
 
195
201
  let(:primary) do
196
- Mongo::Server.new(address, double('cluster'), monitoring, listeners, TEST_OPTIONS)
202
+ Mongo::Server.new(address, cluster, monitoring, listeners, TEST_OPTIONS)
197
203
  end
198
204
 
199
205
  let(:primary_description) do
@@ -274,7 +280,7 @@ describe Mongo::Cluster::Topology::ReplicaSet do
274
280
  describe '#remove_server?' do
275
281
 
276
282
  let(:secondary) do
277
- Mongo::Server.new(address, double('cluster'), monitoring, listeners, TEST_OPTIONS)
283
+ Mongo::Server.new(address, cluster, monitoring, listeners, TEST_OPTIONS)
278
284
  end
279
285
 
280
286
  let(:secondary_description) do
@@ -18,16 +18,22 @@ describe Mongo::Cluster::Topology::Sharded do
18
18
  Mongo::Event::Listeners.new
19
19
  end
20
20
 
21
+ let(:cluster) do
22
+ double('cluster').tap do |cl|
23
+ allow(cl).to receive(:app_metadata).and_return(app_metadata)
24
+ end
25
+ end
26
+
21
27
  let(:mongos) do
22
- Mongo::Server.new(address, double('cluster'), monitoring, listeners, TEST_OPTIONS)
28
+ Mongo::Server.new(address, cluster, monitoring, listeners, TEST_OPTIONS)
23
29
  end
24
30
 
25
31
  let(:standalone) do
26
- Mongo::Server.new(address, double('cluster'), monitoring, listeners, TEST_OPTIONS)
32
+ Mongo::Server.new(address, cluster, monitoring, listeners, TEST_OPTIONS)
27
33
  end
28
34
 
29
35
  let(:replica_set) do
30
- Mongo::Server.new(address, double('cluster'), monitoring, listeners, TEST_OPTIONS)
36
+ Mongo::Server.new(address, cluster, monitoring, listeners, TEST_OPTIONS)
31
37
  end
32
38
 
33
39
  let(:mongos_description) do
@@ -18,22 +18,28 @@ describe Mongo::Cluster::Topology::Single do
18
18
  Mongo::Event::Listeners.new
19
19
  end
20
20
 
21
+ let(:cluster) do
22
+ double('cluster').tap do |cl|
23
+ allow(cl).to receive(:app_metadata).and_return(app_metadata)
24
+ end
25
+ end
26
+
21
27
  describe '.servers' do
22
28
 
23
29
  let(:mongos) do
24
- Mongo::Server.new(address, double('cluster'), monitoring, listeners, TEST_OPTIONS)
30
+ Mongo::Server.new(address, cluster, monitoring, listeners, TEST_OPTIONS)
25
31
  end
26
32
 
27
33
  let(:standalone) do
28
- Mongo::Server.new(address, double('cluster'), monitoring, listeners, TEST_OPTIONS)
34
+ Mongo::Server.new(address, cluster, monitoring, listeners, TEST_OPTIONS)
29
35
  end
30
36
 
31
37
  let(:standalone_two) do
32
- Mongo::Server.new(address, double('cluster'), monitoring, listeners, TEST_OPTIONS)
38
+ Mongo::Server.new(address, cluster, monitoring, listeners, TEST_OPTIONS)
33
39
  end
34
40
 
35
41
  let(:replica_set) do
36
- Mongo::Server.new(address, double('cluster'), monitoring, listeners, TEST_OPTIONS)
42
+ Mongo::Server.new(address, cluster, monitoring, listeners, TEST_OPTIONS)
37
43
  end
38
44
 
39
45
  let(:mongos_description) do
@@ -463,4 +463,33 @@ describe Mongo::Cluster do
463
463
  expect(primary_candidates).to include(cluster.next_primary)
464
464
  end
465
465
  end
466
+
467
+ describe '#app_metadata' do
468
+
469
+ it 'returns an AppMetadata object' do
470
+ expect(cluster.app_metadata).to be_a(Mongo::Cluster::AppMetadata)
471
+ end
472
+
473
+ context 'when the client has an app_name set' do
474
+
475
+ let(:cluster) do
476
+ authorized_client.with(app_name: 'reports').cluster
477
+ end
478
+
479
+ it 'constructs an AppMetadata object with the app_name' do
480
+ expect(cluster.app_metadata.send(:full_client_document)[:application]).to eq('name' => 'reports')
481
+ end
482
+ end
483
+
484
+ context 'when the client does not have an app_name set' do
485
+
486
+ let(:cluster) do
487
+ authorized_client.cluster
488
+ end
489
+
490
+ it 'constructs an AppMetadata object with no app_name' do
491
+ expect(cluster.app_metadata.send(:full_client_document)[:application]).to be_nil
492
+ end
493
+ end
494
+ end
466
495
  end
@@ -26,6 +26,10 @@ describe Mongo::Collection::View::Aggregation do
26
26
  described_class.new(view, pipeline, options)
27
27
  end
28
28
 
29
+ after do
30
+ authorized_collection.delete_many
31
+ end
32
+
29
33
  describe '#allow_disk_use' do
30
34
 
31
35
  let(:new_agg) do
@@ -143,6 +147,31 @@ describe Mongo::Collection::View::Aggregation do
143
147
  expect(aggregation.to_a.size).to eq(2)
144
148
  end
145
149
  end
150
+
151
+ context 'when the view has a write concern' do
152
+
153
+ let(:collection) do
154
+ authorized_collection.with(write: { w: WRITE_CONCERN[:w]+1 })
155
+ end
156
+
157
+ let(:view) do
158
+ Mongo::Collection::View.new(collection, selector, view_options)
159
+ end
160
+
161
+ context 'when the server supports write concern on the aggregate command', if: collation_enabled? do
162
+
163
+ it 'does not apply the write concern' do
164
+ expect(aggregation.to_a.size).to eq(2)
165
+ end
166
+ end
167
+
168
+ context 'when the server does not support write concern on the aggregation command', unless: collation_enabled? do
169
+
170
+ it 'does not apply the write concern' do
171
+ expect(aggregation.to_a.size).to eq(2)
172
+ end
173
+ end
174
+ end
146
175
  end
147
176
 
148
177
  describe '#initialize' do
@@ -173,6 +202,41 @@ describe Mongo::Collection::View::Aggregation do
173
202
  it 'executes an explain' do
174
203
  expect(aggregation.explain).to_not be_empty
175
204
  end
205
+
206
+ context 'when a collation is specified' do
207
+
208
+ before do
209
+ authorized_collection.insert_many([ { name: 'bang' }, { name: 'bang' }])
210
+ end
211
+
212
+ let(:pipeline) do
213
+ [{ "$match" => { "name" => "BANG" } }]
214
+ end
215
+
216
+ let(:options) do
217
+ { collation: { locale: 'en_US', strength: 2 } }
218
+ end
219
+
220
+ let(:result) do
221
+ aggregation.explain['$cursor']['queryPlanner']['collation']['locale']
222
+ end
223
+
224
+ context 'when the server selected supports collations', if: collation_enabled? do
225
+
226
+ it 'applies the collation' do
227
+ expect(result).to eq('en_US')
228
+ end
229
+ end
230
+
231
+ context 'when the server selected does not support collations', unless: collation_enabled? do
232
+
233
+ it 'raises an exception' do
234
+ expect {
235
+ result
236
+ }.to raise_exception(Mongo::Error::UnsupportedCollation)
237
+ end
238
+ end
239
+ end
176
240
  end
177
241
 
178
242
  describe '#aggregate_spec' do
@@ -323,6 +387,41 @@ describe Mongo::Collection::View::Aggregation do
323
387
  end
324
388
  end
325
389
 
390
+ context 'when the aggregation has a collation defined' do
391
+
392
+ before do
393
+ authorized_collection.insert_many([ { name: 'bang' }, { name: 'bang' }])
394
+ end
395
+
396
+ let(:pipeline) do
397
+ [{ "$match" => { "name" => "BANG" } }]
398
+ end
399
+
400
+ let(:options) do
401
+ { collation: { locale: 'en_US', strength: 2 } }
402
+ end
403
+
404
+ let(:result) do
405
+ aggregation.collect { |doc| doc['name']}
406
+ end
407
+
408
+ context 'when the server selected supports collations', if: collation_enabled? do
409
+
410
+ it 'applies the collation' do
411
+ expect(result).to eq(['bang', 'bang'])
412
+ end
413
+ end
414
+
415
+ context 'when the server selected does not support collations', unless: collation_enabled? do
416
+
417
+ it 'raises an exception' do
418
+ expect {
419
+ result
420
+ }.to raise_exception(Mongo::Error::UnsupportedCollation)
421
+ end
422
+ end
423
+ end
424
+
326
425
  context 'when $out is in the pipeline', if: write_command_enabled? do
327
426
 
328
427
  let(:pipeline) do
@@ -385,6 +484,46 @@ describe Mongo::Collection::View::Aggregation do
385
484
  expect(Mongo::Logger.logger).not_to receive(:warn?)
386
485
  aggregation.to_a
387
486
  end
487
+
488
+ context 'when the view has a write concern' do
489
+
490
+ let(:collection) do
491
+ authorized_collection.with(write: { w: WRITE_CONCERN[:w]+1 })
492
+ end
493
+
494
+ let(:view) do
495
+ Mongo::Collection::View.new(collection, selector, view_options)
496
+ end
497
+
498
+ context 'when the server supports write concern on the aggregate command', if: collation_enabled? do
499
+
500
+ it 'uses the write concern' do
501
+ expect {
502
+ aggregation.to_a
503
+ }.to raise_exception(Mongo::Error::OperationFailure)
504
+ end
505
+ end
506
+
507
+ context 'when the server does not support write concern on the aggregation command', unless: collation_enabled? do
508
+
509
+ let(:documents) do
510
+ [
511
+ { city: "Berlin", pop: 18913, neighborhood: "Kreuzberg" },
512
+ { city: "Berlin", pop: 84143, neighborhood: "Mitte" },
513
+ { city: "New York", pop: 40270, neighborhood: "Brooklyn" }
514
+ ]
515
+ end
516
+
517
+ before do
518
+ authorized_collection.insert_many(documents)
519
+ aggregation.to_a
520
+ end
521
+
522
+ it 'does not apply the write concern' do
523
+ expect(authorized_client['output_collection'].find.count).to eq(2)
524
+ end
525
+ end
526
+ end
388
527
  end
389
528
  end
390
529
  end