mongo 2.11.0.rc0 → 2.11.0

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 (154) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data.tar.gz.sig +0 -0
  4. data/Rakefile +2 -0
  5. data/lib/mongo/auth.rb +11 -2
  6. data/lib/mongo/auth/cr/conversation.rb +1 -1
  7. data/lib/mongo/auth/ldap/conversation.rb +1 -1
  8. data/lib/mongo/auth/scram/conversation.rb +4 -1
  9. data/lib/mongo/auth/user.rb +15 -1
  10. data/lib/mongo/auth/user/view.rb +10 -4
  11. data/lib/mongo/auth/x509.rb +11 -1
  12. data/lib/mongo/auth/x509/conversation.rb +15 -6
  13. data/lib/mongo/background_thread.rb +28 -13
  14. data/lib/mongo/client.rb +23 -15
  15. data/lib/mongo/collection/view/change_stream.rb +5 -1
  16. data/lib/mongo/collection/view/readable.rb +5 -2
  17. data/lib/mongo/collection/view/writable.rb +3 -1
  18. data/lib/mongo/cursor/builder/get_more_command.rb +4 -1
  19. data/lib/mongo/cursor/builder/kill_cursors_command.rb +16 -5
  20. data/lib/mongo/cursor/builder/op_get_more.rb +2 -2
  21. data/lib/mongo/cursor/builder/op_kill_cursors.rb +17 -5
  22. data/lib/mongo/error/operation_failure.rb +3 -3
  23. data/lib/mongo/monitoring/command_log_subscriber.rb +5 -3
  24. data/lib/mongo/monitoring/event/command_started.rb +13 -3
  25. data/lib/mongo/monitoring/publishable.rb +4 -2
  26. data/lib/mongo/operation/create_user/command.rb +1 -0
  27. data/lib/mongo/operation/remove_user/command.rb +1 -0
  28. data/lib/mongo/operation/update_user/command.rb +1 -0
  29. data/lib/mongo/protocol/get_more.rb +2 -1
  30. data/lib/mongo/protocol/kill_cursors.rb +6 -13
  31. data/lib/mongo/protocol/serializers.rb +10 -4
  32. data/lib/mongo/retryable.rb +1 -1
  33. data/lib/mongo/server/connection.rb +6 -2
  34. data/lib/mongo/server/connection_base.rb +2 -1
  35. data/lib/mongo/server/monitor.rb +1 -1
  36. data/lib/mongo/server/pending_connection.rb +6 -0
  37. data/lib/mongo/socket/ssl.rb +1 -1
  38. data/lib/mongo/uri.rb +5 -41
  39. data/lib/mongo/version.rb +1 -1
  40. data/mongo.gemspec +11 -2
  41. data/spec/README.md +105 -9
  42. data/spec/USERS.md +72 -0
  43. data/spec/integration/auth_spec.rb +20 -6
  44. data/spec/integration/client_construction_spec.rb +3 -1
  45. data/spec/integration/client_options_spec.rb +437 -0
  46. data/spec/integration/command_monitoring_spec.rb +4 -1
  47. data/spec/integration/connection_pool_populator_spec.rb +4 -0
  48. data/spec/integration/connection_spec.rb +4 -2
  49. data/spec/integration/cursor_reaping_spec.rb +1 -1
  50. data/spec/integration/get_more_spec.rb +32 -0
  51. data/spec/integration/retryable_errors_spec.rb +99 -0
  52. data/spec/integration/retryable_writes_errors_spec.rb +11 -10
  53. data/spec/lite_spec_helper.rb +2 -1
  54. data/spec/mongo/auth/scram_spec.rb +1 -0
  55. data/spec/mongo/auth/user/view_spec.rb +102 -1
  56. data/spec/mongo/auth/user_spec.rb +56 -15
  57. data/spec/mongo/auth/x509_spec.rb +31 -1
  58. data/spec/mongo/bulk_write_spec.rb +2 -2
  59. data/spec/mongo/collection/view/change_stream_spec.rb +2 -2
  60. data/spec/mongo/collection/view/readable_spec.rb +8 -4
  61. data/spec/mongo/cursor/builder/get_more_command_spec.rb +4 -2
  62. data/spec/mongo/cursor/builder/op_get_more_spec.rb +4 -2
  63. data/spec/mongo/cursor_spec.rb +3 -3
  64. data/spec/mongo/retryable_spec.rb +31 -52
  65. data/spec/mongo/server/connection_auth_spec.rb +3 -0
  66. data/spec/mongo/server/connection_pool_spec.rb +4 -0
  67. data/spec/mongo/server/connection_spec.rb +12 -4
  68. data/spec/mongo/server/monitor_spec.rb +19 -1
  69. data/spec/mongo/socket/ssl_spec.rb +1 -1
  70. data/spec/mongo/uri/srv_protocol_spec.rb +0 -13
  71. data/spec/mongo/uri_option_parsing_spec.rb +0 -8
  72. data/spec/mongo/uri_spec.rb +6 -20
  73. data/spec/runners/connection_string.rb +116 -0
  74. data/spec/runners/read_write_concern_document.rb +67 -0
  75. data/spec/spec_tests/change_streams_spec.rb +17 -2
  76. data/spec/spec_tests/connection_string_spec.rb +2 -59
  77. data/spec/spec_tests/data/change_streams/change-streams-errors.yml +3 -3
  78. data/spec/spec_tests/data/change_streams/change-streams.yml +88 -20
  79. data/spec/spec_tests/data/cmap/connection-must-have-id.yml +6 -0
  80. data/spec/spec_tests/data/cmap/connection-must-order-ids.yml +6 -0
  81. data/spec/spec_tests/data/cmap/pool-checkin-destroy-closed.yml +3 -0
  82. data/spec/spec_tests/data/cmap/pool-checkin-destroy-stale.yml +3 -0
  83. data/spec/spec_tests/data/cmap/pool-checkin-make-available.yml +3 -0
  84. data/spec/spec_tests/data/cmap/pool-checkin.yml +1 -0
  85. data/spec/spec_tests/data/cmap/pool-checkout-connection.yml +2 -0
  86. data/spec/spec_tests/data/cmap/pool-checkout-error-closed.yml +5 -0
  87. data/spec/spec_tests/data/cmap/pool-checkout-multiple.yml +3 -0
  88. data/spec/spec_tests/data/cmap/pool-checkout-no-idle.yml +4 -0
  89. data/spec/spec_tests/data/cmap/pool-checkout-no-stale.yml +4 -0
  90. data/spec/spec_tests/data/cmap/pool-close-destroy-conns.yml +2 -0
  91. data/spec/spec_tests/data/cmap/pool-create-max-size.yml +15 -0
  92. data/spec/spec_tests/data/cmap/pool-create-min-size.yml +4 -0
  93. data/spec/spec_tests/data/cmap/wait-queue-fairness.yml +31 -1
  94. data/spec/spec_tests/data/cmap/wait-queue-timeout.yml +5 -0
  95. data/spec/spec_tests/data/read_write_concern/connection-string/read-concern.yml +32 -0
  96. data/spec/spec_tests/data/read_write_concern/connection-string/write-concern.yml +82 -0
  97. data/spec/spec_tests/data/read_write_concern/document/read-concern.yml +37 -0
  98. data/spec/spec_tests/data/read_write_concern/document/write-concern.yml +100 -0
  99. data/spec/spec_tests/data/retryable_reads/aggregate-merge.yml +39 -0
  100. data/spec/spec_tests/data/retryable_reads/aggregate-serverErrors.yml +1 -1
  101. data/spec/spec_tests/data/retryable_reads/changeStreams-client.watch-serverErrors.yml +2 -2
  102. data/spec/spec_tests/data/retryable_reads/changeStreams-client.watch.yml +1 -1
  103. data/spec/spec_tests/data/retryable_reads/changeStreams-db.coll.watch-serverErrors.yml +2 -2
  104. data/spec/spec_tests/data/retryable_reads/changeStreams-db.coll.watch.yml +1 -1
  105. data/spec/spec_tests/data/retryable_reads/changeStreams-db.watch-serverErrors.yml +2 -2
  106. data/spec/spec_tests/data/retryable_reads/changeStreams-db.watch.yml +1 -1
  107. data/spec/spec_tests/data/retryable_reads/count-serverErrors.yml +1 -1
  108. data/spec/spec_tests/data/retryable_reads/countDocuments-serverErrors.yml +1 -1
  109. data/spec/spec_tests/data/retryable_reads/distinct-serverErrors.yml +1 -1
  110. data/spec/spec_tests/data/retryable_reads/estimatedDocumentCount-serverErrors.yml +1 -1
  111. data/spec/spec_tests/data/retryable_reads/find-serverErrors.yml +1 -1
  112. data/spec/spec_tests/data/retryable_reads/findOne-serverErrors.yml +1 -1
  113. data/spec/spec_tests/data/retryable_reads/gridfs-download-serverErrors.yml +1 -1
  114. data/spec/spec_tests/data/retryable_reads/gridfs-downloadByName-serverErrors.yml +1 -1
  115. data/spec/spec_tests/data/retryable_reads/listCollectionNames-serverErrors.yml +1 -1
  116. data/spec/spec_tests/data/retryable_reads/listCollectionObjects-serverErrors.yml +1 -1
  117. data/spec/spec_tests/data/retryable_reads/listCollections-serverErrors.yml +1 -1
  118. data/spec/spec_tests/data/retryable_reads/listDatabaseNames-serverErrors.yml +1 -1
  119. data/spec/spec_tests/data/retryable_reads/listDatabaseObjects-serverErrors.yml +1 -1
  120. data/spec/spec_tests/data/retryable_reads/listDatabases-serverErrors.yml +1 -1
  121. data/spec/spec_tests/data/retryable_reads/listIndexNames-serverErrors.yml +1 -1
  122. data/spec/spec_tests/data/retryable_reads/listIndexes-serverErrors.yml +1 -1
  123. data/spec/spec_tests/data/transactions/read-concern.yml +6 -6
  124. data/spec/spec_tests/data/transactions/transaction-options-repl.yml +117 -0
  125. data/spec/spec_tests/data/transactions/transaction-options.yml +14 -121
  126. data/spec/spec_tests/data/transactions/write-concern.yml +3 -0
  127. data/spec/spec_tests/data/transactions_api/transaction-options.yml +11 -12
  128. data/spec/spec_tests/dns_seedlist_discovery_spec.rb +17 -7
  129. data/spec/spec_tests/read_write_concern_connection_string_spec.rb +8 -0
  130. data/spec/spec_tests/read_write_concern_document_spec.rb +74 -0
  131. data/spec/spec_tests/retryable_reads_spec.rb +32 -1
  132. data/spec/spec_tests/uri_options_spec.rb +4 -2
  133. data/spec/support/auth.rb +5 -14
  134. data/spec/support/certificates/client-x509.crt +78 -0
  135. data/spec/support/certificates/client-x509.key +27 -0
  136. data/spec/support/certificates/client-x509.pem +105 -0
  137. data/spec/support/change_streams.rb +8 -11
  138. data/spec/support/client_registry.rb +26 -12
  139. data/spec/support/cluster_tools.rb +2 -2
  140. data/spec/support/cmap.rb +11 -7
  141. data/spec/support/command_monitoring.rb +8 -8
  142. data/spec/support/connection_string.rb +56 -28
  143. data/spec/support/constraints.rb +8 -0
  144. data/spec/support/crud/spec.rb +5 -8
  145. data/spec/support/event_subscriber.rb +7 -0
  146. data/spec/support/gridfs.rb +4 -7
  147. data/spec/support/server_discovery_and_monitoring.rb +3 -8
  148. data/spec/support/server_selection.rb +4 -9
  149. data/spec/support/server_selection_rtt.rb +4 -7
  150. data/spec/support/spec_config.rb +47 -19
  151. data/spec/support/spec_setup.rb +5 -0
  152. data/spec/support/utils.rb +46 -8
  153. metadata +637 -597
  154. metadata.gz.sig +0 -0
@@ -349,8 +349,6 @@ class ClusterTools
349
349
  end
350
350
  end
351
351
 
352
- private
353
-
354
352
  def each_server(&block)
355
353
  admin_client.cluster.servers_list.each(&block)
356
354
  end
@@ -361,6 +359,8 @@ class ClusterTools
361
359
  end
362
360
  end
363
361
 
362
+ private
363
+
364
364
  def reset_server_states
365
365
  each_server do |server|
366
366
  server.unknown!
@@ -35,12 +35,9 @@ module Mongo
35
35
 
36
36
  # Instantiate the new spec.
37
37
  #
38
- # @example Create the spec.
39
- # Spec.new(file)
40
- #
41
- # @param [ String ] file The name of the file.
42
- def initialize(file)
43
- @test = YAML.load(ERB.new(File::read(file)).result)
38
+ # @param [ String ] test_path The path to the file.
39
+ def initialize(test_path)
40
+ @test = YAML.load(File.read(test_path))
44
41
 
45
42
  @description = @test['description']
46
43
  @pool_options = Utils.snakeize_hash(process_options(@test['poolOptions']))
@@ -99,36 +96,43 @@ module Mongo
99
96
  {
100
97
  'type' => 'ConnectionCreated',
101
98
  'connectionId' => event.connection_id,
99
+ 'address' => event.address,
102
100
  }
103
101
  when Mongo::Monitoring::Event::Cmap::ConnectionReady
104
102
  {
105
103
  'type' => 'ConnectionReady',
106
104
  'connectionId' => event.connection_id,
105
+ 'address' => event.address,
107
106
  }
108
107
  when Mongo::Monitoring::Event::Cmap::ConnectionClosed
109
108
  {
110
109
  'type' => 'ConnectionClosed',
111
110
  'connectionId' => event.connection_id,
112
111
  'reason' => event.reason,
112
+ 'address' => event.address,
113
113
  }
114
114
  when Mongo::Monitoring::Event::Cmap::ConnectionCheckOutStarted
115
115
  {
116
116
  'type' => 'ConnectionCheckOutStarted',
117
- }
117
+ 'address' => event.address,
118
+ }
118
119
  when Mongo::Monitoring::Event::Cmap::ConnectionCheckOutFailed
119
120
  {
120
121
  'type' => 'ConnectionCheckOutFailed',
121
122
  'reason' => event.reason,
123
+ 'address' => event.address,
122
124
  }
123
125
  when Mongo::Monitoring::Event::Cmap::ConnectionCheckedOut
124
126
  {
125
127
  'type' => 'ConnectionCheckedOut',
126
128
  'connectionId' => event.connection_id,
129
+ 'address' => event.address,
127
130
  }
128
131
  when Mongo::Monitoring::Event::Cmap::ConnectionCheckedIn
129
132
  {
130
133
  'type' => 'ConnectionCheckedIn',
131
134
  'connectionId' => event.connection_id,
135
+ 'address' => event.address,
132
136
  }
133
137
  when Mongo::Monitoring::Event::Cmap::PoolCleared
134
138
  {
@@ -134,6 +134,11 @@ module Mongo
134
134
  end
135
135
  if expected.keys.first == '$numberLong'
136
136
  converted = expected.values.first.to_i
137
+ if actual.is_a?(BSON::Int64)
138
+ actual = actual.value
139
+ elsif actual.is_a?(BSON::Int32)
140
+ return false
141
+ end
137
142
  (actual == converted) || actual >= 0
138
143
  else
139
144
  expected.each do |key, value|
@@ -192,16 +197,11 @@ module Mongo
192
197
 
193
198
  # Create the spec.
194
199
  #
195
- # @example Create the spec.
196
- # Spec.new('/path/to/test')
197
- #
198
- # @param [ String ] file The yaml test file.
200
+ # @param [ String ] test_path The yaml test path.
199
201
  #
200
202
  # @since 2.1.0
201
- def initialize(file)
202
- file = File.new(file)
203
- @spec = YAML.load(ERB.new(file.read).result)
204
- file.close
203
+ def initialize(test_path)
204
+ @spec = YAML.load(File.read(test_path))
205
205
  @data = @spec['data']
206
206
  @tests = @spec['tests']
207
207
  end
@@ -12,13 +12,17 @@
12
12
  # See the License for the specific language governing permissions and
13
13
  # limitations under the License.
14
14
 
15
- RSpec::Matchers.define :have_hosts do |test|
15
+ RSpec::Matchers.define :have_hosts do |test, hosts|
16
16
 
17
17
  match do |cl|
18
18
 
19
19
  def find_server(client, host)
20
- client.cluster.instance_variable_get(:@servers).detect do |s|
21
- s.address.host == host.host
20
+ client.cluster.servers_list.detect do |s|
21
+ if host.port
22
+ s.address.host == host.host && s.address.port == host.port
23
+ else
24
+ s.address.host == host.host
25
+ end
22
26
  end
23
27
  end
24
28
 
@@ -39,18 +43,19 @@ RSpec::Matchers.define :have_hosts do |test|
39
43
  server.address.instance_variable_get(:@resolver).class
40
44
  end
41
45
 
42
- test.hosts.all? do |host|
46
+ hosts.all? do |host|
43
47
  server = find_server(cl, host)
44
- match_host?(server, host) &&
45
- match_port?(server, host) if server #&&
46
- #match_address_family?(server, host) if server
48
+ server &&
49
+ match_host?(server, host) &&
50
+ match_port?(server, host) #&&
51
+ #match_address_family?(server, host)
47
52
  end
53
+ end
48
54
 
49
- failure_message do |client|
50
- "With URI: #{test.uri_string}\n" +
51
- "Expected that test hosts: #{test.hosts} would match " +
52
- "client hosts: #{cl.cluster.instance_variable_get(:@servers)}"
53
- end
55
+ failure_message do |client|
56
+ "With URI: #{test.uri_string}\n" +
57
+ "Expected client hosts: #{client.cluster.instance_variable_get(:@servers)} " +
58
+ "to match #{hosts}"
54
59
  end
55
60
  end
56
61
 
@@ -102,17 +107,12 @@ module Mongo
102
107
 
103
108
  # Instantiate the new spec.
104
109
  #
105
- # @example Create the spec.
106
- # Spec.new(file)
107
- #
108
- # @param [ String ] file The name of the file.
110
+ # @param [ String ] test_path The path to the file.
109
111
  #
110
112
  # @since 2.0.0
111
- def initialize(file)
112
- file = File.new(file)
113
- @spec = YAML.load(ERB.new(file.read).result)
114
- file.close
115
- @description = File.basename(file)
113
+ def initialize(test_path)
114
+ @spec = YAML.load(File.read(test_path))
115
+ @description = File.basename(test_path)
116
116
  end
117
117
 
118
118
  def tests
@@ -148,6 +148,16 @@ module Mongo
148
148
  end
149
149
  end
150
150
 
151
+ def seeds
152
+ if @spec['seeds']
153
+ @seeds ||= (@spec['seeds'] || []).collect do |host|
154
+ Host.new(host)
155
+ end
156
+ else
157
+ nil
158
+ end
159
+ end
160
+
151
161
  def options
152
162
  @options ||= Options.new(@spec['options']) if @spec['options']
153
163
  end
@@ -171,6 +181,14 @@ module Mongo
171
181
  def raise_error?
172
182
  @spec['error']
173
183
  end
184
+
185
+ def read_concern_expectation
186
+ @spec['readConcern']
187
+ end
188
+
189
+ def write_concern_expectation
190
+ @spec['writeConcern']
191
+ end
174
192
  end
175
193
 
176
194
  class Host
@@ -185,9 +203,17 @@ module Mongo
185
203
  attr_reader :port
186
204
 
187
205
  def initialize(spec)
188
- @spec = spec
189
- @host = @spec['host']
190
- @port = @spec['port']
206
+ if spec.is_a?(Hash)
207
+ # Connection string spec tests
208
+ @spec = spec
209
+ @host = @spec['host']
210
+ @port = @spec['port']
211
+ else
212
+ # DNS seed list spec tests
213
+ address = Mongo::Address.new(spec)
214
+ @host = address.host
215
+ @port = address.port
216
+ end
191
217
  end
192
218
 
193
219
  def address_family
@@ -276,8 +302,6 @@ module Mongo
276
302
  case k
277
303
  when 'authmechanism'
278
304
  Mongo::URI::AUTH_MECH_MAP[v].downcase.to_s
279
- when 'authsource'
280
- v == '$external' ? 'external' : v.downcase
281
305
  when 'authmechanismproperties'
282
306
  v.reduce({}) do |new_v, prop|
283
307
  prop_key = prop.first.downcase
@@ -315,8 +339,12 @@ module Mongo
315
339
  opts[MAPPINGS[k]]
316
340
  end
317
341
 
318
- actual = actual.to_s if actual.is_a?(Symbol)
319
- actual.downcase! if actual.is_a?(String)
342
+ if actual.is_a?(Symbol)
343
+ actual = actual.to_s
344
+ end
345
+ if actual.is_a?(String)
346
+ actual = actual.downcase
347
+ end
320
348
 
321
349
  expected == actual
322
350
  end
@@ -148,6 +148,14 @@ module Constraints
148
148
  end
149
149
  end
150
150
 
151
+ def require_no_x509_auth
152
+ before(:all) do
153
+ if SpecConfig.instance.x509_auth?
154
+ skip "X.509 auth not allowed"
155
+ end
156
+ end
157
+ end
158
+
151
159
  # Can the driver specify a write concern that won't be overridden?
152
160
  # (mongos 4.0+ overrides the write concern)
153
161
  def require_set_write_concern
@@ -5,14 +5,11 @@ module Mongo
5
5
 
6
6
  # Instantiate the new spec.
7
7
  #
8
- # @example Create the spec.
9
- # Spec.new(file)
10
- #
11
- # @param [ String ] file The name of the file.
8
+ # @param [ String ] test_path The path to the file.
12
9
  #
13
10
  # @since 2.0.0
14
- def initialize(file)
15
- contents = ERB.new(File.read(file)).result
11
+ def initialize(test_path)
12
+ contents = File.read(test_path)
16
13
 
17
14
  # Since Ruby driver binds a client to a database, change the
18
15
  # database name in the spec to the one we are using
@@ -21,8 +18,8 @@ module Mongo
21
18
  contents.sub!(/"transaction-tests"/, '"ruby-driver"')
22
19
  contents.sub!(/"withTransaction-tests"/, '"ruby-driver"')
23
20
 
24
- @spec = YAML.load(ERB.new(contents).result)
25
- @description = File.basename(file)
21
+ @spec = YAML.load(contents)
22
+ @description = File.basename(test_path)
26
23
  @data = @spec['data']
27
24
  @tests = @spec['tests']
28
25
 
@@ -44,6 +44,13 @@ class EventSubscriber
44
44
  end
45
45
  end
46
46
 
47
+ # Filters command started events for the specified command name.
48
+ def command_started_events(command_name)
49
+ started_events.select do |event|
50
+ event.command[command_name]
51
+ end
52
+ end
53
+
47
54
  # Locates command stated events for the specified command name,
48
55
  # asserts that there is exactly one such event, and returns it.
49
56
  def single_command_started_event(command_name)
@@ -93,15 +93,12 @@ module Mongo
93
93
 
94
94
  # Instantiate the new spec.
95
95
  #
96
- # @example Create the spec.
97
- # Spec.new(file)
98
- #
99
- # @param [ String ] file The name of the file.
96
+ # @param [ String ] test_path The path to the file.
100
97
  #
101
98
  # @since 2.1.0
102
- def initialize(file)
103
- @spec = YAML.load(ERB.new(File.new(file).read).result)
104
- @description = File.basename(file)
99
+ def initialize(test_path)
100
+ @spec = YAML.load(File.read(test_path))
101
+ @description = File.basename(test_path)
105
102
  @data = @spec['data']
106
103
  end
107
104
 
@@ -76,16 +76,11 @@ module Mongo
76
76
 
77
77
  # Instantiate the new spec.
78
78
  #
79
- # @example Create the spec.
80
- # Spec.new(file)
81
- #
82
- # @param [ String ] file The name of the file.
79
+ # @param [ String ] test_path The path to the file.
83
80
  #
84
81
  # @since 2.0.0
85
- def initialize(file)
86
- file = File.new(file)
87
- @test = YAML.load(ERB.new(file.read).result)
88
- file.close
82
+ def initialize(test_path)
83
+ @test = YAML.load(File.read(test_path))
89
84
  @description = @test['description']
90
85
  @uri_string = @test['uri']
91
86
  @uri = URI.new(uri_string)
@@ -57,17 +57,12 @@ module Mongo
57
57
 
58
58
  # Instantiate the new spec.
59
59
  #
60
- # @example Create the spec.
61
- # Spec.new(file)
62
- #
63
- # @param [ String ] file The name of the file.
60
+ # @param [ String ] test_path The path to the file.
64
61
  #
65
62
  # @since 2.0.0
66
- def initialize(file)
67
- file = File.new(file)
68
- @test = YAML.load(ERB.new(file.read).result)
69
- file.close
70
- @description = "#{@test['topology_description']['type']}: #{File.basename(file)}"
63
+ def initialize(test_path)
64
+ @test = YAML.load(File.read(test_path))
65
+ @description = "#{@test['topology_description']['type']}: #{File.basename(test_path)}"
71
66
  @heartbeat_frequency = @test['heartbeatFrequencyMS'] / 1000 if @test['heartbeatFrequencyMS']
72
67
  @read_preference = @test['read_preference']
73
68
  @read_preference['mode'] = READ_PREFERENCES[@read_preference['mode']]
@@ -21,15 +21,12 @@ module Mongo
21
21
 
22
22
  # Instantiate the new spec.
23
23
  #
24
- # @example Create the spec.
25
- # Spec.new(file)
26
- #
27
- # @param [ String ] file The name of the file.
24
+ # @param [ String ] test_path The path to the file.
28
25
  #
29
26
  # @since 2.0.0
30
- def initialize(file)
31
- @test = YAML.load(ERB.new(File.new(file).read).result)
32
- @description = "#{File.basename(file)}: avg_rtt_ms: #{@test['avg_rtt_ms']}, new_rtt_ms: #{@test['new_rtt_ms']}," +
27
+ def initialize(test_path)
28
+ @test = YAML.load(File.read(test_path))
29
+ @description = "#{File.basename(test_path)}: avg_rtt_ms: #{@test['avg_rtt_ms']}, new_rtt_ms: #{@test['new_rtt_ms']}," +
33
30
  " new_avg_rtt: #{@test['new_avg_rtt']}"
34
31
  @average_rtt = @test['avg_rtt_ms'] == 'NULL' ? nil : @test['avg_rtt_ms'].to_f / 1000
35
32
  @new_rtt = @test['new_rtt_ms'].to_f / 1000
@@ -75,20 +75,23 @@ class SpecConfig
75
75
  client = Mongo::Client.new(addresses, Mongo::Options::Redacted.new(
76
76
  server_selection_timeout: 5,
77
77
  ).merge(ssl_options))
78
- options = case client.cluster.topology.class.name
79
- when /Replica/
80
- { connect: :replica_set, replica_set: client.cluster.topology.replica_set_name }
81
- when /Sharded/
82
- { connect: :sharded }
83
- when /Single/
84
- { connect: :direct }
85
- when /Unknown/
86
- raise "Could not detect topology because the test client failed to connect to MongoDB deployment"
87
- else
88
- raise "Weird topology #{client.cluster.topology}"
78
+
79
+ begin
80
+ case client.cluster.topology.class.name
81
+ when /Replica/
82
+ { connect: :replica_set, replica_set: client.cluster.topology.replica_set_name }
83
+ when /Sharded/
84
+ { connect: :sharded }
85
+ when /Single/
86
+ { connect: :direct }
87
+ when /Unknown/
88
+ raise "Could not detect topology because the test client failed to connect to MongoDB deployment"
89
+ else
90
+ raise "Weird topology #{client.cluster.topology}"
91
+ end
92
+ ensure
93
+ client.close
89
94
  end
90
- client.close
91
- options
92
95
  end
93
96
  end
94
97
 
@@ -255,6 +258,10 @@ EOT
255
258
  end
256
259
  end
257
260
 
261
+ def client_x509_pem_path
262
+ "#{ssl_certs_dir}/client-x509.pem"
263
+ end
264
+
258
265
  def second_level_cert_path
259
266
  "#{ssl_certs_dir}/client-second-level.crt"
260
267
  end
@@ -307,11 +314,18 @@ EOT
307
314
  # Option hashes
308
315
 
309
316
  def auth_options
310
- {
311
- user: user,
312
- password: password,
313
- auth_source: auth_source,
314
- }
317
+ if x509_auth?
318
+ {
319
+ auth_mech: @uri_options[:auth_mech],
320
+ auth_source: '$external',
321
+ }
322
+ else
323
+ {
324
+ user: user,
325
+ password: password,
326
+ auth_source: auth_source,
327
+ }
328
+ end
315
329
  end
316
330
 
317
331
  def ssl_options
@@ -322,7 +336,7 @@ EOT
322
336
  ssl_cert: client_cert_path,
323
337
  ssl_key: client_key_path,
324
338
  ssl_ca_cert: ca_cert_path,
325
- }.merge(@uri_tls_options)
339
+ }.merge(Utils.underscore_hash(@uri_tls_options))
326
340
  else
327
341
  {}
328
342
  end
@@ -412,4 +426,18 @@ EOT
412
426
  ]
413
427
  )
414
428
  end
429
+
430
+ def x509_auth?
431
+ @uri_options[:auth_mech] == :mongodb_x509
432
+ end
433
+
434
+ # When we use x.509 authentication, omit all of the users we normally create
435
+ # and authenticate with x.509.
436
+ def credentials_or_x509(creds)
437
+ if x509_auth?
438
+ {auth_mech: :mongodb_x509}
439
+ else
440
+ creds
441
+ end
442
+ end
415
443
  end