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
@@ -5,7 +5,11 @@ describe 'Server::Monitor' do
5
5
  let(:client) do
6
6
  new_local_client([ClusterConfig.instance.primary_address_str],
7
7
  SpecConfig.instance.test_options.merge(SpecConfig.instance.auth_options.merge(
8
- heartbeat_frequency: 1)))
8
+ monitor_options)))
9
+ end
10
+
11
+ let(:monitor_options) do
12
+ {heartbeat_frequency: 1}
9
13
  end
10
14
 
11
15
  it 'refreshes server descriptions in background', retry: 3 do
@@ -25,4 +29,24 @@ describe 'Server::Monitor' do
25
29
 
26
30
  expect(server.description).not_to be_unknown
27
31
  end
32
+
33
+ context 'server-pushed ismaster' do
34
+ min_server_fcv '4.4'
35
+ require_topology :replica_set
36
+
37
+ let(:monitor_options) do
38
+ {heartbeat_frequency: 20}
39
+ end
40
+
41
+ it 'updates server description' do
42
+ starting_primary_address = client.cluster.next_primary.address
43
+
44
+ ClusterTools.instance.step_down
45
+
46
+ sleep 2
47
+
48
+ new_primary_address = client.cluster.next_primary.address
49
+ new_primary_address.should_not == starting_primary_address
50
+ end
51
+ end
28
52
  end
@@ -36,7 +36,7 @@ describe 'BSON & command size limits' do
36
36
  end
37
37
 
38
38
  authorized_collection.insert_many(documents)
39
- authorized_collection.count_documents({}).should == 8
39
+ authorized_collection.count_documents.should == 8
40
40
  end
41
41
 
42
42
  # This test ensures that document which are too big definitely fail insertion.
@@ -49,7 +49,7 @@ describe 'BSON & command size limits' do
49
49
  lambda do
50
50
  authorized_collection.insert_many(documents)
51
51
  end.should raise_error(Mongo::Error::MaxBSONSize, /The document exceeds maximum allowed BSON object size after serialization/)
52
- authorized_collection.count_documents({}).should == 0
52
+ authorized_collection.count_documents.should == 0
53
53
  end
54
54
 
55
55
  it 'allows user-provided documents to be exactly 16MiB' do
@@ -81,6 +81,10 @@ describe 'BSON & command size limits' do
81
81
  end
82
82
 
83
83
  it 'allows bulk writes of multiple documents of exactly 16 MiB each' do
84
+ if SpecConfig.instance.compressors
85
+ pending "RUBY-2234"
86
+ end
87
+
84
88
  documents = []
85
89
  1.upto(3) do |index|
86
90
  document = { key: 'a' * (max_document_size - 28), _id: "in#{index}" }
@@ -89,6 +93,6 @@ describe 'BSON & command size limits' do
89
93
  end
90
94
 
91
95
  authorized_collection.insert_many(documents)
92
- authorized_collection.count_documents({}).should == 3
96
+ authorized_collection.count_documents.should == 3
93
97
  end
94
98
  end
@@ -0,0 +1,98 @@
1
+ require 'spec_helper'
2
+
3
+ describe 'BSON & command size limits' do
4
+ let(:max_document_size) { 16*1024*1024 }
5
+
6
+ before do
7
+ authorized_collection.delete_many
8
+ end
9
+
10
+ # This test uses a large document that is significantly smaller than the
11
+ # size limit. It is a basic sanity check.
12
+ it 'allows user-provided documents to be 15MiB' do
13
+ document = { key: 'a' * 15*1024*1024, _id: 'foo' }
14
+
15
+ authorized_collection.insert_one(document)
16
+ end
17
+
18
+ # This test uses a large document that is significantly larger than the
19
+ # size limit. It is a basic sanity check.
20
+ it 'fails single write of oversized documents' do
21
+ document = { key: 'a' * 17*1024*1024, _id: 'foo' }
22
+
23
+ lambda do
24
+ authorized_collection.insert_one(document)
25
+ end.should raise_error(Mongo::Error::MaxBSONSize, /The document exceeds maximum allowed BSON object size after serialization/)
26
+ end
27
+
28
+ # This test checks our bulk write splitting when documents are not close
29
+ # to the limit, but where splitting is definitely required.
30
+ it 'allows split bulk write of medium sized documents' do
31
+ # 8 documents of 4 MiB each = 32 MiB total data, should be split over
32
+ # either 2 or 3 bulk writes depending on how well the driver splits
33
+ documents = []
34
+ 1.upto(8) do |index|
35
+ documents << { key: 'a' * 4*1024*1024, _id: "in#{index}" }
36
+ end
37
+
38
+ authorized_collection.insert_many(documents)
39
+ authorized_collection.count_documents({}).should == 8
40
+ end
41
+
42
+ # This test ensures that document which are too big definitely fail insertion.
43
+ it 'fails bulk write of oversized documents' do
44
+ documents = []
45
+ 1.upto(3) do |index|
46
+ documents << { key: 'a' * 17*1024*1024, _id: "in#{index}" }
47
+ end
48
+
49
+ lambda do
50
+ authorized_collection.insert_many(documents)
51
+ end.should raise_error(Mongo::Error::MaxBSONSize, /The document exceeds maximum allowed BSON object size after serialization/)
52
+ authorized_collection.count_documents({}).should == 0
53
+ end
54
+
55
+ it 'allows user-provided documents to be exactly 16MiB' do
56
+ # The document must contain the _id field, otherwise the server will
57
+ # add it which will increase the size of the document as persisted by
58
+ # the server.
59
+ document = { key: 'a' * (max_document_size - 28), _id: 'foo' }
60
+ expect(document.to_bson.length).to eq(max_document_size)
61
+
62
+ authorized_collection.insert_one(document)
63
+ end
64
+
65
+ it 'fails on the server when a document larger than 16MiB is inserted' do
66
+ document = { key: 'a' * (max_document_size - 27), _id: 'foo' }
67
+ expect(document.to_bson.length).to eq(max_document_size+1)
68
+
69
+ lambda do
70
+ authorized_collection.insert_one(document)
71
+ end.should raise_error(Mongo::Error::OperationFailure, /object to insert too large/)
72
+ end
73
+
74
+ it 'fails in the driver when a document larger than 16MiB+16KiB is inserted' do
75
+ document = { key: 'a' * (max_document_size - 27 + 16*1024), _id: 'foo' }
76
+ expect(document.to_bson.length).to eq(max_document_size+16*1024+1)
77
+
78
+ lambda do
79
+ authorized_collection.insert_one(document)
80
+ end.should raise_error(Mongo::Error::MaxBSONSize, /The document exceeds maximum allowed BSON object size after serialization/)
81
+ end
82
+
83
+ it 'allows bulk writes of multiple documents of exactly 16 MiB each' do
84
+ if SpecConfig.instance.compressors
85
+ pending "RUBY-2234"
86
+ end
87
+
88
+ documents = []
89
+ 1.upto(3) do |index|
90
+ document = { key: 'a' * (max_document_size - 28), _id: "in#{index}" }
91
+ expect(document.to_bson.length).to eq(max_document_size)
92
+ documents << document
93
+ end
94
+
95
+ authorized_collection.insert_many(documents)
96
+ authorized_collection.count_documents({}).should == 3
97
+ end
98
+ end
@@ -20,6 +20,6 @@ describe 'SSL connections with URI options' do
20
20
 
21
21
  it 'successfully connects and runs an operation' do
22
22
  client = new_local_client(uri)
23
- expect { client[:foo].count_documents({}) }.not_to raise_error
23
+ expect { client[:foo].count_documents }.not_to raise_error
24
24
  end
25
- end
25
+ end
@@ -0,0 +1,25 @@
1
+ require 'spec_helper'
2
+
3
+ describe 'Zlib compression' do
4
+ require_compression
5
+
6
+ before do
7
+ authorized_client['test'].drop
8
+ end
9
+
10
+ context 'when client has zlib compressor option enabled' do
11
+ it 'compresses the message to the server' do
12
+ # Double check that the client has zlib compression enabled
13
+ expect(authorized_client.options[:compressors]).to include('zlib')
14
+
15
+ expect(Mongo::Protocol::Compressed).to receive(:new).twice.and_call_original
16
+ expect(Zlib::Deflate).to receive(:deflate).twice.and_call_original
17
+ expect(Zlib::Inflate).to receive(:inflate).twice.and_call_original
18
+
19
+ authorized_client['test'].insert_one(_id: 1, text: 'hello world')
20
+ document = authorized_client['test'].find(_id: 1).first
21
+
22
+ expect(document['text']).to eq('hello world')
23
+ end
24
+ end
25
+ end
@@ -4,8 +4,6 @@ CURRENT_PATH = File.expand_path(File.dirname(__FILE__))
4
4
  SERVER_DISCOVERY_TESTS = Dir.glob("#{CURRENT_PATH}/spec_tests/data/sdam/**/*.yml").sort
5
5
  SDAM_MONITORING_TESTS = Dir.glob("#{CURRENT_PATH}/spec_tests/data/sdam_monitoring/*.yml").sort
6
6
  SERVER_SELECTION_RTT_TESTS = Dir.glob("#{CURRENT_PATH}/spec_tests/data/server_selection_rtt/*.yml").sort
7
- SERVER_SELECTION_TESTS = Dir.glob("#{CURRENT_PATH}/spec_tests/data/server_selection/**/*.yml").sort
8
- MAX_STALENESS_TESTS = Dir.glob("#{CURRENT_PATH}/spec_tests/data/max_staleness/**/*.yml").sort
9
7
  CRUD_TESTS = Dir.glob("#{CURRENT_PATH}/spec_tests/data/crud/**/*.yml").sort
10
8
  CRUD2_TESTS = Dir.glob("#{CURRENT_PATH}/spec_tests/data/crud_v2/**/*.yml").sort
11
9
  RETRYABLE_WRITES_TESTS = Dir.glob("#{CURRENT_PATH}/spec_tests/data/retryable_writes/**/*.yml").sort
@@ -22,7 +20,11 @@ CMAP_TESTS = Dir.glob("#{CURRENT_PATH}/spec_tests/data/cmap/*.yml").sort
22
20
  AUTH_TESTS = Dir.glob("#{CURRENT_PATH}/spec_tests/data/auth/*.yml").sort
23
21
  CLIENT_SIDE_ENCRYPTION_TESTS = Dir.glob("#{CURRENT_PATH}/spec_tests/data/client_side_encryption/*.yml").sort
24
22
 
25
- if ENV['CI']
23
+ # Disable output buffering: https://www.rubyguides.com/2019/02/ruby-io/
24
+ STDOUT.sync = true
25
+ STDERR.sync = true
26
+
27
+ if %w(1 true yes).include?(ENV['CI']&.downcase)
26
28
  autoload :Byebug, 'byebug'
27
29
  else
28
30
  # Load debuggers before loading the driver code, so that breakpoints
@@ -107,14 +109,19 @@ RSpec.configure do |config|
107
109
  # Tests should take under 10 seconds ideally but it seems
108
110
  # we have some that run for more than 10 seconds in CI.
109
111
  config.around(:each) do |example|
110
- TimeoutInterrupt.timeout(45) do
112
+ timeout = if %w(1 true yes).include?(ENV['STRESS']&.downcase)
113
+ 210
114
+ else
115
+ 45
116
+ end
117
+ TimeoutInterrupt.timeout(timeout) do
111
118
  example.run
112
119
  end
113
120
  end
114
121
  end
115
122
 
116
123
  if SpecConfig.instance.ci?
117
- if defined?(Rfc)
124
+ if defined?(Rfc::Rif)
118
125
  unless BSON::Environment.jruby?
119
126
  Rfc::Rif.output_object_space_stats = true
120
127
  end
@@ -0,0 +1,76 @@
1
+ require 'spec_helper'
2
+
3
+ describe Mongo::Auth::Aws::Request do
4
+
5
+ describe "#formatted_time" do
6
+ context "when time is provided and frozen" do
7
+ let(:original_time) { Time.at(1592399523).freeze }
8
+ let(:request) do
9
+ described_class.new(access_key_id: 'access_key_id',
10
+ secret_access_key: 'secret_access_key',
11
+ session_token: 'session_token',
12
+ host: 'host',
13
+ server_nonce: 'server_nonce',
14
+ time: original_time
15
+ )
16
+ end
17
+
18
+ it 'doesn\'t modify the time instance variable' do
19
+ expect { request.formatted_time }.to_not raise_error
20
+ end
21
+
22
+ it 'returns the correct formatted time' do
23
+ expect(request.formatted_time).to eq('20200617T131203Z')
24
+ end
25
+ end
26
+
27
+ context "when time is not provided" do
28
+ let(:request) do
29
+ described_class.new(access_key_id: 'access_key_id',
30
+ secret_access_key: 'secret_access_key',
31
+ session_token: 'session_token',
32
+ host: 'host',
33
+ server_nonce: 'server_nonce'
34
+ )
35
+ end
36
+
37
+ it 'doesn\'t raise an error on formatted_time' do
38
+ expect { request.formatted_time }.to_not raise_error
39
+ end
40
+ end
41
+ end
42
+
43
+ describe "#signature" do
44
+ context "when time is provided and frozen" do
45
+ let(:original_time) { Time.at(1592399523).freeze }
46
+ let(:request) do
47
+ described_class.new(access_key_id: 'access_key_id',
48
+ secret_access_key: 'secret_access_key',
49
+ session_token: 'session_token',
50
+ host: 'host',
51
+ server_nonce: 'server_nonce',
52
+ time: original_time
53
+ )
54
+ end
55
+
56
+ it 'doesn\'t raise error on signature' do
57
+ expect { request.signature }.to_not raise_error
58
+ end
59
+ end
60
+
61
+ context "when time is not provided" do
62
+ let(:request) do
63
+ described_class.new(access_key_id: 'access_key_id',
64
+ secret_access_key: 'secret_access_key',
65
+ session_token: 'session_token',
66
+ host: 'host',
67
+ server_nonce: 'server_nonce'
68
+ )
69
+ end
70
+
71
+ it 'doesn\'t raise error on signature' do
72
+ expect { request.signature }.to_not raise_error
73
+ end
74
+ end
75
+ end
76
+ end
@@ -65,7 +65,7 @@ describe Mongo::Auth::Scram do
65
65
  it 'does not compress the message' do
66
66
  expect(Mongo::Protocol::Compressed).not_to receive(:new)
67
67
  expect {
68
- authenticator.login(connection)
68
+ authenticator.login
69
69
  }.to raise_error(Mongo::Auth::Unauthorized)
70
70
  end
71
71
  end
@@ -319,6 +319,104 @@ describe Mongo::Client do
319
319
  end
320
320
  end
321
321
 
322
+ context 'timeout options' do
323
+ let(:client) do
324
+ new_local_client(SpecConfig.instance.addresses,
325
+ SpecConfig.instance.authorized_test_options.merge(options))
326
+ end
327
+
328
+ context 'when network timeouts are zero' do
329
+ let(:options) do
330
+ { socket_timeout: 0, connect_timeout: 0 }
331
+ end
332
+
333
+ it 'sets options to zeros' do
334
+ client.options[:socket_timeout].should == 0
335
+ client.options[:connect_timeout].should == 0
336
+ end
337
+
338
+ it 'connects and performs operations successfully' do
339
+ lambda do
340
+ client.database.command(ping: 1)
341
+ end.should_not raise_error
342
+ end
343
+ end
344
+
345
+ %i(socket_timeout connect_timeout).each do |option|
346
+ context "when #{option} is negative" do
347
+ let(:options) do
348
+ { option => -1 }
349
+ end
350
+
351
+ it 'fails client creation' do
352
+ lambda do
353
+ client
354
+ end.should raise_error(ArgumentError, /#{option} must be a non-negative number/)
355
+ end
356
+ end
357
+
358
+ context "when #{option} is of the wrong type" do
359
+ let(:options) do
360
+ { option => '42' }
361
+ end
362
+
363
+ it 'fails client creation' do
364
+ lambda do
365
+ client
366
+ end.should raise_error(ArgumentError, /#{option} must be a non-negative number/)
367
+ end
368
+ end
369
+ end
370
+
371
+ context "when :connect_timeout is very small" do
372
+ # The driver reads first and checks the deadline second.
373
+ # This means the read (in a monitor) can technically take more than
374
+ # the connect timeout. Restrict to TLS configurations to make
375
+ # the network I/O take longer.
376
+ require_tls
377
+
378
+ let(:options) do
379
+ { connect_timeout: 1e-6, server_selection_timeout: 2 }
380
+ end
381
+
382
+ it 'allows client creation' do
383
+ lambda do
384
+ client
385
+ end.should_not raise_error
386
+ end
387
+
388
+ it 'fails server selection due to very small timeout' do
389
+ lambda do
390
+ client.database.command(ping: 1)
391
+ end.should raise_error(Mongo::Error::NoServerAvailable)
392
+ end
393
+ end
394
+
395
+ context "when :socket_timeout is very small" do
396
+ # The driver reads first and checks the deadline second.
397
+ # This means the read (in a monitor) can technically take more than
398
+ # the connect timeout. Restrict to TLS configurations to make
399
+ # the network I/O take longer.
400
+ require_tls
401
+
402
+ let(:options) do
403
+ { socket_timeout: 1e-6, server_selection_timeout: 2 }
404
+ end
405
+
406
+ it 'allows client creation' do
407
+ lambda do
408
+ client
409
+ end.should_not raise_error
410
+ end
411
+
412
+ it 'fails operations due to very small timeout' do
413
+ lambda do
414
+ client.database.command(ping: 1)
415
+ end.should raise_error(Mongo::Error::SocketTimeoutError)
416
+ end
417
+ end
418
+ end
419
+
322
420
  context 'retry_writes option' do
323
421
  let(:client) do
324
422
  new_local_client_nmio(SpecConfig.instance.addresses, options)
@@ -1138,6 +1236,48 @@ describe Mongo::Client do
1138
1236
  end
1139
1237
  end
1140
1238
 
1239
+ context ':bg_error_backtrace option' do
1240
+ [true, false, nil, 42].each do |valid_value|
1241
+ context "valid value: #{valid_value.inspect}" do
1242
+ let(:options) do
1243
+ {bg_error_backtrace: valid_value}
1244
+ end
1245
+
1246
+ it 'is accepted' do
1247
+ client.options[:bg_error_backtrace].should == valid_value
1248
+ end
1249
+ end
1250
+ end
1251
+
1252
+ context 'invalid value type' do
1253
+ let(:options) do
1254
+ {bg_error_backtrace: 'yes'}
1255
+ end
1256
+
1257
+ it 'is rejected' do
1258
+ lambda do
1259
+ client
1260
+ end.should raise_error(ArgumentError, /:bg_error_backtrace option value must be true, false, nil or a positive integer/)
1261
+ end
1262
+ end
1263
+
1264
+ context 'invalid value' do
1265
+ [0, -1, 42.0].each do |invalid_value|
1266
+ context "invalid value: #{invalid_value.inspect}" do
1267
+ let(:options) do
1268
+ {bg_error_backtrace: invalid_value}
1269
+ end
1270
+
1271
+ it 'is rejected' do
1272
+ lambda do
1273
+ client
1274
+ end.should raise_error(ArgumentError, /:bg_error_backtrace option value must be true, false, nil or a positive integer/)
1275
+ end
1276
+ end
1277
+ end
1278
+ end
1279
+ end
1280
+
1141
1281
  describe ':read option' do
1142
1282
  [
1143
1283
  :primary, :primary_preferred, :secondary, :secondary_preferred, :nearest
@@ -1243,6 +1383,73 @@ describe Mongo::Client do
1243
1383
  end
1244
1384
  =end
1245
1385
  end
1386
+
1387
+ context 'when making a block client' do
1388
+ context 'when the block doesn\'t raise an error' do
1389
+ let(:block_client) do
1390
+ c = nil
1391
+ Mongo::Client.new(
1392
+ SpecConfig.instance.addresses,
1393
+ SpecConfig.instance.test_options.merge(database: SpecConfig.instance.test_db),
1394
+ ) do |client|
1395
+ c = client
1396
+ end
1397
+ c
1398
+ end
1399
+
1400
+ it 'is closed after block' do
1401
+ expect(block_client.cluster.connected?).to eq(false)
1402
+ end
1403
+ end
1404
+
1405
+ context 'when the block raises an error' do
1406
+ it 'it is closed after the block' do
1407
+ block_client_raise = nil
1408
+ expect do
1409
+ Mongo::Client.new(
1410
+ SpecConfig.instance.addresses,
1411
+ SpecConfig.instance.test_options.merge(database: SpecConfig.instance.test_db),
1412
+ ) do |client|
1413
+ block_client_raise = client
1414
+ raise "This is an error!"
1415
+ end
1416
+ end.to raise_error(StandardError, "This is an error!")
1417
+ expect(block_client_raise.cluster.connected?).to eq(false)
1418
+ end
1419
+ end
1420
+
1421
+ context 'when the hosts given include the protocol' do
1422
+ it 'raises an error on mongodb://' do
1423
+ expect do
1424
+ Mongo::Client.new(['mongodb://127.0.0.1:27017/test'])
1425
+ end.to raise_error(ArgumentError, "Host 'mongodb://127.0.0.1:27017/test' should not contain protocol. Did you mean to not use an array?")
1426
+ end
1427
+
1428
+ it 'raises an error on mongodb+srv://' do
1429
+ expect do
1430
+ Mongo::Client.new(['mongodb+srv://127.0.0.1:27017/test'])
1431
+ end.to raise_error(ArgumentError, "Host 'mongodb+srv://127.0.0.1:27017/test' should not contain protocol. Did you mean to not use an array?")
1432
+ end
1433
+
1434
+ it 'raises an error on multiple items' do
1435
+ expect do
1436
+ Mongo::Client.new(['127.0.0.1:27017', 'mongodb+srv://127.0.0.1:27017/test'])
1437
+ end.to raise_error(ArgumentError, "Host 'mongodb+srv://127.0.0.1:27017/test' should not contain protocol. Did you mean to not use an array?")
1438
+ end
1439
+
1440
+ it 'raises an error only at beginning of string' do
1441
+ expect do
1442
+ Mongo::Client.new(['somethingmongodb://127.0.0.1:27017/test', 'mongodb+srv://127.0.0.1:27017/test'])
1443
+ end.to raise_error(ArgumentError, "Host 'mongodb+srv://127.0.0.1:27017/test' should not contain protocol. Did you mean to not use an array?")
1444
+ end
1445
+
1446
+ it 'raises an error with different case' do
1447
+ expect do
1448
+ Mongo::Client.new(['MongOdB://127.0.0.1:27017/test'])
1449
+ end.to raise_error(ArgumentError, "Host 'MongOdB://127.0.0.1:27017/test' should not contain protocol. Did you mean to not use an array?")
1450
+ end
1451
+ end
1452
+ end
1246
1453
  end
1247
1454
 
1248
1455
  shared_examples_for 'duplicated client with duplicated monitoring' do