Skip to content

Commit dadb6e5

Browse files
committed
implement uri option spec tests
1 parent 90340ab commit dadb6e5

11 files changed

+564
-6
lines changed

lib/mongo/uri.rb

Lines changed: 112 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -430,17 +430,19 @@ def self.uri_option(uri_key, name, extra = {})
430430
uri_option 'sockettimeoutms', :socket_timeout, :type => :ms_convert
431431
uri_option 'serverselectiontimeoutms', :server_selection_timeout, :type => :ms_convert
432432
uri_option 'localthresholdms', :local_threshold, :type => :ms_convert
433+
uri_option 'heartbeatfrequencyms', :heartbeat_frequency, :type => :ms_convert
434+
uri_option 'maxidletimems', :max_idle_time, :type => :ms_convert
433435

434436
# Write Options
435437
uri_option 'w', :w, :group => :write
436-
uri_option 'journal', :j, :group => :write
438+
uri_option 'journal', :j, :group => :write, :type => :bool
437439
uri_option 'fsync', :fsync, :group => :write
438-
uri_option 'wtimeoutms', :timeout, :group => :write
440+
uri_option 'wtimeoutms', :timeout, :group => :write, :type => :unsigned_int
439441

440442
# Read Options
441443
uri_option 'readpreference', :mode, :group => :read, :type => :read_mode
442444
uri_option 'readpreferencetags', :tag_sets, :group => :read, :type => :read_tags
443-
uri_option 'maxstalenessseconds', :max_staleness, :group => :read
445+
uri_option 'maxstalenessseconds', :max_staleness, :group => :read, :type => :max_staleness
444446

445447
# Pool options
446448
uri_option 'minpoolsize', :min_pool_size
@@ -449,6 +451,13 @@ def self.uri_option(uri_key, name, extra = {})
449451

450452
# Security Options
451453
uri_option 'ssl', :ssl
454+
uri_option 'tls', :ssl
455+
uri_option 'tlsallowinvalidcertificates', :ssl_verify, :type => :inverse_bool
456+
uri_option 'tlscafilepath', :ssl_ca_cert
457+
uri_option 'tlsclientcertfilepath', :ssl_cert
458+
uri_option 'tlsclientkeyfilepath', :ssl_key
459+
uri_option 'tlsclientkeypassword', :ssl_key_pass_phrase
460+
452461

453462
# Topology options
454463
uri_option 'connect', :connect
@@ -461,7 +470,9 @@ def self.uri_option(uri_key, name, extra = {})
461470
# Client Options
462471
uri_option 'appname', :app_name
463472
uri_option 'compressors', :compressors, :type => :array
464-
uri_option 'zlibcompressionlevel', :zlib_compression_level
473+
uri_option 'readconcernlevel', :read_concern
474+
uri_option 'retrywrites', :retry_writes, :type => :bool
475+
uri_option 'zlibcompressionlevel', :zlib_compression_level, :type => :zlib_compression_level
465476

466477
# Casts option values that do not have a specifically provided
467478
# transformation to the appropriate type.
@@ -571,7 +582,7 @@ def auth_source(value)
571582
#
572583
# @return [Symbol] The transformed authentication mechanism.
573584
def auth_mech(value)
574-
AUTH_MECH_MAP[value.upcase]
585+
AUTH_MECH_MAP[value.upcase] || log_warn("#{value} is not a valid auth mechanism")
575586
end
576587

577588
# Read preference mode transformation.
@@ -615,6 +626,92 @@ def auth_mech_props(value)
615626
properties
616627
end
617628

629+
# Parses the zlib compression level.
630+
#
631+
# @param value [ String ] The zlib compression level string.
632+
#
633+
# @return [ Integer | nil ] The compression level value if it is between -1 and 9 (inclusive),
634+
# otherwise nil (and a warning will be raised).
635+
def zlib_compression_level(value)
636+
if /^-?\d+$/ =~ value
637+
i = value.to_i
638+
639+
if i >= -1 && i <= 9
640+
return i
641+
end
642+
end
643+
644+
log_warn("#{value} is not a valid zlibCompressionLevel")
645+
nil
646+
end
647+
648+
649+
# Parses a boolean value.
650+
#
651+
# @param value [ String ] The URI option value.
652+
#
653+
# @return [ true | false | nil ] The boolean value parsed out, otherwise nil (and a warning
654+
# will be raised).
655+
def bool(value)
656+
case value
657+
when "true"
658+
true
659+
when "false"
660+
false
661+
else
662+
log_warn("invalid boolean: #{value}")
663+
nil
664+
end
665+
end
666+
667+
# Parses a boolean value and returns its inverse. This is used for options where the spec
668+
# defines the boolean value semantics of enabling/disabling something in the reverse way that
669+
# the driver does. For instance, the client option `ssl_verify` will disable certificate
670+
# checking when the value is false, but the spec defines the option
671+
# `tlsAllowInvalidCertificates`, which disables certificate checking when the value is true.
672+
#
673+
# @param value [ String ] The URI option.
674+
#
675+
# @return [ true | false | nil ] The inverse of boolean value parsed out, otherwise nil (and a
676+
# warning will be raised).
677+
def inverse_bool(value)
678+
!bool(value)
679+
end
680+
681+
# Parses the max staleness value, which must be either "0" or an integer greater or equal to 90.
682+
#
683+
# @param value [ String ] The max staleness string.
684+
#
685+
# @return [ Integer | nil ] The max staleness integer parsed out if it is valid, otherwise nil
686+
# (and a warning will be raised).
687+
def max_staleness(value)
688+
if /^\d+$/ =~ value
689+
int = value.to_i
690+
691+
if int == 0 || int >= 90
692+
return int
693+
end
694+
end
695+
696+
log_warn("Invalid max staleness value: #{value}")
697+
nil
698+
end
699+
700+
# Parses an unsigned integer value.
701+
#
702+
# @param value [ String ] The URI option value.
703+
#
704+
# @return [ Integer | nil ] The integer parsed out, otherwise nil (and a warning will be
705+
# raised).
706+
def unsigned_int(value)
707+
unless /^-?\d+$/ =~ value
708+
log_warn("Invalid unsigned integer value: #{value}")
709+
return nil
710+
end
711+
712+
value.to_i
713+
end
714+
618715
# Ruby's convention is to provide timeouts in seconds, not milliseconds and
619716
# to use fractions where more precision is necessary. The connection string
620717
# options are always in MS so we provide an easy conversion type.
@@ -625,6 +722,11 @@ def auth_mech_props(value)
625722
#
626723
# @since 2.0.0
627724
def ms_convert(value)
725+
unless /^-?\d+(\.\d+)?$/ =~ value
726+
log_warn("Invalid ms value: #{value}")
727+
return nil
728+
end
729+
628730
value.to_f / 1000
629731
end
630732

@@ -636,6 +738,11 @@ def ms_convert(value)
636738
def hash_extractor(value)
637739
value.split(',').reduce({}) do |set, tag|
638740
k, v = tag.split(':')
741+
if v.nil?
742+
log_warn("#{value} is not a valid URI hash")
743+
return nil
744+
end
745+
639746
set.merge(decode(k).downcase.to_sym => decode(v))
640747
end
641748
end

spec/lite_spec_helper.rb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
RETRYABLE_WRITES_TESTS = Dir.glob("#{CURRENT_PATH}/spec_tests/data/retryable_writes/**/*.yml")
1010
COMMAND_MONITORING_TESTS = Dir.glob("#{CURRENT_PATH}/spec_tests/data/command_monitoring/**/*.yml")
1111
CONNECTION_STRING_TESTS = Dir.glob("#{CURRENT_PATH}/spec_tests/data/connection_string/*.yml")
12+
URI_OPTIONS_TESTS = Dir.glob("#{CURRENT_PATH}/spec_tests/data/uri_options/*.yml")
1213
DNS_SEEDLIST_DISCOVERY_TESTS = Dir.glob("#{CURRENT_PATH}/spec_tests/data/dns_seedlist_discovery/*.yml")
1314
GRIDFS_TESTS = Dir.glob("#{CURRENT_PATH}/spec_tests/data/gridfs/*.yml")
1415
TRANSACTIONS_TESTS = Dir.glob("#{CURRENT_PATH}/spec_tests/data/transactions/*.yml")
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
tests:
2+
-
3+
description: "Valid auth options are parsed correctly"
4+
uri: "mongodb://example.com/?authMechanism=GSSAPI&authMechanismProperties=SERVICE_NAME:other,CANONICALIZE_HOST_NAME:true&authSource=$external"
5+
valid: true
6+
warning: false
7+
hosts: ~
8+
auth:
9+
username: ~
10+
password: ~
11+
db: ~
12+
options:
13+
authmechanism: "GSSAPI"
14+
authMechanismProperties:
15+
SERVICE_NAME: "other"
16+
CANONICALIZE_HOST_NAME: "true"
17+
authSource: "$external"
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
tests:
2+
-
3+
description: "Valid compression options are parsed correctly"
4+
uri: "mongodb://example.com/?compressors=zlib&zlibCompressionLevel=9"
5+
valid: true
6+
warning: false
7+
hosts: ~
8+
auth:
9+
username: ~
10+
password: ~
11+
db: ~
12+
options:
13+
compressors: "zlib"
14+
zlibCompressionLevel: "9"
15+
-
16+
description: "Invalid compressors cause a warning"
17+
uri: "mongodb://example.com/?compressors=jpeg"
18+
valid: true
19+
warning: true
20+
hosts: ~
21+
auth:
22+
username: ~
23+
password: ~
24+
db: ~
25+
options: {}
26+
-
27+
description: "Invalid zlibCompressionLevel causes a warning"
28+
uri: "mongodb://example.com/?compressors=zlib&zlibCompressionLevel=invalid"
29+
valid: true
30+
warning: true
31+
hosts: ~
32+
auth:
33+
username: ~
34+
password: ~
35+
db: ~
36+
options: {}
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
tests:
2+
-
3+
description: "Valid read and write concern are parsed correctly"
4+
uri: "mongodb://example.com/?readConcernLevel=majority&w=5&wTimeoutMS=30000&journal=false"
5+
valid: true
6+
warning: false
7+
hosts: ~
8+
auth:
9+
username: ~
10+
password: ~
11+
db: ~
12+
options:
13+
readConcernLevel: "majority"
14+
w: "5"
15+
wTimeoutMS: "30000"
16+
journal: "false"
17+
-
18+
description: "Arbitrary string readConcernLevel does not cause a warning"
19+
uri: "mongodb://example.com/?readConcernLevel=arbitraryButStillValid"
20+
valid: true
21+
warning: false
22+
hosts: ~
23+
auth:
24+
username: ~
25+
password: ~
26+
db: ~
27+
options:
28+
readConcernLevel: "arbitraryButStillValid"
29+
-
30+
description: "Arbitrary string w doesn't cause a warning"
31+
uri: "mongodb://example.com/?w=arbitraryButStillValid"
32+
valid: true
33+
warning: false
34+
hosts: ~
35+
auth:
36+
username: ~
37+
password: ~
38+
db: ~
39+
options:
40+
w: "arbitraryButStillValid"
41+
-
42+
description: "Invalid wTimeoutMS causes a warning"
43+
uri: "mongodb://example.com/?wTimeoutMS=invalid"
44+
valid: true
45+
warning: true
46+
hosts: ~
47+
auth:
48+
username: ~
49+
password: ~
50+
db: ~
51+
options: {}
52+
-
53+
description: "Invalid journal causes a warning"
54+
uri: "mongodb://example.com/?journal=invalid"
55+
valid: true
56+
warning: true
57+
hosts: ~
58+
auth:
59+
username: ~
60+
password: ~
61+
db: ~
62+
options: {}
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
tests:
2+
-
3+
description: "Valid connection and timeout options are parsed correctly"
4+
uri: "mongodb://example.com/?appname=URI-OPTIONS-SPEC-TEST&connectTimeoutMS=20000&heartbeatFrequencyMS=5000&localThresholdMS=3000&replicaSet=uri-options-spec&retryWrites=true&serverSelectionTimeoutMS=15000&socketTimeoutMS=7500"
5+
valid: true
6+
warning: false
7+
hosts: ~
8+
auth:
9+
username: ~
10+
password: ~
11+
db: ~
12+
options:
13+
appname: "URI-OPTIONS-SPEC-TEST"
14+
connectTimeoutMS: "20000"
15+
heartbeatFrequencyMS: "5000"
16+
localThresholdMS: "3000"
17+
maxIdleTimeMS: "50000"
18+
replicaSet: "uri-options-spec"
19+
retryWrites: "true"
20+
serverSelectionTimeoutMS: "15000"
21+
socketTimeoutMS: "7500"
22+
-
23+
description: "Invalid connectTimeoutMS causes a warning"
24+
uri: "mongodb://example.com/?connectTimeoutMS=invalid"
25+
valid: true
26+
warning: true
27+
hosts: ~
28+
auth:
29+
username: ~
30+
password: ~
31+
db: ~
32+
options: {}
33+
-
34+
description: "Invalid heartbeatFrequencyMS causes a warning"
35+
uri: "mongodb://example.com/?heartbeatFrequencyMS=invalid"
36+
valid: true
37+
warning: true
38+
hosts: ~
39+
auth:
40+
username: ~
41+
password: ~
42+
db: ~
43+
options: {}
44+
-
45+
description: "Invalid localThresholdMS causes a warning"
46+
uri: "mongodb://example.com/?localThresholdMS=invalid"
47+
valid: true
48+
warning: true
49+
hosts: ~
50+
auth:
51+
username: ~
52+
password: ~
53+
db: ~
54+
options: {}
55+
-
56+
description: "Invalid serverSelectionTimeoutMS causes a warning"
57+
uri: "mongodb://example.com/?serverSelectionTimeoutMS=invalid"
58+
valid: true
59+
warning: true
60+
hosts: ~
61+
auth:
62+
username: ~
63+
password: ~
64+
db: ~
65+
options: {}
66+
-
67+
description: "Invalid socketTimeoutMS causes a warning"
68+
uri: "mongodb://example.com/?socketTimeoutMS=invalid"
69+
valid: true
70+
warning: true
71+
hosts: ~
72+
auth:
73+
username: ~
74+
password: ~
75+
db: ~
76+
options: {}

0 commit comments

Comments
 (0)