mongo 2.10.5 → 2.11.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 (191) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data.tar.gz.sig +0 -0
  4. data/CONTRIBUTING.md +1 -1
  5. data/lib/mongo.rb +2 -0
  6. data/lib/mongo/address.rb +4 -0
  7. data/lib/mongo/address/validator.rb +99 -0
  8. data/lib/mongo/auth.rb +7 -2
  9. data/lib/mongo/auth/user.rb +1 -7
  10. data/lib/mongo/background_thread.rb +135 -0
  11. data/lib/mongo/bulk_write/transformable.rb +3 -3
  12. data/lib/mongo/client.rb +74 -16
  13. data/lib/mongo/cluster.rb +193 -41
  14. data/lib/mongo/cluster/periodic_executor.rb +31 -43
  15. data/lib/mongo/cluster/sdam_flow.rb +26 -3
  16. data/lib/mongo/cluster/srv_monitor.rb +127 -0
  17. data/lib/mongo/collection/view/readable.rb +3 -5
  18. data/lib/mongo/collection/view/writable.rb +3 -3
  19. data/lib/mongo/cursor/builder/get_more_command.rb +1 -4
  20. data/lib/mongo/cursor/builder/kill_cursors_command.rb +5 -23
  21. data/lib/mongo/cursor/builder/op_get_more.rb +2 -2
  22. data/lib/mongo/cursor/builder/op_kill_cursors.rb +5 -24
  23. data/lib/mongo/error.rb +1 -0
  24. data/lib/mongo/error/auth_error.rb +1 -1
  25. data/lib/mongo/error/connection_check_out_timeout.rb +7 -8
  26. data/lib/mongo/error/invalid_address.rb +24 -0
  27. data/lib/mongo/error/notable.rb +2 -2
  28. data/lib/mongo/error/operation_failure.rb +3 -3
  29. data/lib/mongo/error/pool_closed_error.rb +11 -4
  30. data/lib/mongo/event.rb +1 -1
  31. data/lib/mongo/grid/file.rb +0 -5
  32. data/lib/mongo/grid/file/chunk.rb +0 -2
  33. data/lib/mongo/grid/fs_bucket.rb +13 -15
  34. data/lib/mongo/grid/stream/write.rb +3 -9
  35. data/lib/mongo/loggable.rb +5 -1
  36. data/lib/mongo/monitoring.rb +1 -0
  37. data/lib/mongo/monitoring/event/cmap/connection_check_out_failed.rb +7 -0
  38. data/lib/mongo/monitoring/event/cmap/connection_checked_in.rb +11 -3
  39. data/lib/mongo/monitoring/event/cmap/connection_checked_out.rb +11 -3
  40. data/lib/mongo/monitoring/event/cmap/pool_closed.rb +11 -3
  41. data/lib/mongo/monitoring/event/cmap/pool_created.rb +12 -3
  42. data/lib/mongo/monitoring/unified_sdam_log_subscriber.rb +62 -0
  43. data/lib/mongo/operation/shared/executable.rb +5 -10
  44. data/lib/mongo/operation/shared/sessions_supported.rb +1 -5
  45. data/lib/mongo/protocol/get_more.rb +1 -2
  46. data/lib/mongo/protocol/kill_cursors.rb +13 -6
  47. data/lib/mongo/protocol/serializers.rb +4 -20
  48. data/lib/mongo/retryable.rb +9 -34
  49. data/lib/mongo/semaphore.rb +1 -1
  50. data/lib/mongo/server.rb +113 -42
  51. data/lib/mongo/server/connection.rb +12 -5
  52. data/lib/mongo/server/connection_pool.rb +250 -40
  53. data/lib/mongo/server/connection_pool/populator.rb +58 -0
  54. data/lib/mongo/server/description.rb +9 -2
  55. data/lib/mongo/server/monitor.rb +68 -93
  56. data/lib/mongo/server/monitor/connection.rb +2 -0
  57. data/lib/mongo/server_selector/selectable.rb +13 -5
  58. data/lib/mongo/session.rb +0 -13
  59. data/lib/mongo/srv.rb +17 -0
  60. data/lib/mongo/srv/monitor.rb +96 -0
  61. data/lib/mongo/srv/resolver.rb +130 -0
  62. data/lib/mongo/srv/result.rb +126 -0
  63. data/lib/mongo/srv/warning_result.rb +35 -0
  64. data/lib/mongo/uri.rb +45 -55
  65. data/lib/mongo/uri/srv_protocol.rb +89 -42
  66. data/lib/mongo/version.rb +1 -1
  67. data/mongo.gemspec +3 -4
  68. data/spec/README.md +6 -1
  69. data/spec/enterprise_auth/kerberos_spec.rb +7 -6
  70. data/spec/integration/change_stream_examples_spec.rb +0 -4
  71. data/spec/integration/client_construction_spec.rb +14 -2
  72. data/spec/integration/connect_single_rs_name_spec.rb +2 -2
  73. data/spec/integration/connection_pool_populator_spec.rb +296 -0
  74. data/spec/integration/connection_spec.rb +31 -22
  75. data/spec/integration/cursor_reaping_spec.rb +1 -2
  76. data/spec/integration/docs_examples_spec.rb +0 -4
  77. data/spec/integration/heartbeat_events_spec.rb +17 -15
  78. data/spec/integration/reconnect_spec.rb +144 -1
  79. data/spec/integration/retryable_writes_errors_spec.rb +0 -4
  80. data/spec/integration/retryable_writes_spec.rb +36 -36
  81. data/spec/integration/sdam_error_handling_spec.rb +31 -25
  82. data/spec/integration/sdam_events_spec.rb +2 -6
  83. data/spec/integration/server_monitor_spec.rb +28 -0
  84. data/spec/integration/server_selector_spec.rb +7 -5
  85. data/spec/integration/srv_monitoring_spec.rb +360 -0
  86. data/spec/integration/step_down_spec.rb +4 -6
  87. data/spec/lite_spec_helper.rb +22 -0
  88. data/spec/mongo/address/validator_spec.rb +51 -0
  89. data/spec/mongo/auth/cr_spec.rb +1 -29
  90. data/spec/mongo/auth/ldap_spec.rb +1 -29
  91. data/spec/mongo/auth/scram/conversation_spec.rb +0 -2
  92. data/spec/mongo/auth/scram/negotiation_spec.rb +1 -1
  93. data/spec/mongo/auth/scram_spec.rb +1 -29
  94. data/spec/mongo/auth/user/view_spec.rb +1 -36
  95. data/spec/mongo/auth/user_spec.rb +0 -12
  96. data/spec/mongo/auth/x509_spec.rb +1 -29
  97. data/spec/mongo/bulk_write_spec.rb +2 -2
  98. data/spec/mongo/client_construction_spec.rb +56 -15
  99. data/spec/mongo/client_spec.rb +31 -27
  100. data/spec/mongo/cluster/periodic_executor_spec.rb +16 -0
  101. data/spec/mongo/cluster/srv_monitor_spec.rb +214 -0
  102. data/spec/mongo/cluster/topology/replica_set_spec.rb +16 -11
  103. data/spec/mongo/cluster/topology/sharded_spec.rb +12 -9
  104. data/spec/mongo/cluster/topology/single_spec.rb +20 -11
  105. data/spec/mongo/cluster_spec.rb +45 -29
  106. data/spec/mongo/collection/view/map_reduce_spec.rb +14 -9
  107. data/spec/mongo/collection/view/readable_spec.rb +0 -16
  108. data/spec/mongo/collection_spec.rb +0 -44
  109. data/spec/mongo/cursor/builder/get_more_command_spec.rb +2 -4
  110. data/spec/mongo/cursor/builder/op_get_more_spec.rb +2 -4
  111. data/spec/mongo/cursor_spec.rb +27 -7
  112. data/spec/mongo/monitoring/event/cmap/connection_checked_in_spec.rb +10 -3
  113. data/spec/mongo/monitoring/event/cmap/connection_checked_out_spec.rb +10 -3
  114. data/spec/mongo/monitoring/event/cmap/pool_closed_spec.rb +10 -3
  115. data/spec/mongo/monitoring/event/cmap/pool_created_spec.rb +10 -3
  116. data/spec/mongo/operation/delete/op_msg_spec.rb +17 -8
  117. data/spec/mongo/operation/insert/op_msg_spec.rb +50 -35
  118. data/spec/mongo/operation/update/op_msg_spec.rb +14 -7
  119. data/spec/mongo/retryable_spec.rb +52 -31
  120. data/spec/mongo/server/app_metadata_spec.rb +0 -8
  121. data/spec/mongo/server/connection_auth_spec.rb +5 -2
  122. data/spec/mongo/server/connection_pool/populator_spec.rb +101 -0
  123. data/spec/mongo/server/connection_pool_spec.rb +256 -107
  124. data/spec/mongo/server/connection_spec.rb +22 -33
  125. data/spec/mongo/server/description_spec.rb +42 -4
  126. data/spec/mongo/server/monitor/connection_spec.rb +22 -11
  127. data/spec/mongo/server/monitor_spec.rb +66 -107
  128. data/spec/mongo/server_spec.rb +82 -60
  129. data/spec/mongo/session/session_pool_spec.rb +1 -5
  130. data/spec/mongo/session_spec.rb +0 -4
  131. data/spec/mongo/socket/ssl_spec.rb +2 -2
  132. data/spec/mongo/srv/monitor_spec.rb +211 -0
  133. data/spec/mongo/srv/result_spec.rb +54 -0
  134. data/spec/mongo/uri/srv_protocol_spec.rb +30 -15
  135. data/spec/mongo/uri_spec.rb +125 -4
  136. data/spec/spec_helper.rb +6 -0
  137. data/spec/spec_tests/auth_spec.rb +39 -0
  138. data/spec/spec_tests/cmap_spec.rb +55 -8
  139. data/spec/spec_tests/connection_string_spec.rb +6 -31
  140. data/spec/spec_tests/data/auth/connection-string.yml +297 -0
  141. data/spec/spec_tests/data/cmap/pool-checkout-error-closed.yml +4 -1
  142. data/spec/spec_tests/data/cmap/pool-create-with-options.yml +1 -0
  143. data/spec/spec_tests/data/command_monitoring/insertMany.yml +1 -1
  144. data/spec/spec_tests/data/connection_string/invalid-uris.yml +20 -0
  145. data/spec/spec_tests/data/connection_string/valid-auth.yml +16 -0
  146. data/spec/spec_tests/data/connection_string/valid-warnings.yml +26 -30
  147. data/spec/spec_tests/data/transactions/abort.yml +3 -3
  148. data/spec/spec_tests/data/transactions/error-labels.yml +3 -3
  149. data/spec/spec_tests/data/transactions_api/callback-retry.yml +3 -3
  150. data/spec/spec_tests/data/uri_options/auth-options.yml +1 -1
  151. data/spec/spec_tests/max_staleness_spec.rb +7 -2
  152. data/spec/spec_tests/retryable_reads_spec.rb +0 -31
  153. data/spec/spec_tests/sdam_monitoring_spec.rb +12 -12
  154. data/spec/spec_tests/sdam_spec.rb +4 -7
  155. data/spec/spec_tests/server_selection_spec.rb +6 -2
  156. data/spec/spec_tests/transactions_spec.rb +0 -2
  157. data/spec/spec_tests/uri_options_spec.rb +4 -2
  158. data/spec/stress/connection_pool_stress_spec.rb +203 -0
  159. data/spec/stress/connection_pool_timing_spec.rb +181 -0
  160. data/spec/support/auth.rb +113 -0
  161. data/spec/support/background_thread_registry.rb +63 -0
  162. data/spec/support/client_registry.rb +11 -2
  163. data/spec/support/cluster_config.rb +65 -46
  164. data/spec/support/cluster_tools.rb +2 -2
  165. data/spec/support/cmap.rb +13 -14
  166. data/spec/support/cmap/verifier.rb +4 -5
  167. data/spec/support/command_monitoring.rb +0 -5
  168. data/spec/support/common_shortcuts.rb +101 -1
  169. data/spec/support/constraints.rb +25 -0
  170. data/spec/support/dns.rb +13 -0
  171. data/spec/support/event_subscriber.rb +0 -7
  172. data/spec/support/json_ext_formatter.rb +5 -1
  173. data/spec/support/lite_constraints.rb +22 -6
  174. data/spec/support/local_resource_registry.rb +34 -0
  175. data/spec/support/sdam_monitoring.rb +115 -0
  176. data/spec/support/spec_config.rb +20 -6
  177. data/spec/support/spec_setup.rb +2 -2
  178. data/spec/support/transactions.rb +1 -1
  179. data/spec/support/transactions/test.rb +1 -1
  180. data/spec/support/utils.rb +1 -16
  181. metadata +685 -659
  182. metadata.gz.sig +0 -0
  183. data/lib/mongo/event/description_changed.rb +0 -52
  184. data/spec/integration/bson_symbol_spec.rb +0 -34
  185. data/spec/integration/crud_spec.rb +0 -45
  186. data/spec/integration/get_more_spec.rb +0 -32
  187. data/spec/integration/grid_fs_bucket_spec.rb +0 -48
  188. data/spec/integration/retryable_errors_spec.rb +0 -265
  189. data/spec/integration/size_limit_spec.rb~12e1e9c4f... RUBY-2242 Fix zlib compression (#2021) +0 -98
  190. data/spec/mongo/cursor/builder/op_kill_cursors_spec.rb +0 -56
  191. data/spec/runners/sdam/verifier.rb +0 -88
@@ -305,10 +305,10 @@ tests:
305
305
  document:
306
306
  _id: 1
307
307
  result:
308
- # Don't assert on errorCodeName because (after SERVER-38583) the
309
- # DuplicateKey is reported in writeErrors, not as a top-level
310
- # command error.
311
308
  errorLabelsOmit: ["TransientTransactionError", "UnknownTransactionCommitResult"]
309
+ # DuplicateKey error code included in the bulk write error message
310
+ # returned by the server
311
+ errorContains: E11000
312
312
  # Make sure the server aborted the transaction.
313
313
  - name: insertOne
314
314
  object: collection
@@ -25,10 +25,10 @@ tests:
25
25
  - _id: 1
26
26
  - _id: 1
27
27
  result:
28
- # Don't assert on errorCodeName because (after SERVER-38583) the
29
- # DuplicateKey is reported in writeErrors, not as a top-level
30
- # command error.
31
28
  errorLabelsOmit: ["TransientTransactionError", "UnknownTransactionCommitResult"]
29
+ # DuplicateKey error code included in the bulk write error message
30
+ # returned by the server
31
+ errorContains: E11000
32
32
  - name: abortTransaction
33
33
  object: session0
34
34
 
@@ -160,10 +160,10 @@ tests:
160
160
  result:
161
161
  errorLabelsOmit: ["TransientTransactionError", "UnknownTransactionCommitResult"]
162
162
  result:
163
- # Don't assert on errorCodeName because (after SERVER-38583) the
164
- # DuplicateKey is reported in writeErrors, not as a top-level
165
- # command error.
166
163
  errorLabelsOmit: ["TransientTransactionError", "UnknownTransactionCommitResult"]
164
+ # DuplicateKey error code included in the bulk write error message
165
+ # returned by the server
166
+ errorContains: E11000
167
167
  expectations:
168
168
  -
169
169
  command_started_event:
@@ -1,6 +1,6 @@
1
1
  tests:
2
2
  -
3
- description: "Valid auth options are parsed correctly"
3
+ description: "Valid auth options are parsed correctly (GSSAPI)"
4
4
  uri: "mongodb://foo:bar@example.com/?authMechanism=GSSAPI&authMechanismProperties=SERVICE_NAME:other,CANONICALIZE_HOST_NAME:true&authSource=$external"
5
5
  valid: true
6
6
  warning: false
@@ -56,6 +56,8 @@ describe 'Max Staleness Spec' do
56
56
  allow(c).to receive(:options).and_return(options)
57
57
  allow(c).to receive(:scan!).and_return(true)
58
58
  allow(c).to receive(:app_metadata).and_return(app_metadata)
59
+ allow(c).to receive(:heartbeat_interval).and_return(
60
+ spec.heartbeat_frequency || Mongo::Server::Monitor::HEARTBEAT_FREQUENCY)
59
61
  end
60
62
  end
61
63
 
@@ -66,7 +68,9 @@ describe 'Max Staleness Spec' do
66
68
  allow(feat).to receive(:check_driver_support!).and_return(true)
67
69
  end
68
70
  address = Mongo::Address.new(server['address'])
69
- Mongo::Server.new(address, cluster, monitoring, listeners, options).tap do |s|
71
+ Mongo::Server.new(address, cluster, monitoring, listeners,
72
+ {monitoring_io: false}.update(options)
73
+ ).tap do |s|
70
74
  allow(s).to receive(:average_round_trip_time).and_return(server['avg_rtt_ms'] / 1000.0) if server['avg_rtt_ms']
71
75
  allow(s).to receive(:tags).and_return(server['tags'])
72
76
  allow(s).to receive(:secondary?).and_return(server['type'] == 'RSSecondary')
@@ -83,7 +87,8 @@ describe 'Max Staleness Spec' do
83
87
 
84
88
  let(:in_latency_window) do
85
89
  spec.in_latency_window.collect do |server|
86
- Mongo::Server.new(Mongo::Address.new(server['address']), cluster, monitoring, listeners, options.merge(monitor: false))
90
+ Mongo::Server.new(Mongo::Address.new(server['address']), cluster, monitoring, listeners,
91
+ options.merge(monitoring_io: false))
87
92
  end
88
93
  end
89
94
 
@@ -12,34 +12,3 @@ describe 'Retryable reads spec tests' do
12
12
  end
13
13
  end
14
14
  end
15
-
16
- describe 'Retryable reads spec tests - legacy' do
17
- require_no_multi_shard
18
-
19
- define_crud_spec_tests(RETRYABLE_READS_TESTS) do |spec, req, test|
20
- let(:client_options) do
21
- {
22
- max_read_retries: 1,
23
- read_retry_interval: 0,
24
- retry_reads: false,
25
- }.update(test.client_options)
26
- end
27
-
28
- let(:client) do
29
- authorized_client.with(client_options).tap do |client|
30
- client.subscribe(Mongo::Monitoring::COMMAND, event_subscriber)
31
- end
32
- end
33
-
34
- around do |example|
35
- desc = example.full_description
36
- # Skip tests that disable modern retryable reads because they expect
37
- # no retries - and since legacy retryable reads are used, the tests
38
- # will fail.
39
- if desc =~/retryReads is false|fails on first attempt/
40
- skip 'Test not applicable to legacy read retries'
41
- end
42
- example.run
43
- end
44
- end
45
- end
@@ -1,7 +1,5 @@
1
1
  require 'lite_spec_helper'
2
2
 
3
- require_relative '../runners/sdam/verifier'
4
-
5
3
  describe 'SDAM Monitoring' do
6
4
  include Mongo::SDAM
7
5
 
@@ -31,11 +29,17 @@ describe 'SDAM Monitoring' do
31
29
  @servers_cache = {}
32
30
  @client.cluster.servers_list.each do |server|
33
31
  @servers_cache[server.address.to_s] = server
32
+
33
+ # Since we set monitoring_io: false, servers are not monitored
34
+ # by the cluster. Start monitoring on them manually (this publishes
35
+ # the server opening event but, again due to monitoring_io being
36
+ # false, does not do network I/O or change server status)>
37
+ server.start_monitoring
34
38
  end
35
39
  end
36
40
 
37
41
  after(:all) do
38
- @client.close(true)
42
+ @client.close
39
43
  end
40
44
 
41
45
  spec.phases.each_with_index do |phase, phase_index|
@@ -59,8 +63,7 @@ describe 'SDAM Monitoring' do
59
63
  result['maxWireVersion'] ||= 0
60
64
  new_description = Mongo::Server::Description.new(
61
65
  server.description.address, result, 0.5)
62
- publisher = SdamSpecEventPublisher.new(@client.cluster.send(:event_listeners))
63
- publisher.publish(Mongo::Event::DESCRIPTION_CHANGED, server.description, new_description)
66
+ @client.cluster.run_sdam_flow(server.description, new_description)
64
67
  end
65
68
  @subscriber.phase_finished(phase_index)
66
69
  end
@@ -69,15 +72,12 @@ describe 'SDAM Monitoring' do
69
72
  expect(@subscriber.phase_events(phase_index).length).to eq(phase.outcome.events.length)
70
73
  end
71
74
 
72
- let(:verifier) do
73
- Sdam::Verifier.new
74
- end
75
-
76
75
  phase.outcome.events.each_with_index do |expectation, index|
77
76
 
78
- it "expects event #{index+1} to be #{expectation.name}" do
79
- verifier.verify_sdam_event(
80
- phase.outcome.events, @subscriber.phase_events(phase_index), index)
77
+ it "expects a #{expectation.name} to be published" do
78
+ published_event = @subscriber.phase_events(phase_index)[index]
79
+ expect(published_event).not_to be_nil
80
+ expect(published_event).to match_sdam_monitoring_event(expectation)
81
81
  end
82
82
  end
83
83
  end
@@ -29,14 +29,12 @@ describe 'Server Discovery and Monitoring' do
29
29
  before(:all) do
30
30
  # Since we supply all server descriptions and drive events,
31
31
  # background monitoring only gets in the way. Disable it.
32
- @client = Mongo::Client.new(spec.uri_string, monitoring_io: false)
33
- client_options = @client.instance_variable_get(:@options)
34
- @client.instance_variable_set(:@options, client_options.merge(heartbeat_frequency: 100, connect_timeout: 0.1))
35
- @client.cluster.instance_variable_set(:@options, client_options.merge(heartbeat_frequency: 100, connect_timeout: 0.1))
32
+ @client = new_local_client_nmio(spec.uri_string,
33
+ heartbeat_frequency: 1000, connect_timeout: 0.1)
36
34
  end
37
35
 
38
36
  after(:all) do
39
- @client && @client.close(true)
37
+ @client && @client.close
40
38
  end
41
39
 
42
40
  spec.phases.each_with_index do |phase, index|
@@ -66,8 +64,7 @@ describe 'Server Discovery and Monitoring' do
66
64
  result['maxWireVersion'] ||= 0
67
65
  new_description = Mongo::Server::Description.new(
68
66
  server.description.address, result, 0.5)
69
- publisher = SdamSpecEventPublisher.new(@client.cluster.send(:event_listeners))
70
- publisher.publish(Mongo::Event::DESCRIPTION_CHANGED, server.description, new_description)
67
+ @client.cluster.run_sdam_flow(server.description, new_description)
71
68
  end
72
69
  end
73
70
 
@@ -53,7 +53,9 @@ describe 'Server Selection' do
53
53
  let(:candidate_servers) do
54
54
  spec.candidate_servers.collect do |server|
55
55
  address = Mongo::Address.new(server['address'])
56
- Mongo::Server.new(address, cluster, monitoring, listeners, SpecConfig.instance.test_options).tap do |s|
56
+ Mongo::Server.new(address, cluster, monitoring, listeners,
57
+ {monitoring_io: false}.update(SpecConfig.instance.test_options)
58
+ ).tap do |s|
57
59
  allow(s).to receive(:average_round_trip_time).and_return(server['avg_rtt_ms'] / 1000.0)
58
60
  allow(s).to receive(:tags).and_return(server['tags'])
59
61
  allow(s).to receive(:secondary?).and_return(server['type'] == 'RSSecondary')
@@ -67,7 +69,9 @@ describe 'Server Selection' do
67
69
  let(:in_latency_window) do
68
70
  spec.in_latency_window.collect do |server|
69
71
  address = Mongo::Address.new(server['address'])
70
- Mongo::Server.new(address, cluster, monitoring, listeners, SpecConfig.instance.test_options).tap do |s|
72
+ Mongo::Server.new(address, cluster, monitoring, listeners,
73
+ {monitoring_io: false}.update(SpecConfig.instance.test_options)
74
+ ).tap do |s|
71
75
  allow(s).to receive(:average_round_trip_time).and_return(server['avg_rtt_ms'] / 1000.0)
72
76
  allow(s).to receive(:tags).and_return(server['tags'])
73
77
  allow(s).to receive(:connectable?).and_return(true)
@@ -1,7 +1,5 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  describe 'Transactions' do
4
- clean_slate_on_evergreen
5
-
6
4
  define_transactions_spec_tests(TRANSACTIONS_TESTS)
7
5
  end
@@ -1,4 +1,4 @@
1
- require 'lite_spec_helper'
1
+ require 'spec_helper'
2
2
 
3
3
  describe 'Uri Options' do
4
4
  include Mongo::ConnectionString
@@ -17,8 +17,10 @@ describe 'Uri Options' do
17
17
  end
18
18
 
19
19
  spec.tests.each do |test|
20
-
21
20
  context "#{test.description}" do
21
+ if test.description.downcase.include?("gssapi")
22
+ require_mongo_kerberos
23
+ end
22
24
 
23
25
  context 'when the uri should warn', if: test.warn? do
24
26
 
@@ -0,0 +1,203 @@
1
+ require 'spec_helper'
2
+
3
+ describe 'Connection pool stress test' do
4
+ before(:all) do
5
+ if !SpecConfig.instance.stress_spec?
6
+ skip 'Stress spec not enabled'
7
+ end
8
+ end
9
+
10
+ let(:options) do
11
+ { max_pool_size: 5, min_pool_size: 3 }
12
+ end
13
+
14
+ let(:thread_count) { 5 }
15
+
16
+ let(:documents) do
17
+ [].tap do |documents|
18
+ 10000.times do |i|
19
+ documents << { a: i}
20
+ end
21
+ end
22
+ end
23
+
24
+ let(:operation_threads) do
25
+ [].tap do |threads|
26
+ thread_count.times do |i|
27
+ threads << Thread.new do
28
+ 10.times do |j|
29
+ collection.find(a: i+j).to_a
30
+ sleep 0.5
31
+ collection.find(a: i+j).to_a
32
+ end
33
+ end
34
+ end
35
+ end
36
+ end
37
+
38
+ let(:client) do
39
+ authorized_client.with(options)
40
+ end
41
+
42
+ let(:collection) do
43
+ client[authorized_collection.name].tap do |collection|
44
+ collection.drop
45
+ collection.insert_many(documents)
46
+ end
47
+ end
48
+
49
+ shared_examples_for 'does not raise error' do
50
+ it 'does not raise error' do
51
+ collection
52
+
53
+ expect {
54
+ threads.collect { |t| t.join }
55
+ }.not_to raise_error
56
+ end
57
+ end
58
+
59
+ describe 'when several threads run operations on the collection' do
60
+ let(:threads) { operation_threads }
61
+
62
+ context 'min pool size 0, max pool size 5' do
63
+ let(:options) do
64
+ { max_pool_size: 5, min_pool_size: 0 }
65
+ end
66
+ let(:thread_count) { 7 }
67
+
68
+ it_behaves_like 'does not raise error'
69
+ end
70
+
71
+ context 'min pool size 1, max pool size 5' do
72
+ let(:options) do
73
+ { max_pool_size: 5, min_pool_size: 1 }
74
+ end
75
+ let(:thread_count) { 7 }
76
+
77
+ it_behaves_like 'does not raise error'
78
+ end
79
+
80
+ context 'min pool size 2, max pool size 5' do
81
+ let(:options) do
82
+ { max_pool_size: 5, min_pool_size: 2 }
83
+ end
84
+ let(:thread_count) { 7 }
85
+
86
+ it_behaves_like 'does not raise error'
87
+ end
88
+
89
+ context 'min pool size 3, max pool size 5' do
90
+ let(:options) do
91
+ { max_pool_size: 5, min_pool_size: 3 }
92
+ end
93
+ let(:thread_count) { 7 }
94
+
95
+ it_behaves_like 'does not raise error'
96
+ end
97
+
98
+ context 'min pool size 4, max pool size 5' do
99
+ let(:options) do
100
+ { max_pool_size: 5, min_pool_size: 4 }
101
+ end
102
+ let(:thread_count) { 7 }
103
+
104
+ it_behaves_like 'does not raise error'
105
+ end
106
+
107
+ context 'min pool size 5, max pool size 5' do
108
+ let(:options) do
109
+ { max_pool_size: 5, min_pool_size: 5 }
110
+ end
111
+ let(:thread_count) { 7 }
112
+
113
+ it_behaves_like 'does not raise error'
114
+ end
115
+ end
116
+
117
+ describe 'when there are many more threads than the max pool size' do
118
+ let(:threads) { operation_threads }
119
+
120
+ context '10 threads, max pool size 5' do
121
+ let(:thread_count) { 10 }
122
+
123
+ it_behaves_like 'does not raise error'
124
+ end
125
+
126
+ context '15 threads, max pool size 5' do
127
+ let(:thread_count) { 15 }
128
+
129
+ it_behaves_like 'does not raise error'
130
+ end
131
+
132
+ context '20 threads, max pool size 5' do
133
+ let(:thread_count) { 20 }
134
+
135
+ it_behaves_like 'does not raise error'
136
+ end
137
+
138
+ context '25 threads, max pool size 5' do
139
+ let(:thread_count) { 20 }
140
+
141
+ it_behaves_like 'does not raise error'
142
+ end
143
+ end
144
+
145
+ context 'when primary pool is disconnected' do
146
+ let(:threads) do
147
+ threads = operation_threads
148
+
149
+ # thread that disconnects primary's pool
150
+ threads << Thread.new do
151
+ sleep 0.2
152
+ server = client.cluster.next_primary
153
+ server.pool.disconnect!
154
+ end
155
+ end
156
+
157
+ it_behaves_like 'does not raise error'
158
+ end
159
+
160
+ context 'when all pools are disconnected' do
161
+ let(:threads) do
162
+ threads = operation_threads
163
+
164
+ # thread that disconnects each server's pool
165
+ threads << Thread.new do
166
+ sleep 0.2
167
+
168
+ client.cluster.servers_list.each do |server|
169
+ if server.description.data_bearing?
170
+ server.pool.disconnect!
171
+ end
172
+ end
173
+ end
174
+ end
175
+
176
+ it_behaves_like 'does not raise error'
177
+ end
178
+
179
+ context 'when populator connection auth sometimes fails' do
180
+ let(:threads) { operation_threads }
181
+
182
+ it 'does not raise error' do
183
+ server = client.cluster.next_primary
184
+
185
+ # We only want to test connection failure on the populator; connection failures
186
+ # occurring in the check_out method should raise an error.
187
+ # The populator calls create_and_add_connection, which calls connection.connect!
188
+ # and raises if an error occurs (eg, an auth error), so in this test we
189
+ # randomly raise errors on this method.
190
+ expect(server.pool).to receive(:create_and_add_connection).at_least(:once).and_wrap_original { |m, *args|
191
+ if rand < 0.05
192
+ raise Mongo::Error::SocketError
193
+ else
194
+ m.call(*args)
195
+ end
196
+ }
197
+
198
+ expect {
199
+ threads.collect { |t| t.join }
200
+ }.not_to raise_error
201
+ end
202
+ end
203
+ end