diff options
author | David Heinemeier Hansson <david@loudthinking.com> | 2005-02-18 10:35:25 +0000 |
---|---|---|
committer | David Heinemeier Hansson <david@loudthinking.com> | 2005-02-18 10:35:25 +0000 |
commit | e7a29380292902eae4799b2658507b3cfffb9cec (patch) | |
tree | 99a7cd3c7d720ef73f998c2756be1fef77ff0ee1 /actionservice/test | |
parent | e39bf105941133d3d6699c52c18dbd3b9aa0bf5c (diff) | |
download | rails-e7a29380292902eae4799b2658507b3cfffb9cec.tar.gz rails-e7a29380292902eae4799b2658507b3cfffb9cec.tar.bz2 rails-e7a29380292902eae4799b2658507b3cfffb9cec.zip |
Added Action Service to the repository
git-svn-id: http://svn-commit.rubyonrails.org/rails/trunk@658 5ecf4fe2-1ee6-0310-87b1-e25e094e27de
Diffstat (limited to 'actionservice/test')
-rw-r--r-- | actionservice/test/abstract_client.rb | 124 | ||||
-rw-r--r-- | actionservice/test/abstract_soap.rb | 58 | ||||
-rw-r--r-- | actionservice/test/abstract_unit.rb | 9 | ||||
-rw-r--r-- | actionservice/test/api_test.rb | 52 | ||||
-rw-r--r-- | actionservice/test/base_test.rb | 42 | ||||
-rw-r--r-- | actionservice/test/client_soap_test.rb | 87 | ||||
-rw-r--r-- | actionservice/test/client_xmlrpc_test.rb | 86 | ||||
-rw-r--r-- | actionservice/test/container_test.rb | 53 | ||||
-rw-r--r-- | actionservice/test/invocation_test.rb | 158 | ||||
-rw-r--r-- | actionservice/test/protocol_registry_test.rb | 53 | ||||
-rw-r--r-- | actionservice/test/protocol_soap_test.rb | 226 | ||||
-rw-r--r-- | actionservice/test/protocol_xmlrpc_test.rb | 157 | ||||
-rw-r--r-- | actionservice/test/router_action_controller_test.rb | 139 | ||||
-rw-r--r-- | actionservice/test/router_wsdl_test.rb | 100 | ||||
-rw-r--r-- | actionservice/test/struct_test.rb | 40 |
15 files changed, 1384 insertions, 0 deletions
diff --git a/actionservice/test/abstract_client.rb b/actionservice/test/abstract_client.rb new file mode 100644 index 0000000000..662bdd9431 --- /dev/null +++ b/actionservice/test/abstract_client.rb @@ -0,0 +1,124 @@ +require File.dirname(__FILE__) + '/abstract_unit' +require 'webrick' +require 'webrick/log' +require 'singleton' + +module ClientTest + class Person < ActionService::Struct + member :firstnames, [:string] + member :lastname, :string + + def ==(other) + firstnames == other.firstnames && lastname == other.lastname + end + end + + class API < ActionService::API::Base + api_method :void + api_method :normal, :expects => [:int, :int], :returns => [:int] + api_method :array_return, :returns => [[Person]] + api_method :struct_pass, :expects => [[Person]], :returns => [:bool] + api_method :client_container, :returns => [:int] + end + + class NullLogOut + def <<(*args); end + end + + class Container < ActionController::Base + service_api API + + attr :value_void + attr :value_normal + attr :value_array_return + attr :value_struct_pass + + def initialize + @session = @assigns = {} + @value_void = nil + @value_normal = nil + @value_array_return = nil + @value_struct_pass = nil + end + + def void + @value_void = @method_params + end + + def normal + @value_normal = @method_params + 5 + end + + def array_return + person = Person.new + person.firstnames = ["one", "two"] + person.lastname = "last" + @value_array_return = [person] + end + + def struct_pass + @value_struct_pass = @method_params + true + end + + def client_container + 50 + end + + def protocol_request(request) + probe_request_protocol(request) + end + + def dispatch_request(protocol_request) + dispatch_service_request(protocol_request) + end + end + + class AbstractClientLet < WEBrick::HTTPServlet::AbstractServlet + def initialize(controller) + @controller = controller + end + + def get_instance(*args) + self + end + + def require_path_info? + false + end + + def do_GET(req, res) + raise WEBrick::HTTPStatus::MethodNotAllowed, "GET request not allowed." + end + + def do_POST(req, res) + raise NotImplementedError + end + end + + class AbstractServer + include ClientTest + include Singleton + attr :container + def initialize + @container = Container.new + @clientlet = create_clientlet(@container) + log = WEBrick::BasicLog.new(NullLogOut.new) + @server = WEBrick::HTTPServer.new(:Port => server_port, :Logger => log, :AccessLog => log) + @server.mount('/', @clientlet) + @thr = Thread.new { @server.start } + until @server.status == :Running; end + at_exit { @server.stop; @thr.join } + end + + protected + def create_clientlet + raise NotImplementedError + end + + def server_port + raise NotImplementedError + end + end +end diff --git a/actionservice/test/abstract_soap.rb b/actionservice/test/abstract_soap.rb new file mode 100644 index 0000000000..7454be9bdf --- /dev/null +++ b/actionservice/test/abstract_soap.rb @@ -0,0 +1,58 @@ +require File.dirname(__FILE__) + '/abstract_unit' +require 'soap/rpc/element' + +class SoapTestError < StandardError +end + +class AbstractSoapTest < Test::Unit::TestCase + def default_test + end + + protected + def service_name + raise NotImplementedError + end + + def do_soap_call(public_method_name, *args) + mapper = @container.class.soap_mapper + param_def = [] + i = 1 + args.each do |arg| + mapping = mapper.lookup(arg.class) + param_def << ["in", "param#{i}", mapping.registry_mapping] + i += 1 + end + qname = XSD::QName.new('urn:ActionService', public_method_name) + request = SOAP::RPC::SOAPMethodRequest.new(qname, param_def) + soap_args = [] + i = 1 + args.each do |arg| + soap_args << ["param#{i}", SOAP::Mapping.obj2soap(arg)] + i += 1 + end + request.set_param(soap_args) + header = SOAP::SOAPHeader.new + body = SOAP::SOAPBody.new(request) + envelope = SOAP::SOAPEnvelope.new(header, body) + raw_request = SOAP::Processor.marshal(envelope) + test_request = ActionController::TestRequest.new + test_request.request_parameters['action'] = service_name + test_request.env['REQUEST_METHOD'] = "POST" + test_request.env['HTTP_CONTENTTYPE'] = 'text/xml' + test_request.env['HTTP_SOAPACTION'] = "/soap/#{service_name}/#{public_method_name}" + test_request.env['RAW_POST_DATA'] = raw_request + test_response = ActionController::TestResponse.new + response = yield test_request, test_response + raw_body = response.respond_to?(:body) ? response.body : response.raw_body + envelope = SOAP::Processor.unmarshal(raw_body) + if envelope + if envelope.body.response + SOAP::Mapping.soap2obj(envelope.body.response) + else + nil + end + else + raise(SoapTestError, "empty/invalid body from server") + end + end +end diff --git a/actionservice/test/abstract_unit.rb b/actionservice/test/abstract_unit.rb new file mode 100644 index 0000000000..54ca73b35c --- /dev/null +++ b/actionservice/test/abstract_unit.rb @@ -0,0 +1,9 @@ +$:.unshift(File.dirname(__FILE__) + '/../lib') + +require 'test/unit' +require 'action_service' +require 'action_controller' +require 'action_controller/test_process' + +ActionController::Base.logger = nil +ActionController::Base.ignore_missing_templates = true diff --git a/actionservice/test/api_test.rb b/actionservice/test/api_test.rb new file mode 100644 index 0000000000..2ef5cc7bda --- /dev/null +++ b/actionservice/test/api_test.rb @@ -0,0 +1,52 @@ +require File.dirname(__FILE__) + '/abstract_unit' + +module APITest + class API < ActionService::API::Base + api_method :void + api_method :expects_and_returns, :expects_and_returns => [:string] + api_method :expects, :expects => [:int, :bool] + api_method :returns, :returns => [:int, [:string]] + api_method :named_signature, :expects => [{:appkey=>:int}, {:publish=>:bool}] + api_method :string_types, :expects => ['int', 'string', 'bool'] + api_method :class_types, :expects => [TrueClass, Bignum, String] + end +end + +class TC_API < Test::Unit::TestCase + API = APITest::API + + def test_api_method_declaration + %w( + void + expects_and_returns + expects + returns + named_signature + string_types + class_types + ).each do |name| + name = name.to_sym + public_name = API.public_api_method_name(name) + assert(API.has_api_method?(name)) + assert(API.has_public_api_method?(public_name)) + assert(API.api_method_name(public_name) == name) + assert(API.api_methods.has_key?(name)) + end + end + + def test_signature_canonicalization + assert_equal({:expects=>nil, :returns=>nil}, API.api_methods[:void]) + assert_equal({:expects=>[String], :returns=>[String]}, API.api_methods[:expects_and_returns]) + assert_equal({:expects=>[Integer, TrueClass], :returns=>nil}, API.api_methods[:expects]) + assert_equal({:expects=>nil, :returns=>[Integer, [String]]}, API.api_methods[:returns]) + assert_equal({:expects=>[{:appkey=>Integer}, {:publish=>TrueClass}], :returns=>nil}, API.api_methods[:named_signature]) + assert_equal({:expects=>[Integer, String, TrueClass], :returns=>nil}, API.api_methods[:string_types]) + assert_equal({:expects=>[TrueClass, Bignum, String], :returns=>nil}, API.api_methods[:class_types]) + end + + def test_not_instantiable + assert_raises(NoMethodError) do + API.new + end + end +end diff --git a/actionservice/test/base_test.rb b/actionservice/test/base_test.rb new file mode 100644 index 0000000000..21456f6c5a --- /dev/null +++ b/actionservice/test/base_test.rb @@ -0,0 +1,42 @@ +require File.dirname(__FILE__) + '/abstract_unit' + +module BaseTest + class API < ActionService::API::Base + api_method :add, :expects => [:int, :int], :returns => [:int] + api_method :void + end + + class PristineAPI < ActionService::API::Base + inflect_names false + + api_method :add + api_method :under_score + end + + class Service < ActionService::Base + service_api API + + def add(a, b) + end + + def void + end + end + + class PristineService < ActionService::Base + service_api PristineAPI + + def add + end + + def under_score + end + end +end + +class TC_Base < Test::Unit::TestCase + def test_options + assert(BaseTest::PristineService.service_api.inflect_names == false) + assert(BaseTest::Service.service_api.inflect_names == true) + end +end diff --git a/actionservice/test/client_soap_test.rb b/actionservice/test/client_soap_test.rb new file mode 100644 index 0000000000..e802812cc1 --- /dev/null +++ b/actionservice/test/client_soap_test.rb @@ -0,0 +1,87 @@ +require File.dirname(__FILE__) + '/abstract_client' + + +module ClientSoapTest + PORT = 8998 + + class SoapClientLet < ClientTest::AbstractClientLet + def do_POST(req, res) + test_request = ActionController::TestRequest.new + test_request.request_parameters['action'] = req.path.gsub(/^\//, '').split(/\//)[1] + test_request.env['REQUEST_METHOD'] = "POST" + test_request.env['HTTP_CONTENTTYPE'] = 'text/xml' + test_request.env['HTTP_SOAPACTION'] = req.header['soapaction'][0] + test_request.env['RAW_POST_DATA'] = req.body + protocol_request = @controller.protocol_request(test_request) + response = @controller.dispatch_request(protocol_request) + res.header['content-type'] = 'text/xml' + res.body = response.raw_body + rescue Exception => e + $stderr.puts e.message + $stderr.puts e.backtrace.join("\n") + end + end + + class ClientContainer < ActionController::Base + client_api :client, :soap, "http://localhost:#{PORT}/client/api", :api => ClientTest::API + + def get_client + client + end + end + + class SoapServer < ClientTest::AbstractServer + def create_clientlet(controller) + SoapClientLet.new(controller) + end + + def server_port + PORT + end + end +end + +class TC_ClientSoap < Test::Unit::TestCase + include ClientTest + include ClientSoapTest + + def setup + @server = SoapServer.instance + @container = @server.container + @client = ActionService::Client::Soap.new(API, "http://localhost:#{@server.server_port}/client/api") + end + + def test_void + assert(@container.value_void.nil?) + @client.void + assert(!@container.value_void.nil?) + end + + def test_normal + assert(@container.value_normal.nil?) + assert_equal(5, @client.normal(5, 6)) + assert_equal([5, 6], @container.value_normal) + end + + def test_array_return + assert(@container.value_array_return.nil?) + new_person = Person.new + new_person.firstnames = ["one", "two"] + new_person.lastname = "last" + assert_equal([new_person], @client.array_return) + assert_equal([new_person], @container.value_array_return) + end + + def test_struct_pass + assert(@container.value_struct_pass.nil?) + new_person = Person.new + new_person.firstnames = ["one", "two"] + new_person.lastname = "last" + assert_equal(true, @client.struct_pass([new_person])) + assert_equal([[new_person]], @container.value_struct_pass) + end + + def test_client_container + assert_equal(50, ClientContainer.new.get_client.client_container) + end +end diff --git a/actionservice/test/client_xmlrpc_test.rb b/actionservice/test/client_xmlrpc_test.rb new file mode 100644 index 0000000000..9c6abc3520 --- /dev/null +++ b/actionservice/test/client_xmlrpc_test.rb @@ -0,0 +1,86 @@ +require File.dirname(__FILE__) + '/abstract_client' + + +module ClientXmlRpcTest + PORT = 8999 + + class XmlRpcClientLet < ClientTest::AbstractClientLet + def do_POST(req, res) + test_request = ActionController::TestRequest.new + test_request.request_parameters['action'] = req.path.gsub(/^\//, '').split(/\//)[1] + test_request.env['REQUEST_METHOD'] = "POST" + test_request.env['HTTP_CONTENTTYPE'] = 'text/xml' + test_request.env['RAW_POST_DATA'] = req.body + protocol_request = @controller.protocol_request(test_request) + response = @controller.dispatch_request(protocol_request) + res.header['content-type'] = 'text/xml' + res.body = response.raw_body + rescue Exception => e + $stderr.puts e.message + $stderr.puts e.backtrace.join("\n") + end + end + + class ClientContainer < ActionController::Base + client_api :client, :xmlrpc, "http://localhost:#{PORT}/client/api", :api => ClientTest::API + + def get_client + client + end + end + + class XmlRpcServer < ClientTest::AbstractServer + def create_clientlet(controller) + XmlRpcClientLet.new(controller) + end + + def server_port + PORT + end + end +end + +class TC_ClientXmlRpc < Test::Unit::TestCase + include ClientTest + include ClientXmlRpcTest + + def setup + @server = XmlRpcServer.instance + @container = @server.container + @client = ActionService::Client::XmlRpc.new(API, "http://localhost:#{@server.server_port}/client/api") + end + + def test_void + assert(@container.value_void.nil?) + @client.void + assert(!@container.value_void.nil?) + end + + def test_normal + assert(@container.value_normal.nil?) + assert_equal(5, @client.normal(5, 6)) + assert_equal([5, 6], @container.value_normal) + end + + def test_array_return + assert(@container.value_array_return.nil?) + new_person = Person.new + new_person.firstnames = ["one", "two"] + new_person.lastname = "last" + assert_equal([new_person], @client.array_return) + assert_equal([new_person], @container.value_array_return) + end + + def test_struct_pass + assert(@container.value_struct_pass.nil?) + new_person = Person.new + new_person.firstnames = ["one", "two"] + new_person.lastname = "last" + assert_equal(true, @client.struct_pass([new_person])) + assert_equal([[new_person]], @container.value_struct_pass) + end + + def test_client_container + assert_equal(50, ClientContainer.new.get_client.client_container) + end +end diff --git a/actionservice/test/container_test.rb b/actionservice/test/container_test.rb new file mode 100644 index 0000000000..b222138087 --- /dev/null +++ b/actionservice/test/container_test.rb @@ -0,0 +1,53 @@ +require File.dirname(__FILE__) + '/abstract_unit' + +module ContainerTest + + $immediate_service = Object.new + $deferred_service = Object.new + + class DelegateContainer < ActionController::Base + service_dispatching_mode :delegated + + attr :flag + attr :previous_flag + + def initialize + @previous_flag = nil + @flag = true + end + + service :immediate_service, $immediate_service + service(:deferred_service) { @previous_flag = @flag; @flag = false; $deferred_service } + end + + class DirectContainer < ActionController::Base + service_dispatching_mode :direct + end +end + +class TC_Container < Test::Unit::TestCase + def setup + @delegate_container = ContainerTest::DelegateContainer.new + @direct_container = ContainerTest::DirectContainer.new + end + + def test_registration + assert(ContainerTest::DelegateContainer.has_service?(:immediate_service)) + assert(ContainerTest::DelegateContainer.has_service?(:deferred_service)) + assert(!ContainerTest::DelegateContainer.has_service?(:fake_service)) + end + + def test_service_object + assert(@delegate_container.flag == true) + assert(@delegate_container.service_object(:immediate_service) == $immediate_service) + assert(@delegate_container.previous_flag.nil?) + assert(@delegate_container.flag == true) + assert(@delegate_container.service_object(:deferred_service) == $deferred_service) + assert(@delegate_container.previous_flag == true) + assert(@delegate_container.flag == false) + end + + def test_direct_container + assert(ContainerTest::DirectContainer.service_dispatching_mode == :direct) + end +end diff --git a/actionservice/test/invocation_test.rb b/actionservice/test/invocation_test.rb new file mode 100644 index 0000000000..d8ecdc4e0b --- /dev/null +++ b/actionservice/test/invocation_test.rb @@ -0,0 +1,158 @@ +require File.dirname(__FILE__) + '/abstract_unit' + +module InvocationTest + class API < ActionService::API::Base + api_method :add, :expects => [:int, :int], :returns => [:int] + api_method :transmogrify, :expects_and_returns => [:string] + api_method :fail_with_reason + api_method :fail_generic + api_method :no_before + api_method :no_after + api_method :only_one + api_method :only_two + end + + class Service < ActionService::Base + service_api API + + before_invocation :intercept_before, :except => [:no_before] + after_invocation :intercept_after, :except => [:no_after] + before_invocation :intercept_only, :only => [:only_one, :only_two] + + attr_accessor :before_invoked + attr_accessor :after_invoked + attr_accessor :only_invoked + attr_accessor :invocation_result + + def initialize + @before_invoked = nil + @after_invoked = nil + @only_invoked = nil + @invocation_result = nil + end + + def add(a, b) + a + b + end + + def transmogrify(str) + str.upcase + end + + def fail_with_reason + end + + def fail_generic + end + + def no_before + 5 + end + + def no_after + end + + def only_one + end + + def only_two + end + + def not_public + end + + protected + def intercept_before(name, args) + @before_invoked = name + return [false, "permission denied"] if name == :fail_with_reason + return false if name == :fail_generic + end + + def intercept_after(name, args, result) + @after_invoked = name + @invocation_result = result + end + + def intercept_only(name, args) + raise "Interception error" unless name == :only_one || name == :only_two + @only_invoked = name + end + end +end + +class TC_Invocation < Test::Unit::TestCase + include ActionService::Invocation + + def setup + @service = InvocationTest::Service.new + end + + def test_invocation + assert(perform_invocation(:add, 5, 10) == 15) + assert(perform_invocation(:transmogrify, "hello") == "HELLO") + assert_raises(InvocationError) do + perform_invocation(:not_public) + end + assert_raises(InvocationError) do + perform_invocation(:nonexistent_method_xyzzy) + end + end + + def test_interceptor_registration + assert(InvocationTest::Service.before_invocation_interceptors.length == 2) + assert(InvocationTest::Service.after_invocation_interceptors.length == 1) + end + + def test_interception + assert(@service.before_invoked.nil? && @service.after_invoked.nil? && @service.only_invoked.nil? && @service.invocation_result.nil?) + perform_invocation(:add, 20, 50) + assert(@service.before_invoked == :add) + assert(@service.after_invoked == :add) + assert(@service.invocation_result == 70) + end + + def test_interception_canceling + reason = nil + perform_invocation(:fail_with_reason){|r| reason = r} + assert(@service.before_invoked == :fail_with_reason) + assert(@service.after_invoked.nil?) + assert(@service.invocation_result.nil?) + assert(reason == "permission denied") + reason = true + @service.before_invoked = @service.after_invoked = @service.invocation_result = nil + perform_invocation(:fail_generic){|r| reason = r} + assert(@service.before_invoked == :fail_generic) + assert(@service.after_invoked.nil?) + assert(@service.invocation_result.nil?) + assert(reason == true) + end + + def test_interception_except_conditions + perform_invocation(:no_before) + assert(@service.before_invoked.nil?) + assert(@service.after_invoked == :no_before) + assert(@service.invocation_result == 5) + @service.before_invoked = @service.after_invoked = @service.invocation_result = nil + perform_invocation(:no_after) + assert(@service.before_invoked == :no_after) + assert(@service.after_invoked.nil?) + assert(@service.invocation_result.nil?) + end + + def test_interception_only_conditions + assert(@service.only_invoked.nil?) + perform_invocation(:only_one) + assert(@service.only_invoked == :only_one) + @service.only_invoked = nil + perform_invocation(:only_two) + assert(@service.only_invoked == :only_two) + end + + private + def perform_invocation(method_name, *args, &block) + public_method_name = @service.class.service_api.public_api_method_name(method_name) + args ||= [] + request = InvocationRequest.new(ConcreteInvocation, public_method_name, method_name, args) + @service.perform_invocation(request, &block) + end +end diff --git a/actionservice/test/protocol_registry_test.rb b/actionservice/test/protocol_registry_test.rb new file mode 100644 index 0000000000..8e2b9659a6 --- /dev/null +++ b/actionservice/test/protocol_registry_test.rb @@ -0,0 +1,53 @@ +require File.dirname(__FILE__) + '/abstract_unit' + + +module Foo + include ActionService::Protocol + + def self.append_features(base) + super + base.register_protocol(BodyOnly, FooMinimalProtocol) + base.register_protocol(HeaderAndBody, FooMinimalProtocolTwo) + base.register_protocol(HeaderAndBody, FooMinimalProtocolTwo) + base.register_protocol(HeaderAndBody, FooFullProtocol) + end + + class FooFullProtocol < AbstractProtocol + def self.create_protocol_request(klass, request) + protocol = FooFullProtocol.new klass + ActionService::Protocol::ProtocolRequest.new(protocol, '', '', '', '') + end + end + + class FooMinimalProtocol < AbstractProtocol + def self.create_protocol_request(klass, request) + protocol = FooMinimalProtocol.new klass + ActionService::Protocol::ProtocolRequest.new(protocol, '', '', '', '') + end + end + + class FooMinimalProtocolTwo < AbstractProtocol + end +end + +class ProtocolRegistry + include ActionService::Protocol::Registry + include Foo + + def all_protocols + header_and_body_protocols + body_only_protocols + end + + def protocol_request + probe_request_protocol(nil) + end +end + + +class TC_ProtocolRegistry < Test::Unit::TestCase + def test_registration + registry = ProtocolRegistry.new + assert(registry.all_protocols.length == 4) + assert(registry.protocol_request.protocol.is_a?(Foo::FooFullProtocol)) + end +end diff --git a/actionservice/test/protocol_soap_test.rb b/actionservice/test/protocol_soap_test.rb new file mode 100644 index 0000000000..eaccd64e4e --- /dev/null +++ b/actionservice/test/protocol_soap_test.rb @@ -0,0 +1,226 @@ +require File.dirname(__FILE__) + '/abstract_soap' + +module ProtocolSoapTest + class Person < ActionService::Struct + member :id, Integer + member :names, [String] + member :lastname, String + member :deleted, TrueClass + + def ==(other) + id == other.id && names == other.names && lastname == other.lastname && deleted == other.deleted + end + end + + class API < ActionService::API::Base + api_method :argument_passing, :expects => [{:int=>:int}, {:string=>:string}, {:array=>[:int]}], :returns => [:bool] + api_method :array_returner, :returns => [[:int]] + api_method :nil_returner + api_method :struct_array_returner, :returns => [[Person]] + api_method :exception_thrower + + default_api_method :default + end + + class Service < ActionService::Base + service_api API + + attr :int + attr :string + attr :array + attr :values + attr :person + attr :default_args + + def initialize + @int = 20 + @string = "wrong string value" + @default_args = nil + end + + def argument_passing(int, string, array) + @int = int + @string = string + @array = array + true + end + + def array_returner + @values = [1, 2, 3] + end + + def nil_returner + nil + end + + def struct_array_returner + @person = Person.new + @person.id = 5 + @person.names = ["one", "two"] + @person.lastname = "test" + @person.deleted = false + [@person] + end + + def exception_thrower + raise "Hi, I'm a SOAP error" + end + + def default(*args) + @default_args = args + nil + end + end + + class AbstractContainer + include ActionService::API + include ActionService::Container + include ActionService::Protocol::Registry + include ActionService::Protocol::Soap + + wsdl_service_name 'Test' + + def protocol_request(request) + probe_request_protocol(request) + end + + def dispatch_request(protocol_request) + dispatch_service_request(protocol_request) + end + end + + class DelegatedContainer < AbstractContainer + service_dispatching_mode :delegated + service :protocol_soap_service, Service.new + end + + class DirectContainer < AbstractContainer + service_api API + service_dispatching_mode :direct + + attr :int + attr :string + attr :array + attr :values + attr :person + attr :default_args + + def initialize + @int = 20 + @string = "wrong string value" + @default_args = nil + end + + def argument_passing + @int = @params['int'] + @string = @params['string'] + @array = @params['array'] + true + end + + def array_returner + @values = [1, 2, 3] + end + + def nil_returner + nil + end + + def struct_array_returner + @person = Person.new + @person.id = 5 + @person.names = ["one", "two"] + @person.lastname = "test" + @person.deleted = false + [@person] + end + + def exception_thrower + raise "Hi, I'm a SOAP error" + end + + def default + @default_args = @method_params + nil + end + end +end + +class TC_ProtocolSoap < AbstractSoapTest + def setup + @delegated_container = ProtocolSoapTest::DelegatedContainer.new + @direct_container = ProtocolSoapTest::DirectContainer.new + end + + def test_argument_passing + in_all_containers do + assert(do_soap_call('ArgumentPassing', 5, "test string", [true, false]) == true) + assert(service.int == 5) + assert(service.string == "test string") + assert(service.array == [true, false]) + end + end + + def test_array_returner + in_all_containers do + assert(do_soap_call('ArrayReturner') == [1, 2, 3]) + assert(service.values == [1, 2, 3]) + end + end + + def test_nil_returner + in_all_containers do + assert(do_soap_call('NilReturner') == nil) + end + end + + def test_struct_array_returner + in_all_containers do + assert(do_soap_call('StructArrayReturner') == [service.person]) + end + end + + def test_exception_thrower + in_all_containers do + assert_raises(RuntimeError) do + do_soap_call('ExceptionThrower') + end + end + end + + def test_default_api_method + in_all_containers do + assert(do_soap_call('NonExistentMethodName', 50, false).nil?) + assert(service.default_args == [50, false]) + end + end + + def test_service_name_setting + in_all_containers do + assert(ProtocolSoapTest::DelegatedContainer.soap_mapper.custom_namespace == 'urn:Test') + end + end + + protected + def service_name + @container == @direct_container ? 'api' : 'protocol_soap_service' + end + + def service + @container == @direct_container ? @container : @container.service_object(:protocol_soap_service) + end + + def in_all_containers(&block) + [@direct_container].each do |container| + @container = container + block.call + end + end + + def do_soap_call(public_method_name, *args) + super(public_method_name, *args) do |test_request, test_response| + protocol_request = @container.protocol_request(test_request) + @container.dispatch_request(protocol_request) + end + end +end diff --git a/actionservice/test/protocol_xmlrpc_test.rb b/actionservice/test/protocol_xmlrpc_test.rb new file mode 100644 index 0000000000..a9cafc0a73 --- /dev/null +++ b/actionservice/test/protocol_xmlrpc_test.rb @@ -0,0 +1,157 @@ +require File.dirname(__FILE__) + '/abstract_unit' +require 'xmlrpc/parser' +require 'xmlrpc/create' +require 'xmlrpc/config' + +module XMLRPC + class XmlRpcTestHelper + include ParserWriterChooseMixin + + def create_request(methodName, *args) + create().methodCall(methodName, *args) + end + + def parse_response(response) + parser().parseMethodResponse(response) + end + end +end + +module ProtocolXmlRpcTest + class Person < ActionService::Struct + member :firstname, String + member :lastname, String + member :active, TrueClass + end + + class API < ActionService::API::Base + api_method :add, :expects => [Integer, Integer], :returns => [Integer] + api_method :hash_returner, :returns => [Hash] + api_method :array_returner, :returns => [[Integer]] + api_method :something_hash, :expects => [Hash] + api_method :struct_array_returner, :returns => [[Person]] + + default_api_method :default + end + + class Service < ActionService::Base + service_api API + + attr :result + attr :hashvalue + attr :default_args + + def initialize + @result = nil + @hashvalue = nil + @default_args = nil + end + + def add(a, b) + @result = a + b + end + + def something_hash(hash) + @hashvalue = hash + end + + def array_returner + [1, 2, 3] + end + + def hash_returner + {'name' => 1, 'value' => 2} + end + + def struct_array_returner + person = Person.new + person.firstname = "John" + person.lastname = "Doe" + person.active = true + [person] + end + + def default(*args) + @default_args = args + nil + end + end + + $service = Service.new + + class Container + include ActionService::Container + include ActionService::Protocol::Registry + include ActionService::Protocol::Soap + include ActionService::Protocol::XmlRpc + + def protocol_request(request) + probe_request_protocol(request) + end + + def dispatch_request(protocol_request) + dispatch_service_request(protocol_request) + end + + service :xmlrpc, $service + service_dispatching_mode :delegated + end +end + +class TC_ProtocolXmlRpc < Test::Unit::TestCase + def setup + @helper = XMLRPC::XmlRpcTestHelper.new + @container = ProtocolXmlRpcTest::Container.new + end + + def test_xmlrpc_request_dispatching + retval = do_xmlrpc_call('Add', 50, 30) + assert(retval == [true, 80]) + end + + def test_array_returning + retval = do_xmlrpc_call('ArrayReturner') + assert(retval == [true, [1, 2, 3]]) + end + + def test_hash_returning + retval = do_xmlrpc_call('HashReturner') + assert(retval == [true, {'name' => 1, 'value' => 2}]) + end + + def test_struct_array_returning + retval = do_xmlrpc_call('StructArrayReturner') + assert(retval == [true, [{"firstname"=>"John", "lastname"=>"Doe", "active"=>true}]]) + end + + def test_hash_parameter + retval = do_xmlrpc_call('SomethingHash', {'name' => 1, 'value' => 2}) + assert(retval == [true, true]) + assert($service.hashvalue == {'name' => 1, 'value' => 2}) + end + + def test_default_api_method + retval = do_xmlrpc_call('SomeNonexistentMethod', 'test', [1, 2], {'name'=>'value'}) + assert(retval == [true, true]) + assert($service.default_args == ['test', [1, 2], {'name'=>'value'}]) + end + + def test_xmlrpc_introspection + retval = do_xmlrpc_call('system.listMethods', 'test', [1, 2], {'name'=>'value'}) + assert(retval == [true, ["Add", "ArrayReturner", "HashReturner", "SomethingHash", "StructArrayReturner"]]) + end + + private + def do_xmlrpc_call(public_method_name, *args) + service_name = 'xmlrpc' + raw_request = @helper.create_request(public_method_name, *args) + test_request = ActionController::TestRequest.new + test_request.request_parameters['action'] = service_name + test_request.env['REQUEST_METHOD'] = "POST" + test_request.env['HTTP_CONTENTTYPE'] = 'text/xml' + test_request.env['RAW_POST_DATA'] = raw_request + protocol_request = @container.protocol_request(test_request) + response = @container.dispatch_request(protocol_request) + @helper.parse_response(response.raw_body) + end +end diff --git a/actionservice/test/router_action_controller_test.rb b/actionservice/test/router_action_controller_test.rb new file mode 100644 index 0000000000..b541b46542 --- /dev/null +++ b/actionservice/test/router_action_controller_test.rb @@ -0,0 +1,139 @@ +require File.dirname(__FILE__) + '/abstract_soap' +require 'wsdl/parser' + +module RouterActionControllerTest + class API < ActionService::API::Base + api_method :add, :expects => [:int, :int], :returns => [:int] + end + + class Service < ActionService::Base + service_api API + + attr :added + + def add(a, b) + @added = a + b + end + end + + class DelegatedController < ActionController::Base + service_dispatching_mode :delegated + + service(:test_service) { @service ||= Service.new; @service } + end + + class DirectAPI < ActionService::API::Base + api_method :add, :expects => [{:a=>:int}, {:b=>:int}], :returns => [:int] + api_method :before_filtered + api_method :after_filtered, :returns => [:int] + api_method :thrower + end + + class DirectController < ActionController::Base + service_api DirectAPI + service_dispatching_mode :direct + + before_filter :alwaysfail, :only => [:before_filtered] + after_filter :alwaysok, :only => [:after_filtered] + + attr :added + attr :before_filter_called + attr :before_filter_target_called + attr :after_filter_called + attr :after_filter_target_called + + def initialize + @before_filter_called = false + @before_filter_target_called = false + @after_filter_called = false + @after_filter_target_called = false + end + + def add + @added = @params['a'] + @params['b'] + end + + def before_filtered + @before_filter_target_called = true + end + + def after_filtered + @after_filter_target_called = true + 5 + end + + def thrower + raise "Hi, I'm a SOAP exception" + end + + protected + def alwaysfail + @before_filter_called = true + false + end + + def alwaysok + @after_filter_called = true + end + end +end + +class TC_RouterActionController < AbstractSoapTest + def test_direct_routing + @container = RouterActionControllerTest::DirectController.new + assert(do_soap_call('Add', 20, 50) == 70) + assert(@container.added == 70) + end + + def test_direct_entrypoint + @container = RouterActionControllerTest::DirectController.new + assert(@container.respond_to?(:api)) + end + + def test_direct_filtering + @container = RouterActionControllerTest::DirectController.new + assert(@container.before_filter_called == false) + assert(@container.before_filter_target_called == false) + assert(do_soap_call('BeforeFiltered').nil?) + assert(@container.before_filter_called == true) + assert(@container.before_filter_target_called == false) + assert(@container.after_filter_called == false) + assert(@container.after_filter_target_called == false) + assert(do_soap_call('AfterFiltered') == 5) + assert(@container.after_filter_called == true) + assert(@container.after_filter_target_called == true) + end + + def test_delegated_routing + @container = RouterActionControllerTest::DelegatedController.new + assert(do_soap_call('Add', 50, 80) == 130) + assert(service.added == 130) + end + + def test_exception_marshaling + @container = RouterActionControllerTest::DirectController.new + result = do_soap_call('Thrower') + exception = result.detail + assert(exception.cause.is_a?(RuntimeError)) + assert_equal("Hi, I'm a SOAP exception", exception.cause.message) + @container.service_exception_reporting = false + assert_raises(SoapTestError) do + do_soap_call('Thrower') + end + end + + protected + def service_name + @container.is_a?(RouterActionControllerTest::DelegatedController) ? 'test_service' : 'api' + end + + def service + @container.service_object(:test_service) + end + + def do_soap_call(public_method_name, *args) + super(public_method_name, *args) do |test_request, test_response| + response = @container.process(test_request, test_response) + end + end +end diff --git a/actionservice/test/router_wsdl_test.rb b/actionservice/test/router_wsdl_test.rb new file mode 100644 index 0000000000..b141d8304b --- /dev/null +++ b/actionservice/test/router_wsdl_test.rb @@ -0,0 +1,100 @@ +require File.dirname(__FILE__) + '/abstract_unit' +require 'wsdl/parser' + +module RouterWsdlTest + class Person < ActionService::Struct + member :id, Integer + member :names, [String] + member :lastname, String + member :deleted, TrueClass + end + + class API < ActionService::API::Base + api_method :add, :expects => [{:a=>:int}, {:b=>:int}], :returns => [:int] + api_method :find_people, :returns => [[Person]] + api_method :nil_returner + end + + class Service < ActionService::Base + service_api API + + def add(a, b) + a + b + end + + def find_people + [] + end + + def nil_returner + end + end + + class AbstractController < ActionController::Base + def generate_wsdl(container, uri, soap_action_base) + to_wsdl(container, uri, soap_action_base) + end + end + + class DirectController < AbstractController + service_api API + + def add + end + + def find_people + end + + def nil_returner + end + end + + class DelegatedController < AbstractController + service_dispatching_mode :delegated + service(:test_service) { Service.new } + end +end + +class TC_RouterWsdl < Test::Unit::TestCase + include RouterWsdlTest + + def test_wsdl_generation + ensure_valid_generation DelegatedController.new + ensure_valid_generation DirectController.new + end + + def + + def test_wsdl_action + ensure_valid_wsdl_action DelegatedController.new + ensure_valid_wsdl_action DirectController.new + end + + protected + def ensure_valid_generation(controller) + wsdl = controller.generate_wsdl(controller, 'http://localhost:3000/test/', '/test') + ensure_valid_wsdl(wsdl) + end + + def ensure_valid_wsdl(wsdl) + definitions = WSDL::Parser.new.parse(wsdl) + assert(definitions.is_a?(WSDL::Definitions)) + definitions.bindings.each do |binding| + assert(binding.name.name.index(':').nil?) + end + definitions.services.each do |service| + service.ports.each do |port| + assert(port.name.name.index(':').nil?) + end + end + end + + def ensure_valid_wsdl_action(controller) + test_request = ActionController::TestRequest.new({ 'action' => 'wsdl' }) + test_request.env['REQUEST_METHOD'] = 'GET' + test_request.env['HTTP_HOST'] = 'localhost:3000' + test_response = ActionController::TestResponse.new + wsdl = controller.process(test_request, test_response).body + ensure_valid_wsdl(wsdl) + end +end diff --git a/actionservice/test/struct_test.rb b/actionservice/test/struct_test.rb new file mode 100644 index 0000000000..b883c6d991 --- /dev/null +++ b/actionservice/test/struct_test.rb @@ -0,0 +1,40 @@ +require File.dirname(__FILE__) + '/abstract_unit' + +module StructTest + class Struct < ActionService::Struct + member :id, Integer + member :name, String + member :items, [String] + member :deleted, :bool + member :emails, [:string] + end +end + +class TC_Struct < Test::Unit::TestCase + def test_members + assert_equal(5, StructTest::Struct.members.size) + assert_equal(Integer, StructTest::Struct.members[:id]) + assert_equal(String, StructTest::Struct.members[:name]) + assert_equal([String], StructTest::Struct.members[:items]) + assert_equal(TrueClass, StructTest::Struct.members[:deleted]) + assert_equal([String], StructTest::Struct.members[:emails]) + end + + def test_initializer_and_lookup + s = StructTest::Struct.new(:id => 5, + :name => 'hello', + :items => ['one', 'two'], + :deleted => true, + :emails => ['test@test.com']) + assert_equal(5, s.id) + assert_equal('hello', s.name) + assert_equal(['one', 'two'], s.items) + assert_equal(true, s.deleted) + assert_equal(['test@test.com'], s.emails) + assert_equal(5, s['id']) + assert_equal('hello', s['name']) + assert_equal(['one', 'two'], s['items']) + assert_equal(true, s['deleted']) + assert_equal(['test@test.com'], s['emails']) + end +end |