require 'minitest/autorun' require 'xmlrpc/client' require 'net/http' module XMLRPC class ClientTest < MiniTest::Unit::TestCase module Fake class HTTP attr_accessor :read_timeout, :open_timeout, :use_ssl def initialize responses = {} @started = false @responses = responses end def started? @started end def start @started = true if block_given? begin return yield(self) ensure @started = false end end self end def request_post path, request, headers @responses[path].shift end end class Client < XMLRPC::Client attr_reader :args, :http def initialize(*args) @args = args super end private def net_http host, port, proxy_host, proxy_port HTTP.new end end class Response def self.new body, fields = [], status = '200' klass = Class.new(Net::HTTPResponse::CODE_TO_OBJ[status]) { def initialize(*args) super @read = true end } resp = klass.new '1.1', status, 'OK' resp.body = body fields.each do |k,v| resp.add_field k, v end resp end end end def test_new2_host_path_port client = Fake::Client.new2 'http://example.org/foo' host, path, port, *rest = client.args assert_equal 'example.org', host assert_equal '/foo', path assert_equal 80, port rest.each { |x| refute x } end def test_new2_custom_port client = Fake::Client.new2 'http://example.org:1234/foo' host, path, port, *rest = client.args assert_equal 'example.org', host assert_equal '/foo', path assert_equal 1234, port rest.each { |x| refute x } end def test_new2_ssl client = Fake::Client.new2 'https://example.org/foo' host, path, port, proxy_host, proxy_port, user, password, use_ssl, timeout = client.args assert_equal 'example.org', host assert_equal '/foo', path assert_equal 443, port assert use_ssl refute proxy_host refute proxy_port refute user refute password refute timeout end if defined?(OpenSSL) def test_new2_ssl_custom_port client = Fake::Client.new2 'https://example.org:1234/foo' host, path, port, proxy_host, proxy_port, user, password, use_ssl, timeout = client.args assert_equal 'example.org', host assert_equal '/foo', path assert_equal 1234, port refute proxy_host refute proxy_port refute user refute password refute timeout end if defined?(OpenSSL) def test_new2_user_password client = Fake::Client.new2 'http://aaron:tenderlove@example.org/foo' host, path, port, proxy_host, proxy_port, user, password, use_ssl, timeout = client.args [ host, path, port ].each { |x| assert x } assert_equal 'aaron', user assert_equal 'tenderlove', password [ proxy_host, proxy_port, use_ssl, timeout ].each { |x| refute x } end def test_new2_proxy_host client = Fake::Client.new2 'http://example.org/foo', 'example.com' host, path, port, proxy_host, proxy_port, user, password, use_ssl, timeout = client.args [ host, path, port ].each { |x| assert x } assert_equal 'example.com', proxy_host [ user, password, proxy_port, use_ssl, timeout ].each { |x| refute x } end def test_new2_proxy_port client = Fake::Client.new2 'http://example.org/foo', 'example.com:1234' host, path, port, proxy_host, proxy_port, user, password, use_ssl, timeout = client.args [ host, path, port ].each { |x| assert x } assert_equal 'example.com', proxy_host assert_equal 1234, proxy_port [ user, password, use_ssl, timeout ].each { |x| refute x } end def test_new2_no_path client = Fake::Client.new2 'http://example.org' host, path, port, *rest = client.args assert_equal 'example.org', host assert_nil path assert port rest.each { |x| refute x } end def test_new2_slash_path client = Fake::Client.new2 'http://example.org/' host, path, port, *rest = client.args assert_equal 'example.org', host assert_equal '/', path assert port rest.each { |x| refute x } end def test_new2_bad_protocol assert_raises(ArgumentError) do XMLRPC::Client.new2 'ftp://example.org' end end def test_new2_bad_uri assert_raises(ArgumentError) do XMLRPC::Client.new2 ':::::' end end def test_new2_path_with_query client = Fake::Client.new2 'http://example.org/foo?bar=baz' host, path, port, *rest = client.args assert_equal 'example.org', host assert_equal '/foo?bar=baz', path assert port rest.each { |x| refute x } end def test_request fh = read 'blog.xml' responses = { '/foo' => [ Fake::Response.new(fh, [['Content-Type', 'text/xml']]) ] } client = fake_client(responses).new2 'http://example.org/foo' resp = client.call('wp.getUsersBlogs', 'tlo', 'omg') expected = [{ "isAdmin" => true, "url" => "http://tenderlovemaking.com/", "blogid" => "1", "blogName" => "Tender Lovemaking", "xmlrpc" => "http://tenderlovemaking.com/xmlrpc.php" }] assert_equal expected, resp end def test_async_request fh = read 'blog.xml' responses = { '/foo' => [ Fake::Response.new(fh, [['Content-Type', 'text/xml']]) ] } client = fake_client(responses).new2 'http://example.org/foo' resp = client.call_async('wp.getUsersBlogs', 'tlo', 'omg') expected = [{ "isAdmin" => true, "url" => "http://tenderlovemaking.com/", "blogid" => "1", "blogName" => "Tender Lovemaking", "xmlrpc" => "http://tenderlovemaking.com/xmlrpc.php" }] assert_equal expected, resp end # make a request without content-type header def test_bad_content_type fh = read 'blog.xml' responses = { '/foo' => [ Fake::Response.new(fh) ] } client = fake_client(responses).new2 'http://example.org/foo' resp = client.call('wp.getUsersBlogs', 'tlo', 'omg') expected = [{ "isAdmin" => true, "url" => "http://tenderlovemaking.com/", "blogid" => "1", "blogName" => "Tender Lovemaking", "xmlrpc" => "http://tenderlovemaking.com/xmlrpc.php" }] assert_equal expected, resp end def test_i8_tag fh = read('blog.xml').gsub(/string/, 'i8') responses = { '/foo' => [ Fake::Response.new(fh) ] } client = fake_client(responses).new2 'http://example.org/foo' resp = client.call('wp.getUsersBlogs', 'tlo', 'omg') assert_equal 1, resp.first['blogid'] end private def read filename File.read File.expand_path(File.join(__FILE__, '..', 'data', filename)) end def fake_client responses Class.new(Fake::Client) { define_method(:net_http) { |*_| Fake::HTTP.new(responses) } } end end end