mongo 2.9.2 → 2.10.0.rc0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (227) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data.tar.gz.sig +0 -0
  4. data/lib/mongo.rb +1 -0
  5. data/lib/mongo/auth/user/view.rb +4 -4
  6. data/lib/mongo/bulk_write.rb +14 -8
  7. data/lib/mongo/bulk_write/result.rb +1 -1
  8. data/lib/mongo/bulk_write/result_combiner.rb +2 -2
  9. data/lib/mongo/bulk_write/transformable.rb +17 -9
  10. data/lib/mongo/client.rb +107 -16
  11. data/lib/mongo/cluster.rb +47 -25
  12. data/lib/mongo/cluster/topology/replica_set_no_primary.rb +1 -1
  13. data/lib/mongo/cluster_time.rb +139 -0
  14. data/lib/mongo/collection.rb +84 -25
  15. data/lib/mongo/collection/view.rb +7 -3
  16. data/lib/mongo/collection/view/aggregation.rb +4 -4
  17. data/lib/mongo/collection/view/builder/aggregation.rb +31 -6
  18. data/lib/mongo/collection/view/builder/find_command.rb +4 -1
  19. data/lib/mongo/collection/view/builder/map_reduce.rb +4 -1
  20. data/lib/mongo/collection/view/change_stream.rb +54 -66
  21. data/lib/mongo/collection/view/iterable.rb +2 -2
  22. data/lib/mongo/collection/view/map_reduce.rb +6 -4
  23. data/lib/mongo/collection/view/readable.rb +36 -16
  24. data/lib/mongo/collection/view/writable.rb +68 -22
  25. data/lib/mongo/cursor.rb +87 -20
  26. data/lib/mongo/database.rb +47 -43
  27. data/lib/mongo/database/view.rb +54 -11
  28. data/lib/mongo/error.rb +13 -4
  29. data/lib/mongo/error/invalid_write_concern.rb +2 -2
  30. data/lib/mongo/error/operation_failure.rb +65 -11
  31. data/lib/mongo/error/parser.rb +41 -8
  32. data/lib/mongo/grid/fs_bucket.rb +26 -6
  33. data/lib/mongo/grid/stream/read.rb +9 -2
  34. data/lib/mongo/grid/stream/write.rb +21 -5
  35. data/lib/mongo/index/view.rb +3 -3
  36. data/lib/mongo/lint.rb +10 -3
  37. data/lib/mongo/operation.rb +2 -0
  38. data/lib/mongo/operation/aggregate/result.rb +19 -6
  39. data/lib/mongo/operation/collections_info.rb +1 -1
  40. data/lib/mongo/operation/get_more/result.rb +9 -0
  41. data/lib/mongo/operation/list_collections/command.rb +1 -3
  42. data/lib/mongo/operation/list_collections/op_msg.rb +1 -2
  43. data/lib/mongo/operation/parallel_scan/command.rb +4 -1
  44. data/lib/mongo/operation/parallel_scan/op_msg.rb +4 -1
  45. data/lib/mongo/operation/result.rb +27 -4
  46. data/lib/mongo/operation/shared/executable.rb +19 -5
  47. data/lib/mongo/operation/shared/executable_no_validate.rb +1 -2
  48. data/lib/mongo/operation/shared/executable_transaction_label.rb +0 -9
  49. data/lib/mongo/operation/shared/polymorphic_result.rb +9 -1
  50. data/lib/mongo/operation/shared/result/aggregatable.rb +2 -2
  51. data/lib/mongo/operation/shared/sessions_supported.rb +42 -32
  52. data/lib/mongo/operation/shared/specifiable.rb +40 -0
  53. data/lib/mongo/operation/shared/unpinnable.rb +39 -0
  54. data/lib/mongo/operation/shared/write.rb +1 -1
  55. data/lib/mongo/protocol/update.rb +6 -2
  56. data/lib/mongo/retryable.rb +79 -39
  57. data/lib/mongo/server/connection.rb +10 -3
  58. data/lib/mongo/server/description.rb +25 -1
  59. data/lib/mongo/server/monitor/connection.rb +1 -1
  60. data/lib/mongo/server_selector.rb +10 -0
  61. data/lib/mongo/server_selector/selectable.rb +172 -32
  62. data/lib/mongo/session.rb +654 -581
  63. data/lib/mongo/session/session_pool.rb +1 -1
  64. data/lib/mongo/socket.rb +7 -28
  65. data/lib/mongo/socket/ssl.rb +26 -1
  66. data/lib/mongo/socket/tcp.rb +3 -0
  67. data/lib/mongo/socket/unix.rb +3 -0
  68. data/lib/mongo/uri.rb +112 -265
  69. data/lib/mongo/uri/srv_protocol.rb +4 -1
  70. data/lib/mongo/version.rb +1 -1
  71. data/lib/mongo/write_concern.rb +10 -29
  72. data/lib/mongo/write_concern/acknowledged.rb +12 -0
  73. data/lib/mongo/write_concern/base.rb +17 -13
  74. data/lib/mongo/write_concern/unacknowledged.rb +12 -0
  75. data/spec/atlas/atlas_connectivity_spec.rb +7 -37
  76. data/spec/atlas/operations_spec.rb +25 -0
  77. data/spec/integration/change_stream_examples_spec.rb +45 -31
  78. data/spec/integration/change_stream_spec.rb +305 -5
  79. data/spec/integration/client_spec.rb +44 -0
  80. data/spec/integration/command_monitoring_spec.rb +1 -0
  81. data/spec/integration/command_spec.rb +7 -1
  82. data/spec/integration/mmapv1_spec.rb +28 -0
  83. data/spec/integration/mongos_pinning_spec.rb +34 -0
  84. data/spec/integration/operation_failure_code_spec.rb +2 -2
  85. data/spec/integration/{read_concern.rb → read_concern_spec.rb} +7 -1
  86. data/spec/integration/read_preference_spec.rb +485 -0
  87. data/spec/integration/retryable_writes_spec.rb +8 -19
  88. data/spec/integration/sdam_error_handling_spec.rb +1 -1
  89. data/spec/integration/sdam_events_spec.rb +2 -2
  90. data/spec/integration/server_description_spec.rb +14 -17
  91. data/spec/integration/server_selector_spec.rb +7 -3
  92. data/spec/integration/server_spec.rb +48 -0
  93. data/spec/integration/ssl_uri_options_spec.rb +1 -1
  94. data/spec/integration/step_down_spec.rb +10 -4
  95. data/spec/integration/transactions_examples_spec.rb +11 -10
  96. data/spec/lite_spec_helper.rb +19 -16
  97. data/spec/mongo/auth/scram/negotiation_spec.rb +11 -8
  98. data/spec/mongo/bulk_write/ordered_combiner_spec.rb +6 -6
  99. data/spec/mongo/bulk_write/unordered_combiner_spec.rb +4 -4
  100. data/spec/mongo/bulk_write_spec.rb +12 -2
  101. data/spec/mongo/client_construction_spec.rb +160 -8
  102. data/spec/mongo/client_spec.rb +5 -4
  103. data/spec/mongo/cluster_spec.rb +6 -6
  104. data/spec/mongo/cluster_time_spec.rb +148 -0
  105. data/spec/mongo/collection/view/aggregation_spec.rb +34 -15
  106. data/spec/mongo/collection/view/change_stream_spec.rb +62 -3
  107. data/spec/mongo/collection/view/map_reduce_spec.rb +7 -5
  108. data/spec/mongo/collection/view/readable_spec.rb +4 -4
  109. data/spec/mongo/collection_spec.rb +331 -14
  110. data/spec/mongo/cursor_spec.rb +117 -5
  111. data/spec/mongo/database_spec.rb +240 -8
  112. data/spec/mongo/error/operation_failure_spec.rb +47 -1
  113. data/spec/mongo/error/parser_spec.rb +160 -23
  114. data/spec/mongo/operation/insert/bulk_spec.rb +2 -1
  115. data/spec/mongo/operation/result_spec.rb +27 -0
  116. data/spec/mongo/operation/update/bulk_spec.rb +1 -0
  117. data/spec/mongo/retryable_spec.rb +2 -0
  118. data/spec/mongo/server/app_metadata_spec.rb +2 -2
  119. data/spec/mongo/server/connection_spec.rb +13 -17
  120. data/spec/mongo/server/monitor/connection_spec.rb +13 -10
  121. data/spec/mongo/server_selector_spec.rb +34 -2
  122. data/spec/mongo/session/session_pool_spec.rb +14 -3
  123. data/spec/mongo/session_spec.rb +3 -3
  124. data/spec/mongo/session_transaction_spec.rb +4 -3
  125. data/spec/mongo/socket/ssl_spec.rb +19 -5
  126. data/spec/mongo/socket_spec.rb +1 -62
  127. data/spec/mongo/uri/srv_protocol_spec.rb +14 -20
  128. data/spec/mongo/uri_option_parsing_spec.rb +94 -8
  129. data/spec/mongo/uri_spec.rb +23 -10
  130. data/spec/mongo/write_concern_spec.rb +56 -3
  131. data/spec/spec_tests/change_streams_spec.rb +2 -1
  132. data/spec/spec_tests/cmap_spec.rb +1 -1
  133. data/spec/spec_tests/crud_spec.rb +12 -2
  134. data/spec/spec_tests/data/change_streams/change-streams-errors.yml +24 -1
  135. data/spec/spec_tests/data/change_streams/change-streams.yml +172 -3
  136. data/spec/spec_tests/data/command_monitoring/bulkWrite.yml +1 -1
  137. data/spec/spec_tests/data/command_monitoring/updateMany.yml +0 -2
  138. data/spec/spec_tests/data/command_monitoring/updateOne.yml +0 -5
  139. data/spec/spec_tests/data/crud/read/aggregate-out.yml +0 -6
  140. data/spec/spec_tests/data/crud/read/count-empty.yml +29 -0
  141. data/spec/spec_tests/data/crud/write/bulkWrite-arrayFilters.yml +1 -0
  142. data/spec/spec_tests/data/crud/write/bulkWrite-collation.yml +101 -0
  143. data/spec/spec_tests/data/crud/write/bulkWrite.yml +401 -0
  144. data/spec/spec_tests/data/crud/write/insertMany.yml +58 -2
  145. data/spec/spec_tests/data/crud/write/updateMany-arrayFilters.yml +3 -0
  146. data/spec/spec_tests/data/crud/write/updateOne-arrayFilters.yml +6 -1
  147. data/spec/spec_tests/data/crud_v2/aggregate-merge.yml +103 -0
  148. data/spec/spec_tests/data/crud_v2/aggregate-out-readConcern.yml +110 -0
  149. data/spec/spec_tests/data/crud_v2/bulkWrite-arrayFilters.yml +81 -0
  150. data/spec/spec_tests/data/crud_v2/db-aggregate.yml +38 -0
  151. data/spec/spec_tests/data/crud_v2/updateWithPipelines.yml +92 -0
  152. data/spec/spec_tests/data/retryable_writes/insertOne-serverErrors.yml +2 -2
  153. data/spec/spec_tests/data/transactions/abort.yml +3 -0
  154. data/spec/spec_tests/data/transactions/bulk.yml +3 -8
  155. data/spec/spec_tests/data/transactions/causal-consistency.yml +3 -8
  156. data/spec/spec_tests/data/transactions/commit.yml +3 -1
  157. data/spec/spec_tests/data/transactions/count.yml +3 -0
  158. data/spec/spec_tests/data/transactions/delete.yml +3 -0
  159. data/spec/spec_tests/data/transactions/error-labels.yml +4 -1
  160. data/spec/spec_tests/data/transactions/errors-client.yml +56 -0
  161. data/spec/spec_tests/data/transactions/errors.yml +3 -0
  162. data/spec/spec_tests/data/transactions/findOneAndDelete.yml +3 -0
  163. data/spec/spec_tests/data/transactions/findOneAndReplace.yml +3 -0
  164. data/spec/spec_tests/data/transactions/findOneAndUpdate.yml +3 -0
  165. data/spec/spec_tests/data/transactions/insert.yml +3 -0
  166. data/spec/spec_tests/data/transactions/isolation.yml +3 -0
  167. data/spec/spec_tests/data/transactions/mongos-pin-auto.yml +1671 -0
  168. data/spec/spec_tests/data/transactions/mongos-recovery-token.yml +347 -0
  169. data/spec/spec_tests/data/transactions/pin-mongos.yml +557 -0
  170. data/spec/spec_tests/data/transactions/read-concern.yml +3 -0
  171. data/spec/spec_tests/data/transactions/read-pref.yml +3 -0
  172. data/spec/spec_tests/data/transactions/reads.yml +3 -0
  173. data/spec/spec_tests/data/transactions/retryable-abort.yml +5 -2
  174. data/spec/spec_tests/data/transactions/retryable-commit.yml +4 -1
  175. data/spec/spec_tests/data/transactions/retryable-writes.yml +3 -0
  176. data/spec/spec_tests/data/transactions/run-command.yml +3 -0
  177. data/spec/spec_tests/data/transactions/transaction-options.yml +6 -0
  178. data/spec/spec_tests/data/transactions/update.yml +3 -8
  179. data/spec/spec_tests/data/transactions/write-concern.yml +348 -38
  180. data/spec/spec_tests/data/transactions_api/callback-aborts.yml +6 -0
  181. data/spec/spec_tests/data/transactions_api/callback-commits.yml +5 -0
  182. data/spec/spec_tests/data/transactions_api/callback-retry.yml +7 -2
  183. data/spec/spec_tests/data/transactions_api/commit-retry.yml +70 -15
  184. data/spec/spec_tests/data/transactions_api/commit-transienttransactionerror-4.2.yml +3 -0
  185. data/spec/spec_tests/data/transactions_api/commit-transienttransactionerror.yml +3 -0
  186. data/spec/spec_tests/data/transactions_api/commit-writeconcernerror.yml +59 -109
  187. data/spec/spec_tests/data/transactions_api/commit.yml +5 -0
  188. data/spec/spec_tests/data/transactions_api/transaction-options.yml +10 -0
  189. data/spec/spec_tests/retryable_reads_spec.rb +5 -2
  190. data/spec/spec_tests/retryable_writes_spec.rb +5 -2
  191. data/spec/spec_tests/sdam_monitoring_spec.rb +3 -3
  192. data/spec/spec_tests/sdam_spec.rb +2 -2
  193. data/spec/spec_tests/transactions_api_spec.rb +1 -67
  194. data/spec/spec_tests/transactions_spec.rb +2 -66
  195. data/spec/support/authorization.rb +4 -0
  196. data/spec/support/change_streams.rb +30 -10
  197. data/spec/support/change_streams/operation.rb +27 -0
  198. data/spec/support/client_registry.rb +44 -25
  199. data/spec/support/cluster_config.rb +25 -14
  200. data/spec/support/cluster_tools.rb +32 -10
  201. data/spec/support/command_monitoring.rb +1 -1
  202. data/spec/support/common_shortcuts.rb +30 -0
  203. data/spec/support/connection_string.rb +8 -3
  204. data/spec/support/constraints.rb +34 -0
  205. data/spec/support/crud.rb +31 -16
  206. data/spec/support/crud/context.rb +23 -0
  207. data/spec/support/crud/operation.rb +311 -14
  208. data/spec/support/crud/spec.rb +2 -1
  209. data/spec/support/crud/test.rb +24 -27
  210. data/spec/support/crud/test_base.rb +22 -0
  211. data/spec/support/crud/verifier.rb +15 -1
  212. data/spec/support/event_subscriber.rb +12 -0
  213. data/spec/support/sdam_formatter_integration.rb +12 -6
  214. data/spec/support/shared/server_selector.rb +10 -0
  215. data/spec/support/shared/session.rb +13 -12
  216. data/spec/support/spec_config.rb +32 -22
  217. data/spec/support/spec_setup.rb +2 -2
  218. data/spec/support/transactions.rb +87 -0
  219. data/spec/support/transactions/context.rb +33 -0
  220. data/spec/support/transactions/operation.rb +99 -349
  221. data/spec/support/transactions/spec.rb +1 -3
  222. data/spec/support/transactions/test.rb +110 -49
  223. data/spec/support/utils.rb +74 -1
  224. metadata +52 -10
  225. metadata.gz.sig +0 -0
  226. data/spec/support/crud/read.rb +0 -265
  227. data/spec/support/crud/write.rb +0 -284
@@ -28,17 +28,27 @@ describe Mongo::Cursor do
28
28
  end
29
29
 
30
30
  context 'cursor exhausted by initial result' do
31
+ before do
32
+ ClientRegistry.instance.close_all_clients
33
+ end
34
+
31
35
  let(:view) do
32
36
  Mongo::Collection::View.new(authorized_collection)
33
37
  end
34
38
 
35
39
  it 'does not schedule the finalizer' do
36
- expect(ObjectSpace).not_to receive(:define_finalizer)
37
- cursor
40
+ # Due to https://jira.mongodb.org/browse/RUBY-1772, restrict
41
+ # the scope of the assertion
42
+ RSpec::Mocks.with_temporary_scope do
43
+ expect(ObjectSpace).not_to receive(:define_finalizer)
44
+ cursor
45
+ end
38
46
  end
39
47
  end
40
48
 
41
49
  context 'cursor not exhausted by initial result' do
50
+ clean_slate
51
+
42
52
  let(:view) do
43
53
  Mongo::Collection::View.new(authorized_collection, {}, batch_size: 2)
44
54
  end
@@ -273,7 +283,7 @@ describe Mongo::Cursor do
273
283
  context 'when the cursor is not fully iterated and is garbage collected' do
274
284
 
275
285
  let(:documents) do
276
- (1..3).map{ |i| { field: "test#{i}" }}
286
+ (1..6).map{ |i| { field: "test#{i}" }}
277
287
  end
278
288
 
279
289
  let(:cluster) do
@@ -304,14 +314,42 @@ describe Mongo::Cursor do
304
314
  cluster.instance_variable_get(:@periodic_executor).flush
305
315
  expect {
306
316
  cursor.to_a
307
- }.to raise_exception(Mongo::Error::OperationFailure)
317
+ }.to raise_exception(Mongo::Error::OperationFailure, /[cC]ursor.*not found/)
308
318
  end
309
319
 
310
320
  context 'when the cursor is unregistered before the kill cursors operations are executed' do
311
321
 
312
322
  it 'does not send a kill cursors operation for the unregistered cursor' do
323
+ # We need to verify that the cursor was able to retrieve more documents
324
+ # from the server so that more than one batch is successfully received
325
+
313
326
  cluster.unregister_cursor(cursor.id)
314
- expect(cursor.to_a.size).to eq(documents.size)
327
+
328
+ # The initial read is done on an enum obtained from the cursor.
329
+ # The read below is done directly on the cursor. These are two
330
+ # different objects. In MRI, iterating like this yields all of the
331
+ # documents, hence we retrieved one document in the setup and
332
+ # we expect to retrieve the remaining 5 here. In JRuby it appears that
333
+ # the enum may buffers the first batch, such that the second document
334
+ # sometimes is lost to the iteration and we retrieve 4 documents below.
335
+ # But sometimes we get all 5 documents. In either case, all of the
336
+ # documents are retrieved via two batches thus fulfilling the
337
+ # requirement of the test to continue iterating the cursor.
338
+
339
+ =begin When repeated iteration of cursors is prohibited, these are the expectations
340
+ if BSON::Environment.jruby?
341
+ expected_counts = [4, 5]
342
+ else
343
+ expected_counts = [5]
344
+ end
345
+ =end
346
+
347
+ # Since currently repeated iteration of cursors is allowed, calling
348
+ # to_a on the cursor would perform such an iteration and return
349
+ # all documents of the initial read.
350
+ expected_counts = [6]
351
+
352
+ expect(expected_counts).to include(cursor.to_a.size)
315
353
  end
316
354
  end
317
355
  end
@@ -460,4 +498,78 @@ describe Mongo::Cursor do
460
498
  expect(cursor.inspect).to match(/.*#{view.inspect}.*/)
461
499
  end
462
500
  end
501
+
502
+ describe '#to_a' do
503
+
504
+ let(:view) do
505
+ Mongo::Collection::View.new(authorized_collection, {}, batch_size: 10)
506
+ end
507
+
508
+ let(:query_spec) do
509
+ { :selector => {}, :options => {}, :db_name => SpecConfig.instance.test_db,
510
+ :coll_name => authorized_collection.name }
511
+ end
512
+
513
+ let(:reply) do
514
+ view.send(:send_initial_query, authorized_primary)
515
+ end
516
+
517
+ let(:cursor) do
518
+ described_class.new(view, reply, authorized_primary)
519
+ end
520
+
521
+ context 'after partially iterating the cursor' do
522
+ before do
523
+ authorized_collection.drop
524
+ docs = []
525
+ 100.times do |i|
526
+ docs << {a: i}
527
+ end
528
+ authorized_collection.insert_many(docs)
529
+ end
530
+
531
+ context 'after #each was called once' do
532
+ before do
533
+ cursor.each do |doc|
534
+ break
535
+ end
536
+ end
537
+
538
+ it 'iterates from the beginning of the view' do
539
+ expect(cursor.to_a.map { |doc| doc['a'] }).to eq((0..99).to_a)
540
+ end
541
+ end
542
+
543
+ context 'after exactly one batch was iterated' do
544
+ before do
545
+ cursor.each_with_index do |doc, i|
546
+ break if i == 9
547
+ end
548
+ end
549
+
550
+ it 'iterates from the beginning of the view' do
551
+ expect(cursor.to_a.map { |doc| doc['a'] }).to eq((0..99).to_a)
552
+ end
553
+ end
554
+
555
+ context 'after two batches were iterated' do
556
+ before do
557
+ cursor.each_with_index do |doc, i|
558
+ break if i == 19
559
+ end
560
+ end
561
+
562
+ =begin Behavior of pre-2.10 driver:
563
+ it 'skips the second batch' do
564
+ expect(cursor.to_a.map { |doc| doc['a'] }).to eq((0..9).to_a + (20..99).to_a)
565
+ end
566
+ =end
567
+ it 'raises NotImplementedError' do
568
+ expect do
569
+ cursor.to_a
570
+ end.to raise_error(NotImplementedError, 'Cannot restart iteration of a cursor which issued a getMore')
571
+ end
572
+ end
573
+ end
574
+ end
463
575
  end
@@ -96,12 +96,25 @@ describe Mongo::Database do
96
96
  database[:users].create
97
97
  end
98
98
 
99
+ let(:actual) do
100
+ database.collection_names
101
+ end
102
+
99
103
  it 'returns the stripped names of the collections' do
100
- expect(database.collection_names).to include('users')
104
+ expect(actual).to include('users')
101
105
  end
102
106
 
103
107
  it 'does not include system collections' do
104
- expect(database.collection_names).to_not include('system.indexes')
108
+ expect(actual).to_not include('version')
109
+ expect(actual).to_not include('system.version')
110
+ end
111
+
112
+ context 'on 2.6 server' do
113
+ max_server_version '2.6'
114
+ end
115
+
116
+ it 'does not include collections with $ in names' do
117
+ expect(actual.none? { |name| name.include?('$') }).to be true
105
118
  end
106
119
 
107
120
  context 'when provided a session' do
@@ -136,7 +149,9 @@ describe Mongo::Database do
136
149
  end
137
150
 
138
151
  it 'returns all collections' do
139
- expect(database.collection_names(batch_size: 1).select { |c| c =~ /dalmatians/}.size).to eq(2)
152
+ collection_names = database.collection_names(batch_size: 1)
153
+ expect(collection_names).to include('0_dalmatians')
154
+ expect(collection_names).to include('1_dalmatians')
140
155
  end
141
156
 
142
157
  end
@@ -155,15 +170,15 @@ describe Mongo::Database do
155
170
  end
156
171
 
157
172
  before do
158
- database[:users].drop
159
- database[:users].create
173
+ database[:acol].drop
174
+ database[:acol].create
160
175
  end
161
176
 
162
177
  context 'server 3.0+' do
163
178
  min_server_fcv '3.0'
164
179
 
165
180
  it 'returns a list of the collections info' do
166
- expect(result).to include('users')
181
+ expect(result).to include('acol')
167
182
  end
168
183
  end
169
184
 
@@ -171,7 +186,37 @@ describe Mongo::Database do
171
186
  max_server_fcv '2.6'
172
187
 
173
188
  it 'returns a list of the collections info' do
174
- expect(result).to include("#{SpecConfig.instance.test_db}.users")
189
+ expect(result).to include("#{SpecConfig.instance.test_db}.acol")
190
+ end
191
+ end
192
+
193
+ it 'does not include collections with $ in names' do
194
+ expect(result.none? { |name| name.include?('$') }).to be true
195
+ end
196
+
197
+ context 'on admin database' do
198
+ let(:database) do
199
+ described_class.new(root_authorized_client, 'admin')
200
+ end
201
+
202
+ it 'does not include system collections' do
203
+ expect(result.none? { |name| name =~ /(^|\.)system\./ }).to be true
204
+ end
205
+
206
+ context 'server 3.0+' do
207
+ min_server_fcv '3.0'
208
+
209
+ it 'returns results' do
210
+ expect(result).to include('acol')
211
+ end
212
+ end
213
+
214
+ context 'server 2.6-' do
215
+ max_server_version '2.6'
216
+
217
+ it 'returns results' do
218
+ expect(result).to include('admin.acol')
219
+ end
175
220
  end
176
221
  end
177
222
  end
@@ -197,8 +242,21 @@ describe Mongo::Database do
197
242
  expect(database.collections).to include(collection)
198
243
  end
199
244
 
245
+ it 'does not include collections with $ in names' do
246
+ expect(database.collections.none? { |c| c.name.include?('$') }).to be true
247
+ end
248
+ end
249
+
250
+ context 'on admin database' do
251
+
252
+ let(:database) do
253
+ described_class.new(root_authorized_client, 'admin')
254
+ end
255
+
200
256
  it 'does not include the system collections' do
201
- expect(database.collections.collect(&:name).none? { |name| name =~ /system\.|\$/ }).to be(true)
257
+ collection_names = database.collections.map(&:name)
258
+ expect(collection_names).not_to include('system.version')
259
+ expect(collection_names.none? { |name| name =~ /(^|\.)system\./ }).to be true
202
260
  end
203
261
  end
204
262
 
@@ -631,4 +689,178 @@ describe Mongo::Database do
631
689
  end
632
690
  end
633
691
  end
692
+
693
+ describe '#write_concern' do
694
+
695
+ let(:client) do
696
+ new_local_client(['127.0.0.1:27017'],
697
+ {monitoring_io: false}.merge(client_options))
698
+ end
699
+
700
+ let(:database) { client.database }
701
+
702
+ context 'when client write concern uses :write' do
703
+
704
+ let(:client_options) do
705
+ { :write => { :w => 1 } }
706
+ end
707
+
708
+ it 'is the correct write concern' do
709
+ expect(database.write_concern).to be_a(Mongo::WriteConcern::Acknowledged)
710
+ expect(database.write_concern.options).to eq(w: 1)
711
+ end
712
+ end
713
+
714
+ context 'when client write concern uses :write_concern' do
715
+
716
+ let(:client_options) do
717
+ { :write_concern => { :w => 1 } }
718
+ end
719
+
720
+ it 'is the correct write concern' do
721
+ expect(database.write_concern).to be_a(Mongo::WriteConcern::Acknowledged)
722
+ expect(database.write_concern.options).to eq(w: 1)
723
+ end
724
+ end
725
+ end
726
+
727
+ describe '#aggregate' do
728
+ min_server_fcv '3.6'
729
+
730
+ let(:client) do
731
+ root_authorized_admin_client
732
+ end
733
+
734
+ let(:database) { client.database }
735
+
736
+ let(:pipeline) do
737
+ [{'$currentOp' => {}}]
738
+ end
739
+
740
+ describe 'updating cluster time' do
741
+ # The shared examples use their own client which we cannot override
742
+ # from here, and it uses the wrong credentials for admin database which
743
+ # is the one we need for our pipeline when auth is on.
744
+ require_no_auth
745
+
746
+ let(:database_via_client) do
747
+ client.use(:admin).database
748
+ end
749
+
750
+ let(:operation) do
751
+ database_via_client.aggregate(pipeline).first
752
+ end
753
+
754
+ let(:operation_with_session) do
755
+ database_via_client.aggregate(pipeline, session: session).first
756
+ end
757
+
758
+ let(:second_operation) do
759
+ database_via_client.aggregate(pipeline, session: session).first
760
+ end
761
+
762
+ it_behaves_like 'an operation updating cluster time'
763
+ end
764
+
765
+ it 'returns an Aggregation object' do
766
+ expect(database.aggregate(pipeline)).to be_a(Mongo::Collection::View::Aggregation)
767
+ end
768
+
769
+ context 'when options are provided' do
770
+
771
+ let(:options) do
772
+ { :allow_disk_use => true, :bypass_document_validation => true }
773
+ end
774
+
775
+ it 'sets the options on the Aggregation object' do
776
+ expect(database.aggregate(pipeline, options).options).to eq(BSON::Document.new(options))
777
+ end
778
+
779
+ context 'when the :comment option is provided' do
780
+
781
+ let(:options) do
782
+ { :comment => 'testing' }
783
+ end
784
+
785
+ it 'sets the options on the Aggregation object' do
786
+ expect(database.aggregate(pipeline, options).options).to eq(BSON::Document.new(options))
787
+ end
788
+ end
789
+
790
+ context 'when a session is provided' do
791
+
792
+ let(:session) do
793
+ client.start_session
794
+ end
795
+
796
+ let(:operation) do
797
+ database.aggregate(pipeline, session: session).to_a
798
+ end
799
+
800
+ let(:failed_operation) do
801
+ database.aggregate([ { '$invalid' => 1 }], session: session).to_a
802
+ end
803
+
804
+ it_behaves_like 'an operation using a session'
805
+ it_behaves_like 'a failed operation using a session'
806
+ end
807
+
808
+ context 'when a hint is provided' do
809
+
810
+ let(:options) do
811
+ { 'hint' => { 'y' => 1 } }
812
+ end
813
+
814
+ it 'sets the options on the Aggregation object' do
815
+ expect(database.aggregate(pipeline, options).options).to eq(options)
816
+ end
817
+ end
818
+
819
+ context 'when collation is provided' do
820
+
821
+ let(:pipeline) do
822
+ [{ "$currentOp" => {} }]
823
+ end
824
+
825
+ let(:options) do
826
+ { collation: { locale: 'en_US', strength: 2 } }
827
+ end
828
+
829
+ let(:result) do
830
+ database.aggregate(pipeline, options).collect { |doc| doc.keys.grep(/host/).first }
831
+ end
832
+
833
+ context 'when the server selected supports collations' do
834
+ min_server_fcv '3.4'
835
+
836
+ it 'applies the collation' do
837
+ expect(result.uniq).to eq(['host'])
838
+ end
839
+ end
840
+
841
+ context 'when the server selected does not support collations' do
842
+ max_server_version '3.2'
843
+
844
+ it 'raises an exception' do
845
+ expect {
846
+ result
847
+ }.to raise_exception(Mongo::Error::UnsupportedCollation)
848
+ end
849
+
850
+ context 'when a String key is used' do
851
+
852
+ let(:options) do
853
+ { 'collation' => { locale: 'en_US', strength: 2 } }
854
+ end
855
+
856
+ it 'raises an exception' do
857
+ expect {
858
+ result
859
+ }.to raise_exception(Mongo::Error::UnsupportedCollation)
860
+ end
861
+ end
862
+ end
863
+ end
864
+ end
865
+ end
634
866
  end