mongo 2.1.2 → 2.2.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 (140) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data.tar.gz.sig +0 -0
  4. data/README.md +10 -3
  5. data/Rakefile +1 -7
  6. data/lib/csasl/csasl.bundle +0 -0
  7. data/lib/mongo/auth/user/view.rb +1 -1
  8. data/lib/mongo/bulk_write.rb +7 -1
  9. data/lib/mongo/client.rb +17 -15
  10. data/lib/mongo/cluster.rb +4 -2
  11. data/lib/mongo/collection.rb +36 -2
  12. data/lib/mongo/collection/view.rb +24 -21
  13. data/lib/mongo/collection/view/aggregation.rb +5 -42
  14. data/lib/mongo/collection/view/builder.rb +20 -0
  15. data/lib/mongo/collection/view/builder/aggregation.rb +98 -0
  16. data/lib/mongo/collection/view/builder/find_command.rb +111 -0
  17. data/lib/mongo/collection/view/builder/flags.rb +62 -0
  18. data/lib/mongo/collection/view/builder/map_reduce.rb +134 -0
  19. data/lib/mongo/collection/view/builder/modifiers.rb +80 -0
  20. data/lib/mongo/collection/view/builder/op_query.rb +83 -0
  21. data/lib/mongo/collection/view/explainable.rb +15 -0
  22. data/lib/mongo/collection/view/immutable.rb +5 -12
  23. data/lib/mongo/collection/view/iterable.rb +24 -2
  24. data/lib/mongo/collection/view/map_reduce.rb +18 -27
  25. data/lib/mongo/collection/view/readable.rb +70 -112
  26. data/lib/mongo/collection/view/writable.rb +23 -7
  27. data/lib/mongo/cursor.rb +76 -25
  28. data/lib/mongo/cursor/builder.rb +18 -0
  29. data/lib/mongo/cursor/builder/get_more_command.rb +71 -0
  30. data/lib/mongo/cursor/builder/kill_cursors_command.rb +62 -0
  31. data/lib/mongo/cursor/builder/op_get_more.rb +61 -0
  32. data/lib/mongo/cursor/builder/op_kill_cursors.rb +56 -0
  33. data/lib/mongo/database.rb +2 -2
  34. data/lib/mongo/database/view.rb +9 -5
  35. data/lib/mongo/dbref.rb +3 -3
  36. data/lib/mongo/error.rb +1 -0
  37. data/lib/mongo/error/invalid_write_concern.rb +35 -0
  38. data/lib/mongo/grid/file/chunk.rb +2 -2
  39. data/lib/mongo/index/view.rb +5 -2
  40. data/lib/mongo/operation.rb +1 -0
  41. data/lib/mongo/operation/commands.rb +2 -0
  42. data/lib/mongo/operation/commands/aggregate.rb +39 -45
  43. data/lib/mongo/operation/commands/aggregate/result.rb +54 -68
  44. data/lib/mongo/operation/commands/collections_info.rb +38 -36
  45. data/lib/mongo/operation/commands/collections_info/result.rb +17 -15
  46. data/lib/mongo/operation/commands/command.rb +24 -22
  47. data/lib/mongo/operation/commands/find.rb +27 -0
  48. data/lib/mongo/operation/commands/find/result.rb +62 -0
  49. data/lib/mongo/operation/commands/get_more.rb +27 -0
  50. data/lib/mongo/operation/commands/get_more/result.rb +62 -0
  51. data/lib/mongo/operation/commands/indexes.rb +41 -39
  52. data/lib/mongo/operation/commands/list_collections.rb +25 -31
  53. data/lib/mongo/operation/commands/list_collections/result.rb +63 -81
  54. data/lib/mongo/operation/commands/list_indexes.rb +27 -35
  55. data/lib/mongo/operation/commands/list_indexes/result.rb +67 -85
  56. data/lib/mongo/operation/commands/map_reduce.rb +29 -37
  57. data/lib/mongo/operation/commands/map_reduce/result.rb +85 -88
  58. data/lib/mongo/operation/commands/parallel_scan.rb +29 -33
  59. data/lib/mongo/operation/commands/parallel_scan/result.rb +34 -42
  60. data/lib/mongo/operation/commands/user_query.rb +40 -38
  61. data/lib/mongo/operation/commands/users_info.rb +24 -29
  62. data/lib/mongo/operation/commands/users_info/result.rb +13 -11
  63. data/lib/mongo/operation/object_id_generator.rb +36 -0
  64. data/lib/mongo/operation/result.rb +30 -0
  65. data/lib/mongo/operation/specifiable.rb +35 -1
  66. data/lib/mongo/operation/write/bulk/bulkable.rb +4 -3
  67. data/lib/mongo/operation/write/bulk/delete/result.rb +18 -25
  68. data/lib/mongo/operation/write/bulk/legacy_mergable.rb +2 -2
  69. data/lib/mongo/operation/write/command/delete.rb +3 -2
  70. data/lib/mongo/operation/write/command/insert.rb +4 -2
  71. data/lib/mongo/operation/write/command/update.rb +6 -3
  72. data/lib/mongo/operation/write/gle.rb +2 -1
  73. data/lib/mongo/operation/write/idable.rb +19 -2
  74. data/lib/mongo/options/mapper.rb +22 -0
  75. data/lib/mongo/protocol/bit_vector.rb +3 -3
  76. data/lib/mongo/protocol/delete.rb +15 -5
  77. data/lib/mongo/protocol/get_more.rb +10 -5
  78. data/lib/mongo/protocol/insert.rb +1 -6
  79. data/lib/mongo/protocol/kill_cursors.rb +14 -1
  80. data/lib/mongo/protocol/message.rb +32 -8
  81. data/lib/mongo/protocol/serializers.rb +15 -16
  82. data/lib/mongo/protocol/update.rb +35 -12
  83. data/lib/mongo/server/connectable.rb +3 -1
  84. data/lib/mongo/server/connection.rb +5 -5
  85. data/lib/mongo/server/description.rb +8 -2
  86. data/lib/mongo/server/description/features.rb +2 -1
  87. data/lib/mongo/server/monitor.rb +1 -12
  88. data/lib/mongo/server/monitor/connection.rb +30 -26
  89. data/lib/mongo/server_selector/selectable.rb +21 -4
  90. data/lib/mongo/uri.rb +2 -0
  91. data/lib/mongo/version.rb +1 -1
  92. data/lib/mongo/write_concern.rb +21 -6
  93. data/mongo.gemspec +1 -2
  94. data/spec/mongo/bulk_write/ordered_combiner_spec.rb +13 -0
  95. data/spec/mongo/bulk_write_spec.rb +58 -0
  96. data/spec/mongo/client_spec.rb +6 -4
  97. data/spec/mongo/collection/view/builder/find_command_spec.rb +167 -0
  98. data/spec/mongo/collection/view/builder/flags_spec.rb +106 -0
  99. data/spec/mongo/collection/view/builder/modifiers_spec.rb +210 -0
  100. data/spec/mongo/collection/view/builder/op_query_spec.rb +154 -0
  101. data/spec/mongo/collection/view/explainable_spec.rb +1 -2
  102. data/spec/mongo/collection/view/immutable_spec.rb +3 -52
  103. data/spec/mongo/collection/view/map_reduce_spec.rb +12 -12
  104. data/spec/mongo/collection/view/readable_spec.rb +86 -80
  105. data/spec/mongo/collection/view_spec.rb +109 -703
  106. data/spec/mongo/collection_spec.rb +594 -11
  107. data/spec/mongo/command_monitoring_spec.rb +40 -27
  108. data/spec/mongo/cursor/builder/get_more_command_spec.rb +160 -0
  109. data/spec/mongo/cursor/builder/op_get_more_spec.rb +52 -0
  110. data/spec/mongo/cursor_spec.rb +10 -60
  111. data/spec/mongo/database_spec.rb +24 -3
  112. data/spec/mongo/dbref_spec.rb +4 -4
  113. data/spec/mongo/grid/file/chunk_spec.rb +1 -1
  114. data/spec/mongo/grid/fs_bucket_spec.rb +3 -3
  115. data/spec/mongo/index/view_spec.rb +41 -0
  116. data/spec/mongo/operation/{aggregate → commands/aggregate}/result_spec.rb +1 -1
  117. data/spec/mongo/operation/commands/aggregate_spec.rb +1 -1
  118. data/spec/mongo/operation/commands/collections_info_spec.rb +1 -1
  119. data/spec/mongo/operation/commands/command_spec.rb +1 -1
  120. data/spec/mongo/operation/commands/indexes_spec.rb +1 -1
  121. data/spec/mongo/operation/commands/map_reduce_spec.rb +1 -1
  122. data/spec/mongo/operation/write/command/delete_spec.rb +25 -0
  123. data/spec/mongo/operation/write/command/insert_spec.rb +25 -0
  124. data/spec/mongo/operation/write/command/update_spec.rb +25 -0
  125. data/spec/mongo/protocol/delete_spec.rb +4 -4
  126. data/spec/mongo/protocol/get_more_spec.rb +4 -4
  127. data/spec/mongo/protocol/insert_spec.rb +3 -3
  128. data/spec/mongo/protocol/kill_cursors_spec.rb +3 -3
  129. data/spec/mongo/protocol/query_spec.rb +7 -7
  130. data/spec/mongo/protocol/update_spec.rb +5 -5
  131. data/spec/mongo/server/description/features_spec.rb +25 -0
  132. data/spec/mongo/write_concern_spec.rb +126 -0
  133. data/spec/spec_helper.rb +9 -19
  134. data/spec/support/command_monitoring.rb +8 -0
  135. data/spec/support/command_monitoring/find.yml +53 -4
  136. data/spec/support/matchers.rb +1 -1
  137. data/spec/support/shared/protocol.rb +5 -5
  138. data/spec/support/travis.rb +1 -1
  139. metadata +43 -10
  140. metadata.gz.sig +0 -0
@@ -1,47 +1,60 @@
1
1
  require 'spec_helper'
2
2
 
3
- def runnable?(file)
3
+ def skippable?(file)
4
4
  !write_command_enabled? && (file.include?('bulkWrite') || file.include?('insert'))
5
5
  end
6
6
 
7
+ def ignore?(test)
8
+ if version = test.ignore_if_server_version_greater_than
9
+ return true if version == "3.0" && find_command_enabled?
10
+ end
11
+ if version = test.ignore_if_server_version_less_than
12
+ return true if version == "3.1" && !find_command_enabled?
13
+ end
14
+ false
15
+ end
16
+
7
17
  describe 'Command Monitoring Events' do
8
18
 
9
19
  COMMAND_MONITORING_TESTS.each do |file|
10
20
 
11
- spec = Mongo::CommandMonitoring::Spec.new(file)
21
+ if !skippable?(file)
12
22
 
13
- spec.tests.each do |test|
23
+ spec = Mongo::CommandMonitoring::Spec.new(file)
14
24
 
15
- context(test.description) do
25
+ spec.tests.each do |test|
16
26
 
17
- let(:subscriber) do
18
- Mongo::CommandMonitoring::TestSubscriber.new
19
- end
27
+ context(test.description) do
20
28
 
21
- let(:monitoring) do
22
- authorized_client.instance_variable_get(:@monitoring)
23
- end
29
+ let(:subscriber) do
30
+ Mongo::CommandMonitoring::TestSubscriber.new
31
+ end
24
32
 
25
- before do
26
- authorized_collection.find.delete_many
27
- authorized_client.subscribe(Mongo::Monitoring::COMMAND, subscriber)
28
- end
33
+ let(:monitoring) do
34
+ authorized_client.instance_variable_get(:@monitoring)
35
+ end
29
36
 
30
- after do
31
- monitoring.subscribers[Mongo::Monitoring::COMMAND].delete(subscriber)
32
- authorized_collection.find.delete_many
33
- end
37
+ before do
38
+ authorized_collection.find.delete_many
39
+ authorized_client.subscribe(Mongo::Monitoring::COMMAND, subscriber)
40
+ end
41
+
42
+ after do
43
+ monitoring.subscribers[Mongo::Monitoring::COMMAND].delete(subscriber)
44
+ authorized_collection.find.delete_many
45
+ end
34
46
 
35
- test.expectations.each do |expectation|
47
+ test.expectations.each do |expectation|
36
48
 
37
- it "generates a #{expectation.event_name} for #{expectation.command_name}", unless: runnable?(file) do
38
- begin
39
- test.run(authorized_collection)
40
- event = subscriber.send(expectation.event_type)[expectation.command_name]
41
- expect(event).to send(expectation.matcher, expectation)
42
- rescue Mongo::Error::OperationFailure, Mongo::Error::BulkWriteError => e
43
- event = subscriber.send(expectation.event_type)[expectation.command_name]
44
- expect(event).to send(expectation.matcher, expectation)
49
+ it "generates a #{expectation.event_name} for #{expectation.command_name}", unless: ignore?(test) do
50
+ begin
51
+ test.run(authorized_collection)
52
+ event = subscriber.send(expectation.event_type)[expectation.command_name]
53
+ expect(event).to send(expectation.matcher, expectation)
54
+ rescue Mongo::Error::OperationFailure, Mongo::Error::BulkWriteError => e
55
+ event = subscriber.send(expectation.event_type)[expectation.command_name]
56
+ expect(event).to send(expectation.matcher, expectation)
57
+ end
45
58
  end
46
59
  end
47
60
  end
@@ -0,0 +1,160 @@
1
+ require 'spec_helper'
2
+
3
+ describe Mongo::Cursor::Builder::GetMoreCommand do
4
+
5
+ describe '#specification' do
6
+
7
+ let(:reply) do
8
+ Mongo::Protocol::Reply.allocate
9
+ end
10
+
11
+ let(:result) do
12
+ Mongo::Operation::Result.new(reply)
13
+ end
14
+
15
+ let(:cursor) do
16
+ Mongo::Cursor.new(view, result, authorized_primary)
17
+ end
18
+
19
+ let(:builder) do
20
+ described_class.new(cursor)
21
+ end
22
+
23
+ let(:specification) do
24
+ builder.specification
25
+ end
26
+
27
+ let(:selector) do
28
+ specification[:selector]
29
+ end
30
+
31
+ shared_examples_for 'a getmore command builder' do
32
+
33
+ it 'includes the database name' do
34
+ expect(specification[:db_name]).to eq(TEST_DB)
35
+ end
36
+
37
+ it 'includes getmore with cursor id' do
38
+ expect(selector[:getMore]).to eq(cursor.id)
39
+ end
40
+
41
+ it 'includes the collection name' do
42
+ expect(selector[:collection]).to eq(TEST_COLL)
43
+ end
44
+ end
45
+
46
+ context 'when the query is standard' do
47
+
48
+ let(:view) do
49
+ Mongo::Collection::View.new(authorized_collection)
50
+ end
51
+
52
+ it_behaves_like 'a getmore command builder'
53
+
54
+ it 'does not include max time' do
55
+ expect(selector[:maxTimeMS]).to be_nil
56
+ end
57
+
58
+ it 'does not include batch size' do
59
+ expect(selector[:batchSize]).to be_nil
60
+ end
61
+ end
62
+
63
+ context 'when the query has a batch size' do
64
+
65
+ let(:view) do
66
+ Mongo::Collection::View.new(authorized_collection, {}, batch_size: 10)
67
+ end
68
+
69
+ it_behaves_like 'a getmore command builder'
70
+
71
+ it 'does not include max time' do
72
+ expect(selector[:maxTimeMS]).to be_nil
73
+ end
74
+
75
+ it 'includes batch size' do
76
+ expect(selector[:batchSize]).to eq(10)
77
+ end
78
+ end
79
+
80
+ context 'when a max await time is specified' do
81
+
82
+ context 'when the cursor is not tailable' do
83
+
84
+ let(:view) do
85
+ Mongo::Collection::View.new(authorized_collection, {}, max_await_time_ms: 100)
86
+ end
87
+
88
+ it_behaves_like 'a getmore command builder'
89
+
90
+ it 'does not include max time' do
91
+ expect(selector[:maxTimeMS]).to be_nil
92
+ end
93
+
94
+ it 'does not include max await time' do
95
+ expect(selector[:maxAwaitTimeMS]).to be_nil
96
+ end
97
+
98
+ it 'does not include batch size' do
99
+ expect(selector[:batchSize]).to be_nil
100
+ end
101
+ end
102
+
103
+ context 'when the cursor is tailable' do
104
+
105
+ context 'when await data is true' do
106
+
107
+ let(:view) do
108
+ Mongo::Collection::View.new(
109
+ authorized_collection,
110
+ {},
111
+ await_data: true,
112
+ tailable: true,
113
+ max_await_time_ms: 100
114
+ )
115
+ end
116
+
117
+ it_behaves_like 'a getmore command builder'
118
+
119
+ it 'includes max time' do
120
+ expect(selector[:maxTimeMS]).to eq(100)
121
+ end
122
+
123
+ it 'does not include max await time' do
124
+ expect(selector[:maxAwaitTimeMS]).to be_nil
125
+ end
126
+
127
+ it 'does not include batch size' do
128
+ expect(selector[:batchSize]).to be_nil
129
+ end
130
+ end
131
+
132
+ context 'when await data is false' do
133
+
134
+ let(:view) do
135
+ Mongo::Collection::View.new(
136
+ authorized_collection,
137
+ {},
138
+ tailable: true,
139
+ max_await_time_ms: 100
140
+ )
141
+ end
142
+
143
+ it_behaves_like 'a getmore command builder'
144
+
145
+ it 'does not include max time' do
146
+ expect(selector[:maxTimeMS]).to be_nil
147
+ end
148
+
149
+ it 'does not include max await time' do
150
+ expect(selector[:maxAwaitTimeMS]).to be_nil
151
+ end
152
+
153
+ it 'does not include batch size' do
154
+ expect(selector[:batchSize]).to be_nil
155
+ end
156
+ end
157
+ end
158
+ end
159
+ end
160
+ end
@@ -0,0 +1,52 @@
1
+ require 'spec_helper'
2
+
3
+ describe Mongo::Cursor::Builder::OpGetMore do
4
+
5
+ describe '#specification' do
6
+
7
+ let(:reply) do
8
+ Mongo::Protocol::Reply.allocate
9
+ end
10
+
11
+ let(:result) do
12
+ Mongo::Operation::Result.new(reply)
13
+ end
14
+
15
+ let(:view) do
16
+ Mongo::Collection::View.new(
17
+ authorized_collection,
18
+ {},
19
+ tailable: true,
20
+ max_time_ms: 100
21
+ )
22
+ end
23
+
24
+ let(:cursor) do
25
+ Mongo::Cursor.new(view, result, authorized_primary)
26
+ end
27
+
28
+ let(:builder) do
29
+ described_class.new(cursor)
30
+ end
31
+
32
+ let(:specification) do
33
+ builder.specification
34
+ end
35
+
36
+ it 'includes to return' do
37
+ expect(specification[:to_return]).to eq(0)
38
+ end
39
+
40
+ it 'includes the cursor id' do
41
+ expect(specification[:cursor_id]).to eq(cursor.id)
42
+ end
43
+
44
+ it 'includes the database name' do
45
+ expect(specification[:db_name]).to eq(TEST_DB)
46
+ end
47
+
48
+ it 'includes the collection name' do
49
+ expect(specification[:coll_name]).to eq(TEST_COLL)
50
+ end
51
+ end
52
+ end
@@ -4,12 +4,16 @@ describe Mongo::Cursor do
4
4
 
5
5
  describe '#each' do
6
6
 
7
+ let(:server) do
8
+ view.read.select_server(authorized_client.cluster)
9
+ end
10
+
7
11
  let(:reply) do
8
- Mongo::Operation::Read::Query.new(query_spec).execute(authorized_primary.context)
12
+ view.send(:send_initial_query, server)
9
13
  end
10
14
 
11
15
  let(:cursor) do
12
- described_class.new(view, reply, authorized_primary)
16
+ described_class.new(view, reply, server)
13
17
  end
14
18
 
15
19
  context 'when no options are provided to the view' do
@@ -18,10 +22,6 @@ describe Mongo::Cursor do
18
22
  Mongo::Collection::View.new(authorized_collection)
19
23
  end
20
24
 
21
- let(:query_spec) do
22
- { :selector => {}, :options => {}, :db_name => TEST_DB, :coll_name => TEST_COLL }
23
- end
24
-
25
25
  context 'when the initial query retieves all documents' do
26
26
 
27
27
  let(:documents) do
@@ -97,15 +97,6 @@ describe Mongo::Cursor do
97
97
  Mongo::Collection::View.new(authorized_collection, {}, :limit => 2)
98
98
  end
99
99
 
100
- let(:query_spec) do
101
- {
102
- :selector => {},
103
- :options => { :limit => 2 },
104
- :db_name => TEST_DB,
105
- :coll_name => TEST_COLL
106
- }
107
- end
108
-
109
100
  it 'returns the correct amount' do
110
101
  expect(cursor.to_a.count).to eq(2)
111
102
  end
@@ -123,17 +114,12 @@ describe Mongo::Cursor do
123
114
  Mongo::Collection::View.new(authorized_collection, {}, :limit => -2)
124
115
  end
125
116
 
126
- let(:query_spec) do
127
- {
128
- :selector => {},
129
- :options => { :limit => -2 },
130
- :db_name => TEST_DB,
131
- :coll_name => TEST_COLL
132
- }
117
+ it 'returns the positive number of documents', unless: find_command_enabled? do
118
+ expect(cursor.to_a.count).to eq(2)
133
119
  end
134
120
 
135
- it 'returns the positive number of documents' do
136
- expect(cursor.to_a.count).to eq(2)
121
+ it 'returns all documents', if: find_command_enabled? do
122
+ expect(cursor.to_a.count).to eq(10)
137
123
  end
138
124
 
139
125
  it 'iterates the documents' do
@@ -149,15 +135,6 @@ describe Mongo::Cursor do
149
135
  Mongo::Collection::View.new(authorized_collection, {}, :limit => 0)
150
136
  end
151
137
 
152
- let(:query_spec) do
153
- {
154
- :selector => {},
155
- :options => { :limit => 0 },
156
- :db_name => TEST_DB,
157
- :coll_name => TEST_COLL
158
- }
159
- end
160
-
161
138
  it 'returns all documents' do
162
139
  expect(cursor.to_a.count).to eq(10)
163
140
  end
@@ -182,15 +159,6 @@ describe Mongo::Cursor do
182
159
  )
183
160
  end
184
161
 
185
- let(:query_spec) do
186
- {
187
- :selector => {},
188
- :options => { :limit => 5, :batch_size => 3 },
189
- :db_name => TEST_DB,
190
- :coll_name => TEST_COLL
191
- }
192
- end
193
-
194
162
  it 'returns the limited number of documents' do
195
163
  expect(cursor.to_a.count).to eq(5)
196
164
  end
@@ -212,15 +180,6 @@ describe Mongo::Cursor do
212
180
  )
213
181
  end
214
182
 
215
- let(:query_spec) do
216
- {
217
- :selector => {},
218
- :options => { :limit => 5, :batch_size => 7 },
219
- :db_name => TEST_DB,
220
- :coll_name => TEST_COLL
221
- }
222
- end
223
-
224
183
  it 'returns the limited number of documents' do
225
184
  expect(cursor.to_a.count).to eq(5)
226
185
  end
@@ -242,15 +201,6 @@ describe Mongo::Cursor do
242
201
  )
243
202
  end
244
203
 
245
- let(:query_spec) do
246
- {
247
- :selector => {},
248
- :options => { :limit => 5, :batch_size => 5 },
249
- :db_name => TEST_DB,
250
- :coll_name => TEST_COLL
251
- }
252
- end
253
-
254
204
  it 'returns the limited number of documents' do
255
205
  expect(cursor.to_a.count).to eq(5)
256
206
  end
@@ -97,19 +97,19 @@ describe Mongo::Database do
97
97
  context 'when there are more collections than the initial batch size' do
98
98
 
99
99
  before do
100
- 200.times do |i|
100
+ 2.times do |i|
101
101
  database["#{i}_dalmatians"].create
102
102
  end
103
103
  end
104
104
 
105
105
  after do
106
- 200.times do |i|
106
+ 2.times do |i|
107
107
  database["#{i}_dalmatians"].drop
108
108
  end
109
109
  end
110
110
 
111
111
  it 'returns all collections' do
112
- expect(database.collection_names.select { |c| c =~ /dalmatians/}.size).to eq(200)
112
+ expect(database.collection_names(batch_size: 1).select { |c| c =~ /dalmatians/}.size).to eq(2)
113
113
  end
114
114
 
115
115
  end
@@ -204,6 +204,27 @@ describe Mongo::Database do
204
204
  expect(database.command(:ismaster => 1).written_count).to eq(0)
205
205
  end
206
206
 
207
+ context 'when a read concern is provided', if: find_command_enabled? do
208
+
209
+ context 'when the read concern is valid' do
210
+
211
+ it 'sends the read concern' do
212
+ expect {
213
+ database.command(:ismaster => 1, readConcern: { level: 'local' })
214
+ }.to_not raise_error
215
+ end
216
+ end
217
+
218
+ context 'when the read concern is not valid' do
219
+
220
+ it 'raises an exception', if: (find_command_enabled? && !sharded?) do
221
+ expect {
222
+ database.command(:ismaster => 1, readConcern: { level: 'yay' })
223
+ }.to raise_error(Mongo::Error::OperationFailure)
224
+ end
225
+ end
226
+ end
227
+
207
228
  context 'when an alternate read preference is specified' do
208
229
 
209
230
  before do