mongo 2.13.2 → 2.14.0.rc1

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 (174) 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 +9 -0
  5. data/lib/mongo/address.rb +1 -1
  6. data/lib/mongo/address/ipv4.rb +1 -1
  7. data/lib/mongo/address/ipv6.rb +1 -1
  8. data/lib/mongo/bulk_write.rb +17 -0
  9. data/lib/mongo/caching_cursor.rb +74 -0
  10. data/lib/mongo/client.rb +47 -8
  11. data/lib/mongo/cluster.rb +3 -3
  12. data/lib/mongo/cluster/topology/single.rb +1 -1
  13. data/lib/mongo/collection.rb +26 -0
  14. data/lib/mongo/collection/view.rb +24 -20
  15. data/lib/mongo/collection/view/aggregation.rb +25 -4
  16. data/lib/mongo/collection/view/builder/find_command.rb +38 -18
  17. data/lib/mongo/collection/view/explainable.rb +27 -8
  18. data/lib/mongo/collection/view/iterable.rb +72 -12
  19. data/lib/mongo/collection/view/readable.rb +12 -2
  20. data/lib/mongo/collection/view/writable.rb +15 -1
  21. data/lib/mongo/crypt/encryption_io.rb +6 -6
  22. data/lib/mongo/cursor.rb +1 -0
  23. data/lib/mongo/database.rb +6 -0
  24. data/lib/mongo/database/view.rb +1 -1
  25. data/lib/mongo/error.rb +2 -0
  26. data/lib/mongo/error/invalid_read_concern.rb +28 -0
  27. data/lib/mongo/error/server_certificate_revoked.rb +22 -0
  28. data/lib/mongo/error/unsupported_option.rb +14 -12
  29. data/lib/mongo/lint.rb +2 -1
  30. data/lib/mongo/logger.rb +3 -3
  31. data/lib/mongo/operation.rb +2 -0
  32. data/lib/mongo/operation/aggregate/result.rb +9 -8
  33. data/lib/mongo/operation/collections_info/command.rb +0 -5
  34. data/lib/mongo/operation/collections_info/result.rb +3 -16
  35. data/lib/mongo/operation/delete/bulk_result.rb +2 -0
  36. data/lib/mongo/operation/delete/result.rb +3 -0
  37. data/lib/mongo/operation/explain/command.rb +4 -0
  38. data/lib/mongo/operation/explain/legacy.rb +4 -0
  39. data/lib/mongo/operation/explain/op_msg.rb +6 -0
  40. data/lib/mongo/operation/explain/result.rb +3 -0
  41. data/lib/mongo/operation/find/legacy/result.rb +2 -0
  42. data/lib/mongo/operation/find/result.rb +3 -0
  43. data/lib/mongo/operation/get_more/result.rb +3 -0
  44. data/lib/mongo/operation/indexes/result.rb +5 -0
  45. data/lib/mongo/operation/insert/bulk_result.rb +5 -0
  46. data/lib/mongo/operation/insert/result.rb +5 -0
  47. data/lib/mongo/operation/list_collections/result.rb +5 -0
  48. data/lib/mongo/operation/map_reduce/result.rb +10 -0
  49. data/lib/mongo/operation/parallel_scan/result.rb +4 -0
  50. data/lib/mongo/operation/result.rb +35 -6
  51. data/lib/mongo/operation/shared/bypass_document_validation.rb +1 -0
  52. data/lib/mongo/operation/shared/causal_consistency_supported.rb +1 -0
  53. data/lib/mongo/operation/shared/collections_info_or_list_collections.rb +2 -0
  54. data/lib/mongo/operation/shared/executable.rb +1 -0
  55. data/lib/mongo/operation/shared/idable.rb +2 -1
  56. data/lib/mongo/operation/shared/limited.rb +1 -0
  57. data/lib/mongo/operation/shared/object_id_generator.rb +1 -0
  58. data/lib/mongo/operation/shared/result/aggregatable.rb +1 -0
  59. data/lib/mongo/operation/shared/sessions_supported.rb +1 -0
  60. data/lib/mongo/operation/shared/specifiable.rb +1 -0
  61. data/lib/mongo/operation/shared/write.rb +1 -0
  62. data/lib/mongo/operation/shared/write_concern_supported.rb +1 -0
  63. data/lib/mongo/operation/update/legacy/result.rb +7 -0
  64. data/lib/mongo/operation/update/result.rb +8 -0
  65. data/lib/mongo/operation/users_info/result.rb +3 -0
  66. data/lib/mongo/query_cache.rb +242 -0
  67. data/lib/mongo/retryable.rb +8 -1
  68. data/lib/mongo/server.rb +5 -1
  69. data/lib/mongo/server/connection_common.rb +2 -2
  70. data/lib/mongo/server/connection_pool.rb +3 -0
  71. data/lib/mongo/server/monitor.rb +1 -1
  72. data/lib/mongo/server/monitor/connection.rb +3 -3
  73. data/lib/mongo/server/pending_connection.rb +2 -2
  74. data/lib/mongo/server/push_monitor.rb +1 -1
  75. data/lib/mongo/server_selector/base.rb +5 -1
  76. data/lib/mongo/session.rb +3 -0
  77. data/lib/mongo/socket.rb +6 -4
  78. data/lib/mongo/socket/ocsp_cache.rb +97 -0
  79. data/lib/mongo/socket/ocsp_verifier.rb +368 -0
  80. data/lib/mongo/socket/ssl.rb +45 -24
  81. data/lib/mongo/srv/monitor.rb +7 -13
  82. data/lib/mongo/srv/resolver.rb +14 -10
  83. data/lib/mongo/timeout.rb +2 -0
  84. data/lib/mongo/uri.rb +21 -390
  85. data/lib/mongo/uri/options_mapper.rb +582 -0
  86. data/lib/mongo/uri/srv_protocol.rb +3 -2
  87. data/lib/mongo/utils.rb +12 -1
  88. data/lib/mongo/version.rb +1 -1
  89. data/spec/NOTES.aws-auth.md +12 -7
  90. data/spec/README.md +56 -1
  91. data/spec/integration/bson_symbol_spec.rb +2 -4
  92. data/spec/integration/bulk_write_spec.rb +48 -0
  93. data/spec/integration/client_authentication_options_spec.rb +55 -28
  94. data/spec/integration/connection_pool_populator_spec.rb +3 -1
  95. data/spec/integration/cursor_reaping_spec.rb +53 -17
  96. data/spec/integration/ocsp_connectivity_spec.rb +26 -0
  97. data/spec/integration/ocsp_verifier_cache_spec.rb +188 -0
  98. data/spec/integration/ocsp_verifier_spec.rb +334 -0
  99. data/spec/integration/query_cache_spec.rb +1045 -0
  100. data/spec/integration/query_cache_transactions_spec.rb +179 -0
  101. data/spec/integration/retryable_writes/retryable_writes_40_and_newer_spec.rb +1 -0
  102. data/spec/integration/retryable_writes/shared/performs_legacy_retries.rb +2 -0
  103. data/spec/integration/sdam_error_handling_spec.rb +68 -17
  104. data/spec/integration/sdam_events_spec.rb +5 -8
  105. data/spec/integration/server_selection_spec.rb +36 -0
  106. data/spec/integration/srv_monitoring_spec.rb +38 -3
  107. data/spec/integration/srv_spec.rb +56 -0
  108. data/spec/lite_spec_helper.rb +4 -2
  109. data/spec/mongo/address_spec.rb +1 -1
  110. data/spec/mongo/caching_cursor_spec.rb +70 -0
  111. data/spec/mongo/client_construction_spec.rb +54 -1
  112. data/spec/mongo/client_encryption_spec.rb +10 -16
  113. data/spec/mongo/client_spec.rb +40 -0
  114. data/spec/mongo/cluster/topology/single_spec.rb +14 -5
  115. data/spec/mongo/cluster_spec.rb +3 -0
  116. data/spec/mongo/collection/view/explainable_spec.rb +87 -4
  117. data/spec/mongo/collection/view/map_reduce_spec.rb +2 -0
  118. data/spec/mongo/collection_spec.rb +60 -0
  119. data/spec/mongo/crypt/auto_decryption_context_spec.rb +1 -1
  120. data/spec/mongo/crypt/auto_encryption_context_spec.rb +1 -1
  121. data/spec/mongo/crypt/data_key_context_spec.rb +1 -1
  122. data/spec/mongo/crypt/explicit_decryption_context_spec.rb +1 -1
  123. data/spec/mongo/crypt/explicit_encryption_context_spec.rb +1 -1
  124. data/spec/mongo/database_spec.rb +44 -64
  125. data/spec/mongo/error/no_server_available_spec.rb +1 -1
  126. data/spec/mongo/logger_spec.rb +13 -11
  127. data/spec/mongo/query_cache_spec.rb +279 -0
  128. data/spec/mongo/server/app_metadata_shared.rb +1 -1
  129. data/spec/mongo/server/connection_pool_spec.rb +7 -3
  130. data/spec/mongo/server/connection_spec.rb +14 -7
  131. data/spec/mongo/socket/ssl_spec.rb +1 -1
  132. data/spec/mongo/socket_spec.rb +1 -1
  133. data/spec/mongo/uri/srv_protocol_spec.rb +64 -33
  134. data/spec/mongo/uri_option_parsing_spec.rb +11 -11
  135. data/spec/mongo/uri_spec.rb +68 -41
  136. data/spec/mongo/utils_spec.rb +39 -0
  137. data/spec/runners/auth.rb +3 -0
  138. data/spec/runners/connection_string.rb +35 -124
  139. data/spec/spec_tests/cmap_spec.rb +7 -3
  140. data/spec/spec_tests/data/change_streams/change-streams-errors.yml +0 -1
  141. data/spec/spec_tests/data/change_streams/change-streams.yml +0 -1
  142. data/spec/spec_tests/data/cmap/pool-checkout-connection.yml +6 -2
  143. data/spec/spec_tests/data/cmap/pool-create-min-size.yml +3 -0
  144. data/spec/spec_tests/data/connection_string/valid-warnings.yml +24 -0
  145. data/spec/spec_tests/data/sdam_monitoring/discovered_standalone.yml +1 -3
  146. data/spec/spec_tests/data/sdam_monitoring/standalone.yml +2 -2
  147. data/spec/spec_tests/data/sdam_monitoring/standalone_repeated.yml +2 -2
  148. data/spec/spec_tests/data/sdam_monitoring/standalone_suppress_equal_description_changes.yml +2 -2
  149. data/spec/spec_tests/data/sdam_monitoring/standalone_to_rs_with_me_mismatch.yml +2 -2
  150. data/spec/spec_tests/data/uri_options/auth-options.yml +25 -0
  151. data/spec/spec_tests/data/uri_options/compression-options.yml +6 -3
  152. data/spec/spec_tests/data/uri_options/read-preference-options.yml +24 -0
  153. data/spec/spec_tests/data/uri_options/ruby-connection-options.yml +1 -0
  154. data/spec/spec_tests/data/uri_options/tls-options.yml +160 -4
  155. data/spec/spec_tests/dns_seedlist_discovery_spec.rb +9 -1
  156. data/spec/spec_tests/uri_options_spec.rb +31 -33
  157. data/spec/support/certificates/atlas-ocsp-ca.crt +28 -0
  158. data/spec/support/certificates/atlas-ocsp.crt +41 -0
  159. data/spec/support/client_registry_macros.rb +11 -2
  160. data/spec/support/common_shortcuts.rb +45 -0
  161. data/spec/support/constraints.rb +23 -0
  162. data/spec/support/lite_constraints.rb +24 -0
  163. data/spec/support/matchers.rb +16 -0
  164. data/spec/support/ocsp +1 -0
  165. data/spec/support/session_registry.rb +52 -0
  166. data/spec/support/spec_config.rb +22 -0
  167. data/spec/support/utils.rb +19 -1
  168. metadata +1017 -992
  169. metadata.gz.sig +0 -0
  170. data/spec/shared/LICENSE +0 -20
  171. data/spec/shared/lib/mrss/child_process_helper.rb +0 -80
  172. data/spec/shared/lib/mrss/constraints.rb +0 -303
  173. data/spec/shared/lib/mrss/lite_constraints.rb +0 -175
  174. data/spec/shared/lib/mrss/spec_organizer.rb +0 -149
@@ -76,7 +76,7 @@ describe Mongo::Crypt::AutoDecryptionContext do
76
76
  end
77
77
 
78
78
  let(:logger) do
79
- ::Logger.new($stdout).tap do |logger|
79
+ ::Logger.new(STDOUT).tap do |logger|
80
80
  logger.level = ::Logger::DEBUG
81
81
  end
82
82
  end
@@ -93,7 +93,7 @@ describe Mongo::Crypt::AutoEncryptionContext do
93
93
  end
94
94
 
95
95
  let(:logger) do
96
- ::Logger.new($stdout).tap do |logger|
96
+ ::Logger.new(STDOUT).tap do |logger|
97
97
  logger.level = ::Logger::DEBUG
98
98
  end
99
99
  end
@@ -188,7 +188,7 @@ describe Mongo::Crypt::DataKeyContext do
188
188
  end
189
189
 
190
190
  context 'with valid endpoint' do
191
- let(:options) { { master_key: { region: 'us-east-2', key: 'arn', endpoint: 'kms.us-east-2.amazonaws.com:443' } } }
191
+ let(:options) { { master_key: { region: 'us-east-2', key: 'arn', endpoint: 'endpoint/to/kms' } } }
192
192
 
193
193
  it 'does not raise an exception' do
194
194
  expect do
@@ -57,7 +57,7 @@ describe Mongo::Crypt::ExplicitDecryptionContext do
57
57
  end
58
58
 
59
59
  let(:logger) do
60
- ::Logger.new($stdout).tap do |logger|
60
+ ::Logger.new(STDOUT).tap do |logger|
61
61
  logger.level = ::Logger::DEBUG
62
62
  end
63
63
  end
@@ -153,7 +153,7 @@ describe Mongo::Crypt::ExplicitEncryptionContext do
153
153
 
154
154
  let(:key_alt_name) { nil }
155
155
  let(:logger) do
156
- ::Logger.new($stdout).tap do |logger|
156
+ ::Logger.new(STDOUT).tap do |logger|
157
157
  logger.level = ::Logger::DEBUG
158
158
  end
159
159
  end
@@ -2,19 +2,6 @@ require 'spec_helper'
2
2
 
3
3
  describe Mongo::Database do
4
4
 
5
- shared_context 'more than 100 collections' do
6
- let(:client) do
7
- root_authorized_client.use('many-collections')
8
- end
9
-
10
- before do
11
- 120.times do |i|
12
- client["coll-#{i}"].drop
13
- client["coll-#{i}"].create
14
- end
15
- end
16
- end
17
-
18
5
  describe '#==' do
19
6
 
20
7
  let(:database) do
@@ -241,20 +228,6 @@ describe Mongo::Database do
241
228
  end
242
229
  end
243
230
  end
244
-
245
- context 'when there are more than 100 collections' do
246
- include_context 'more than 100 collections'
247
-
248
- let(:collection_names) do
249
- client.database.collection_names.sort
250
- end
251
-
252
- it 'lists all collections' do
253
- collection_names.length.should == 120
254
- collection_names.should include('coll-0')
255
- collection_names.should include('coll-119')
256
- end
257
- end
258
231
  end
259
232
 
260
233
  describe '#list_collections' do
@@ -418,25 +391,6 @@ describe Mongo::Database do
418
391
  end
419
392
  end
420
393
  end
421
-
422
- context 'when there are more than 100 collections' do
423
- include_context 'more than 100 collections'
424
-
425
- let(:collections) do
426
- client.database.list_collections
427
- end
428
-
429
- let(:collection_names) do
430
- # 2.6 server prefixes collection names with database name
431
- collections.map { |info| info['name'].sub(/^many-collections\./, '') }.sort
432
- end
433
-
434
- it 'lists all collections' do
435
- collections.length.should == 120
436
- collection_names.should include('coll-0')
437
- collection_names.should include('coll-119')
438
- end
439
- end
440
394
  end
441
395
 
442
396
  describe '#collections' do
@@ -587,24 +541,6 @@ describe Mongo::Database do
587
541
  end
588
542
  end
589
543
  end
590
-
591
- context 'when there are more than 100 collections' do
592
- include_context 'more than 100 collections'
593
-
594
- let(:collections) do
595
- client.database.collections
596
- end
597
-
598
- let(:collection_names) do
599
- collections.map(&:name).sort
600
- end
601
-
602
- it 'lists all collections' do
603
- collections.length.should == 120
604
- collection_names.should include('coll-0')
605
- collection_names.should include('coll-119')
606
- end
607
- end
608
544
  end
609
545
 
610
546
  describe '#command' do
@@ -889,6 +825,50 @@ describe Mongo::Database do
889
825
  end
890
826
  end
891
827
 
828
+ context 'when write concern is passed in as an option' do
829
+ min_server_fcv '3.4'
830
+ require_topology :single
831
+
832
+ let(:client_options) do
833
+ {
834
+ write_concern: {w: 0},
835
+ database: :test
836
+ }
837
+ end
838
+
839
+ let(:session) do
840
+ client.start_session
841
+ end
842
+
843
+ let(:subscriber) { EventSubscriber.new }
844
+
845
+ let(:client) do
846
+ root_authorized_client.tap do |client|
847
+ client.subscribe(Mongo::Monitoring::COMMAND, subscriber)
848
+ end.with(client_options)
849
+ end
850
+
851
+ let(:events) do
852
+ subscriber.command_started_events('dropDatabase')
853
+ end
854
+
855
+ let(:database_test_wc) do
856
+ client.database
857
+ end
858
+
859
+ let!(:command) do
860
+ Utils.get_command_event(client, 'dropDatabase') do |client|
861
+ database_test_wc.drop({ write_concern: {w: 'majority'} })
862
+ end.command
863
+ end
864
+
865
+ it 'applies the write concern passed in as an option' do
866
+ expect(events.length).to eq(1)
867
+ expect(command).to_not be_nil
868
+ expect(command[:writeConcern][:w]).to eq('majority')
869
+ end
870
+ end
871
+
892
872
  context 'when the server does not support write concern on the dropDatabase command' do
893
873
  max_server_version '3.2'
894
874
 
@@ -16,7 +16,7 @@ describe Mongo::Error::NoServerAvailable do
16
16
  end
17
17
 
18
18
  it 'is correct' do
19
- expect(error.message).to eq('No primary server is available in cluster: #<Cluster topology=Unknown[127.0.0.1:27017] servers=[#<Server address=127.0.0.1:27017 UNKNOWN>]> with timeout=30, LT=0.015')
19
+ expect(error.message).to eq('No primary server is available in cluster: #<Cluster topology=Unknown[127.0.0.1:27017] servers=[#<Server address=127.0.0.1:27017 UNKNOWN NO-MONITORING>]> with timeout=30, LT=0.015')
20
20
  end
21
21
 
22
22
  context 'when cluster is nil' do
@@ -6,6 +6,16 @@ describe Mongo::Logger do
6
6
  described_class.logger
7
7
  end
8
8
 
9
+ around do |example|
10
+ saved_logger = Mongo::Logger.logger
11
+
12
+ begin
13
+ example.run
14
+ ensure
15
+ Mongo::Logger.logger = saved_logger
16
+ end
17
+ end
18
+
9
19
  describe '.logger' do
10
20
 
11
21
  context 'when no logger has been set' do
@@ -18,25 +28,21 @@ describe Mongo::Logger do
18
28
  Mongo::Logger.logger = nil
19
29
  end
20
30
 
21
- after do
22
- Mongo::Logger.logger = test_logger
23
- end
24
-
25
31
  it 'returns the default logger' do
26
- expect(logger.level).to eq(Logger::DEBUG)
32
+ expect(logger.level).to eq(Logger::INFO)
27
33
  end
28
34
  end
29
35
 
30
36
  context 'when a logger has been set' do
31
37
 
32
38
  let(:info) do
33
- Logger.new($stdout).tap do |log|
39
+ Logger.new(STDOUT).tap do |log|
34
40
  log.level = Logger::INFO
35
41
  end
36
42
  end
37
43
 
38
44
  let(:debug) do
39
- Logger.new($stdout).tap do |log|
45
+ Logger.new(STDOUT).tap do |log|
40
46
  log.level = Logger::DEBUG
41
47
  end
42
48
  end
@@ -45,10 +51,6 @@ describe Mongo::Logger do
45
51
  described_class.logger = debug
46
52
  end
47
53
 
48
- after do
49
- described_class.logger = info
50
- end
51
-
52
54
  it 'returns the provided logger' do
53
55
  expect(logger.level).to eq(Logger::DEBUG)
54
56
  end
@@ -0,0 +1,279 @@
1
+ require 'spec_helper'
2
+
3
+ describe Mongo::QueryCache do
4
+
5
+ around do |spec|
6
+ Mongo::QueryCache.clear
7
+ Mongo::QueryCache.cache { spec.run }
8
+ end
9
+
10
+ before do
11
+ authorized_collection.delete_many
12
+ end
13
+
14
+ let(:subscriber) { EventSubscriber.new }
15
+
16
+ let(:client) do
17
+ authorized_client.tap do |client|
18
+ client.subscribe(Mongo::Monitoring::COMMAND, subscriber)
19
+ end
20
+ end
21
+
22
+ let(:authorized_collection) { client['collection_spec'] }
23
+
24
+ let(:events) do
25
+ subscriber.command_started_events('find')
26
+ end
27
+
28
+ describe '#enabled' do
29
+
30
+ context 'when query cache is disabled' do
31
+
32
+ before do
33
+ Mongo::QueryCache.enabled = false
34
+ end
35
+
36
+ it 'disables the query cache' do
37
+ expect(Mongo::QueryCache.enabled?).to be(false)
38
+ end
39
+ end
40
+
41
+ context 'when query cache is enabled' do
42
+
43
+ before do
44
+ Mongo::QueryCache.enabled = true
45
+ end
46
+
47
+ it 'enables the query cache' do
48
+ expect(Mongo::QueryCache.enabled?).to be(true)
49
+ end
50
+ end
51
+ end
52
+
53
+ describe '#cache' do
54
+
55
+ before do
56
+ Mongo::QueryCache.enabled = false
57
+ end
58
+
59
+ it 'enables the query cache inside the block' do
60
+ Mongo::QueryCache.cache do
61
+ expect(Mongo::QueryCache.enabled?).to be(true)
62
+ end
63
+ expect(Mongo::QueryCache.enabled?).to be(false)
64
+ end
65
+ end
66
+
67
+ describe '#uncached' do
68
+
69
+ it 'disables the query cache inside the block' do
70
+ Mongo::QueryCache.uncached do
71
+ expect(Mongo::QueryCache.enabled?).to be(false)
72
+ end
73
+ expect(Mongo::QueryCache.enabled?).to be(true)
74
+ end
75
+ end
76
+
77
+ describe '#cache_table' do
78
+
79
+ before do
80
+ authorized_collection.insert_one({ name: 'testing' })
81
+ authorized_collection.find(name: 'testing').to_a
82
+ end
83
+
84
+ it 'gets the cached query' do
85
+ expect(Mongo::QueryCache.send(:cache_table).length).to eq(1)
86
+ authorized_collection.find(name: 'testing').to_a
87
+ expect(events.length).to eq(1)
88
+ end
89
+ end
90
+
91
+ describe '#clear' do
92
+
93
+ before do
94
+ authorized_collection.insert_one({ name: 'testing' })
95
+ authorized_collection.find(name: 'testing').to_a
96
+ end
97
+
98
+ it 'clears the cache' do
99
+ expect(Mongo::QueryCache.send(:cache_table).length).to eq(1)
100
+ Mongo::QueryCache.clear
101
+ expect(Mongo::QueryCache.send(:cache_table).length).to eq(0)
102
+ end
103
+ end
104
+
105
+ describe '#set' do
106
+ let(:caching_cursor) { double("Mongo::CachingCursor") }
107
+ let(:namespace) { 'db.coll' }
108
+ let(:selector) { { field: 'value' } }
109
+ let(:skip) { 5 }
110
+ let(:sort) { { field: 'asc' } }
111
+ let(:limit) { 5 }
112
+ let(:projection) { { field: 1 } }
113
+ let(:collation) { { locale: 'fr_CA' } }
114
+ let(:read_concern) { { level: :majority } }
115
+ let(:read_preference) { { mode: :secondary } }
116
+
117
+ let(:options) do
118
+ {
119
+ namespace: namespace,
120
+ selector: selector,
121
+ skip: skip,
122
+ sort: sort,
123
+ limit: limit,
124
+ projection: projection,
125
+ collation: collation,
126
+ read_concern: read_concern,
127
+ read_preference: read_preference,
128
+ }
129
+ end
130
+
131
+ it 'stores the cursor at the correct key' do
132
+ Mongo::QueryCache.set(caching_cursor, **options)
133
+ expect(Mongo::QueryCache.send(:cache_table)[namespace][[namespace, selector, skip, sort, projection, collation, read_concern, read_preference]]).to eq(caching_cursor)
134
+ end
135
+ end
136
+
137
+ describe '#get' do
138
+ let(:view) { double("Mongo::Collection::View") }
139
+ let(:result) { double("Mongo::Operation::Result") }
140
+ let(:server) { double("Mongo::Server") }
141
+ let(:caching_cursor) { Mongo::CachingCursor.new(view, result, server) }
142
+
143
+ let(:options) do
144
+ {
145
+ namespace: 'db.coll',
146
+ selector: { field: 'value' },
147
+ }
148
+ end
149
+
150
+ before do
151
+ allow(result).to receive(:cursor_id) { 0 }
152
+ allow(view).to receive(:limit) { nil }
153
+ end
154
+
155
+ context 'when there is no entry in the cache' do
156
+ it 'returns nil' do
157
+ expect(Mongo::QueryCache.get(**options)).to be_nil
158
+ end
159
+ end
160
+
161
+ context 'when there is an entry in the cache' do
162
+ before do
163
+ Mongo::QueryCache.set(caching_cursor, **caching_cursor_options)
164
+ end
165
+
166
+ context 'when that entry has no limit' do
167
+ let(:caching_cursor_options) do
168
+ {
169
+ namespace: 'db.coll',
170
+ selector: { field: 'value' },
171
+ }
172
+ end
173
+
174
+ let(:query_options) do
175
+ caching_cursor_options.merge(limit: limit)
176
+ end
177
+
178
+ context 'when the query has a limit' do
179
+ let(:limit) { 5 }
180
+
181
+ it 'returns the caching cursor' do
182
+ expect(Mongo::QueryCache.get(**query_options)).to eq(caching_cursor)
183
+ end
184
+ end
185
+
186
+ context 'when the query has no limit' do
187
+ let(:limit) { nil }
188
+
189
+ it 'returns the caching cursor' do
190
+ expect(Mongo::QueryCache.get(**query_options)).to eq(caching_cursor)
191
+ end
192
+ end
193
+ end
194
+
195
+ context 'when that entry has a limit' do
196
+ let(:caching_cursor_options) do
197
+ {
198
+ namespace: 'db.coll',
199
+ selector: { field: 'value' },
200
+ limit: 5,
201
+ }
202
+ end
203
+
204
+ let(:query_options) do
205
+ caching_cursor_options.merge(limit: limit)
206
+ end
207
+
208
+ before do
209
+ allow(view).to receive(:limit) { 5 }
210
+ end
211
+
212
+ context 'and the new query has a smaller limit' do
213
+ let(:limit) { 4 }
214
+
215
+ it 'returns the caching cursor' do
216
+ expect(Mongo::QueryCache.get(**query_options)).to eq(caching_cursor)
217
+ end
218
+ end
219
+
220
+ context 'and the new query has a larger limit' do
221
+ let(:limit) { 6 }
222
+
223
+ it 'returns nil' do
224
+ expect(Mongo::QueryCache.get(**query_options)).to be_nil
225
+ end
226
+ end
227
+
228
+ context 'and the new query has the same limit' do
229
+ let(:limit) { 5 }
230
+
231
+ it 'returns the caching cursor' do
232
+ expect(Mongo::QueryCache.get(**query_options)).to eq(caching_cursor)
233
+ end
234
+ end
235
+
236
+ context 'and the new query has no limit' do
237
+ let(:limit) { nil }
238
+
239
+ it 'returns nil' do
240
+ expect(Mongo::QueryCache.get(**query_options)).to be_nil
241
+ end
242
+ end
243
+ end
244
+ end
245
+ end
246
+
247
+ describe '#clear_namespace' do
248
+ let(:caching_cursor) { double("Mongo::CachingCursor") }
249
+ let(:namespace1) { 'db.coll' }
250
+ let(:namespace2) { 'db.coll2' }
251
+ let(:namespace3) { 'db.coll3' }
252
+ let(:selector) { { field: 'value' } }
253
+
254
+ before do
255
+ Mongo::QueryCache.set(caching_cursor, namespace: namespace1, selector: selector)
256
+ Mongo::QueryCache.set(caching_cursor, namespace: namespace2, selector: selector)
257
+ Mongo::QueryCache.set(caching_cursor, namespace: namespace3, selector: selector, multi_collection: true)
258
+ end
259
+
260
+ it 'returns nil' do
261
+ expect(Mongo::QueryCache.clear_namespace(namespace1)).to be_nil
262
+ end
263
+
264
+ it 'clears the specified namespace in the query cache' do
265
+ Mongo::QueryCache.clear_namespace(namespace1)
266
+ expect(Mongo::QueryCache.send(:cache_table)[namespace1]).to be_nil
267
+ end
268
+
269
+ it 'does not clear other namespaces in the query cache' do
270
+ Mongo::QueryCache.clear_namespace(namespace1)
271
+ expect(Mongo::QueryCache.send(:cache_table)[namespace2]).not_to be_nil
272
+ end
273
+
274
+ it 'clears the nil namespace' do
275
+ Mongo::QueryCache.clear_namespace(namespace1)
276
+ expect(Mongo::QueryCache.send(:cache_table)[nil]).to be_nil
277
+ end
278
+ end
279
+ end