aboutsummaryrefslogtreecommitdiffstats
path: root/actionwebservice/test
diff options
context:
space:
mode:
authorDavid Heinemeier Hansson <david@loudthinking.com>2005-02-18 23:43:09 +0000
committerDavid Heinemeier Hansson <david@loudthinking.com>2005-02-18 23:43:09 +0000
commit7a67d0f617db7d2962b6c3b80466e21570b244bf (patch)
tree56fa640e31f4f7f22d34a246bc1b197706a07e3a /actionwebservice/test
parentfdecb6843ba8c5b0f718225f343017e11fa7f711 (diff)
downloadrails-7a67d0f617db7d2962b6c3b80466e21570b244bf.tar.gz
rails-7a67d0f617db7d2962b6c3b80466e21570b244bf.tar.bz2
rails-7a67d0f617db7d2962b6c3b80466e21570b244bf.zip
Renamed Action Service to Action Web Service
git-svn-id: http://svn-commit.rubyonrails.org/rails/trunk@669 5ecf4fe2-1ee6-0310-87b1-e25e094e27de
Diffstat (limited to 'actionwebservice/test')
-rw-r--r--actionwebservice/test/abstract_client.rb124
-rw-r--r--actionwebservice/test/abstract_soap.rb58
-rw-r--r--actionwebservice/test/abstract_unit.rb9
-rw-r--r--actionwebservice/test/api_test.rb52
-rw-r--r--actionwebservice/test/base_test.rb42
-rw-r--r--actionwebservice/test/client_soap_test.rb87
-rw-r--r--actionwebservice/test/client_xmlrpc_test.rb86
-rw-r--r--actionwebservice/test/container_test.rb53
-rw-r--r--actionwebservice/test/invocation_test.rb158
-rw-r--r--actionwebservice/test/protocol_registry_test.rb53
-rw-r--r--actionwebservice/test/protocol_soap_test.rb226
-rw-r--r--actionwebservice/test/protocol_xmlrpc_test.rb157
-rw-r--r--actionwebservice/test/router_action_controller_test.rb139
-rw-r--r--actionwebservice/test/router_wsdl_test.rb100
-rw-r--r--actionwebservice/test/struct_test.rb40
15 files changed, 1384 insertions, 0 deletions
diff --git a/actionwebservice/test/abstract_client.rb b/actionwebservice/test/abstract_client.rb
new file mode 100644
index 0000000000..70d2d21124
--- /dev/null
+++ b/actionwebservice/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
+ web_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_web_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/actionwebservice/test/abstract_soap.rb b/actionwebservice/test/abstract_soap.rb
new file mode 100644
index 0000000000..7454be9bdf
--- /dev/null
+++ b/actionwebservice/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/actionwebservice/test/abstract_unit.rb b/actionwebservice/test/abstract_unit.rb
new file mode 100644
index 0000000000..54ca73b35c
--- /dev/null
+++ b/actionwebservice/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/actionwebservice/test/api_test.rb b/actionwebservice/test/api_test.rb
new file mode 100644
index 0000000000..2ef5cc7bda
--- /dev/null
+++ b/actionwebservice/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/actionwebservice/test/base_test.rb b/actionwebservice/test/base_test.rb
new file mode 100644
index 0000000000..a9fbdd1a8b
--- /dev/null
+++ b/actionwebservice/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
+ web_service_api API
+
+ def add(a, b)
+ end
+
+ def void
+ end
+ end
+
+ class PristineService < ActionService::Base
+ web_service_api PristineAPI
+
+ def add
+ end
+
+ def under_score
+ end
+ end
+end
+
+class TC_Base < Test::Unit::TestCase
+ def test_options
+ assert(BaseTest::PristineService.web_service_api.inflect_names == false)
+ assert(BaseTest::Service.web_service_api.inflect_names == true)
+ end
+end
diff --git a/actionwebservice/test/client_soap_test.rb b/actionwebservice/test/client_soap_test.rb
new file mode 100644
index 0000000000..80fae90543
--- /dev/null
+++ b/actionwebservice/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
+ web_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/actionwebservice/test/client_xmlrpc_test.rb b/actionwebservice/test/client_xmlrpc_test.rb
new file mode 100644
index 0000000000..35768adf32
--- /dev/null
+++ b/actionwebservice/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
+ web_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/actionwebservice/test/container_test.rb b/actionwebservice/test/container_test.rb
new file mode 100644
index 0000000000..8c66651b64
--- /dev/null
+++ b/actionwebservice/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
+ web_service_dispatching_mode :delegated
+
+ attr :flag
+ attr :previous_flag
+
+ def initialize
+ @previous_flag = nil
+ @flag = true
+ end
+
+ web_service :immediate_service, $immediate_service
+ web_service(:deferred_service) { @previous_flag = @flag; @flag = false; $deferred_service }
+ end
+
+ class DirectContainer < ActionController::Base
+ web_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_web_service?(:immediate_service))
+ assert(ContainerTest::DelegateContainer.has_web_service?(:deferred_service))
+ assert(!ContainerTest::DelegateContainer.has_web_service?(:fake_service))
+ end
+
+ def test_service_object
+ assert(@delegate_container.flag == true)
+ assert(@delegate_container.web_service_object(:immediate_service) == $immediate_service)
+ assert(@delegate_container.previous_flag.nil?)
+ assert(@delegate_container.flag == true)
+ assert(@delegate_container.web_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.web_service_dispatching_mode == :direct)
+ end
+end
diff --git a/actionwebservice/test/invocation_test.rb b/actionwebservice/test/invocation_test.rb
new file mode 100644
index 0000000000..e4c82a35f8
--- /dev/null
+++ b/actionwebservice/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
+ web_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.web_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/actionwebservice/test/protocol_registry_test.rb b/actionwebservice/test/protocol_registry_test.rb
new file mode 100644
index 0000000000..8e2b9659a6
--- /dev/null
+++ b/actionwebservice/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/actionwebservice/test/protocol_soap_test.rb b/actionwebservice/test/protocol_soap_test.rb
new file mode 100644
index 0000000000..164d06bbd6
--- /dev/null
+++ b/actionwebservice/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
+ web_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_web_service_request(protocol_request)
+ end
+ end
+
+ class DelegatedContainer < AbstractContainer
+ web_service_dispatching_mode :delegated
+ web_service :protocol_soap_service, Service.new
+ end
+
+ class DirectContainer < AbstractContainer
+ web_service_api API
+ web_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.web_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/actionwebservice/test/protocol_xmlrpc_test.rb b/actionwebservice/test/protocol_xmlrpc_test.rb
new file mode 100644
index 0000000000..a8a6efc07e
--- /dev/null
+++ b/actionwebservice/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
+ web_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_web_service_request(protocol_request)
+ end
+
+ web_service :xmlrpc, $service
+ web_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/actionwebservice/test/router_action_controller_test.rb b/actionwebservice/test/router_action_controller_test.rb
new file mode 100644
index 0000000000..e26d67c194
--- /dev/null
+++ b/actionwebservice/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
+ web_service_api API
+
+ attr :added
+
+ def add(a, b)
+ @added = a + b
+ end
+ end
+
+ class DelegatedController < ActionController::Base
+ web_service_dispatching_mode :delegated
+
+ web_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
+ web_service_api DirectAPI
+ web_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.web_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.web_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/actionwebservice/test/router_wsdl_test.rb b/actionwebservice/test/router_wsdl_test.rb
new file mode 100644
index 0000000000..6812d25579
--- /dev/null
+++ b/actionwebservice/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
+ web_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
+ web_service_api API
+
+ def add
+ end
+
+ def find_people
+ end
+
+ def nil_returner
+ end
+ end
+
+ class DelegatedController < AbstractController
+ web_service_dispatching_mode :delegated
+ web_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/actionwebservice/test/struct_test.rb b/actionwebservice/test/struct_test.rb
new file mode 100644
index 0000000000..b883c6d991
--- /dev/null
+++ b/actionwebservice/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