mongo 2.13.1 → 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 (161) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data.tar.gz.sig +1 -4
  4. data/lib/mongo.rb +9 -0
  5. data/lib/mongo/address/ipv4.rb +1 -1
  6. data/lib/mongo/address/ipv6.rb +1 -1
  7. data/lib/mongo/bulk_write.rb +17 -0
  8. data/lib/mongo/caching_cursor.rb +74 -0
  9. data/lib/mongo/client.rb +47 -8
  10. data/lib/mongo/cluster.rb +3 -3
  11. data/lib/mongo/cluster/topology/single.rb +1 -1
  12. data/lib/mongo/collection.rb +26 -0
  13. data/lib/mongo/collection/view.rb +24 -20
  14. data/lib/mongo/collection/view/aggregation.rb +25 -4
  15. data/lib/mongo/collection/view/builder/find_command.rb +38 -18
  16. data/lib/mongo/collection/view/explainable.rb +27 -8
  17. data/lib/mongo/collection/view/iterable.rb +72 -12
  18. data/lib/mongo/collection/view/readable.rb +12 -2
  19. data/lib/mongo/collection/view/writable.rb +15 -1
  20. data/lib/mongo/crypt/encryption_io.rb +6 -6
  21. data/lib/mongo/cursor.rb +1 -0
  22. data/lib/mongo/database.rb +6 -0
  23. data/lib/mongo/error.rb +2 -0
  24. data/lib/mongo/error/invalid_read_concern.rb +28 -0
  25. data/lib/mongo/error/server_certificate_revoked.rb +22 -0
  26. data/lib/mongo/error/unsupported_option.rb +14 -12
  27. data/lib/mongo/lint.rb +2 -1
  28. data/lib/mongo/logger.rb +3 -3
  29. data/lib/mongo/operation.rb +2 -0
  30. data/lib/mongo/operation/aggregate/result.rb +9 -8
  31. data/lib/mongo/operation/collections_info/result.rb +2 -0
  32. data/lib/mongo/operation/delete/bulk_result.rb +2 -0
  33. data/lib/mongo/operation/delete/result.rb +3 -0
  34. data/lib/mongo/operation/explain/command.rb +4 -0
  35. data/lib/mongo/operation/explain/legacy.rb +4 -0
  36. data/lib/mongo/operation/explain/op_msg.rb +6 -0
  37. data/lib/mongo/operation/explain/result.rb +3 -0
  38. data/lib/mongo/operation/find/legacy/result.rb +2 -0
  39. data/lib/mongo/operation/find/result.rb +3 -0
  40. data/lib/mongo/operation/get_more/result.rb +3 -0
  41. data/lib/mongo/operation/indexes/result.rb +5 -0
  42. data/lib/mongo/operation/insert/bulk_result.rb +5 -0
  43. data/lib/mongo/operation/insert/result.rb +5 -0
  44. data/lib/mongo/operation/list_collections/result.rb +5 -0
  45. data/lib/mongo/operation/map_reduce/result.rb +10 -0
  46. data/lib/mongo/operation/parallel_scan/result.rb +4 -0
  47. data/lib/mongo/operation/result.rb +35 -6
  48. data/lib/mongo/operation/shared/bypass_document_validation.rb +1 -0
  49. data/lib/mongo/operation/shared/causal_consistency_supported.rb +1 -0
  50. data/lib/mongo/operation/shared/collections_info_or_list_collections.rb +2 -0
  51. data/lib/mongo/operation/shared/executable.rb +1 -0
  52. data/lib/mongo/operation/shared/idable.rb +2 -1
  53. data/lib/mongo/operation/shared/limited.rb +1 -0
  54. data/lib/mongo/operation/shared/object_id_generator.rb +1 -0
  55. data/lib/mongo/operation/shared/result/aggregatable.rb +1 -0
  56. data/lib/mongo/operation/shared/sessions_supported.rb +1 -0
  57. data/lib/mongo/operation/shared/specifiable.rb +1 -0
  58. data/lib/mongo/operation/shared/write.rb +1 -0
  59. data/lib/mongo/operation/shared/write_concern_supported.rb +1 -0
  60. data/lib/mongo/operation/update/legacy/result.rb +7 -0
  61. data/lib/mongo/operation/update/result.rb +8 -0
  62. data/lib/mongo/operation/users_info/result.rb +3 -0
  63. data/lib/mongo/query_cache.rb +242 -0
  64. data/lib/mongo/retryable.rb +8 -1
  65. data/lib/mongo/server.rb +5 -1
  66. data/lib/mongo/server/connection_common.rb +2 -2
  67. data/lib/mongo/server/connection_pool.rb +3 -0
  68. data/lib/mongo/server/monitor.rb +1 -1
  69. data/lib/mongo/server/monitor/connection.rb +3 -3
  70. data/lib/mongo/server/pending_connection.rb +2 -2
  71. data/lib/mongo/server/push_monitor.rb +1 -1
  72. data/lib/mongo/server_selector/base.rb +5 -1
  73. data/lib/mongo/session.rb +3 -0
  74. data/lib/mongo/socket.rb +6 -4
  75. data/lib/mongo/socket/ocsp_cache.rb +97 -0
  76. data/lib/mongo/socket/ocsp_verifier.rb +368 -0
  77. data/lib/mongo/socket/ssl.rb +45 -24
  78. data/lib/mongo/srv/monitor.rb +7 -13
  79. data/lib/mongo/srv/resolver.rb +14 -10
  80. data/lib/mongo/timeout.rb +2 -0
  81. data/lib/mongo/uri.rb +21 -390
  82. data/lib/mongo/uri/options_mapper.rb +582 -0
  83. data/lib/mongo/uri/srv_protocol.rb +3 -2
  84. data/lib/mongo/utils.rb +12 -1
  85. data/lib/mongo/version.rb +1 -1
  86. data/spec/NOTES.aws-auth.md +12 -7
  87. data/spec/README.md +56 -1
  88. data/spec/integration/bulk_write_spec.rb +48 -0
  89. data/spec/integration/client_authentication_options_spec.rb +55 -28
  90. data/spec/integration/connection_pool_populator_spec.rb +3 -1
  91. data/spec/integration/cursor_reaping_spec.rb +53 -17
  92. data/spec/integration/ocsp_connectivity_spec.rb +26 -0
  93. data/spec/integration/ocsp_verifier_cache_spec.rb +188 -0
  94. data/spec/integration/ocsp_verifier_spec.rb +334 -0
  95. data/spec/integration/query_cache_spec.rb +1045 -0
  96. data/spec/integration/query_cache_transactions_spec.rb +179 -0
  97. data/spec/integration/retryable_writes/retryable_writes_40_and_newer_spec.rb +1 -0
  98. data/spec/integration/retryable_writes/shared/performs_legacy_retries.rb +2 -0
  99. data/spec/integration/sdam_error_handling_spec.rb +68 -0
  100. data/spec/integration/server_selection_spec.rb +36 -0
  101. data/spec/integration/srv_monitoring_spec.rb +38 -3
  102. data/spec/integration/srv_spec.rb +56 -0
  103. data/spec/lite_spec_helper.rb +3 -1
  104. data/spec/mongo/address_spec.rb +1 -1
  105. data/spec/mongo/caching_cursor_spec.rb +70 -0
  106. data/spec/mongo/client_construction_spec.rb +54 -1
  107. data/spec/mongo/client_spec.rb +40 -0
  108. data/spec/mongo/cluster/topology/single_spec.rb +14 -5
  109. data/spec/mongo/cluster_spec.rb +3 -0
  110. data/spec/mongo/collection/view/explainable_spec.rb +87 -4
  111. data/spec/mongo/collection/view/map_reduce_spec.rb +2 -0
  112. data/spec/mongo/collection_spec.rb +60 -0
  113. data/spec/mongo/crypt/auto_decryption_context_spec.rb +1 -1
  114. data/spec/mongo/crypt/auto_encryption_context_spec.rb +1 -1
  115. data/spec/mongo/crypt/explicit_decryption_context_spec.rb +1 -1
  116. data/spec/mongo/crypt/explicit_encryption_context_spec.rb +1 -1
  117. data/spec/mongo/database_spec.rb +44 -0
  118. data/spec/mongo/error/no_server_available_spec.rb +1 -1
  119. data/spec/mongo/logger_spec.rb +13 -11
  120. data/spec/mongo/query_cache_spec.rb +279 -0
  121. data/spec/mongo/server/connection_pool_spec.rb +7 -3
  122. data/spec/mongo/server/connection_spec.rb +14 -7
  123. data/spec/mongo/socket/ssl_spec.rb +1 -1
  124. data/spec/mongo/socket_spec.rb +1 -1
  125. data/spec/mongo/uri/srv_protocol_spec.rb +64 -33
  126. data/spec/mongo/uri_option_parsing_spec.rb +11 -11
  127. data/spec/mongo/uri_spec.rb +68 -41
  128. data/spec/mongo/utils_spec.rb +39 -0
  129. data/spec/runners/auth.rb +3 -0
  130. data/spec/runners/connection_string.rb +35 -124
  131. data/spec/spec_tests/cmap_spec.rb +7 -3
  132. data/spec/spec_tests/data/change_streams/change-streams-errors.yml +0 -1
  133. data/spec/spec_tests/data/change_streams/change-streams.yml +0 -1
  134. data/spec/spec_tests/data/cmap/pool-checkout-connection.yml +6 -2
  135. data/spec/spec_tests/data/cmap/pool-create-min-size.yml +3 -0
  136. data/spec/spec_tests/data/connection_string/valid-warnings.yml +24 -0
  137. data/spec/spec_tests/data/sdam_monitoring/discovered_standalone.yml +1 -3
  138. data/spec/spec_tests/data/sdam_monitoring/standalone.yml +2 -2
  139. data/spec/spec_tests/data/sdam_monitoring/standalone_repeated.yml +2 -2
  140. data/spec/spec_tests/data/sdam_monitoring/standalone_suppress_equal_description_changes.yml +2 -2
  141. data/spec/spec_tests/data/sdam_monitoring/standalone_to_rs_with_me_mismatch.yml +2 -2
  142. data/spec/spec_tests/data/uri_options/auth-options.yml +25 -0
  143. data/spec/spec_tests/data/uri_options/compression-options.yml +6 -3
  144. data/spec/spec_tests/data/uri_options/read-preference-options.yml +24 -0
  145. data/spec/spec_tests/data/uri_options/ruby-connection-options.yml +1 -0
  146. data/spec/spec_tests/data/uri_options/tls-options.yml +160 -4
  147. data/spec/spec_tests/dns_seedlist_discovery_spec.rb +9 -1
  148. data/spec/spec_tests/uri_options_spec.rb +31 -33
  149. data/spec/support/certificates/atlas-ocsp-ca.crt +28 -0
  150. data/spec/support/certificates/atlas-ocsp.crt +41 -0
  151. data/spec/support/client_registry_macros.rb +11 -2
  152. data/spec/support/common_shortcuts.rb +45 -0
  153. data/spec/support/constraints.rb +23 -0
  154. data/spec/support/lite_constraints.rb +24 -0
  155. data/spec/support/matchers.rb +16 -0
  156. data/spec/support/ocsp +1 -0
  157. data/spec/support/session_registry.rb +52 -0
  158. data/spec/support/spec_config.rb +22 -0
  159. data/spec/support/utils.rb +19 -1
  160. metadata +38 -3
  161. metadata.gz.sig +0 -0
@@ -60,7 +60,15 @@ describe 'DNS Seedlist Discovery' do
60
60
  end
61
61
 
62
62
  it 'creates a client with the correct options' do
63
- expect(test.client).to match_options(test)
63
+ mapped = Mongo::URI::OptionsMapper.new.ruby_to_smc(test.client.options)
64
+ # Connection string spec tests do not use canonical URI option names
65
+ actual = Utils.downcase_keys(mapped)
66
+ expected = Utils.downcase_keys(test.options)
67
+ # SRV tests use ssl URI option instead of tls one
68
+ if expected.key?('ssl') && !expected.key?('tls')
69
+ expected['tls'] = expected.delete('ssl')
70
+ end
71
+ actual.should == expected
64
72
  end
65
73
  end
66
74
  end
@@ -2,7 +2,7 @@ require 'lite_spec_helper'
2
2
 
3
3
  require 'runners/connection_string'
4
4
 
5
- describe 'Uri Options' do
5
+ describe 'URI options' do
6
6
  include Mongo::ConnectionString
7
7
 
8
8
  # Since the tests issue global assertions on Mongo::Logger,
@@ -22,39 +22,23 @@ describe 'Uri Options' do
22
22
  require_mongo_kerberos
23
23
  end
24
24
 
25
- context 'when the uri should warn', if: test.warn? do
25
+ if test.valid?
26
26
 
27
- before do
28
- expect(Mongo::Logger.logger).to receive(:warn)
29
- end
30
-
31
- it 'warns' do
32
- expect(test.client).to be_a(Mongo::Client)
33
- end
34
- end
35
-
36
- context 'when the uri is invalid', unless: test.valid? do
37
-
38
- it 'raises an error' do
39
- expect{
40
- test.uri
41
- }.to raise_exception(Mongo::Error::InvalidURI)
42
- end
43
- end
44
-
45
- context 'when the uri should not warn', if: !test.warn? && test.valid? do
46
-
47
- before do
48
- expect(Mongo::Logger.logger).not_to receive(:warn)
27
+ # The warning assertion needs to be first because the test caches
28
+ # the client instance, and subsequent examples don't instantiate it
29
+ # again.
30
+ if test.warn?
31
+ it 'warns' do
32
+ expect(Mongo::Logger.logger).to receive(:warn)#.and_call_original
33
+ expect(test.client).to be_a(Mongo::Client)
34
+ end
35
+ else
36
+ it 'does not warn' do
37
+ expect(Mongo::Logger.logger).not_to receive(:warn)
38
+ expect(test.client).to be_a(Mongo::Client)
39
+ end
49
40
  end
50
41
 
51
- it 'does not raise an exception or warning' do
52
- expect(test.client).to be_a(Mongo::Client)
53
- end
54
- end
55
-
56
- context 'when the uri is valid', if: test.valid? do
57
-
58
42
  if test.hosts
59
43
  it 'creates a client with the correct hosts' do
60
44
  expect(test.client).to have_hosts(test, test.hosts)
@@ -65,8 +49,22 @@ describe 'Uri Options' do
65
49
  expect(test.client).to match_auth(test)
66
50
  end
67
51
 
68
- it 'creates a client with the correct options' do
69
- expect(test.client).to match_options(test)
52
+ if test.options
53
+ it 'creates a client with the correct options' do
54
+ mapped = Mongo::URI::OptionsMapper.new.ruby_to_smc(test.client.options)
55
+ expected = Mongo::ConnectionString.adjust_expected_mongo_client_options(
56
+ test.options,
57
+ )
58
+ mapped.should == expected
59
+ end
60
+ end
61
+
62
+ else
63
+
64
+ it 'raises an error' do
65
+ expect{
66
+ test.uri
67
+ }.to raise_exception(Mongo::Error::InvalidURI)
70
68
  end
71
69
  end
72
70
  end
@@ -0,0 +1,28 @@
1
+ -----BEGIN CERTIFICATE-----
2
+ MIIElDCCA3ygAwIBAgIQAf2j627KdciIQ4tyS8+8kTANBgkqhkiG9w0BAQsFADBh
3
+ MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3
4
+ d3cuZGlnaWNlcnQuY29tMSAwHgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBD
5
+ QTAeFw0xMzAzMDgxMjAwMDBaFw0yMzAzMDgxMjAwMDBaME0xCzAJBgNVBAYTAlVT
6
+ MRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxJzAlBgNVBAMTHkRpZ2lDZXJ0IFNIQTIg
7
+ U2VjdXJlIFNlcnZlciBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB
8
+ ANyuWJBNwcQwFZA1W248ghX1LFy949v/cUP6ZCWA1O4Yok3wZtAKc24RmDYXZK83
9
+ nf36QYSvx6+M/hpzTc8zl5CilodTgyu5pnVILR1WN3vaMTIa16yrBvSqXUu3R0bd
10
+ KpPDkC55gIDvEwRqFDu1m5K+wgdlTvza/P96rtxcflUxDOg5B6TXvi/TC2rSsd9f
11
+ /ld0Uzs1gN2ujkSYs58O09rg1/RrKatEp0tYhG2SS4HD2nOLEpdIkARFdRrdNzGX
12
+ kujNVA075ME/OV4uuPNcfhCOhkEAjUVmR7ChZc6gqikJTvOX6+guqw9ypzAO+sf0
13
+ /RR3w6RbKFfCs/mC/bdFWJsCAwEAAaOCAVowggFWMBIGA1UdEwEB/wQIMAYBAf8C
14
+ AQAwDgYDVR0PAQH/BAQDAgGGMDQGCCsGAQUFBwEBBCgwJjAkBggrBgEFBQcwAYYY
15
+ aHR0cDovL29jc3AuZGlnaWNlcnQuY29tMHsGA1UdHwR0MHIwN6A1oDOGMWh0dHA6
16
+ Ly9jcmwzLmRpZ2ljZXJ0LmNvbS9EaWdpQ2VydEdsb2JhbFJvb3RDQS5jcmwwN6A1
17
+ oDOGMWh0dHA6Ly9jcmw0LmRpZ2ljZXJ0LmNvbS9EaWdpQ2VydEdsb2JhbFJvb3RD
18
+ QS5jcmwwPQYDVR0gBDYwNDAyBgRVHSAAMCowKAYIKwYBBQUHAgEWHGh0dHBzOi8v
19
+ d3d3LmRpZ2ljZXJ0LmNvbS9DUFMwHQYDVR0OBBYEFA+AYRyCMWHVLyjnjUY4tCzh
20
+ xtniMB8GA1UdIwQYMBaAFAPeUDVW0Uy7ZvCj4hsbw5eyPdFVMA0GCSqGSIb3DQEB
21
+ CwUAA4IBAQAjPt9L0jFCpbZ+QlwaRMxp0Wi0XUvgBCFsS+JtzLHgl4+mUwnNqipl
22
+ 5TlPHoOlblyYoiQm5vuh7ZPHLgLGTUq/sELfeNqzqPlt/yGFUzZgTHbO7Djc1lGA
23
+ 8MXW5dRNJ2Srm8c+cftIl7gzbckTB+6WohsYFfZcTEDts8Ls/3HB40f/1LkAtDdC
24
+ 2iDJ6m6K7hQGrn2iWZiIqBtvLfTyyRRfJs8sjX7tN8Cp1Tm5gr8ZDOo0rwAhaPit
25
+ c+LJMto4JQtV05od8GiG7S5BNO98pVAdvzr508EIDObtHopYJeS4d60tbvVS3bR0
26
+ j6tJLp07kzQoH3jOlOrHvdPJbRzeXDLz
27
+ -----END CERTIFICATE-----
28
+
@@ -0,0 +1,41 @@
1
+ -----BEGIN CERTIFICATE-----
2
+ MIIHOjCCBiKgAwIBAgIQBHwKuME6qrWYg7D7VTlKYjANBgkqhkiG9w0BAQsFADBN
3
+ MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMScwJQYDVQQDEx5E
4
+ aWdpQ2VydCBTSEEyIFNlY3VyZSBTZXJ2ZXIgQ0EwHhcNMTgwMjA3MDAwMDAwWhcN
5
+ MjEwNTA3MDAwMDAwWjB7MQswCQYDVQQGEwJVUzERMA8GA1UECBMITmV3IFlvcmsx
6
+ ETAPBgNVBAcTCE5ldyBZb3JrMRYwFAYDVQQKEw1Nb25nb0RCLCBJbmMuMRIwEAYD
7
+ VQQLEwlDbG91ZCBTUkUxGjAYBgNVBAMMESoubW9uZ29kYi1kZXYubmV0MIIBIjAN
8
+ BgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA0oEdsION7ajeosGKBaZ4szN58kFz
9
+ 4EHBrgGs7N5X+4weolk4LouU0nUO2SDwjdJL5Kpbb1rUb3satTVAuNj2CDp3LynW
10
+ Zggtf3OCbBHMKmFUMxYiriEGU/BCHo+qKlWj0eM1qRWC/9qjbg5+pvnhYEOYZgMw
11
+ rIjD8V/j/8fO2mfBTpK+5xXeLXaIZKLgFlHWhLueTBONhSjGCHCKuI9xL6lBys3s
12
+ QqsSMZY1weecD4jP8nVxuHpOnwdWOo2BH8d4nh8PowQYSjbrKm2n1cDGnak7oqZ4
13
+ hpR4zjG04zOrLzw9p5uzUj4ofPhsaUC9K4sLAh01PZRnIl9tIvQkp0Xc8QIDAQAB
14
+ o4ID5jCCA+IwHwYDVR0jBBgwFoAUD4BhHIIxYdUvKOeNRji0LOHG2eIwHQYDVR0O
15
+ BBYEFCN2C7OPPJfzGKESo8DdeuMzXWFLMC0GA1UdEQQmMCSCESoubW9uZ29kYi1k
16
+ ZXYubmV0gg9tb25nb2RiLWRldi5uZXQwDgYDVR0PAQH/BAQDAgWgMB0GA1UdJQQW
17
+ MBQGCCsGAQUFBwMBBggrBgEFBQcDAjBrBgNVHR8EZDBiMC+gLaArhilodHRwOi8v
18
+ Y3JsMy5kaWdpY2VydC5jb20vc3NjYS1zaGEyLWc2LmNybDAvoC2gK4YpaHR0cDov
19
+ L2NybDQuZGlnaWNlcnQuY29tL3NzY2Etc2hhMi1nNi5jcmwwTAYDVR0gBEUwQzA3
20
+ BglghkgBhv1sAQEwKjAoBggrBgEFBQcCARYcaHR0cHM6Ly93d3cuZGlnaWNlcnQu
21
+ Y29tL0NQUzAIBgZngQwBAgIwfAYIKwYBBQUHAQEEcDBuMCQGCCsGAQUFBzABhhho
22
+ dHRwOi8vb2NzcC5kaWdpY2VydC5jb20wRgYIKwYBBQUHMAKGOmh0dHA6Ly9jYWNl
23
+ cnRzLmRpZ2ljZXJ0LmNvbS9EaWdpQ2VydFNIQTJTZWN1cmVTZXJ2ZXJDQS5jcnQw
24
+ DAYDVR0TAQH/BAIwADCCAfkGCisGAQQB1nkCBAIEggHpBIIB5QHjAHcApLkJkLQY
25
+ WBSHuxOizGdwCjw1mAT5G9+443fNDsgN3BAAAAFhcQh6hAAABAMASDBGAiEAsBwl
26
+ EUAJoqWKGHlG1Iw+Z9hr3RPPySoPT4PBjWRnWpcCIQC7V9EFENl7Pk6NOwRo1joZ
27
+ OB4UNyZh1YVlQOXyZK0tUgB2AId1v+dZfPiMQ5lfvfNu/1aNR1Y2/0q1YMG06v9e
28
+ oIMPAAABYXEIep0AAAQDAEcwRQIhALvaijTUDDPJgr79QDHN7102E3hpilLEmV02
29
+ D5jbI3efAiB18NNDifebYBRBALyVFZf5TPwMJ4Hb//roHdTf+dqbVwB3ALvZ37wf
30
+ inG1k5Qjl6qSe0c4V5UKq1LoGpCWZDaOHtGFAAABYXEIehQAAAQDAEgwRgIhAJao
31
+ S5aKuudv9ZA4dUD/gEzdHZsF3M9xsa+KZHZzinT1AiEA1zAQMKp2pa8/Or5soC7M
32
+ HrsykWEXY3lpFCsyQM+RPHUAdwBvU3asMfAxGdiZAKRRFf93FRwR2QLBACkGjbII
33
+ mjfZEwAAAWFxCHyrAAAEAwBIMEYCIQDhtxcQCz916LqV/RKhTNOi39LW4dMPAl7Q
34
+ eWPTaUk3dAIhAOgQiFAYkgJvun9hZk/wWZ8PaZJOGnKnkLdTM3j7ZdTNMA0GCSqG
35
+ SIb3DQEBCwUAA4IBAQB6rK1wA1IsQCZVSXooVt79EgF3JMlgyCRZKTFD1KZtkKG7
36
+ n9YI0Aatw3hvKpo8OV4KC1Iw1Ie6JwbVTczyHApROLSeSHTtxbfiNXmYqNVECSQt
37
+ I+dHAYc38EKCb/XgxqfFra0vJRcCzd1yHLKJ6uERI6cJ7/vkLqJiRScHNh49Py8Y
38
+ Osijdqd0BZnwAdFKpPtmvPNPH9JWu8RlcfWUukJKF1YgzeCjz50DL47Ykqh7C8aA
39
+ T9B5yzkDNBg65zZSeDnX6FFo0ZC8BMxqN+kCyk3favP3NP8FBmkEZPqY0wMh3Xsd
40
+ OdSNdcGPBlN4MiTOIkWW6JrZl6y/hQ83ktYG8wwY
41
+ -----END CERTIFICATE-----
@@ -4,8 +4,17 @@ module ClientRegistryMacros
4
4
  end
5
5
 
6
6
  def new_local_client_nmio(address, options=nil)
7
- new_local_client(address, Mongo::Options::Redacted.new(
8
- monitoring_io: false).merge(options || {}))
7
+ # Avoid type converting options.
8
+ base_options = {monitoring_io: false}
9
+ if BSON::Document === options || options&.keys&.any? { |key| String === key }
10
+ base_options = Mongo::Options::Redacted.new(base_options)
11
+ end
12
+ options = if options
13
+ base_options.merge(options)
14
+ else
15
+ base_options
16
+ end
17
+ new_local_client(address, options)
9
18
  end
10
19
 
11
20
  def close_local_clients
@@ -96,6 +96,51 @@ module CommonShortcuts
96
96
  end
97
97
  end
98
98
  end
99
+
100
+ def clear_ocsp_cache
101
+ before do
102
+ Mongo.clear_ocsp_cache
103
+ end
104
+ end
105
+
106
+ def with_ocsp_mock(ca_file_path, responder_cert_path, responder_key_path,
107
+ fault: nil, port: 8100
108
+ )
109
+ clear_ocsp_cache
110
+
111
+ around do |example|
112
+ args = [
113
+ SpecConfig.instance.ocsp_files_dir.join('ocsp_mock.py').to_s,
114
+ '--ca_file', ca_file_path.to_s,
115
+ '--ocsp_responder_cert', responder_cert_path.to_s,
116
+ '--ocsp_responder_key', responder_key_path.to_s,
117
+ '-p', port.to_s,
118
+ ]
119
+ if SpecConfig.instance.client_debug?
120
+ # Use when debugging - tests run faster without -v.
121
+ args << '-v'
122
+ end
123
+ if fault
124
+ args += ['--fault', fault]
125
+ end
126
+ process = ChildProcess.new(*args)
127
+
128
+ process.io.inherit!
129
+ process.start
130
+
131
+ begin
132
+ sleep 0.4
133
+ example.run
134
+ ensure
135
+ if process.exited?
136
+ raise "Spawned process exited before we stopped it"
137
+ end
138
+
139
+ process.stop
140
+ process.wait
141
+ end
142
+ end
143
+ end
99
144
  end
100
145
 
101
146
  module InstanceMethods
@@ -101,8 +101,18 @@ module Constraints
101
101
  end
102
102
  end
103
103
 
104
+ # Some tests hardcode the TLS certificates shipped with the driver's
105
+ # test suite, and will fail when using TLS connections that use other
106
+ # certificates.
104
107
  def require_local_tls
105
108
  require_tls
109
+
110
+ before(:all) do
111
+ # TODO This isn't actually the foolproof check
112
+ if ENV['OCSP_ALGORITHM']
113
+ skip 'Driver TLS certificate required, OCSP certificates are not acceptable'
114
+ end
115
+ end
106
116
  end
107
117
 
108
118
  def require_no_retry_writes
@@ -260,4 +270,17 @@ module Constraints
260
270
  end
261
271
  end
262
272
  end
273
+
274
+ # Some tests perform assertions on what the driver is logging.
275
+ # Some test configurations, for example OCSP with unknown response,
276
+ # produce warnings due to optional checks failing.
277
+ # This constraint skips tests that issue logging assertions on configurations
278
+ # that may produce non-test-originated log entries.
279
+ def require_warning_clean
280
+ before(:all) do
281
+ if ENV['OCSP_STATUS'] == 'unknown'
282
+ skip 'Unknown OCSP status is not global warning-clean'
283
+ end
284
+ end
285
+ end
263
286
  end
@@ -138,4 +138,28 @@ module LiteConstraints
138
138
  end
139
139
  end
140
140
  end
141
+
142
+ def require_ocsp
143
+ before(:all) do
144
+ if !SpecConfig.instance.ocsp?
145
+ skip 'Set OCSP=1 in environment to run OCSP tests'
146
+ end
147
+ end
148
+ end
149
+
150
+ def require_ocsp_verifier
151
+ before(:all) do
152
+ if !SpecConfig.instance.ocsp_verifier?
153
+ skip 'Set OCSP_VERIFIER=1 in environment to run OCSP verifier tests'
154
+ end
155
+ end
156
+ end
157
+
158
+ def require_ocsp_connectivity
159
+ before(:all) do
160
+ if !SpecConfig.instance.ocsp_connectivity?
161
+ skip 'Set OCSP_CONNECTIVITY=pass or OCSP_CONNECTIVITY=fail in environment to run OCSP connectivity tests'
162
+ end
163
+ end
164
+ end
141
165
  end
@@ -54,3 +54,19 @@ RSpec::Matchers.define :be_uuid do
54
54
  object.is_a?(BSON::Binary) && object.type == :uuid
55
55
  end
56
56
  end
57
+
58
+ RSpec::Matchers.define :take_longer_than do |min_expected_time|
59
+ match do |proc|
60
+ start_time = Time.now
61
+ proc.call
62
+ (Time.now - start_time).should > min_expected_time
63
+ end
64
+ end
65
+
66
+ RSpec::Matchers.define :take_shorter_than do |min_expected_time|
67
+ match do |proc|
68
+ start_time = Time.now
69
+ proc.call
70
+ (Time.now - start_time).should < min_expected_time
71
+ end
72
+ end
@@ -0,0 +1 @@
1
+ spec/support/../../.mod/drivers-evergreen-tools/.evergreen/ocsp
@@ -0,0 +1,52 @@
1
+ require 'singleton'
2
+
3
+ module Mongo
4
+ class Client
5
+ alias :get_session_without_tracking :get_session
6
+
7
+ def get_session(options = {})
8
+ get_session_without_tracking(options).tap do |session|
9
+ SessionRegistry.instance.register(session)
10
+ end
11
+ end
12
+ end
13
+
14
+ class Session
15
+ alias :end_session_without_tracking :end_session
16
+
17
+ def end_session
18
+ SessionRegistry.instance.unregister(self)
19
+ end_session_without_tracking
20
+ end
21
+ end
22
+ end
23
+
24
+
25
+ class SessionRegistry
26
+ include Singleton
27
+
28
+ def initialize
29
+ @registry = {}
30
+ end
31
+
32
+ def register(session)
33
+ @registry[session.session_id] = session if session
34
+ end
35
+
36
+ def unregister(session)
37
+ @registry.delete(session.session_id) unless session.ended?
38
+ end
39
+
40
+ def verify_sessions_ended!
41
+ @registry.delete_if { |_, session| session.ended? }
42
+
43
+ unless @registry.empty?
44
+ sessions = @registry.map { |_, session| session }
45
+ raise "Session registry contains live sessions: #{sessions.join(', ')}"
46
+ end
47
+ end
48
+
49
+ def clear_registry
50
+ @registry = {}
51
+ end
52
+ end
@@ -122,6 +122,24 @@ class SpecConfig
122
122
  %w(1 true yes).include?(ENV['FORK']&.downcase)
123
123
  end
124
124
 
125
+ # OCSP tests require python and various dependencies.
126
+ # Assumes an OCSP responder is running on port 8100 (configured externally
127
+ # to the test suite).
128
+ def ocsp?
129
+ %w(1 true yes).include?(ENV['OCSP']&.downcase)
130
+ end
131
+
132
+ # OCSP tests require python and various dependencies.
133
+ # When testing OCSP verifier, there cannot be a responder running on
134
+ # port 8100 or the tests will fail.
135
+ def ocsp_verifier?
136
+ %w(1 true yes).include?(ENV['OCSP_VERIFIER']&.downcase)
137
+ end
138
+
139
+ def ocsp_connectivity?
140
+ ENV.key?('OCSP_CONNECTIVITY') && ENV['OCSP_CONNECTIVITY'] != ''
141
+ end
142
+
125
143
  # Test suite configuration
126
144
 
127
145
  def client_debug?
@@ -221,6 +239,10 @@ EOT
221
239
  Pathname.new("#{spec_root}/support/certificates")
222
240
  end
223
241
 
242
+ def ocsp_files_dir
243
+ Pathname.new("#{spec_root}/../.mod/drivers-evergreen-tools/.evergreen/ocsp")
244
+ end
245
+
224
246
  # TLS certificates & keys
225
247
 
226
248
  def local_client_key_path
@@ -85,6 +85,13 @@ module Utils
85
85
  end
86
86
  module_function :camelize
87
87
 
88
+ module_function def downcase_keys(hash)
89
+ # TODO replace with Hash#transform_keys when we require Ruby 2.5+
90
+ Hash[hash.map do |k, v|
91
+ [k.downcase, v]
92
+ end]
93
+ end
94
+
88
95
  module_function def disable_retries_client_options
89
96
  {
90
97
  retry_reads: false,
@@ -98,6 +105,7 @@ module Utils
98
105
  # to Ruby driver underscore options.
99
106
  def convert_client_options(spec_test_options)
100
107
  uri = Mongo::URI.new('mongodb://localhost')
108
+ mapper = Mongo::URI::OptionsMapper.new
101
109
  spec_test_options.reduce({}) do |opts, (name, value)|
102
110
  if name == 'autoEncryptOpts'
103
111
  opts.merge!(
@@ -111,7 +119,7 @@ module Utils
111
119
  )
112
120
  )
113
121
  else
114
- uri.send(:add_uri_option, name, value.to_s, opts)
122
+ mapper.add_uri_option(name, value.to_s, opts)
115
123
  end
116
124
 
117
125
  opts
@@ -494,4 +502,14 @@ module Utils
494
502
 
495
503
  subscriber.single_command_started_event(command_name, include_auth: include_auth)
496
504
  end
505
+
506
+ # Drops and creates a collection for the purpose of starting the test from
507
+ # a clean slate.
508
+ #
509
+ # @param [ Mongo::Client ] client
510
+ # @param [ String ] collection_name
511
+ module_function def create_collection(client, collection_name)
512
+ client[collection_name].drop
513
+ client[collection_name].create
514
+ end
497
515
  end