require 'test_helper' class Elasticsearch::Transport::ClientTest < Test::Unit::TestCase class DummyTransport def initialize(*); end end context "Client" do setup do Elasticsearch::Transport::Client::DEFAULT_TRANSPORT_CLASS.any_instance.stubs(:__build_connections) @client = Elasticsearch::Transport::Client.new end should "be aliased as Elasticsearch::Client" do assert_nothing_raised do assert_instance_of(Elasticsearch::Transport::Client, Elasticsearch::Client.new) end end should "have default transport" do assert_instance_of Elasticsearch::Transport::Client::DEFAULT_TRANSPORT_CLASS, @client.transport end should "instantiate custom transport class" do client = Elasticsearch::Transport::Client.new :transport_class => DummyTransport assert_instance_of DummyTransport, client.transport end should "take custom transport instance" do client = Elasticsearch::Transport::Client.new :transport => DummyTransport.new assert_instance_of DummyTransport, client.transport end should "delegate performing requests to transport" do assert_respond_to @client, :perform_request @client.transport.expects(:perform_request) @client.perform_request 'GET', '/' end should "send GET request as POST with the send_get_body_as option" do transport = DummyTransport.new client = Elasticsearch::Transport::Client.new :transport => transport, :send_get_body_as => 'POST' transport.expects(:perform_request).with 'POST', '/', {}, '{"foo":"bar"}' client.perform_request 'GET', '/', {}, '{"foo":"bar"}' end should "have default logger for transport" do client = Elasticsearch::Transport::Client.new :log => true assert_respond_to client.transport.logger, :info end should "have default tracer for transport" do client = Elasticsearch::Transport::Client.new :trace => true assert_respond_to client.transport.tracer, :info end should "initialize the default transport class" do Elasticsearch::Transport::Client::DEFAULT_TRANSPORT_CLASS.any_instance. unstub(:__build_connections) client = Elasticsearch::Client.new assert_match /Faraday/, client.transport.connections.first.connection.headers['User-Agent'] end should "pass options to the transport" do client = Elasticsearch::Transport::Client.new :transport_options => { :foo => 'bar' } assert_equal 'bar', client.transport.options[:transport_options][:foo] end should "merge request_timeout to the transport options" do client = Elasticsearch::Transport::Client.new :request_timeout => 120 assert_equal 120, client.transport.options[:transport_options][:request][:timeout] end should "set the 'Content-Type' header to 'application/json' by default" do client = Elasticsearch::Transport::Client.new assert_equal 'application/json', client.transport.options[:transport_options][:headers]['Content-Type'] end context "when passed hosts" do should "have localhost by default" do c = Elasticsearch::Transport::Client.new assert_equal 'localhost', c.transport.hosts.first[:host] end should "take :hosts, :host, :url or :urls" do c1 = Elasticsearch::Transport::Client.new :hosts => ['foobar'] c2 = Elasticsearch::Transport::Client.new :host => 'foobar' c3 = Elasticsearch::Transport::Client.new :url => 'foobar' c4 = Elasticsearch::Transport::Client.new :urls => 'foo,bar' assert_equal 'foobar', c1.transport.hosts[0][:host] assert_equal 'foobar', c2.transport.hosts[0][:host] assert_equal 'foobar', c3.transport.hosts[0][:host] assert_equal 'foo', c4.transport.hosts[0][:host] assert_equal 'bar', c4.transport.hosts[1][:host] end end context "when the URL is set in the environment variable" do setup { ENV['ELASTICSEARCH_URL'] = 'foobar' } teardown { ENV.delete('ELASTICSEARCH_URL') } should "use a single host" do c = Elasticsearch::Transport::Client.new assert_equal 1, c.transport.hosts.size assert_equal 'foobar', c.transport.hosts.first[:host] end should "use multiple hosts" do ENV['ELASTICSEARCH_URL'] = 'foo, bar' c = Elasticsearch::Transport::Client.new assert_equal 2, c.transport.hosts.size assert_equal 'foo', c.transport.hosts[0][:host] assert_equal 'bar', c.transport.hosts[1][:host] end end context "extracting hosts" do should "extract from string" do hosts = @client.__extract_hosts 'myhost' assert_equal 'myhost', hosts[0][:host] assert_nil hosts[0][:port] end should "extract from hash" do hosts = @client.__extract_hosts( { :host => 'myhost', :scheme => 'https' } ) assert_equal 'myhost', hosts[0][:host] assert_equal 'https', hosts[0][:scheme] assert_nil hosts[0][:port] end should "extract from hash with a port passed as a string" do hosts = @client.__extract_hosts( { :host => 'myhost', :scheme => 'https', :port => '443' } ) assert_equal 443, hosts[0][:port] end should "extract from hash with a port passed as an integer" do hosts = @client.__extract_hosts( { :host => 'myhost', :scheme => 'https', :port => 443 } ) assert_equal 443, hosts[0][:port] end should "extract from Hashie::Mash" do hosts = @client.__extract_hosts( Hashie::Mash.new(:host => 'myhost', :scheme => 'https') ) assert_equal 'myhost', hosts[0][:host] assert_equal 'https', hosts[0][:scheme] end should "extract from array" do hosts = @client.__extract_hosts ['myhost'] assert_equal 'myhost', hosts[0][:host] end should "extract from array with multiple hosts" do hosts = @client.__extract_hosts ['host1', 'host2'] assert_equal 'host1', hosts[0][:host] assert_equal 'host2', hosts[1][:host] end should "extract from array with ports" do hosts = @client.__extract_hosts ['host1:1000', 'host2:2000'] assert_equal 2, hosts.size assert_equal 'host1', hosts[0][:host] assert_equal 1000, hosts[0][:port] assert_equal 'host2', hosts[1][:host] assert_equal 2000, hosts[1][:port] end should "extract path" do hosts = @client.__extract_hosts 'https://myhost:8080/api' assert_equal '/api', hosts[0][:path] end should "extract scheme (protocol)" do hosts = @client.__extract_hosts 'https://myhost:8080' assert_equal 'https', hosts[0][:scheme] assert_equal 'myhost', hosts[0][:host] assert_equal 8080, hosts[0][:port] end should "extract credentials" do hosts = @client.__extract_hosts 'http://USERNAME:PASSWORD@myhost:8080' assert_equal 'http', hosts[0][:scheme] assert_equal 'USERNAME', hosts[0][:user] assert_equal 'PASSWORD', hosts[0][:password] assert_equal 'myhost', hosts[0][:host] assert_equal 8080, hosts[0][:port] end should "pass hashes over" do hosts = @client.__extract_hosts [{:host => 'myhost', :port => '1000', :foo => 'bar'}] assert_equal 'myhost', hosts[0][:host] assert_equal 1000, hosts[0][:port] assert_equal 'bar', hosts[0][:foo] end should "use URL instance" do require 'uri' hosts = @client.__extract_hosts URI.parse('https://USERNAME:PASSWORD@myhost:4430') assert_equal 'https', hosts[0][:scheme] assert_equal 'USERNAME', hosts[0][:user] assert_equal 'PASSWORD', hosts[0][:password] assert_equal 'myhost', hosts[0][:host] assert_equal 4430, hosts[0][:port] end should "split comma-separated URLs" do hosts = @client.__extract_hosts 'foo, bar' assert_equal 2, hosts.size assert_equal 'foo', hosts[0][:host] assert_equal 'bar', hosts[1][:host] end should "remove trailing slash from URL path" do hosts = @client.__extract_hosts 'http://myhost/' assert_equal '', hosts[0][:path] hosts = @client.__extract_hosts 'http://myhost/foo/bar/' assert_equal '/foo/bar', hosts[0][:path] end should "raise error for incompatible argument" do assert_raise ArgumentError do @client.__extract_hosts 123 end end should "randomize hosts" do hosts = [ {:host => 'host1'}, {:host => 'host2'}, {:host => 'host3'}, {:host => 'host4'}, {:host => 'host5'}] Array.any_instance.expects(:shuffle!).twice @client.__extract_hosts(hosts, :randomize_hosts => true) assert_same_elements hosts, @client.__extract_hosts(hosts, :randomize_hosts => true) end end context "detecting adapter for Faraday" do setup do Elasticsearch::Transport::Client::DEFAULT_TRANSPORT_CLASS.any_instance.unstub(:__build_connections) begin; Object.send(:remove_const, :Typhoeus); rescue NameError; end begin; Object.send(:remove_const, :Patron); rescue NameError; end end should "use the default adapter" do c = Elasticsearch::Transport::Client.new handlers = c.transport.connections.all.first.connection.builder.handlers assert_includes handlers, Faraday::Adapter::NetHttp end should "use the adapter from arguments" do c = Elasticsearch::Transport::Client.new :adapter => :typhoeus handlers = c.transport.connections.all.first.connection.builder.handlers assert_includes handlers, Faraday::Adapter::Typhoeus end should "detect the adapter" do require 'patron'; load 'patron.rb' c = Elasticsearch::Transport::Client.new handlers = c.transport.connections.all.first.connection.builder.handlers assert_includes handlers, Faraday::Adapter::Patron end unless JRUBY end context "configuring Faraday" do setup do Elasticsearch::Transport::Client::DEFAULT_TRANSPORT_CLASS.any_instance.unstub(:__build_connections) begin; Object.send(:remove_const, :Typhoeus); rescue NameError; end end should "apply faraday adapter" do c = Elasticsearch::Transport::Client.new do |faraday| faraday.adapter :typhoeus end handlers = c.transport.connections.all.first.connection.builder.handlers assert_includes handlers, Faraday::Adapter::Typhoeus end should "apply faraday response logger" do c = Elasticsearch::Transport::Client.new do |faraday| faraday.response :logger end handlers = c.transport.connections.all.first.connection.builder.handlers assert_includes handlers, Faraday::Response::Logger end end context "when passed options" do setup do Elasticsearch::Transport::Client::DEFAULT_TRANSPORT_CLASS.any_instance.unstub(:__build_connections) end should "configure the HTTP scheme" do c = Elasticsearch::Transport::Client.new \ :hosts => ['node1', 'node2'], :port => 1234, :scheme => 'https', :user => 'USERNAME', :password => 'PASSWORD' assert_equal 'https://USERNAME:PASSWORD@node1:1234/', c.transport.connections[0].full_url('') assert_equal 'https://USERNAME:PASSWORD@node2:1234/', c.transport.connections[1].full_url('') end should "keep the credentials after reloading" do Elasticsearch::Transport::Client::DEFAULT_TRANSPORT_CLASS.any_instance. stubs(:sniffer). returns( mock(:hosts => [ {:host => 'foobar', :port => 4567, :id => 'foobar4567'} ]) ) c = Elasticsearch::Transport::Client.new \ :url => 'http://foo:1234', :user => 'USERNAME', :password => 'PASSWORD' assert_equal 'http://USERNAME:PASSWORD@foo:1234/', c.transport.connections.first.full_url('') c.transport.reload_connections! assert_equal 'http://USERNAME:PASSWORD@foobar:4567/', c.transport.connections.first.full_url('') end should "transfer selected host parts into the 'http' options" do c = Elasticsearch::Transport::Client.new \ :host => { :scheme => 'https', :port => '8080', :host => 'node1', :user => 'U', :password => 'P' } assert_equal 'https://U:P@node1:8080/', c.transport.connections.first.full_url('') assert_equal 'https', c.transport.options[:http][:scheme] assert_equal 8080, c.transport.options[:http][:port] assert_equal 'U', c.transport.options[:http][:user] assert_equal 'P', c.transport.options[:http][:password] end should "transfer selected host parts from URL into the 'http' options" do c = Elasticsearch::Transport::Client.new :url => 'https://U:P@node1:8080' assert_equal 'https://U:P@node1:8080/', c.transport.connections.first.full_url('') assert_equal 'https', c.transport.options[:http][:scheme] assert_equal 8080, c.transport.options[:http][:port] assert_equal 'U', c.transport.options[:http][:user] assert_equal 'P', c.transport.options[:http][:password] end end end end