mongo 2.14.1 → 2.15.0.alpha

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 (230) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data/README.md +4 -1
  4. data/Rakefile +8 -15
  5. data/lib/mongo/auth/aws/conversation.rb +1 -4
  6. data/lib/mongo/auth/base.rb +13 -7
  7. data/lib/mongo/auth/conversation_base.rb +32 -0
  8. data/lib/mongo/auth/cr/conversation.rb +6 -29
  9. data/lib/mongo/auth/gssapi/conversation.rb +4 -15
  10. data/lib/mongo/auth/ldap/conversation.rb +3 -14
  11. data/lib/mongo/auth/sasl_conversation_base.rb +1 -13
  12. data/lib/mongo/auth/scram_conversation_base.rb +7 -34
  13. data/lib/mongo/auth/user/view.rb +16 -9
  14. data/lib/mongo/auth/x509/conversation.rb +4 -25
  15. data/lib/mongo/bulk_write.rb +21 -18
  16. data/lib/mongo/client.rb +82 -6
  17. data/lib/mongo/cluster/reapers/cursor_reaper.rb +6 -2
  18. data/lib/mongo/cluster.rb +19 -2
  19. data/lib/mongo/collection/view/aggregation.rb +1 -1
  20. data/lib/mongo/collection/view/change_stream.rb +1 -1
  21. data/lib/mongo/collection/view/iterable.rb +7 -17
  22. data/lib/mongo/collection/view/map_reduce.rb +2 -2
  23. data/lib/mongo/collection/view/readable.rb +42 -20
  24. data/lib/mongo/collection/view/writable.rb +14 -14
  25. data/lib/mongo/collection.rb +6 -6
  26. data/lib/mongo/cursor.rb +2 -12
  27. data/lib/mongo/database/view.rb +1 -1
  28. data/lib/mongo/database.rb +8 -3
  29. data/lib/mongo/error/bulk_write_error.rb +17 -3
  30. data/lib/mongo/error/internal_driver_error.rb +22 -0
  31. data/lib/mongo/error/operation_failure.rb +21 -2
  32. data/lib/mongo/error/parser.rb +65 -12
  33. data/lib/mongo/error/server_api_conflict.rb +23 -0
  34. data/lib/mongo/error/server_api_not_supported.rb +24 -0
  35. data/lib/mongo/error/unmet_dependency.rb +21 -0
  36. data/lib/mongo/error.rb +9 -1
  37. data/lib/mongo/index/view.rb +21 -11
  38. data/lib/mongo/monitoring/event/server_heartbeat_failed.rb +27 -16
  39. data/lib/mongo/monitoring/event/server_heartbeat_succeeded.rb +26 -15
  40. data/lib/mongo/monitoring.rb +13 -4
  41. data/lib/mongo/operation/collections_info/command.rb +2 -2
  42. data/lib/mongo/operation/collections_info.rb +18 -1
  43. data/lib/mongo/operation/context.rb +99 -0
  44. data/lib/mongo/operation/indexes.rb +15 -1
  45. data/lib/mongo/operation/insert/command.rb +2 -2
  46. data/lib/mongo/operation/insert/legacy.rb +2 -2
  47. data/lib/mongo/operation/insert/op_msg.rb +2 -2
  48. data/lib/mongo/operation/list_collections/result.rb +4 -1
  49. data/lib/mongo/operation/parallel_scan/command.rb +2 -1
  50. data/lib/mongo/operation/result.rb +2 -0
  51. data/lib/mongo/operation/shared/executable.rb +24 -14
  52. data/lib/mongo/operation/shared/executable_no_validate.rb +2 -2
  53. data/lib/mongo/operation/shared/op_msg_or_command.rb +1 -7
  54. data/lib/mongo/operation/shared/op_msg_or_find_command.rb +1 -7
  55. data/lib/mongo/operation/shared/polymorphic_operation.rb +39 -0
  56. data/lib/mongo/operation/shared/read_preference_supported.rb +36 -38
  57. data/lib/mongo/operation/shared/response_handling.rb +23 -23
  58. data/lib/mongo/operation/shared/sessions_supported.rb +15 -5
  59. data/lib/mongo/operation/shared/write.rb +8 -18
  60. data/lib/mongo/operation.rb +2 -2
  61. data/lib/mongo/protocol/compressed.rb +51 -5
  62. data/lib/mongo/protocol/message.rb +20 -2
  63. data/lib/mongo/protocol/msg.rb +38 -13
  64. data/lib/mongo/protocol/query.rb +11 -11
  65. data/lib/mongo/query_cache.rb +30 -0
  66. data/lib/mongo/retryable.rb +1 -1
  67. data/lib/mongo/server/app_metadata.rb +52 -18
  68. data/lib/mongo/server/connection.rb +5 -0
  69. data/lib/mongo/server/connection_base.rb +13 -10
  70. data/lib/mongo/server/connection_pool.rb +6 -2
  71. data/lib/mongo/server/description/features.rb +9 -8
  72. data/lib/mongo/server/description.rb +4 -0
  73. data/lib/mongo/server/monitor/app_metadata.rb +1 -1
  74. data/lib/mongo/server/monitor/connection.rb +9 -10
  75. data/lib/mongo/server/monitor.rb +20 -1
  76. data/lib/mongo/server/pending_connection.rb +24 -6
  77. data/lib/mongo/server/push_monitor.rb +11 -1
  78. data/lib/mongo/server.rb +7 -1
  79. data/lib/mongo/server_selector/secondary_preferred.rb +7 -2
  80. data/lib/mongo/session/session_pool.rb +4 -2
  81. data/lib/mongo/session.rb +2 -2
  82. data/lib/mongo/socket/ssl.rb +8 -0
  83. data/lib/mongo/socket.rb +29 -4
  84. data/lib/mongo/uri/options_mapper.rb +38 -0
  85. data/lib/mongo/utils.rb +15 -0
  86. data/lib/mongo/version.rb +1 -1
  87. data/lib/mongo.rb +23 -0
  88. data/spec/README.md +24 -1
  89. data/spec/integration/auth_spec.rb +25 -15
  90. data/spec/integration/bulk_write_error_message_spec.rb +41 -0
  91. data/spec/integration/change_stream_spec.rb +4 -4
  92. data/spec/integration/command_monitoring_spec.rb +2 -2
  93. data/spec/integration/connection_spec.rb +2 -0
  94. data/spec/integration/docs_examples_spec.rb +8 -1
  95. data/spec/integration/fork_reconnect_spec.rb +4 -1
  96. data/spec/integration/ocsp_verifier_spec.rb +13 -7
  97. data/spec/integration/operation_failure_code_spec.rb +1 -1
  98. data/spec/integration/operation_failure_message_spec.rb +90 -0
  99. data/spec/integration/query_cache_spec.rb +0 -45
  100. data/spec/integration/reconnect_spec.rb +1 -1
  101. data/spec/integration/snappy_compression_spec.rb +25 -0
  102. data/spec/integration/srv_monitoring_spec.rb +1 -1
  103. data/spec/integration/transactions_examples_spec.rb +6 -0
  104. data/spec/integration/zlib_compression_spec.rb +1 -1
  105. data/spec/integration/zstd_compression_spec.rb +26 -0
  106. data/spec/lite_spec_helper.rb +7 -1
  107. data/spec/mongo/address_spec.rb +15 -11
  108. data/spec/mongo/auth/ldap/conversation_spec.rb +1 -1
  109. data/spec/mongo/auth/ldap_spec.rb +5 -1
  110. data/spec/mongo/auth/scram_negotiation_spec.rb +1 -1
  111. data/spec/mongo/auth/scram_spec.rb +1 -1
  112. data/spec/mongo/auth/x509/conversation_spec.rb +3 -3
  113. data/spec/mongo/client_construction_spec.rb +207 -33
  114. data/spec/mongo/client_spec.rb +17 -0
  115. data/spec/mongo/cluster_spec.rb +1 -0
  116. data/spec/mongo/collection/view/explainable_spec.rb +1 -1
  117. data/spec/mongo/collection/view/readable_spec.rb +33 -19
  118. data/spec/mongo/collection_crud_spec.rb +4357 -0
  119. data/spec/mongo/collection_ddl_spec.rb +534 -0
  120. data/spec/mongo/collection_spec.rb +5 -4859
  121. data/spec/mongo/database_spec.rb +66 -4
  122. data/spec/mongo/error/bulk_write_error_spec.rb +3 -3
  123. data/spec/mongo/error/parser_spec.rb +37 -6
  124. data/spec/mongo/index/view_spec.rb +4 -0
  125. data/spec/mongo/monitoring/event/server_heartbeat_failed_spec.rb +1 -1
  126. data/spec/mongo/monitoring/event/server_heartbeat_succeeded_spec.rb +1 -1
  127. data/spec/mongo/operation/aggregate_spec.rb +2 -1
  128. data/spec/mongo/operation/collections_info_spec.rb +4 -1
  129. data/spec/mongo/operation/command_spec.rb +6 -3
  130. data/spec/mongo/operation/create_index_spec.rb +6 -3
  131. data/spec/mongo/operation/create_user_spec.rb +6 -3
  132. data/spec/mongo/operation/delete/bulk_spec.rb +9 -6
  133. data/spec/mongo/operation/delete_spec.rb +11 -7
  134. data/spec/mongo/operation/drop_index_spec.rb +6 -2
  135. data/spec/mongo/operation/find/legacy_spec.rb +3 -1
  136. data/spec/mongo/operation/get_more_spec.rb +3 -1
  137. data/spec/mongo/operation/indexes_spec.rb +5 -1
  138. data/spec/mongo/operation/insert/bulk_spec.rb +10 -7
  139. data/spec/mongo/operation/insert_spec.rb +15 -12
  140. data/spec/mongo/operation/map_reduce_spec.rb +5 -2
  141. data/spec/mongo/operation/read_preference_legacy_spec.rb +19 -9
  142. data/spec/mongo/operation/read_preference_op_msg_spec.rb +3 -3
  143. data/spec/mongo/operation/remove_user_spec.rb +6 -3
  144. data/spec/mongo/operation/result_spec.rb +1 -1
  145. data/spec/mongo/operation/update/bulk_spec.rb +9 -6
  146. data/spec/mongo/operation/update_spec.rb +10 -7
  147. data/spec/mongo/operation/update_user_spec.rb +4 -1
  148. data/spec/mongo/protocol/compressed_spec.rb +26 -12
  149. data/spec/mongo/query_cache_middleware_spec.rb +55 -0
  150. data/spec/mongo/retryable_spec.rb +3 -2
  151. data/spec/mongo/server/app_metadata_shared.rb +7 -33
  152. data/spec/mongo/server/app_metadata_spec.rb +2 -0
  153. data/spec/mongo/server/connection_pool/populator_spec.rb +3 -1
  154. data/spec/mongo/server/connection_pool_spec.rb +1 -1
  155. data/spec/mongo/server/connection_spec.rb +24 -17
  156. data/spec/mongo/server/monitor/connection_spec.rb +17 -7
  157. data/spec/mongo/server/monitor_spec.rb +9 -1
  158. data/spec/mongo/server_selector/secondary_preferred_spec.rb +6 -6
  159. data/spec/mongo/server_spec.rb +15 -2
  160. data/spec/mongo/socket/ssl_spec.rb +40 -0
  161. data/spec/mongo/socket_spec.rb +2 -2
  162. data/spec/mongo/tls_context_hooks_spec.rb +37 -0
  163. data/spec/runners/connection_string.rb +0 -4
  164. data/spec/runners/crud/requirement.rb +40 -3
  165. data/spec/runners/crud/verifier.rb +8 -0
  166. data/spec/runners/transactions/operation.rb +1 -1
  167. data/spec/runners/transactions/test.rb +1 -0
  168. data/spec/runners/unified/assertions.rb +249 -0
  169. data/spec/runners/unified/change_stream_operations.rb +26 -0
  170. data/spec/runners/unified/crud_operations.rb +199 -0
  171. data/spec/runners/unified/ddl_operations.rb +96 -0
  172. data/spec/runners/unified/entity_map.rb +39 -0
  173. data/spec/runners/unified/error.rb +25 -0
  174. data/spec/runners/unified/event_subscriber.rb +91 -0
  175. data/spec/runners/unified/exceptions.rb +21 -0
  176. data/spec/runners/unified/grid_fs_operations.rb +55 -0
  177. data/spec/runners/unified/support_operations.rb +250 -0
  178. data/spec/runners/unified/test.rb +393 -0
  179. data/spec/runners/unified/test_group.rb +28 -0
  180. data/spec/runners/unified/using_hash.rb +31 -0
  181. data/spec/runners/unified.rb +96 -0
  182. data/spec/shared/lib/mrss/cluster_config.rb +0 -3
  183. data/spec/shared/lib/mrss/docker_runner.rb +0 -3
  184. data/spec/shared/lib/mrss/lite_constraints.rb +0 -16
  185. data/spec/shared/lib/mrss/server_version_registry.rb +0 -3
  186. data/spec/shared/lib/mrss/spec_organizer.rb +0 -3
  187. data/spec/shared/shlib/server.sh +1 -1
  188. data/spec/spec_helper.rb +4 -1
  189. data/spec/spec_tests/crud_unified_spec.rb +10 -0
  190. data/spec/spec_tests/data/change_streams/change-streams.yml +0 -1
  191. data/spec/spec_tests/data/crud_unified/estimatedDocumentCount.yml +267 -0
  192. data/spec/spec_tests/data/retryable_reads/estimatedDocumentCount-4.9.yml +60 -0
  193. data/spec/spec_tests/data/retryable_reads/{estimatedDocumentCount.yml → estimatedDocumentCount-pre4.9.yml} +2 -0
  194. data/spec/spec_tests/data/retryable_reads/estimatedDocumentCount-serverErrors-4.9.yml +146 -0
  195. data/spec/spec_tests/data/retryable_reads/{estimatedDocumentCount-serverErrors.yml → estimatedDocumentCount-serverErrors-pre4.9.yml} +2 -0
  196. data/spec/spec_tests/data/retryable_reads/listIndexNames.yml +1 -1
  197. data/spec/spec_tests/data/unified/valid-fail/operation-failure.yml +31 -0
  198. data/spec/spec_tests/data/unified/valid-pass/poc-change-streams.yml +220 -0
  199. data/spec/spec_tests/data/unified/valid-pass/poc-command-monitoring.yml +102 -0
  200. data/spec/spec_tests/data/unified/valid-pass/poc-crud.yml +184 -0
  201. data/spec/spec_tests/data/unified/valid-pass/poc-gridfs.yml +155 -0
  202. data/spec/spec_tests/data/unified/valid-pass/poc-retryable-reads.yml +193 -0
  203. data/spec/spec_tests/data/unified/valid-pass/poc-retryable-writes.yml +210 -0
  204. data/spec/spec_tests/data/unified/valid-pass/poc-sessions.yml +215 -0
  205. data/spec/spec_tests/data/unified/valid-pass/poc-transactions-convenient-api.yml +235 -0
  206. data/spec/spec_tests/data/unified/valid-pass/poc-transactions-mongos-pin-auto.yml +169 -0
  207. data/spec/spec_tests/data/unified/valid-pass/poc-transactions.yml +170 -0
  208. data/spec/spec_tests/data/uri_options/compression-options.yml +1 -1
  209. data/spec/spec_tests/data/versioned_api/crud-api-version-1-strict.yml +416 -0
  210. data/spec/spec_tests/data/versioned_api/crud-api-version-1.yml +409 -0
  211. data/spec/spec_tests/data/versioned_api/runcommand-helper-no-api-version-declared.yml +67 -0
  212. data/spec/spec_tests/data/versioned_api/test-commands-deprecation-errors.yml +47 -0
  213. data/spec/spec_tests/data/versioned_api/test-commands-strict-mode.yml +44 -0
  214. data/spec/spec_tests/data/versioned_api/transaction-handling.yml +180 -0
  215. data/spec/spec_tests/unified_spec.rb +15 -0
  216. data/spec/spec_tests/uri_options_spec.rb +16 -0
  217. data/spec/spec_tests/versioned_api_spec.rb +10 -0
  218. data/spec/support/client_registry.rb +4 -8
  219. data/spec/support/client_registry_macros.rb +4 -4
  220. data/spec/support/common_shortcuts.rb +15 -1
  221. data/spec/support/shared/session.rb +2 -2
  222. data/spec/support/spec_config.rb +42 -11
  223. data/spec/support/utils.rb +64 -3
  224. data.tar.gz.sig +0 -0
  225. metadata +1005 -915
  226. metadata.gz.sig +0 -0
  227. data/lib/mongo/operation/shared/collections_info_or_list_collections.rb +0 -58
  228. data/lib/mongo/operation/shared/op_msg_or_list_indexes_command.rb +0 -47
  229. data/spec/integration/secondary_reads_spec.rb +0 -102
  230. data/spec/support/cluster_config.rb +0 -207
@@ -53,6 +53,8 @@ describe Mongo::Server::AppMetadata do
53
53
  end
54
54
 
55
55
  context 'when the client document exceeds the max of 512 bytes' do
56
+ # Server api parameters change metadata length
57
+ require_no_required_api_version
56
58
 
57
59
  context 'when the os.type length is too long' do
58
60
 
@@ -61,7 +61,9 @@ describe Mongo::Server::Populator do
61
61
 
62
62
  it 'populates the pool up to min_size' do
63
63
  populator.run!
64
- sleep 1
64
+ ::Utils.wait_for_condition(3) do
65
+ pool.size >= 2
66
+ end
65
67
  expect(pool.size).to eq 2
66
68
  expect(populator.running?).to be true
67
69
  end
@@ -531,7 +531,7 @@ describe Mongo::Server::ConnectionPool do
531
531
  authorized_client
532
532
  end
533
533
 
534
- let(:pool) do
534
+ let(:pool) do
535
535
  client.cluster.next_primary.pool
536
536
  end
537
537
 
@@ -589,6 +589,8 @@ describe Mongo::Server::Connection do
589
589
 
590
590
  let(:server) { monitored_server }
591
591
 
592
+ let(:context) { Mongo::Operation::Context.new }
593
+
592
594
  let!(:connection) do
593
595
  described_class.new(
594
596
  server,
@@ -620,12 +622,12 @@ describe Mongo::Server::Connection do
620
622
  context 'when providing a single message' do
621
623
 
622
624
  let(:reply) do
623
- connection.dispatch([ query ])
625
+ connection.dispatch([ query ], context)
624
626
  end
625
627
 
626
628
  before do
627
629
  authorized_collection.delete_many
628
- connection.dispatch([ insert ])
630
+ authorized_collection.insert_one(name: 'testing')
629
631
  end
630
632
 
631
633
  it 'it dispatches the message to the socket' do
@@ -644,7 +646,7 @@ describe Mongo::Server::Connection do
644
646
  end
645
647
 
646
648
  let(:reply) do
647
- connection.dispatch([ insert, command ])
649
+ connection.dispatch([ insert, command ], context)
648
650
  end
649
651
 
650
652
  before do
@@ -681,22 +683,22 @@ describe Mongo::Server::Connection do
681
683
  end
682
684
 
683
685
  before do
684
- connection.dispatch([ insert ])
686
+ connection.dispatch([ insert ], context)
685
687
  # Fake a query for which we did not read the response. See RUBY-1117
686
688
  allow(query_bob).to receive(:replyable?) { false }
687
- connection.dispatch([ query_bob ])
689
+ connection.dispatch([ query_bob ], context)
688
690
  end
689
691
 
690
692
  it 'raises an UnexpectedResponse error' do
691
693
  expect {
692
- connection.dispatch([ query_alice ])
694
+ connection.dispatch([ query_alice ], context)
693
695
  }.to raise_error(Mongo::Error::UnexpectedResponse,
694
696
  /Got response for request ID \d+ but expected response for request ID \d+/)
695
697
  end
696
698
 
697
699
  it 'marks connection perished' do
698
700
  expect {
699
- connection.dispatch([ query_alice ])
701
+ connection.dispatch([ query_alice ], context)
700
702
  }.to raise_error(Mongo::Error::UnexpectedResponse)
701
703
 
702
704
  connection.should be_error
@@ -704,16 +706,17 @@ describe Mongo::Server::Connection do
704
706
 
705
707
  it 'makes the connection no longer usable' do
706
708
  expect {
707
- connection.dispatch([ query_alice ])
709
+ connection.dispatch([ query_alice ], context)
708
710
  }.to raise_error(Mongo::Error::UnexpectedResponse)
709
711
 
710
712
  expect {
711
- connection.dispatch([ query_alice ])
713
+ connection.dispatch([ query_alice ], context)
712
714
  }.to raise_error(Mongo::Error::ConnectionPerished)
713
715
  end
714
716
  end
715
717
 
716
718
  context 'when a request is interrupted (Thread.kill)' do
719
+ require_no_required_api_version
717
720
 
718
721
  let(:documents) do
719
722
  [{ 'name' => 'bob' }, { 'name' => 'alice' }]
@@ -733,18 +736,19 @@ describe Mongo::Server::Connection do
733
736
 
734
737
  before do
735
738
  authorized_collection.delete_many
736
- connection.dispatch([ insert ])
739
+ connection.dispatch([ insert ], context)
737
740
  end
738
741
 
739
742
  it 'closes the socket and does not use it for subsequent requests' do
740
743
  t = Thread.new {
741
744
  # Kill the thread just before the reply is read
742
745
  allow(Mongo::Protocol::Reply).to receive(:deserialize_header) { t.kill && !t.alive? }
743
- connection.dispatch([ query_bob ])
746
+ connection.dispatch([ query_bob ], context)
744
747
  }
745
748
  t.join
746
749
  allow(Mongo::Protocol::Message).to receive(:deserialize_header).and_call_original
747
- expect(connection.dispatch([ query_alice ]).documents.first['name']).to eq('alice')
750
+ resp = connection.dispatch([ query_alice ], context)
751
+ expect(resp.documents.first['name']).to eq('alice')
748
752
  end
749
753
  end
750
754
 
@@ -761,7 +765,7 @@ describe Mongo::Server::Connection do
761
765
  end
762
766
 
763
767
  let(:reply) do
764
- connection.dispatch([ insert ])
768
+ connection.dispatch([ insert ], context)
765
769
  end
766
770
 
767
771
  it 'checks the size against the max message size' do
@@ -788,7 +792,7 @@ describe Mongo::Server::Connection do
788
792
  end
789
793
 
790
794
  let(:reply) do
791
- connection.dispatch([ command ])
795
+ connection.dispatch([ command ], context)
792
796
  end
793
797
 
794
798
  it 'checks the size against the max bson size' do
@@ -828,7 +832,7 @@ describe Mongo::Server::Connection do
828
832
 
829
833
  let(:result) do
830
834
  expect do
831
- connection.dispatch([ insert ])
835
+ connection.dispatch([ insert ], context)
832
836
  end.to raise_error(Mongo::Error::SocketError)
833
837
  end
834
838
 
@@ -862,7 +866,7 @@ describe Mongo::Server::Connection do
862
866
 
863
867
  let(:result) do
864
868
  expect do
865
- connection.dispatch([ insert ])
869
+ connection.dispatch([ insert ], context)
866
870
  end.to raise_error(Mongo::Error::SocketTimeoutError)
867
871
  end
868
872
 
@@ -906,6 +910,7 @@ describe Mongo::Server::Connection do
906
910
  end
907
911
 
908
912
  before do
913
+ authorized_collection.insert_one(test: 1)
909
914
  client.cluster.next_primary
910
915
  end
911
916
 
@@ -919,6 +924,8 @@ describe Mongo::Server::Connection do
919
924
  end_time = Time.now
920
925
  expect(ex).to be_a(Mongo::Error::SocketTimeoutError)
921
926
  expect(ex.message).to match(/Took more than 1.5 seconds to receive data/)
927
+ else
928
+ fail 'Expected a timeout'
922
929
  end
923
930
  # allow 1.5 seconds +- 0.5 seconds
924
931
  expect(end_time - start).to be_within(1).of(2)
@@ -938,7 +945,7 @@ describe Mongo::Server::Connection do
938
945
 
939
946
  before do
940
947
  expect(message).to receive(:replyable?) { false }
941
- connection.send(:deliver, message, nil)
948
+ connection.send(:deliver, message, context)
942
949
 
943
950
  connection.send(:socket).instance_variable_set(:@timeout, -(Time.now.to_i))
944
951
  end
@@ -9,13 +9,21 @@ describe Mongo::Server::Monitor::Connection do
9
9
 
10
10
  declare_topology_double
11
11
 
12
+ let(:monitor_app_metadata) do
13
+ Mongo::Server::Monitor::AppMetadata.new(
14
+ server_api: SpecConfig.instance.ruby_options[:server_api],
15
+ )
16
+ end
17
+
12
18
  let(:cluster) do
13
- double('cluster').tap do |cl|
14
- allow(cl).to receive(:topology).and_return(topology)
15
- allow(cl).to receive(:app_metadata).and_return(Mongo::Server::Monitor::AppMetadata.new({}))
16
- allow(cl).to receive(:options).and_return({})
17
- allow(cl).to receive(:heartbeat_interval).and_return(1000)
18
- allow(cl).to receive(:run_sdam_flow)
19
+ double('cluster').tap do |cluster|
20
+ allow(cluster).to receive(:topology).and_return(topology)
21
+ allow(cluster).to receive(:app_metadata).and_return(Mongo::Server::Monitor::AppMetadata.new({}))
22
+ allow(cluster).to receive(:options).and_return({})
23
+ allow(cluster).to receive(:monitor_app_metadata).and_return(monitor_app_metadata)
24
+ allow(cluster).to receive(:push_monitor_app_metadata).and_return(monitor_app_metadata)
25
+ allow(cluster).to receive(:heartbeat_interval).and_return(1000)
26
+ allow(cluster).to receive(:run_sdam_flow)
19
27
  end
20
28
  end
21
29
 
@@ -27,10 +35,12 @@ describe Mongo::Server::Monitor::Connection do
27
35
  end
28
36
 
29
37
  let(:monitor) do
38
+ metadata = Mongo::Server::Monitor::AppMetadata.new(options)
30
39
  register_background_thread_object(
31
40
  Mongo::Server::Monitor.new(server, server.event_listeners, server.monitoring,
32
41
  {
33
- app_metadata: Mongo::Server::Monitor::AppMetadata.new(options),
42
+ app_metadata: metadata,
43
+ push_monitor_app_metadata: metadata,
34
44
  }.update(options))
35
45
  ).tap do |monitor|
36
46
  monitor.scan!
@@ -17,6 +17,12 @@ describe Mongo::Server::Monitor do
17
17
  {}
18
18
  end
19
19
 
20
+ let(:monitor_app_metadata) do
21
+ Mongo::Server::Monitor::AppMetadata.new(
22
+ server_api: SpecConfig.instance.ruby_options[:server_api],
23
+ )
24
+ end
25
+
20
26
  let(:cluster) do
21
27
  double('cluster').tap do |cluster|
22
28
  allow(cluster).to receive(:run_sdam_flow)
@@ -32,7 +38,9 @@ describe Mongo::Server::Monitor do
32
38
  let(:monitor) do
33
39
  register_background_thread_object(
34
40
  described_class.new(server, listeners, Mongo::Monitoring.new,
35
- SpecConfig.instance.test_options.merge(cluster: cluster).merge(monitor_options))
41
+ SpecConfig.instance.test_options.merge(cluster: cluster).merge(monitor_options).update(
42
+ app_metadata: monitor_app_metadata,
43
+ push_monitor_app_metadata: monitor_app_metadata))
36
44
  )
37
45
  end
38
46
 
@@ -78,8 +78,8 @@ describe Mongo::ServerSelector::SecondaryPreferred do
78
78
 
79
79
  context 'tag sets not provided' do
80
80
 
81
- it 'returns secondaryPreferred' do
82
- selector.to_mongos.should == {mode: 'secondaryPreferred'}
81
+ it 'returns nil' do
82
+ expect(selector.to_mongos).to be_nil
83
83
  end
84
84
  end
85
85
 
@@ -89,8 +89,8 @@ describe Mongo::ServerSelector::SecondaryPreferred do
89
89
  { :mode => 'secondaryPreferred' }
90
90
  end
91
91
 
92
- it 'returns secondaryPreferred' do
93
- selector.to_mongos.should == {mode: 'secondaryPreferred'}
92
+ it 'returns nil' do
93
+ expect(selector.to_mongos).to be_nil
94
94
  end
95
95
  end
96
96
 
@@ -120,8 +120,8 @@ describe Mongo::ServerSelector::SecondaryPreferred do
120
120
  context 'hedge not provided' do
121
121
  let(:hedge) { nil }
122
122
 
123
- it 'returns secondaryPreferred' do
124
- selector.to_mongos.should == {mode: 'secondaryPreferred'}
123
+ it 'returns nil' do
124
+ expect(selector.to_mongos).to be_nil
125
125
  end
126
126
  end
127
127
 
@@ -40,12 +40,20 @@ describe Mongo::Server do
40
40
  )
41
41
  end
42
42
 
43
+ let(:monitor_app_metadata) do
44
+ Mongo::Server::Monitor::AppMetadata.new(
45
+ server_api: SpecConfig.instance.ruby_options[:server_api],
46
+ )
47
+ end
48
+
43
49
  shared_context 'with monitoring io' do
44
50
  let(:server_options) do
45
51
  {monitoring_io: true}
46
52
  end
47
53
 
48
54
  before do
55
+ allow(cluster).to receive(:monitor_app_metadata).and_return(monitor_app_metadata)
56
+ allow(cluster).to receive(:push_monitor_app_metadata).and_return(monitor_app_metadata)
49
57
  allow(cluster).to receive(:heartbeat_interval).and_return(1000)
50
58
  end
51
59
  end
@@ -144,8 +152,13 @@ describe Mongo::Server do
144
152
  expect(server.options[:monitoring_io]).to be true
145
153
  end
146
154
 
147
- it 'creates monitor with monitoring app metadata' do
148
- expect(server.monitor.options[:app_metadata]).to be_a(Mongo::Server::Monitor::AppMetadata)
155
+ context 'with monitoring app metadata option' do
156
+ require_no_required_api_version
157
+
158
+ it 'creates monitor with monitoring app metadata' do
159
+ server.monitor.scan!
160
+ expect(server.monitor.connection.options[:app_metadata]).to be monitor_app_metadata
161
+ end
149
162
  end
150
163
 
151
164
  context 'monitoring_io: false' do
@@ -50,6 +50,46 @@ describe Mongo::Socket::SSL, retry: 3 do
50
50
  end
51
51
 
52
52
  describe '#connect!' do
53
+ context 'when TLS context hooks are provided' do
54
+ # https://github.com/jruby/jruby-openssl/issues/221
55
+ fails_on_jruby
56
+
57
+ let(:proc) do
58
+ Proc.new do |context|
59
+ if BSON::Environment.jruby?
60
+ context.ciphers = ["AES256-SHA256"]
61
+ else
62
+ context.ciphers = ["AES256-SHA"]
63
+ end
64
+ end
65
+ end
66
+
67
+ before do
68
+ Mongo.tls_context_hooks = [ proc ]
69
+ end
70
+
71
+ after do
72
+ Mongo.tls_context_hooks.clear
73
+ end
74
+
75
+ it 'runs the TLS context hook before connecting' do
76
+ if ENV['OCSP_ALGORITHM']
77
+ skip "OCSP configurations use different certificates which this test does not handle"
78
+ end
79
+
80
+ expect(proc).to receive(:call).and_call_original
81
+ socket
82
+ # Even though we are requesting a single cipher in the hook,
83
+ # there may be multiple ciphers available in the context.
84
+ # All of the ciphers should match the requested one (using
85
+ # OpenSSL's idea of what "match" means).
86
+ socket.context.ciphers.each do |cipher|
87
+ unless cipher.first =~ /SHA256/ || cipher.last == 256
88
+ raise "Unexpected cipher #{cipher} after requesting SHA-256"
89
+ end
90
+ end
91
+ end
92
+ end
53
93
 
54
94
  context 'when a certificate is provided' do
55
95
 
@@ -48,7 +48,7 @@ describe Mongo::Socket do
48
48
  socket.send(:map_exceptions) do
49
49
  raise OpenSSL::SSL::SSLError.new('Test error')
50
50
  end
51
- end.to raise_error(Mongo::Error::SocketError, 'OpenSSL::SSL::SSLError: Test error (for fake-address) (MongoDB may not be configured with TLS support)')
51
+ end.to raise_error(Mongo::Error::SocketError, 'OpenSSL::SSL::SSLError: Test error (for fake-address)')
52
52
  end
53
53
  end
54
54
 
@@ -86,7 +86,7 @@ describe Mongo::Socket do
86
86
 
87
87
  expect do
88
88
  socket.read(10)
89
- end.to raise_error(Mongo::Error::SocketTimeoutError, /Took more than .* seconds to receive data \(for /)
89
+ end.to raise_error(Mongo::Error::SocketTimeoutError, /Took more than .* seconds to receive data.*\(for /)
90
90
  end
91
91
  end
92
92
 
@@ -0,0 +1,37 @@
1
+ require 'spec_helper'
2
+
3
+ describe Mongo do
4
+ before do
5
+ Mongo.tls_context_hooks.clear
6
+ end
7
+
8
+ describe '#tls_context_hooks' do
9
+ it 'returns an array' do
10
+ expect(Mongo.tls_context_hooks).to eq([])
11
+ end
12
+ end
13
+
14
+ describe '#tls_context_hooks=' do
15
+ context 'when argument is not an array' do
16
+ it 'raises an ArgumentError' do
17
+ expect do
18
+ Mongo.tls_context_hooks = "Hello"
19
+ end.to raise_error(ArgumentError, /TLS context hooks must be an array of Procs/)
20
+ end
21
+ end
22
+
23
+ context 'when argument is an array not containing procs' do
24
+ it 'raises an ArgumentError' do
25
+ expect do
26
+ Mongo.tls_context_hooks = [1, 2, 3]
27
+ end.to raise_error(ArgumentError, /TLS context hooks must be an array of Procs/)
28
+ end
29
+ end
30
+
31
+ it 'saves the provided hooks' do
32
+ Mongo.tls_context_hooks = [ Proc.new { |x| x ** 2 } ]
33
+ expect(Mongo.tls_context_hooks.length).to eq(1)
34
+ expect(Mongo.tls_context_hooks.first).to be_a(Proc)
35
+ end
36
+ end
37
+ end
@@ -235,10 +235,6 @@ module Mongo
235
235
  if k.downcase == 'authmechanismproperties'
236
236
  expected[k] = ::Utils.downcase_keys(v)
237
237
  end
238
- # Ruby driver does not support snappy.
239
- if k == 'compressors'
240
- expected[k] = v.reject { |sub_v| sub_v == 'snappy' }
241
- end
242
238
  end
243
239
  # We omit retryReads/retryWrites=true because some tests do not
244
240
  # provide those.
@@ -1,18 +1,39 @@
1
1
  module Mongo
2
2
  module CRUD
3
3
  class Requirement
4
- YAML_KEYS = %w(minServerVersion maxServerVersion topology).freeze
4
+ YAML_KEYS = %w(minServerVersion maxServerVersion topology topologies serverParameters).freeze
5
5
 
6
6
  def initialize(spec)
7
+ spec = spec.dup
8
+ # Legacy tests have the requirements mixed with other test fields
9
+ spec.delete('data')
10
+ spec.delete('tests')
11
+
12
+ unless (unhandled_keys = spec.keys - YAML_KEYS).empty?
13
+ raise "Unhandled requirement specification keys: #{unhandled_keys}"
14
+ end
15
+
7
16
  @min_server_version = spec['minServerVersion']
8
17
  @max_server_version = spec['maxServerVersion']
9
- @topologies = if topologies = spec['topology']
18
+ # topologies is for unified test format.
19
+ # topology is for legacy tests.
20
+ @topologies = if topologies = spec['topology'] || spec['topologies']
10
21
  topologies.map do |topology|
11
- {'replicaset' => :replica_set, 'single' => :single, 'sharded' => :sharded}[topology]
22
+ {
23
+ 'replicaset' => :replica_set,
24
+ 'single' => :single,
25
+ 'sharded' => :sharded,
26
+ 'sharded-replicaset' => :sharded,
27
+ }[topology].tap do |v|
28
+ unless v
29
+ raise "Unknown topology #{topology}"
30
+ end
31
+ end
12
32
  end
13
33
  else
14
34
  nil
15
35
  end
36
+ @server_parameters = spec['serverParameters']
16
37
  end
17
38
 
18
39
  attr_reader :min_server_version
@@ -47,6 +68,22 @@ module Mongo
47
68
  if topologies
48
69
  ok &&= topologies.include?(cc.topology)
49
70
  end
71
+ if @server_parameters
72
+ @server_parameters.each do |k, required_v|
73
+ actual_v = cc.server_parameters[k]
74
+ if actual_v.nil? && !required_v.nil?
75
+ ok = false
76
+ elsif actual_v != required_v
77
+ if Numeric === actual_v && Numeric === required_v
78
+ if actual_v.to_f != required_v.to_f
79
+ ok = false
80
+ end
81
+ else
82
+ ok = false
83
+ end
84
+ end
85
+ end
86
+ end
50
87
  ok
51
88
  end
52
89
 
@@ -193,6 +193,14 @@ EOT
193
193
  return
194
194
  end
195
195
 
196
+ if k == 'updateDescription'
197
+ # Change stream result - verify subset, not exact match
198
+ expected.fetch(k).each do |sub_k, sub_v|
199
+ {sub_k => sub_v}.should == {sub_k => actual.fetch(k).fetch(sub_k)}
200
+ end
201
+ return
202
+ end
203
+
196
204
  if expected[k].is_a?(Time)
197
205
  expect(k => actual[k].utc.to_s).to eq(k => expected[k].utc.to_s)
198
206
  else
@@ -191,7 +191,7 @@ module Mongo
191
191
 
192
192
  def assert_event_count(client, context)
193
193
  events = _select_events(context)
194
- if arguments['event'] == 'ServerMarkedUnknownEvent'
194
+ if %w(ServerMarkedUnknownEvent PoolClearedEvent).include?(arguments['event'])
195
195
  # We publish SDAM events from both regular and push monitors.
196
196
  # This means sometimes there are two ServerMarkedUnknownEvent
197
197
  # events published for the same server transition.
@@ -289,6 +289,7 @@ module Mongo
289
289
  client.command(configureFailPoint: fail_point_command['configureFailPoint'],
290
290
  mode: 'off')
291
291
  end
292
+ $disable_fail_points = nil
292
293
  end
293
294
 
294
295
  if @test_client