mongo 2.11.0.rc0 → 2.11.0

Sign up to get free protection for your applications and to get access to all the features.
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