mongo 2.13.0.beta1 → 2.13.0.rc1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (170) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data.tar.gz.sig +1 -5
  4. data/Rakefile +15 -9
  5. data/lib/mongo.rb +4 -2
  6. data/lib/mongo/auth/aws/request.rb +4 -2
  7. data/lib/mongo/bulk_write.rb +1 -0
  8. data/lib/mongo/client.rb +143 -21
  9. data/lib/mongo/cluster.rb +53 -17
  10. data/lib/mongo/cluster/sdam_flow.rb +13 -10
  11. data/lib/mongo/cluster/topology/replica_set_no_primary.rb +3 -2
  12. data/lib/mongo/cluster/topology/sharded.rb +1 -1
  13. data/lib/mongo/cluster/topology/single.rb +1 -1
  14. data/lib/mongo/collection.rb +17 -13
  15. data/lib/mongo/collection/view/readable.rb +3 -1
  16. data/lib/mongo/collection/view/writable.rb +41 -5
  17. data/lib/mongo/database.rb +31 -4
  18. data/lib/mongo/database/view.rb +19 -4
  19. data/lib/mongo/distinguishing_semaphore.rb +55 -0
  20. data/lib/mongo/error.rb +1 -0
  21. data/lib/mongo/error/invalid_session.rb +2 -1
  22. data/lib/mongo/error/operation_failure.rb +6 -0
  23. data/lib/mongo/error/sessions_not_supported.rb +35 -0
  24. data/lib/mongo/event/base.rb +6 -0
  25. data/lib/mongo/grid/file.rb +5 -0
  26. data/lib/mongo/grid/file/chunk.rb +2 -0
  27. data/lib/mongo/grid/fs_bucket.rb +15 -13
  28. data/lib/mongo/grid/stream/write.rb +9 -3
  29. data/lib/mongo/monitoring.rb +38 -0
  30. data/lib/mongo/monitoring/command_log_subscriber.rb +10 -2
  31. data/lib/mongo/monitoring/event/command_failed.rb +11 -0
  32. data/lib/mongo/monitoring/event/command_started.rb +37 -2
  33. data/lib/mongo/monitoring/event/command_succeeded.rb +11 -0
  34. data/lib/mongo/monitoring/event/server_closed.rb +1 -1
  35. data/lib/mongo/monitoring/event/server_description_changed.rb +27 -4
  36. data/lib/mongo/monitoring/event/server_heartbeat_failed.rb +9 -2
  37. data/lib/mongo/monitoring/event/server_heartbeat_started.rb +9 -2
  38. data/lib/mongo/monitoring/event/server_heartbeat_succeeded.rb +9 -2
  39. data/lib/mongo/monitoring/event/server_opening.rb +1 -1
  40. data/lib/mongo/monitoring/event/topology_changed.rb +1 -1
  41. data/lib/mongo/monitoring/event/topology_closed.rb +1 -1
  42. data/lib/mongo/monitoring/event/topology_opening.rb +1 -1
  43. data/lib/mongo/monitoring/publishable.rb +6 -3
  44. data/lib/mongo/monitoring/server_description_changed_log_subscriber.rb +9 -1
  45. data/lib/mongo/monitoring/topology_changed_log_subscriber.rb +1 -1
  46. data/lib/mongo/protocol/message.rb +36 -8
  47. data/lib/mongo/protocol/msg.rb +14 -0
  48. data/lib/mongo/protocol/serializers.rb +5 -2
  49. data/lib/mongo/server.rb +10 -3
  50. data/lib/mongo/server/connection.rb +4 -4
  51. data/lib/mongo/server/connection_base.rb +3 -1
  52. data/lib/mongo/server/description.rb +5 -0
  53. data/lib/mongo/server/monitor.rb +76 -44
  54. data/lib/mongo/server/monitor/connection.rb +55 -7
  55. data/lib/mongo/server/pending_connection.rb +14 -4
  56. data/lib/mongo/server/push_monitor.rb +173 -0
  57. data/{spec/runners/transactions/context.rb → lib/mongo/server/push_monitor/connection.rb} +9 -14
  58. data/lib/mongo/server_selector.rb +0 -1
  59. data/lib/mongo/server_selector/base.rb +579 -1
  60. data/lib/mongo/server_selector/nearest.rb +1 -6
  61. data/lib/mongo/server_selector/primary.rb +1 -6
  62. data/lib/mongo/server_selector/primary_preferred.rb +7 -10
  63. data/lib/mongo/server_selector/secondary.rb +1 -6
  64. data/lib/mongo/server_selector/secondary_preferred.rb +1 -7
  65. data/lib/mongo/session.rb +2 -0
  66. data/lib/mongo/socket.rb +20 -8
  67. data/lib/mongo/socket/ssl.rb +1 -1
  68. data/lib/mongo/socket/tcp.rb +1 -1
  69. data/lib/mongo/topology_version.rb +9 -0
  70. data/lib/mongo/utils.rb +62 -0
  71. data/lib/mongo/version.rb +1 -1
  72. data/spec/README.aws-auth.md +2 -2
  73. data/spec/integration/awaited_ismaster_spec.rb +28 -0
  74. data/spec/integration/change_stream_examples_spec.rb +6 -2
  75. data/spec/integration/check_clean_slate_spec.rb +16 -0
  76. data/spec/integration/client_construction_spec.rb +1 -0
  77. data/spec/integration/connect_single_rs_name_spec.rb +5 -2
  78. data/spec/integration/connection_spec.rb +7 -4
  79. data/spec/integration/crud_spec.rb +4 -4
  80. data/spec/integration/docs_examples_spec.rb +6 -0
  81. data/spec/integration/grid_fs_bucket_spec.rb +48 -0
  82. data/spec/integration/heartbeat_events_spec.rb +4 -23
  83. data/spec/integration/read_concern_spec.rb +1 -1
  84. data/spec/integration/retryable_errors_spec.rb +1 -1
  85. data/spec/integration/retryable_writes/shared/performs_legacy_retries.rb +2 -2
  86. data/spec/integration/retryable_writes/shared/performs_modern_retries.rb +3 -3
  87. data/spec/integration/retryable_writes/shared/performs_no_retries.rb +2 -2
  88. data/spec/integration/sdam_error_handling_spec.rb +37 -15
  89. data/spec/integration/sdam_events_spec.rb +77 -6
  90. data/spec/integration/sdam_prose_spec.rb +64 -0
  91. data/spec/integration/server_monitor_spec.rb +25 -1
  92. data/spec/integration/size_limit_spec.rb +7 -3
  93. data/spec/integration/size_limit_spec.rb~12e1e9c4f... RUBY-2242 Fix zlib compression (#2021) +98 -0
  94. data/spec/integration/ssl_uri_options_spec.rb +2 -2
  95. data/spec/integration/zlib_compression_spec.rb +25 -0
  96. data/spec/lite_spec_helper.rb +12 -5
  97. data/spec/mongo/auth/aws/request_spec.rb +76 -0
  98. data/spec/mongo/auth/scram_spec.rb +1 -1
  99. data/spec/mongo/client_construction_spec.rb +207 -0
  100. data/spec/mongo/client_spec.rb +38 -3
  101. data/spec/mongo/cluster/topology/replica_set_spec.rb +52 -9
  102. data/spec/mongo/cluster/topology/single_spec.rb +4 -2
  103. data/spec/mongo/cluster_spec.rb +34 -35
  104. data/spec/mongo/collection/view/change_stream_resume_spec.rb +6 -6
  105. data/spec/mongo/collection_spec.rb +500 -0
  106. data/spec/mongo/database_spec.rb +245 -8
  107. data/spec/mongo/distinguishing_semaphore_spec.rb +63 -0
  108. data/spec/mongo/error/operation_failure_spec.rb +40 -0
  109. data/spec/mongo/index/view_spec.rb +2 -2
  110. data/spec/mongo/monitoring/event/server_description_changed_spec.rb +1 -4
  111. data/spec/mongo/protocol/msg_spec.rb +10 -0
  112. data/spec/mongo/semaphore_spec.rb +51 -0
  113. data/spec/mongo/server/connection_auth_spec.rb +2 -2
  114. data/spec/mongo/server_selector/nearest_spec.rb +23 -23
  115. data/spec/mongo/server_selector/primary_preferred_spec.rb +26 -26
  116. data/spec/mongo/server_selector/primary_spec.rb +9 -9
  117. data/spec/mongo/server_selector/secondary_preferred_spec.rb +22 -22
  118. data/spec/mongo/server_selector/secondary_spec.rb +18 -18
  119. data/spec/mongo/server_selector_spec.rb +4 -4
  120. data/spec/mongo/session_spec.rb +35 -0
  121. data/spec/runners/change_streams/test.rb +2 -2
  122. data/spec/runners/cmap.rb +1 -1
  123. data/spec/runners/command_monitoring.rb +3 -34
  124. data/spec/runners/crud/context.rb +9 -5
  125. data/spec/runners/crud/operation.rb +59 -27
  126. data/spec/runners/crud/spec.rb +0 -8
  127. data/spec/runners/crud/test.rb +1 -1
  128. data/spec/runners/sdam.rb +2 -2
  129. data/spec/runners/server_selection.rb +242 -28
  130. data/spec/runners/transactions.rb +12 -12
  131. data/spec/runners/transactions/operation.rb +151 -25
  132. data/spec/runners/transactions/test.rb +60 -16
  133. data/spec/spec_tests/command_monitoring_spec.rb +22 -12
  134. data/spec/spec_tests/crud_spec.rb +1 -1
  135. data/spec/spec_tests/data/change_streams/change-streams-errors.yml +4 -8
  136. data/spec/spec_tests/data/change_streams/change-streams-resume-whitelist.yml +66 -0
  137. data/spec/spec_tests/data/max_staleness/ReplicaSetNoPrimary/MaxStalenessTooSmall.yml +15 -0
  138. data/spec/spec_tests/data/max_staleness/ReplicaSetNoPrimary/NoKnownServers.yml +4 -3
  139. data/spec/spec_tests/data/max_staleness/Unknown/SmallMaxStaleness.yml +1 -0
  140. data/spec/spec_tests/data/sdam_integration/cancel-server-check.yml +96 -0
  141. data/spec/spec_tests/data/sdam_integration/connectTimeoutMS.yml +88 -0
  142. data/spec/spec_tests/data/sdam_integration/find-network-error.yml +83 -0
  143. data/spec/spec_tests/data/sdam_integration/find-shutdown-error.yml +116 -0
  144. data/spec/spec_tests/data/sdam_integration/insert-network-error.yml +86 -0
  145. data/spec/spec_tests/data/sdam_integration/insert-shutdown-error.yml +115 -0
  146. data/spec/spec_tests/data/sdam_integration/isMaster-command-error.yml +168 -0
  147. data/spec/spec_tests/data/sdam_integration/isMaster-network-error.yml +162 -0
  148. data/spec/spec_tests/data/sdam_integration/isMaster-timeout.yml +229 -0
  149. data/spec/spec_tests/data/sdam_integration/rediscover-quickly-after-step-down.yml +87 -0
  150. data/spec/spec_tests/max_staleness_spec.rb +4 -142
  151. data/spec/spec_tests/retryable_reads_spec.rb +2 -2
  152. data/spec/spec_tests/sdam_integration_spec.rb +13 -0
  153. data/spec/spec_tests/sdam_monitoring_spec.rb +1 -2
  154. data/spec/spec_tests/server_selection_spec.rb +4 -116
  155. data/spec/stress/cleanup_spec.rb +17 -2
  156. data/spec/stress/connection_pool_stress_spec.rb +10 -8
  157. data/spec/support/child_process_helper.rb +78 -0
  158. data/spec/support/client_registry.rb +1 -0
  159. data/spec/support/cluster_config.rb +4 -0
  160. data/spec/support/event_subscriber.rb +123 -33
  161. data/spec/support/keyword_struct.rb +26 -0
  162. data/spec/support/shared/server_selector.rb +13 -1
  163. data/spec/support/spec_config.rb +38 -13
  164. data/spec/support/spec_organizer.rb +129 -0
  165. data/spec/support/spec_setup.rb +1 -1
  166. data/spec/support/utils.rb +46 -0
  167. metadata +992 -942
  168. metadata.gz.sig +0 -0
  169. data/lib/mongo/server_selector/selectable.rb +0 -560
  170. data/spec/runners/sdam_monitoring.rb +0 -89
@@ -127,13 +127,13 @@ describe 'CRUD operations' do
127
127
  describe 'upsert' do
128
128
  context 'with default write concern' do
129
129
  it 'upserts' do
130
- collection.count_documents({}).should == 0
130
+ collection.count_documents.should == 0
131
131
 
132
132
  res = collection.find(_id: 'foo').update_one({'$set' => {foo: 'bar'}}, upsert: true)
133
133
 
134
134
  res.documents.first['upserted'].length.should == 1
135
135
 
136
- collection.count_documents({}).should == 1
136
+ collection.count_documents.should == 1
137
137
  end
138
138
  end
139
139
 
@@ -147,7 +147,7 @@ describe 'CRUD operations' do
147
147
  end
148
148
 
149
149
  it 'upserts' do
150
- unack_collection.count_documents({}).should == 0
150
+ unack_collection.count_documents.should == 0
151
151
 
152
152
  res = unack_collection.find(_id: 'foo').update_one({'$set' => {foo: 'bar'}}, upsert: true)
153
153
 
@@ -155,7 +155,7 @@ describe 'CRUD operations' do
155
155
  # persisted (hopefully)
156
156
  sleep 0.25
157
157
 
158
- unack_collection.count_documents({}).should == 1
158
+ unack_collection.count_documents.should == 1
159
159
  end
160
160
  end
161
161
  end
@@ -1,6 +1,12 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  describe 'aggregation examples in Ruby' do
4
+ before(:all) do
5
+ # In sharded clusters we need to ensure the database exists before running
6
+ # the tests in this file.
7
+ ClientRegistry.instance.global_client('authorized')['_placeholder'].create
8
+ end
9
+
4
10
  let(:client) do
5
11
  authorized_client
6
12
  end
@@ -0,0 +1,48 @@
1
+ require 'spec_helper'
2
+
3
+ describe 'GridFS bucket integration' do
4
+ let(:fs) do
5
+ authorized_client.database.fs
6
+ end
7
+
8
+ describe 'UTF-8 string write' do
9
+ let(:data) { "hello\u2210" }
10
+
11
+ before do
12
+ data.length.should_not == data.bytesize
13
+ end
14
+
15
+ shared_examples 'round-trips' do
16
+ it 'round-trips' do
17
+ stream = fs.open_upload_stream('test') do |stream|
18
+ stream.write(data_to_write)
19
+ end
20
+
21
+ actual = nil
22
+ fs.open_download_stream(stream.file_id) do |stream|
23
+ actual = stream.read
24
+ end
25
+
26
+ actual.encoding.name.should == 'ASCII-8BIT'
27
+ actual.should == data.dup.force_encoding('binary')
28
+ end
29
+ end
30
+
31
+ context 'in binary encoding' do
32
+ let(:data_to_write) do
33
+ data.force_encoding('binary').freeze
34
+ end
35
+
36
+ it_behaves_like 'round-trips'
37
+ end
38
+
39
+ context 'in UTF-8 encoding' do
40
+ let(:data_to_write) do
41
+ data.encoding.name.should == 'UTF-8'
42
+ data.freeze
43
+ end
44
+
45
+ it_behaves_like 'round-trips'
46
+ end
47
+ end
48
+ end
@@ -1,33 +1,14 @@
1
1
  require 'spec_helper'
2
2
 
3
- class TestHeartbeatSubscriber
4
- def initialize
5
- @started_events = []
6
- @succeeded_events = []
7
- @failed_events = []
8
- end
9
-
10
- attr_reader :started_events, :succeeded_events, :failed_events
11
-
12
- def started(event)
13
- @started_events << event
14
- end
15
-
16
- def succeeded(event)
17
- @succeeded_events << event
18
- end
19
-
20
- def failed(event)
21
- @failed_events << event
22
- end
23
- end
24
-
25
3
  describe 'Heartbeat events' do
26
4
  class HeartbeatEventsSpecTestException < StandardError; end
27
5
 
6
+ # 4.4 has two monitors and thus issues heartbeats multiple times
7
+ max_server_version '4.2'
8
+
28
9
  clean_slate_for_all
29
10
 
30
- let(:subscriber) { TestHeartbeatSubscriber.new }
11
+ let(:subscriber) { EventSubscriber.new }
31
12
 
32
13
  before do
33
14
  Mongo::Monitoring::Global.subscribe(Mongo::Monitoring::SERVER_HEARTBEAT, subscriber)
@@ -17,7 +17,7 @@ describe 'read concern' do
17
17
 
18
18
  let(:sent_read_concern) do
19
19
  subscriber.clear_events!
20
- collection.count_documents({})
20
+ collection.count_documents
21
21
  subscriber.started_events.find { |c| c.command_name == 'aggregate' }.command[:readConcern]
22
22
  end
23
23
 
@@ -106,7 +106,7 @@ describe 'Failing retryable operations' do
106
106
  },
107
107
  }
108
108
 
109
- if ClusterConfig.instance.short_server_version >= '4.3'
109
+ if ClusterConfig.instance.short_server_version >= '4.4'
110
110
  # Server versions 4.4 and newer will add the RetryableWriteError
111
111
  # label to all retryable errors, and the driver must not add the label
112
112
  # if it is not already present.
@@ -26,7 +26,7 @@ module PerformsLegacyRetries
26
26
  end
27
27
 
28
28
  context 'for ETIMEDOUT' do
29
- min_server_fcv '4.3'
29
+ min_server_fcv '4.4'
30
30
 
31
31
  # shorten socket timeout so these tests take less time to run
32
32
  let(:socket_timeout) { 1 }
@@ -59,7 +59,7 @@ module PerformsLegacyRetries
59
59
  end
60
60
 
61
61
  context 'on server versions >= 4.4' do
62
- min_server_fcv '4.3'
62
+ min_server_fcv '4.4'
63
63
 
64
64
  context 'for OperationFailure with RetryableWriteError label' do
65
65
  before do
@@ -44,8 +44,8 @@ module PerformsModernRetries
44
44
 
45
45
  context 'for ETIMEDOUT' do
46
46
  # blockConnection option in failCommand was introduced in
47
- # server version 4.3
48
- min_server_fcv '4.3'
47
+ # server version 4.4
48
+ min_server_fcv '4.4'
49
49
 
50
50
  # shorten socket timeout so these tests take less time to run
51
51
  let(:socket_timeout) { 1 }
@@ -94,7 +94,7 @@ module PerformsModernRetries
94
94
  end
95
95
 
96
96
  context 'on server versions >= 4.4' do
97
- min_server_fcv '4.3'
97
+ min_server_fcv '4.4'
98
98
 
99
99
  context 'for OperationFailure with RetryableWriteError label' do
100
100
  before do
@@ -25,7 +25,7 @@ module PerformsNoRetries
25
25
  end
26
26
 
27
27
  context 'for ETIMEDOUT' do
28
- min_server_fcv '4.3'
28
+ min_server_fcv '4.4'
29
29
 
30
30
  # shorten socket timeout so these tests take less time to run
31
31
  let(:socket_timeout) { 1 }
@@ -58,7 +58,7 @@ module PerformsNoRetries
58
58
  end
59
59
 
60
60
  context 'on server versions >= 4.4' do
61
- min_server_fcv '4.3'
61
+ min_server_fcv '4.4'
62
62
  # These tests will be implemented in a follow-up PR
63
63
  end
64
64
 
@@ -3,11 +3,27 @@ require 'spec_helper'
3
3
  describe 'SDAM error handling' do
4
4
  clean_slate_for_all
5
5
 
6
+ after do
7
+ # Close all clients after every test to avoid leaking expectations into
8
+ # subsequent tests because we set global assertions on sockets.
9
+ ClientRegistry.instance.close_all_clients
10
+ end
11
+
6
12
  # These tests operate on specific servers, and don't work in a multi
7
13
  # shard cluster where multiple servers are equally eligible
8
14
  require_no_multi_shard
9
15
 
10
- let(:client) { authorized_client_without_any_retries }
16
+ let(:diagnostic_subscriber) { VerboseEventSubscriber.new }
17
+
18
+ let(:client) do
19
+ new_local_client(SpecConfig.instance.addresses,
20
+ SpecConfig.instance.all_test_options.merge(
21
+ socket_timeout: 3, connect_timeout: 3,
22
+ # Uncomment to print all events to stdout:
23
+ #sdam_proc: Utils.subscribe_all_sdam_proc(diagnostic_subscriber),
24
+ **Utils.disable_retries_client_options)
25
+ )
26
+ end
11
27
 
12
28
  let(:server) { client.cluster.next_primary }
13
29
 
@@ -148,6 +164,9 @@ describe 'SDAM error handling' do
148
164
  end
149
165
 
150
166
  context 'network error' do
167
+ # With 4.4 servers we set up two monitoring connections, hence global
168
+ # socket expectations get hit twice.
169
+ max_server_version '4.2'
151
170
 
152
171
  let(:operation) do
153
172
  expect_any_instance_of(Mongo::Socket).to receive(:read).and_raise(exception)
@@ -181,13 +200,6 @@ describe 'SDAM error handling' do
181
200
  describe 'when there is an error on monitoring connection' do
182
201
  clean_slate_for_all
183
202
 
184
- let(:client) do
185
- new_local_client(SpecConfig.instance.addresses,
186
- SpecConfig.instance.test_options.merge(
187
- connect_timeout: 1, socket_timeout: 1,
188
- ))
189
- end
190
-
191
203
  let(:subscriber) { EventSubscriber.new }
192
204
 
193
205
  let(:set_subscribers) do
@@ -209,6 +221,7 @@ describe 'SDAM error handling' do
209
221
  it 'marks server unknown' do
210
222
  expect(server).not_to be_unknown
211
223
 
224
+ #subscriber.clear_events!
212
225
  events = subscriber.select_succeeded_events(Mongo::Monitoring::Event::ServerDescriptionChanged)
213
226
  events.should be_empty
214
227
 
@@ -228,6 +241,7 @@ describe 'SDAM error handling' do
228
241
 
229
242
  shared_examples_for 'clears connection pool - cmap event' do
230
243
  it 'clears connection pool' do
244
+ #subscriber.clear_events!
231
245
  events = subscriber.select_published_events(Mongo::Monitoring::Event::Cmap::PoolCleared)
232
246
  events.should be_empty
233
247
 
@@ -245,6 +259,7 @@ describe 'SDAM error handling' do
245
259
  end
246
260
 
247
261
  shared_examples_for 'marks server unknown and clears connection pool' do
262
+ =begin These tests are not reliable
248
263
  context 'via object inspection' do
249
264
  let(:expect_server_state_change) do
250
265
  server.summary.should =~ /unknown/i
@@ -254,6 +269,7 @@ describe 'SDAM error handling' do
254
269
  it_behaves_like 'marks server unknown'
255
270
  it_behaves_like 'clears connection pool'
256
271
  end
272
+ =end
257
273
 
258
274
  context 'via events' do
259
275
  # When we use events we do not need to examine object state, therefore
@@ -268,16 +284,22 @@ describe 'SDAM error handling' do
268
284
  end
269
285
  end
270
286
 
271
- context 'network timeout' do
272
- let(:exception) { Mongo::Error::SocketTimeoutError }
287
+ context 'via stubs' do
288
+ # With 4.4 servers we set up two monitoring connections, hence global
289
+ # socket expectations get hit twice.
290
+ max_server_version '4.2'
273
291
 
274
- it_behaves_like 'marks server unknown and clears connection pool'
275
- end
292
+ context 'network timeout' do
293
+ let(:exception) { Mongo::Error::SocketTimeoutError }
276
294
 
277
- context 'non-timeout network error' do
278
- let(:exception) { Mongo::Error::SocketError }
295
+ it_behaves_like 'marks server unknown and clears connection pool'
296
+ end
279
297
 
280
- it_behaves_like 'marks server unknown and clears connection pool'
298
+ context 'non-timeout network error' do
299
+ let(:exception) { Mongo::Error::SocketError }
300
+
301
+ it_behaves_like 'marks server unknown and clears connection pool'
302
+ end
281
303
  end
282
304
 
283
305
  context 'non-timeout network error via fail point' do
@@ -1,8 +1,7 @@
1
1
  require 'spec_helper'
2
- require 'runners/sdam_monitoring'
3
2
 
4
3
  describe 'SDAM events' do
5
- let(:subscriber) { Mongo::SDAMMonitoring::TestSubscriber.new }
4
+ let(:subscriber) { EventSubscriber.new }
6
5
 
7
6
  describe 'server closed event' do
8
7
  it 'is published when client is closed' do
@@ -12,11 +11,11 @@ describe 'SDAM events' do
12
11
 
13
12
  # get the client connected
14
13
  client.database.command(ismaster: 1)
15
- expect(subscriber.events).to be_empty
14
+ expect(subscriber.succeeded_events).to be_empty
16
15
 
17
16
  client.close
18
17
 
19
- expect(subscriber.events).not_to be_empty
18
+ expect(subscriber.succeeded_events).not_to be_empty
20
19
  event = subscriber.first_event('server_closed_event')
21
20
  expect(event).not_to be_nil
22
21
  end
@@ -30,15 +29,87 @@ describe 'SDAM events' do
30
29
 
31
30
  # get the client connected
32
31
  client.database.command(ismaster: 1)
33
- expect(subscriber.events).to be_empty
32
+ expect(subscriber.succeeded_events).to be_empty
34
33
 
35
34
  client.close
36
35
 
37
- expect(subscriber.events).not_to be_empty
36
+ expect(subscriber.succeeded_events).not_to be_empty
38
37
  event = subscriber.first_event('topology_closed_event')
39
38
  expect(event).not_to be_nil
40
39
 
41
40
  expect(event.topology).to eql(client.cluster.topology)
42
41
  end
43
42
  end
43
+
44
+ describe 'heartbeat event' do
45
+ require_topology :single
46
+
47
+ context 'pre-4.4 servers' do
48
+ max_server_version '4.2'
49
+
50
+ let(:client) do
51
+ new_local_client(SpecConfig.instance.addresses,
52
+ # Heartbeat interval is bound by 500 ms
53
+ SpecConfig.instance.test_options.merge(heartbeat_frequency: 0.5),
54
+ ).tap do |client|
55
+ client.subscribe(Mongo::Monitoring::SERVER_HEARTBEAT, subscriber)
56
+ end
57
+ end
58
+
59
+ it 'is published every heartbeat interval' do
60
+ client
61
+ sleep 4
62
+ client.close
63
+
64
+ started_events = subscriber.select_started_events(Mongo::Monitoring::Event::ServerHeartbeatStarted)
65
+ # Expect about 8 events, maybe 9 or 7
66
+ started_events.length.should >= 6
67
+ started_events.length.should <= 10
68
+
69
+ succeeded_events = subscriber.select_succeeded_events(Mongo::Monitoring::Event::ServerHeartbeatSucceeded)
70
+ # Since we gracefully close the client, we expect each heartbeat
71
+ # to complete.
72
+ started_events.length.should == succeeded_events.length
73
+ end
74
+ end
75
+
76
+ context '4.4+ servers' do
77
+ min_server_fcv '4.4'
78
+
79
+ let(:client) do
80
+ new_local_client(SpecConfig.instance.addresses,
81
+ # Heartbeat interval is bound by 500 ms
82
+ SpecConfig.instance.test_options.merge(heartbeat_frequency: 0.5),
83
+ ).tap do |client|
84
+ client.subscribe(Mongo::Monitoring::SERVER_HEARTBEAT, subscriber)
85
+ end
86
+ end
87
+
88
+ it 'is published up to twice every heartbeat interval' do
89
+ client
90
+ sleep 3
91
+ client.close
92
+
93
+ events = subscriber.select_started_events(Mongo::Monitoring::Event::ServerHeartbeatStarted)
94
+ # We could have up to 16 events and should have no fewer than 8 events.
95
+ # Whenever an awaited ismaster succeeds while the regular monitor is
96
+ # waiting, the regular monitor's next scan is pushed forward.
97
+ events.length.should >= 6
98
+ events.length.should <= 18
99
+ (started_awaited = events.select(&:awaited?)).should_not be_empty
100
+ (started_regular = events.reject(&:awaited?)).should_not be_empty
101
+
102
+ events = subscriber.select_succeeded_events(Mongo::Monitoring::Event::ServerHeartbeatSucceeded)
103
+ events.length.should >= 6
104
+ events.length.should <= 18
105
+ (succeeded_awaited = events.select(&:awaited?)).should_not be_empty
106
+ (succeeded_regular = events.reject(&:awaited?)).should_not be_empty
107
+
108
+ # Since we gracefully close the client, we expect each heartbeat
109
+ # to complete.
110
+ started_awaited.length.should == succeeded_awaited.length
111
+ started_regular.length.should == succeeded_regular.length
112
+ end
113
+ end
114
+ end
44
115
  end
@@ -0,0 +1,64 @@
1
+ require 'spec_helper'
2
+
3
+ describe 'SDAM prose tests' do
4
+ # The "streaming protocol tests" are covered by the tests in
5
+ # sdam_events_spec.rb.
6
+
7
+ describe 'RTT tests' do
8
+ min_server_fcv '4.4'
9
+ require_topology :single
10
+
11
+ let(:subscriber) { EventSubscriber.new }
12
+
13
+ let(:client) do
14
+ new_local_client(SpecConfig.instance.addresses,
15
+ # Heartbeat interval is bound by 500 ms
16
+ SpecConfig.instance.test_options.merge(
17
+ heartbeat_frequency: 0.5,
18
+ app_name: 'streamingRttTest',
19
+ ),
20
+ ).tap do |client|
21
+ client.subscribe(Mongo::Monitoring::SERVER_HEARTBEAT, subscriber)
22
+ end
23
+ end
24
+
25
+ it 'updates RTT' do
26
+ server = client.cluster.next_primary
27
+
28
+ sleep 2
29
+
30
+ events = subscriber.select_succeeded_events(Mongo::Monitoring::Event::ServerHeartbeatSucceeded)
31
+ events.each do |event|
32
+ event.round_trip_time.should be_a(Numeric)
33
+ event.round_trip_time.should > 0
34
+ end
35
+
36
+ root_authorized_client.use('admin').database.command(
37
+ configureFailPoint: 'failCommand',
38
+ mode: {times: 1000},
39
+ data: {
40
+ failCommands: ["isMaster"],
41
+ blockConnection: true,
42
+ blockTimeMS: 500,
43
+ appName: "streamingRttTest",
44
+ },
45
+ )
46
+
47
+ deadline = Time.now + 10
48
+ loop do
49
+ if server.average_round_trip_time > 0.25
50
+ break
51
+ end
52
+ if Time.now >= deadline
53
+ raise "Failed to witness RTT growing to >= 250 ms in 10 seconds"
54
+ end
55
+ sleep 0.2
56
+ end
57
+ end
58
+
59
+ after do
60
+ root_authorized_client.use('admin').database.command(
61
+ configureFailPoint: 'failCommand', mode: 'off')
62
+ end
63
+ end
64
+ end