Merge pull request #84 from TylerBrock/392-uriparser-spec

RUBY-392 Update URIParser for consistency with Mongo URI spec.
This commit is contained in:
Kyle Banker 2012-01-20 11:23:25 -08:00
commit f56846b444
6 changed files with 92 additions and 30 deletions

1
.gitignore vendored
View File

@ -18,3 +18,4 @@ benchmark
*.log *.log
test/load/unicorn/unicorn.rb test/load/unicorn/unicorn.rb
test/load/thin/config.yml test/load/thin/config.yml
.rvmrc

View File

@ -38,7 +38,7 @@ module Mongo
attr_reader :logger, :size, :auths, :primary, :safe, :host_to_try, attr_reader :logger, :size, :auths, :primary, :safe, :host_to_try,
:pool_size, :connect_timeout, :pool_timeout, :pool_size, :connect_timeout, :pool_timeout,
:primary_pool, :socket_class :primary_pool, :socket_class, :op_timeout
# Create a connection to single MongoDB instance. # Create a connection to single MongoDB instance.
# #
@ -52,7 +52,7 @@ module Mongo
# Connection#arbiters. This is useful if your application needs to connect manually to nodes other # Connection#arbiters. This is useful if your application needs to connect manually to nodes other
# than the primary. # than the primary.
# #
# @param [String, Hash] host. # @param [String, Hash] host
# @param [Integer] port specify a port number here if only one host is being specified. # @param [Integer] port specify a port number here if only one host is being specified.
# #
# @option opts [Boolean, Hash] :safe (false) Set the default safe-mode options # @option opts [Boolean, Hash] :safe (false) Set the default safe-mode options

View File

@ -332,6 +332,7 @@ module Mongo
# @option opts [Boolean] :fsync (false) # @option opts [Boolean] :fsync (false)
# @option opts [Integer] :w (nil) # @option opts [Integer] :w (nil)
# @option opts [Integer] :wtimeout (nil) # @option opts [Integer] :wtimeout (nil)
# @option opts [Boolean] :j (false)
# #
# @return [Hash] the entire response to getlasterror. # @return [Hash] the entire response to getlasterror.
# #

View File

@ -35,36 +35,48 @@ module Mongo
MONGODB_URI_SPEC = "mongodb://[username:password@]host1[:port1][,host2[:port2],...[,hostN[:portN]]][/database]" MONGODB_URI_SPEC = "mongodb://[username:password@]host1[:port1][,host2[:port2],...[,hostN[:portN]]][/database]"
SPEC_ATTRS = [:nodes, :auths] SPEC_ATTRS = [:nodes, :auths]
OPT_ATTRS = [:connect, :replicaset, :slaveok, :safe, :w, :wtimeout, :fsync] OPT_ATTRS = [:connect, :replicaset, :slaveok, :safe, :w, :wtimeout, :fsync, :journal, :connectTimeoutMS, :socketTimeoutMS, :wtimeoutMS]
OPT_VALID = {:connect => lambda {|arg| ['direct', 'replicaset'].include?(arg)}, OPT_VALID = {:connect => lambda {|arg| ['direct', 'replicaset'].include?(arg)},
:replicaset => lambda {|arg| arg.length > 0}, :replicaset => lambda {|arg| arg.length > 0},
:slaveok => lambda {|arg| ['true', 'false'].include?(arg)}, :slaveok => lambda {|arg| ['true', 'false'].include?(arg)},
:safe => lambda {|arg| ['true', 'false'].include?(arg)}, :safe => lambda {|arg| ['true', 'false'].include?(arg)},
:w => lambda {|arg| arg =~ /^\d+$/ }, :w => lambda {|arg| arg =~ /^\d+$/ },
:wtimeout => lambda {|arg| arg =~ /^\d+$/ }, :wtimeout => lambda {|arg| arg =~ /^\d+$/ },
:fsync => lambda {|arg| ['true', 'false'].include?(arg)} :fsync => lambda {|arg| ['true', 'false'].include?(arg)},
:journal => lambda {|arg| ['true', 'false'].include?(arg)},
:connectTimeoutMS => lambda {|arg| arg =~ /^\d+$/ },
:socketTimeoutMS => lambda {|arg| arg =~ /^\d+$/ },
:wtimeoutMS => lambda {|arg| arg =~ /^\d+$/ }
} }
OPT_ERR = {:connect => "must be 'direct' or 'replicaset'", OPT_ERR = {:connect => "must be 'direct' or 'replicaset'",
:replicaset => "must be a string containing the name of the replica set to connect to", :replicaset => "must be a string containing the name of the replica set to connect to",
:slaveok => "must be 'true' or 'false'", :slaveok => "must be 'true' or 'false'",
:safe => "must be 'true' or 'false'", :safe => "must be 'true' or 'false'",
:w => "must be an integer specifying number of nodes to replica to", :w => "must be an integer specifying number of nodes to replica to",
:wtimeout => "must be an integer specifying milliseconds", :wtimeout => "must be an integer specifying milliseconds",
:fsync => "must be 'true' or 'false'" :fsync => "must be 'true' or 'false'",
:journal => "must be 'true' or 'false'",
:connectTimeoutMS => "must be an integer specifying milliseconds a connection can take to be opened before timing out",
:socketTimeoutMS => "must be an integer specifying milliseconds a send or receive on a socket can take before timing out",
:wtimeoutMS => "must be an integer specifying milliseconds a send or receive on a socket can take before timing out"
} }
OPT_CONV = {:connect => lambda {|arg| arg}, OPT_CONV = {:connect => lambda {|arg| arg},
:replicaset => lambda {|arg| arg}, :replicaset => lambda {|arg| arg},
:slaveok => lambda {|arg| arg == 'true' ? true : false}, :slaveok => lambda {|arg| arg == 'true' ? true : false},
:safe => lambda {|arg| arg == 'true' ? true : false}, :safe => lambda {|arg| arg == 'true' ? true : false},
:w => lambda {|arg| arg.to_i}, :w => lambda {|arg| arg.to_i},
:wtimeout => lambda {|arg| arg.to_i}, :wtimeout => lambda {|arg| arg.to_i},
:fsync => lambda {|arg| arg == 'true' ? true : false} :fsync => lambda {|arg| arg == 'true' ? true : false},
:journal => lambda {|arg| arg == 'true' ? true : false},
:connectTimeoutMS => lambda {|arg| arg.to_i },
:socketTimeoutMS => lambda {|arg| arg.to_i },
:wtimeoutMS => lambda {|arg| arg.to_i }
} }
attr_reader :nodes, :auths, :connect, :replicaset, :slaveok, :safe, :w, :wtimeout, :fsync attr_reader :nodes, :auths, :connect, :replicaset, :slaveok, :safe, :w, :wtimeout, :fsync, :journal, :connectTimeoutMS, :socketTimeoutMS, :wtimeoutMS
# Parse a MongoDB URI. This method is used by Connection.from_uri. # Parse a MongoDB URI. This method is used by Connection.from_uri.
# Returns an array of nodes and an array of db authorizations, if applicable. # Returns an array of nodes and an array of db authorizations, if applicable.
@ -88,15 +100,25 @@ module Mongo
def connection_options def connection_options
opts = {} opts = {}
if (@w || @wtimeout || @fsync) && !@safe if (@w || @journal || @wtimeout || @fsync || @wtimeoutMS) && !@safe
raise MongoArgumentError, "Safe must be true if w, wtimeout, or fsync is specified" raise MongoArgumentError, "Safe must be true if w, journal, wtimeoutMS, or fsync is specified"
end end
if @safe if @safe
if @w || @wtimeout || @fsync if @w || @journal || @wtimeout || @fsync || @wtimeoutMS
safe_opts = {} safe_opts = {}
safe_opts[:w] = @w if @w safe_opts[:w] = @w if @w
safe_opts[:wtimeout] = @wtimeout if @wtimeout safe_opts[:j] = @journal if @journal
if @wtimeout
warn "Using wtimeout in a URI is deprecated, please use wtimeoutMS. It will be removed in v2.0."
safe_opts[:wtimeout] = @wtimeout
end
if @wtimeoutMS
safe_opts[:wtimeout] = @wtimeoutMS / 1000
end
safe_opts[:fsync] = @fsync if @fsync safe_opts[:fsync] = @fsync if @fsync
else else
safe_opts = true safe_opts = true
@ -105,6 +127,14 @@ module Mongo
opts[:safe] = safe_opts opts[:safe] = safe_opts
end end
if @connectTimeoutMS
opts[:connect_timeout] = @connectTimeoutMS / 1000
end
if @socketTimeoutMS
opts[:op_timeout] = @socketTimeoutMS / 1000
end
if @slaveok if @slaveok
if @connect == 'direct' if @connect == 'direct'
opts[:slave_ok] = true opts[:slave_ok] = true

View File

@ -46,6 +46,28 @@ class ConnectionTest < Test::Unit::TestCase
assert_equal [host_name, 27017], @conn.host_to_try assert_equal [host_name, 27017], @conn.host_to_try
end end
should "set safe options on connection" do
host_name = "localhost"
opts = "safe=true&w=2&wtimeoutMS=10000&fsync=true&journal=true"
@conn = Connection.from_uri("mongodb://#{host_name}/foo?#{opts}", :connect => false)
assert_equal({:w => 2, :wtimeout => 10, :fsync => true, :j => true}, @conn.safe)
end
should "have wtimeoutMS take precidence over the depricated wtimeout" do
host_name = "localhost"
opts = "safe=true&wtimeout=10&wtimeoutMS=2000"
@conn = Connection.from_uri("mongodb://#{host_name}/foo?#{opts}", :connect => false)
assert_equal({:wtimeout => 2}, @conn.safe)
end
should "set timeout options on connection" do
host_name = "localhost"
opts = "connectTimeoutMS=1000&socketTimeoutMS=5000"
@conn = Connection.from_uri("mongodb://#{host_name}/foo?#{opts}", :connect => false)
assert_equal 1, @conn.connect_timeout
assert_equal 5, @conn.op_timeout
end
should "parse a uri with a hyphen & underscore in the username or password" do should "parse a uri with a hyphen & underscore in the username or password" do
@conn = Connection.from_uri("mongodb://hyphen-user_name:p-s_s@localhost:27017/db", :connect => false) @conn = Connection.from_uri("mongodb://hyphen-user_name:p-s_s@localhost:27017/db", :connect => false)
assert_equal ['localhost', 27017], @conn.host_to_try assert_equal ['localhost', 27017], @conn.host_to_try

View File

@ -78,11 +78,19 @@ class TestThreading < Test::Unit::TestCase
end end
def test_opts_safe def test_opts_safe
parser = Mongo::URIParser.new('mongodb://localhost:27018?safe=true;w=2;wtimeout=200;fsync=true') parser = Mongo::URIParser.new('mongodb://localhost:27018?safe=true;w=2;journal=true;wtimeout=200;fsync=true;wtimeoutMS=200')
assert parser.safe assert parser.safe
assert_equal 2, parser.w assert_equal 2, parser.w
assert_equal 200, parser.wtimeout assert_equal 200, parser.wtimeout
assert parser.fsync assert parser.fsync
assert parser.journal
assert_equal 200, parser.wtimeoutMS
end
def test_opts_unsafe_timeout
parser = Mongo::URIParser.new('mongodb://localhost:27018?connectTimeoutMS=5000&socketTimeoutMS=10000')
assert_equal 5000, parser.connectTimeoutMS
assert_equal 10000, parser.socketTimeoutMS
end end
def test_opts_replica_set def test_opts_replica_set