From 6f5a7b200443baf209d2f33c428ed4a4059782f7 Mon Sep 17 00:00:00 2001 From: Leon Breedt Date: Fri, 25 Feb 2005 23:39:39 +0000 Subject: merged the changes for the upcoming 0.6.0: seperate out protocol marshaling into a small 'ws' library in vendor, so that AWS itself only does integration with ActionPack, and so we can keep protocol specific code in AWS proper to a minimum. refactor unit tests to get 95% code coverage (for a baseline). be far more relaxed about the types given to us by the remote side, don't do any poor man's type checking, just try to cast and marshal to the correct types if possible, and if not, return what they gave us anyway. this should make interoperating with fuzzy XML-RPC clients easier. if exception reporting is turned on, do best-effort error responses, so that we can avoid "Internal protocol error" with no details if there is a bug in AWS itself. also perform extensive cleanups on AWS proper. git-svn-id: http://svn-commit.rubyonrails.org/rails/trunk@800 5ecf4fe2-1ee6-0310-87b1-e25e094e27de --- actionwebservice/test/abstract_client.rb | 19 +- actionwebservice/test/abstract_dispatcher.rb | 294 +++++++++++++++++++++ actionwebservice/test/abstract_soap.rb | 58 ---- actionwebservice/test/abstract_unit.rb | 1 + actionwebservice/test/api_test.rb | 15 +- actionwebservice/test/apis/auto_load_api.rb | 3 + actionwebservice/test/apis/broken_auto_load_api.rb | 2 + actionwebservice/test/client_soap_test.rb | 19 +- actionwebservice/test/client_xmlrpc_test.rb | 20 +- actionwebservice/test/container_test.rb | 36 ++- .../test/dispatcher_action_controller_soap_test.rb | 93 +++++++ .../test/dispatcher_action_controller_test.rb | 186 ------------- .../dispatcher_action_controller_xmlrpc_test.rb | 35 +++ actionwebservice/test/gencov | 2 +- actionwebservice/test/invocation_test.rb | 42 ++- actionwebservice/test/protocol_registry_test.rb | 53 ---- actionwebservice/test/protocol_soap_test.rb | 252 ------------------ actionwebservice/test/protocol_xmlrpc_test.rb | 147 ----------- actionwebservice/test/run | 8 +- actionwebservice/test/ws/abstract_encoding.rb | 68 +++++ actionwebservice/test/ws/abstract_unit.rb | 14 + actionwebservice/test/ws/gencov | 3 + actionwebservice/test/ws/run | 5 + actionwebservice/test/ws/soap_marshaling_test.rb | 91 +++++++ actionwebservice/test/ws/soap_rpc_encoding_test.rb | 47 ++++ actionwebservice/test/ws/types_test.rb | 41 +++ actionwebservice/test/ws/xmlrpc_encoding_test.rb | 34 +++ 27 files changed, 857 insertions(+), 731 deletions(-) create mode 100644 actionwebservice/test/abstract_dispatcher.rb delete mode 100644 actionwebservice/test/abstract_soap.rb create mode 100644 actionwebservice/test/apis/auto_load_api.rb create mode 100644 actionwebservice/test/apis/broken_auto_load_api.rb create mode 100644 actionwebservice/test/dispatcher_action_controller_soap_test.rb delete mode 100644 actionwebservice/test/dispatcher_action_controller_test.rb create mode 100644 actionwebservice/test/dispatcher_action_controller_xmlrpc_test.rb delete mode 100644 actionwebservice/test/protocol_registry_test.rb delete mode 100644 actionwebservice/test/protocol_soap_test.rb delete mode 100644 actionwebservice/test/protocol_xmlrpc_test.rb create mode 100644 actionwebservice/test/ws/abstract_encoding.rb create mode 100644 actionwebservice/test/ws/abstract_unit.rb create mode 100755 actionwebservice/test/ws/gencov create mode 100755 actionwebservice/test/ws/run create mode 100644 actionwebservice/test/ws/soap_marshaling_test.rb create mode 100644 actionwebservice/test/ws/soap_rpc_encoding_test.rb create mode 100644 actionwebservice/test/ws/types_test.rb create mode 100644 actionwebservice/test/ws/xmlrpc_encoding_test.rb (limited to 'actionwebservice/test') diff --git a/actionwebservice/test/abstract_client.rb b/actionwebservice/test/abstract_client.rb index 88f886f05f..0efa1d7ec1 100644 --- a/actionwebservice/test/abstract_client.rb +++ b/actionwebservice/test/abstract_client.rb @@ -20,6 +20,7 @@ module ClientTest api_method :struct_pass, :expects => [[Person]], :returns => [:bool] api_method :client_container, :returns => [:int] api_method :named_parameters, :expects => [{:key=>:string}, {:id=>:int}] + api_method :thrower end class NullLogOut @@ -29,11 +30,11 @@ module ClientTest class Container < ActionController::Base web_service_api API - attr :value_void - attr :value_normal - attr :value_array_return - attr :value_struct_pass - attr :value_named_parameters + attr_accessor :value_void + attr_accessor :value_normal + attr_accessor :value_array_return + attr_accessor :value_struct_pass + attr_accessor :value_named_parameters def initialize @session = @assigns = {} @@ -73,12 +74,8 @@ module ClientTest @value_named_parameters = @method_params end - def protocol_request(request) - probe_request_protocol(request) - end - - def dispatch_request(protocol_request) - dispatch_protocol_request(protocol_request) + def thrower + raise "Hi" end end diff --git a/actionwebservice/test/abstract_dispatcher.rb b/actionwebservice/test/abstract_dispatcher.rb new file mode 100644 index 0000000000..b743afce4c --- /dev/null +++ b/actionwebservice/test/abstract_dispatcher.rb @@ -0,0 +1,294 @@ +require File.dirname(__FILE__) + '/abstract_unit' + +module DispatcherTest + class Node < ActiveRecord::Base + def initialize(*args) + super(*args) + @new_record = false + end + + class << self + def name + "Node" + end + + def columns(*args) + [ + ActiveRecord::ConnectionAdapters::Column.new('id', 0, 'int'), + ActiveRecord::ConnectionAdapters::Column.new('name', nil, 'string'), + ActiveRecord::ConnectionAdapters::Column.new('description', nil, 'string'), + ] + end + + def connection + self + end + end + end + + class API < ActionWebService::API::Base + api_method :add, :expects => [:int, :int], :returns => [:int] + api_method :interceptee + api_method :struct_return, :returns => [[Node]] + api_method :void + end + + class DirectAPI < ActionWebService::API::Base + api_method :add, :expects => [{:a=>:int}, {:b=>:int}], :returns => [:int] + api_method :before_filtered + api_method :after_filtered, :returns => [[:int]] + api_method :struct_return, :returns => [[Node]] + api_method :thrower + api_method :void + end + + class Service < ActionWebService::Base + web_service_api API + + before_invocation :do_intercept, :only => [:interceptee] + + attr :added + attr :intercepted + attr :void_called + + def initialize + @void_called = false + end + + def add(a, b) + @added = a + b + end + + def interceptee + @intercepted = false + end + + def struct_return + n1 = Node.new('id' => 1, 'name' => 'node1', 'description' => 'Node 1') + n2 = Node.new('id' => 2, 'name' => 'node2', 'description' => 'Node 2') + [n1, n2] + end + + def void(*args) + @void_called = args + end + + def do_intercept(name, args) + [false, "permission denied"] + end + end + + class AbstractController < ActionController::Base + def generate_wsdl + to_wsdl + end + end + + class DelegatedController < AbstractController + web_service_dispatching_mode :delegated + + web_service(:test_service) { @service ||= Service.new; @service } + end + + class DirectController < AbstractController + 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 + attr :void_called + + def initialize + @before_filter_called = false + @before_filter_target_called = false + @after_filter_called = false + @after_filter_target_called = false + @void_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, 6, 7] + end + + def thrower + raise "Hi, I'm an exception" + end + + def struct_return + n1 = Node.new('id' => 1, 'name' => 'node1', 'description' => 'Node 1') + n2 = Node.new('id' => 2, 'name' => 'node2', 'description' => 'Node 2') + [n1, n2] + end + + def void + @void_called = @method_params + end + + protected + def alwaysfail + @before_filter_called = true + false + end + + def alwaysok + @after_filter_called = true + end + end +end + +module DispatcherCommonTests + def test_direct_dispatching + assert_equal(70, do_method_call(@direct_controller, 'Add', 20, 50)) + assert_equal(70, @direct_controller.added) + assert(@direct_controller.void_called == false) + case @encoder + when WS::Encoding::SoapRpcEncoding + assert(do_method_call(@direct_controller, 'Void', 3, 4, 5).nil?) + when WS::Encoding::XmlRpcEncoding + assert(do_method_call(@direct_controller, 'Void', 3, 4, 5) == true) + end + assert(@direct_controller.void_called == []) + end + + def test_direct_entrypoint + assert(@direct_controller.respond_to?(:api)) + end + + def test_direct_filtering + assert_equal(false, @direct_controller.before_filter_called) + assert_equal(false, @direct_controller.before_filter_target_called) + do_method_call(@direct_controller, 'BeforeFiltered') + assert_equal(true, @direct_controller.before_filter_called) + assert_equal(false, @direct_controller.before_filter_target_called) + assert_equal(false, @direct_controller.after_filter_called) + assert_equal(false, @direct_controller.after_filter_target_called) + assert_equal([5, 6, 7], do_method_call(@direct_controller, 'AfterFiltered')) + assert_equal(true, @direct_controller.after_filter_called) + assert_equal(true, @direct_controller.after_filter_target_called) + end + + def test_delegated_dispatching + assert_equal(130, do_method_call(@delegated_controller, 'Add', 50, 80)) + service = @delegated_controller.web_service_object(:test_service) + assert_equal(130, service.added) + @delegated_controller.web_service_exception_reporting = true + assert(service.intercepted.nil?) + result = do_method_call(@delegated_controller, 'Interceptee') + assert(service.intercepted.nil?) + assert(is_exception?(result)) + assert_match(/permission denied/, exception_message(result)) + result = do_method_call(@delegated_controller, 'NonExistentMethod') + assert(is_exception?(result)) + assert_match(/NonExistentMethod/, exception_message(result)) + assert(service.void_called == false) + case @encoder + when WS::Encoding::SoapRpcEncoding + assert(do_method_call(@delegated_controller, 'Void', 3, 4, 5).nil?) + when WS::Encoding::XmlRpcEncoding + assert(do_method_call(@delegated_controller, 'Void', 3, 4, 5) == true) + end + assert(service.void_called == []) + end + + def test_garbage_request + [@direct_controller, @delegated_controller].each do |controller| + controller.class.web_service_exception_reporting = true + send_garbage_request = lambda do + request = create_ap_request(controller, 'invalid request body', 'xxx') + response = ActionController::TestResponse.new + controller.process(request, response) + # puts response.body + assert(response.headers['Status'] =~ /^500/) + end + send_garbage_request.call + controller.class.web_service_exception_reporting = false + send_garbage_request.call + end + end + + def test_exception_marshaling + @direct_controller.web_service_exception_reporting = true + result = do_method_call(@direct_controller, 'Thrower') + assert(is_exception?(result)) + assert_equal("Hi, I'm an exception", exception_message(result)) + @direct_controller.web_service_exception_reporting = false + result = do_method_call(@direct_controller, 'Thrower') + assert(exception_message(result) != "Hi, I'm an exception") + end + + def test_ar_struct_return + [@direct_controller, @delegated_controller].each do |controller| + result = do_method_call(controller, 'StructReturn') + case @encoder + when WS::Encoding::SoapRpcEncoding + assert(result[0].is_a?(DispatcherTest::Node)) + assert(result[1].is_a?(DispatcherTest::Node)) + assert_equal('node1', result[0].name) + assert_equal('node2', result[1].name) + when WS::Encoding::XmlRpcEncoding + assert(result[0].is_a?(Hash)) + assert(result[1].is_a?(Hash)) + assert_equal('node1', result[0]['name']) + assert_equal('node2', result[1]['name']) + end + end + end + + protected + def service_name(container) + raise NotImplementedError + end + + def exception_message(obj) + raise NotImplementedError + end + + def is_exception?(obj) + raise NotImplementedError + end + + def do_method_call(container, public_method_name, *params) + mode = container.web_service_dispatching_mode + case mode + when :direct + api = container.class.web_service_api + when :delegated + api = container.web_service_object(service_name(container)).class.web_service_api + end + method_name = api.api_method_name(public_method_name) + info = api.api_methods[method_name] || {} + params = params.dup + ((info[:expects] || []) + (info[:returns] || [])).each do |spec| + @marshaler.register_type(spec) + end + expects = info[:expects] + (0..(params.length-1)).each do |i| + type_binding = @marshaler.register_type(expects ? expects[i] : params[i].class) + info = WS::ParamInfo.create(expects ? expects[i] : params[i].class, i, type_binding) + params[i] = @marshaler.marshal(WS::Param.new(params[i], info)) + end + body = @encoder.encode_rpc_call(public_method_name, params) + # puts body + ap_request = create_ap_request(container, body, public_method_name, *params) + ap_response = ActionController::TestResponse.new + container.process(ap_request, ap_response) + # puts ap_response.body + public_method_name, return_value = @encoder.decode_rpc_response(ap_response.body) + @marshaler.unmarshal(return_value).value + end +end diff --git a/actionwebservice/test/abstract_soap.rb b/actionwebservice/test/abstract_soap.rb deleted file mode 100644 index 351a4f8479..0000000000 --- a/actionwebservice/test/abstract_soap.rb +++ /dev/null @@ -1,58 +0,0 @@ -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:ActionWebService', 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 index e33c5c9bbe..e8304e3790 100644 --- a/actionwebservice/test/abstract_unit.rb +++ b/actionwebservice/test/abstract_unit.rb @@ -1,4 +1,5 @@ $:.unshift(File.dirname(__FILE__) + '/../lib') +$:.unshift(File.dirname(__FILE__) + '/../lib/action_web_service/vendor') require 'test/unit' require 'action_web_service' diff --git a/actionwebservice/test/api_test.rb b/actionwebservice/test/api_test.rb index b61a4b57c5..a84726f0b5 100644 --- a/actionwebservice/test/api_test.rb +++ b/actionwebservice/test/api_test.rb @@ -41,7 +41,7 @@ class TC_API < Test::Unit::TestCase 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]) + assert_equal({:expects=>[TrueClass, Integer, String], :returns=>nil}, API.api_methods[:class_types]) end def test_not_instantiable @@ -49,4 +49,17 @@ class TC_API < Test::Unit::TestCase API.new end end + + def test_api_errors + assert_raises(ActionWebService::ActionWebServiceError) do + klass = Class.new(ActionWebService::API::Base) do + api_method :test, :expects => [ActiveRecord::Base] + end + end + assert_raises(ActionWebService::ActionWebServiceError) do + klass = Class.new(ActionWebService::API::Base) do + api_method :test, :invalid => [:int] + end + end + end end diff --git a/actionwebservice/test/apis/auto_load_api.rb b/actionwebservice/test/apis/auto_load_api.rb new file mode 100644 index 0000000000..a35bbe3ff7 --- /dev/null +++ b/actionwebservice/test/apis/auto_load_api.rb @@ -0,0 +1,3 @@ +class AutoLoadAPI < ActionWebService::API::Base + api_method :void +end diff --git a/actionwebservice/test/apis/broken_auto_load_api.rb b/actionwebservice/test/apis/broken_auto_load_api.rb new file mode 100644 index 0000000000..139597f9cb --- /dev/null +++ b/actionwebservice/test/apis/broken_auto_load_api.rb @@ -0,0 +1,2 @@ + + diff --git a/actionwebservice/test/client_soap_test.rb b/actionwebservice/test/client_soap_test.rb index 5d62b05c82..94a4f24c26 100644 --- a/actionwebservice/test/client_soap_test.rb +++ b/actionwebservice/test/client_soap_test.rb @@ -12,10 +12,10 @@ module ClientSoapTest 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) + response = ActionController::TestResponse.new + @controller.process(test_request, response) res.header['content-type'] = 'text/xml' - res.body = response.raw_body + res.body = response.body rescue Exception => e $stderr.puts e.message $stderr.puts e.backtrace.join("\n") @@ -24,10 +24,15 @@ module ClientSoapTest class ClientContainer < ActionController::Base web_client_api :client, :soap, "http://localhost:#{PORT}/client/api", :api => ClientTest::API + web_client_api :invalid, :null, "", :api => true def get_client client end + + def get_invalid + invalid + end end class SoapServer < ClientTest::AbstractServer @@ -83,6 +88,7 @@ class TC_ClientSoap < Test::Unit::TestCase def test_client_container assert_equal(50, ClientContainer.new.get_client.client_container) + assert(ClientContainer.new.get_invalid.nil?) end def test_named_parameters @@ -90,4 +96,11 @@ class TC_ClientSoap < Test::Unit::TestCase assert(@client.named_parameters("key", 5).nil?) assert_equal(["key", 5], @container.value_named_parameters) end + + def test_capitalized_method_name + @container.value_normal = nil + assert_equal(5, @client.Normal(5, 6)) + assert_equal([5, 6], @container.value_normal) + @container.value_normal = nil + end end diff --git a/actionwebservice/test/client_xmlrpc_test.rb b/actionwebservice/test/client_xmlrpc_test.rb index cd393fbad6..53b6de51e1 100644 --- a/actionwebservice/test/client_xmlrpc_test.rb +++ b/actionwebservice/test/client_xmlrpc_test.rb @@ -9,12 +9,12 @@ module ClientXmlRpcTest 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_CONTENT_TYPE'] = 'text/xml' test_request.env['RAW_POST_DATA'] = req.body - protocol_request = @controller.protocol_request(test_request) - response = @controller.dispatch_request(protocol_request) + response = ActionController::TestResponse.new + @controller.process(test_request, response) res.header['content-type'] = 'text/xml' - res.body = response.raw_body + res.body = response.body rescue Exception => e $stderr.puts e.message $stderr.puts e.backtrace.join("\n") @@ -89,4 +89,16 @@ class TC_ClientXmlRpc < Test::Unit::TestCase assert_equal(true, @client.named_parameters("xxx", 7)) assert_equal(["xxx", 7], @container.value_named_parameters) end + + def test_exception + assert_raises(ActionWebService::Client::ClientError) do + assert(@client.thrower) + end + end + + def test_invalid_signature + assert_raises(ActionWebService::Client::ClientError) do + @client.normal + end + end end diff --git a/actionwebservice/test/container_test.rb b/actionwebservice/test/container_test.rb index 8c66651b64..325d420f24 100644 --- a/actionwebservice/test/container_test.rb +++ b/actionwebservice/test/container_test.rb @@ -1,7 +1,6 @@ require File.dirname(__FILE__) + '/abstract_unit' module ContainerTest - $immediate_service = Object.new $deferred_service = Object.new @@ -22,22 +21,34 @@ module ContainerTest class DirectContainer < ActionController::Base web_service_dispatching_mode :direct - end + end + + class InvalidContainer + include ActionWebService::Container::Direct + end end class TC_Container < Test::Unit::TestCase + include ContainerTest + def setup - @delegate_container = ContainerTest::DelegateContainer.new - @direct_container = ContainerTest::DirectContainer.new + @delegate_container = DelegateContainer.new + @direct_container = 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)) + assert(DelegateContainer.has_web_service?(:immediate_service)) + assert(DelegateContainer.has_web_service?(:deferred_service)) + assert(!DelegateContainer.has_web_service?(:fake_service)) + assert_raises(ActionWebService::Container::Delegated::ContainerError) do + DelegateContainer.web_service('invalid') + end end def test_service_object + assert_raises(ActionWebService::Container::Delegated::ContainerError) do + @delegate_container.web_service_object(:nonexistent) + end assert(@delegate_container.flag == true) assert(@delegate_container.web_service_object(:immediate_service) == $immediate_service) assert(@delegate_container.previous_flag.nil?) @@ -48,6 +59,15 @@ class TC_Container < Test::Unit::TestCase end def test_direct_container - assert(ContainerTest::DirectContainer.web_service_dispatching_mode == :direct) + assert(DirectContainer.web_service_dispatching_mode == :direct) + end + + def test_validity + assert_raises(ActionWebService::Container::Direct::ContainerError) do + InvalidContainer.web_service_api :test + end + assert_raises(ActionWebService::Container::Direct::ContainerError) do + InvalidContainer.web_service_api 50.0 + end end end diff --git a/actionwebservice/test/dispatcher_action_controller_soap_test.rb b/actionwebservice/test/dispatcher_action_controller_soap_test.rb new file mode 100644 index 0000000000..9cb99be78d --- /dev/null +++ b/actionwebservice/test/dispatcher_action_controller_soap_test.rb @@ -0,0 +1,93 @@ +$:.unshift(File.dirname(__FILE__) + '/apis') +require File.dirname(__FILE__) + '/abstract_dispatcher' +require 'wsdl/parser' + +class AutoLoadController < ActionController::Base; end +class FailingAutoLoadController < ActionController::Base; end +class BrokenAutoLoadController < ActionController::Base; end + +class TC_DispatcherActionControllerSoap < Test::Unit::TestCase + include DispatcherTest + include DispatcherCommonTests + + def setup + @encoder = WS::Encoding::SoapRpcEncoding.new + @marshaler = WS::Marshaling::SoapMarshaler.new + @direct_controller = DirectController.new + @delegated_controller = DelegatedController.new + end + + def test_wsdl_generation + ensure_valid_wsdl_generation DelegatedController.new + ensure_valid_wsdl_generation DirectController.new + end + + def test_wsdl_action + ensure_valid_wsdl_action DelegatedController.new + ensure_valid_wsdl_action DirectController.new + end + + def test_autoloading + assert(!AutoLoadController.web_service_api.nil?) + assert(AutoLoadController.web_service_api.has_public_api_method?('Void')) + assert(FailingAutoLoadController.web_service_api.nil?) + assert_raises(LoadError, NameError) do + FailingAutoLoadController.require_web_service_api :blah + end + assert_raises(ArgumentError) do + FailingAutoLoadController.require_web_service_api 50.0 + end + assert(BrokenAutoLoadController.web_service_api.nil?) + end + + protected + def exception_message(soap_fault_exception) + soap_fault_exception.detail.cause.message + end + + def is_exception?(obj) + obj.respond_to?(:detail) && obj.detail.respond_to?(:cause) && \ + obj.detail.cause.is_a?(Exception) + end + + def create_ap_request(container, body, public_method_name, *args) + test_request = ActionController::TestRequest.new + test_request.request_parameters['action'] = service_name(container) + test_request.env['REQUEST_METHOD'] = "POST" + test_request.env['HTTP_CONTENTTYPE'] = 'text/xml' + test_request.env['HTTP_SOAPACTION'] = "/soap/#{service_name(container)}/#{public_method_name}" + test_request.env['RAW_POST_DATA'] = body + test_request + end + + def service_name(container) + container.is_a?(DelegatedController) ? 'test_service' : 'api' + end + + def ensure_valid_wsdl_generation(controller) + wsdl = controller.generate_wsdl + 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/dispatcher_action_controller_test.rb b/actionwebservice/test/dispatcher_action_controller_test.rb deleted file mode 100644 index 11ab21c6a6..0000000000 --- a/actionwebservice/test/dispatcher_action_controller_test.rb +++ /dev/null @@ -1,186 +0,0 @@ -require File.dirname(__FILE__) + '/abstract_soap' -require 'wsdl/parser' - -module DispatcherActionControllerTest - class API < ActionWebService::API::Base - api_method :add, :expects => [:int, :int], :returns => [:int] - end - - class DirectAPI < ActionWebService::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 Service < ActionWebService::Base - web_service_api API - - attr :added - - def add(a, b) - @added = a + b - end - end - - class AbstractController < ActionController::Base - def generate_wsdl(container, uri, soap_action_base) - to_wsdl(container, uri, soap_action_base) - end - end - - class DelegatedController < AbstractController - web_service_dispatching_mode :delegated - - web_service(:test_service) { @service ||= Service.new; @service } - end - - class DirectController < AbstractController - 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_DispatcherActionController < AbstractSoapTest - include DispatcherActionControllerTest - - def test_direct_dispatching - @container = DirectController.new - assert(do_soap_call('Add', 20, 50) == 70) - assert(@container.added == 70) - end - - def test_direct_entrypoint - @container = DirectController.new - assert(@container.respond_to?(:api)) - end - - def test_direct_filtering - @container = 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_dispatching - @container = DelegatedController.new - assert(do_soap_call('Add', 50, 80) == 130) - assert(service.added == 130) - end - - def test_exception_marshaling - @container = 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 - - def test_wsdl_generation - ensure_valid_wsdl_generation DelegatedController.new - ensure_valid_wsdl_generation DirectController.new - end - - def - - def test_wsdl_action - ensure_valid_wsdl_action DelegatedController.new - ensure_valid_wsdl_action DirectController.new - end - - protected - def service_name - @container.is_a?(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 - - def ensure_valid_wsdl_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/dispatcher_action_controller_xmlrpc_test.rb b/actionwebservice/test/dispatcher_action_controller_xmlrpc_test.rb new file mode 100644 index 0000000000..13f193e2c5 --- /dev/null +++ b/actionwebservice/test/dispatcher_action_controller_xmlrpc_test.rb @@ -0,0 +1,35 @@ +require File.dirname(__FILE__) + '/abstract_dispatcher' + +class TC_DispatcherActionControllerXmlRpc < Test::Unit::TestCase + include DispatcherTest + include DispatcherCommonTests + + def setup + @encoder = WS::Encoding::XmlRpcEncoding.new + @marshaler = WS::Marshaling::XmlRpcMarshaler.new + @direct_controller = DirectController.new + @delegated_controller = DelegatedController.new + end + + protected + def exception_message(xmlrpc_fault_exception) + xmlrpc_fault_exception.faultString + end + + def is_exception?(obj) + obj.is_a?(XMLRPC::FaultException) + end + + def create_ap_request(container, body, public_method_name, *args) + test_request = ActionController::TestRequest.new + test_request.request_parameters['action'] = service_name(container) + test_request.env['REQUEST_METHOD'] = "POST" + test_request.env['HTTP_CONTENTTYPE'] = 'text/xml' + test_request.env['RAW_POST_DATA'] = body + test_request + end + + def service_name(container) + container.is_a?(DelegatedController) ? 'test_service' : 'api' + end +end diff --git a/actionwebservice/test/gencov b/actionwebservice/test/gencov index 144233107a..1faab34c07 100755 --- a/actionwebservice/test/gencov +++ b/actionwebservice/test/gencov @@ -1,3 +1,3 @@ #!/bin/sh -rcov -x '.*_test\.rb,rubygems,abstract_,/run' ./run +rcov -x '.*_test\.rb,rubygems,abstract_,/run,/apis' ./run diff --git a/actionwebservice/test/invocation_test.rb b/actionwebservice/test/invocation_test.rb index 0d519bf770..22752fefaf 100644 --- a/actionwebservice/test/invocation_test.rb +++ b/actionwebservice/test/invocation_test.rb @@ -12,23 +12,46 @@ module InvocationTest api_method :only_two end + class Interceptor + attr :args + + def initialize + @args = nil + end + + def intercept(*args) + @args = args + end + end + + InterceptorClass = Interceptor.new + class Service < ActionWebService::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] + prepend_after_invocation :intercept_after_first, :except => [:no_after] + prepend_before_invocation :intercept_only, :only => [:only_one, :only_two] + after_invocation(:only => [:only_one]) do |*args| + args[0].instance_variable_set('@block_invoked', args[1]) + end + after_invocation InterceptorClass, :only => [:only_one] attr_accessor :before_invoked attr_accessor :after_invoked + attr_accessor :after_first_invoked attr_accessor :only_invoked + attr_accessor :block_invoked attr_accessor :invocation_result def initialize @before_invoked = nil @after_invoked = nil + @after_first_invoked = nil @only_invoked = nil @invocation_result = nil + @block_invoked = nil end def add(a, b) @@ -69,6 +92,10 @@ module InvocationTest @after_invoked = name @invocation_result = result end + + def intercept_after_first(name, args, result) + @after_first_invoked = name + end def intercept_only(name, args) raise "Interception error" unless name == :only_one || name == :only_two @@ -94,11 +121,17 @@ class TC_Invocation < Test::Unit::TestCase def test_interceptor_registration assert(InvocationTest::Service.before_invocation_interceptors.length == 2) - assert(InvocationTest::Service.after_invocation_interceptors.length == 1) + assert(InvocationTest::Service.after_invocation_interceptors.length == 4) + assert_equal(:intercept_only, InvocationTest::Service.before_invocation_interceptors[0]) + assert_equal(:intercept_after_first, InvocationTest::Service.after_invocation_interceptors[0]) end def test_interception - assert(@service.before_invoked.nil? && @service.after_invoked.nil? && @service.only_invoked.nil? && @service.invocation_result.nil?) + assert(@service.before_invoked.nil?) + assert(@service.after_invoked.nil?) + assert(@service.only_invoked.nil?) + assert(@service.block_invoked.nil?) + assert(@service.invocation_result.nil?) perform_invocation(:add, 20, 50) assert(@service.before_invoked == :add) assert(@service.after_invoked == :add) @@ -124,6 +157,7 @@ class TC_Invocation < Test::Unit::TestCase def test_interception_except_conditions perform_invocation(:no_before) assert(@service.before_invoked.nil?) + assert(@service.after_first_invoked == :no_before) assert(@service.after_invoked == :no_before) assert(@service.invocation_result == 5) @service.before_invoked = @service.after_invoked = @service.invocation_result = nil @@ -137,6 +171,8 @@ class TC_Invocation < Test::Unit::TestCase assert(@service.only_invoked.nil?) perform_invocation(:only_one) assert(@service.only_invoked == :only_one) + assert(@service.block_invoked == :only_one) + assert(InvocationTest::InterceptorClass.args[1] == :only_one) @service.only_invoked = nil perform_invocation(:only_two) assert(@service.only_invoked == :only_two) diff --git a/actionwebservice/test/protocol_registry_test.rb b/actionwebservice/test/protocol_registry_test.rb deleted file mode 100644 index 261f6f400e..0000000000 --- a/actionwebservice/test/protocol_registry_test.rb +++ /dev/null @@ -1,53 +0,0 @@ -require File.dirname(__FILE__) + '/abstract_unit' - - -module Foo - include ActionWebService::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 - ActionWebService::Protocol::ProtocolRequest.new(protocol, '', '', '', '') - end - end - - class FooMinimalProtocol < AbstractProtocol - def self.create_protocol_request(klass, request) - protocol = FooMinimalProtocol.new klass - ActionWebService::Protocol::ProtocolRequest.new(protocol, '', '', '', '') - end - end - - class FooMinimalProtocolTwo < AbstractProtocol - end -end - -class ProtocolRegistry - include ActionWebService::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 deleted file mode 100644 index c55b7f55af..0000000000 --- a/actionwebservice/test/protocol_soap_test.rb +++ /dev/null @@ -1,252 +0,0 @@ -require File.dirname(__FILE__) + '/abstract_soap' - -module ProtocolSoapTest - class Person < ActionWebService::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 EmptyAPI < ActionWebService::API::Base - end - - class EmptyService < ActionWebService::Base - web_service_api EmptyAPI - end - - class API < ActionWebService::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 < ActionWebService::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 < ActionController::Base - wsdl_service_name 'Test' - - def dispatch_request(request) - protocol_request = probe_request_protocol(request) - dispatch_protocol_request(protocol_request) - end - end - - class DelegatedContainer < AbstractContainer - web_service_dispatching_mode :delegated - web_service :protocol_soap_service, Service.new - web_service :empty_service, EmptyService.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 - - class EmptyContainer < AbstractContainer - web_service_dispatching_mode :delegated - web_service :empty_service, EmptyService.new - end -end - -class TC_ProtocolSoap < AbstractSoapTest - def setup - @delegated_container = ProtocolSoapTest::DelegatedContainer.new - @direct_container = ProtocolSoapTest::DirectContainer.new - @empty_container = ProtocolSoapTest::EmptyContainer.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_nonexistent_method - @container = @empty_container - assert_raises(ActionWebService::Dispatcher::DispatcherError) do - do_soap_call('NonexistentMethod') - 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 - case - when @container == @direct_container - 'api' - when @container == @delegated_container - 'protocol_soap_service' - when @container == @empty_container - 'empty_service' - end - end - - def service - case - when @container == @direct_container - @container - when @container == @delegated_container - @container.web_service_object(:protocol_soap_service) - when @container == @empty_container - @container.web_service_object(:empty_service) - end - end - - def in_all_containers(&block) - [@direct_container, @delegated_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| - @container.dispatch_request(test_request) - end - end -end diff --git a/actionwebservice/test/protocol_xmlrpc_test.rb b/actionwebservice/test/protocol_xmlrpc_test.rb deleted file mode 100644 index cda0bba6d3..0000000000 --- a/actionwebservice/test/protocol_xmlrpc_test.rb +++ /dev/null @@ -1,147 +0,0 @@ -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 < ActionWebService::Struct - member :firstname, String - member :lastname, String - member :active, TrueClass - end - - class API < ActionWebService::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 < ActionWebService::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 < ActionController::Base - def protocol_request(request) - probe_request_protocol(request) - end - - def dispatch_request(protocol_request) - dispatch_protocol_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 - - 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/run b/actionwebservice/test/run index 5c6f8b2bc2..90ad85fff5 100755 --- a/actionwebservice/test/run +++ b/actionwebservice/test/run @@ -1,5 +1,5 @@ #!/usr/bin/env ruby - -Dir[File.join(File.dirname(__FILE__), '*_test.rb')].each do |f| - require f -end +require 'test/unit' +args = Dir[File.join(File.dirname(__FILE__), '*_test.rb')] + Dir[File.join(File.dirname(__FILE__), 'ws/*_test.rb')] +(r = Test::Unit::AutoRunner.new(true)).process_args(args) +exit r.run diff --git a/actionwebservice/test/ws/abstract_encoding.rb b/actionwebservice/test/ws/abstract_encoding.rb new file mode 100644 index 0000000000..9a6aec44e0 --- /dev/null +++ b/actionwebservice/test/ws/abstract_encoding.rb @@ -0,0 +1,68 @@ +require File.dirname(__FILE__) + '/abstract_unit' + +module Nested + class StructClass + attr_accessor :name + attr_accessor :version + + def initialize + @name = 5 + @version = "1.0" + end + + def ==(other) + @name == other.name && @version == other.version + end + end +end + +module EncodingTest + def setup + @call_signature = [:int, :bool, :string, :float, [:time], Nested::StructClass] + @call_params = [1, true, "string", 5.0, [Time.now], Nested::StructClass.new] + @response_signature = [:string] + @response_param = "hello world" + test_setup + end + + def test_abstract + obj = WS::Encoding::AbstractEncoding.new + assert_raises(NotImplementedError) do + obj.encode_rpc_call(nil, nil) + end + assert_raises(NotImplementedError) do + obj.decode_rpc_call(nil) + end + assert_raises(NotImplementedError) do + obj.encode_rpc_response(nil, nil) + end + assert_raises(NotImplementedError) do + obj.decode_rpc_response(nil) + end + end + + def encode_rpc_call(method_name, signature, params) + params = params.dup + (0..(signature.length-1)).each do |i| + type_binding = @marshaler.register_type(signature[i]) + info = WS::ParamInfo.create(signature[i], i, type_binding) + params[i] = @marshaler.marshal(WS::Param.new(params[i], info)) + end + @encoder.encode_rpc_call(method_name, params) + end + + def decode_rpc_call(obj) + @encoder.decode_rpc_call(obj) + end + + def encode_rpc_response(method_name, signature, param) + type_binding = @marshaler.register_type(signature[0]) + info = WS::ParamInfo.create(signature[0], 0, type_binding) + param = @marshaler.marshal(WS::Param.new(param, info)) + @encoder.encode_rpc_response(method_name, param) + end + + def decode_rpc_response(obj) + @encoder.decode_rpc_response(obj) + end +end diff --git a/actionwebservice/test/ws/abstract_unit.rb b/actionwebservice/test/ws/abstract_unit.rb new file mode 100644 index 0000000000..f5015bea69 --- /dev/null +++ b/actionwebservice/test/ws/abstract_unit.rb @@ -0,0 +1,14 @@ +$:.unshift(File.dirname(File.dirname(__FILE__)) + '/../lib') +$:.unshift(File.dirname(File.dirname(__FILE__)) + '/../lib/action_web_service/vendor') +puts $:.inspect +require 'test/unit' +require 'ws' +begin + require 'active_record' +rescue LoadError + begin + require 'rubygems' + require_gem 'activerecord', '>= 1.6.0' + rescue LoadError + end +end diff --git a/actionwebservice/test/ws/gencov b/actionwebservice/test/ws/gencov new file mode 100755 index 0000000000..144233107a --- /dev/null +++ b/actionwebservice/test/ws/gencov @@ -0,0 +1,3 @@ +#!/bin/sh + +rcov -x '.*_test\.rb,rubygems,abstract_,/run' ./run diff --git a/actionwebservice/test/ws/run b/actionwebservice/test/ws/run new file mode 100755 index 0000000000..5c6f8b2bc2 --- /dev/null +++ b/actionwebservice/test/ws/run @@ -0,0 +1,5 @@ +#!/usr/bin/env ruby + +Dir[File.join(File.dirname(__FILE__), '*_test.rb')].each do |f| + require f +end diff --git a/actionwebservice/test/ws/soap_marshaling_test.rb b/actionwebservice/test/ws/soap_marshaling_test.rb new file mode 100644 index 0000000000..ee6413478d --- /dev/null +++ b/actionwebservice/test/ws/soap_marshaling_test.rb @@ -0,0 +1,91 @@ +require File.dirname(__FILE__) + '/abstract_unit' + +module Nested + class MyClass + attr_accessor :id + attr_accessor :name + + def initialize(id, name) + @id = id + @name = name + end + + def ==(other) + @id == other.id && @name == other.name + end + end +end + +class SoapMarshalingTest < Test::Unit::TestCase + def setup + @marshaler = WS::Marshaling::SoapMarshaler.new + end + + def test_abstract + marshaler = WS::Marshaling::AbstractMarshaler.new + assert_raises(NotImplementedError) do + marshaler.marshal(nil) + end + assert_raises(NotImplementedError) do + marshaler.unmarshal(nil) + end + assert_equal(nil, marshaler.register_type(nil)) + end + + def test_marshaling + info = WS::ParamInfo.create(Nested::MyClass) + param = WS::Param.new(Nested::MyClass.new(2, "name"), info) + new_param = @marshaler.unmarshal(@marshaler.marshal(param)) + assert(param == new_param) + end + + def test_exception_marshaling + info = WS::ParamInfo.create(RuntimeError) + param = WS::Param.new(RuntimeError.new("hello, world"), info) + new_param = @marshaler.unmarshal(@marshaler.marshal(param)) + assert_equal("hello, world", new_param.value.detail.cause.message) + end + + def test_registration + type_binding1 = @marshaler.register_type(:int) + type_binding2 = @marshaler.register_type(:int) + assert(type_binding1.equal?(type_binding2)) + end + + def test_active_record + if Object.const_defined?('ActiveRecord') + node_class = Class.new(ActiveRecord::Base) do + def initialize(*args) + super(*args) + @new_record = false + end + + class << self + def name + "Node" + end + + def columns(*args) + [ + ActiveRecord::ConnectionAdapters::Column.new('id', 0, 'int'), + ActiveRecord::ConnectionAdapters::Column.new('name', nil, 'string'), + ActiveRecord::ConnectionAdapters::Column.new('email', nil, 'string'), + ] + end + + def connection + self + end + end + end + info = WS::ParamInfo.create(node_class, 0, @marshaler.register_type(node_class)) + ar_obj = node_class.new('name' => 'hello', 'email' => 'test@test.com') + param = WS::Param.new(ar_obj, info) + obj = @marshaler.marshal(param) + param = @marshaler.unmarshal(obj) + new_ar_obj = param.value + assert_equal(ar_obj, new_ar_obj) + assert(!ar_obj.equal?(new_ar_obj)) + end + end +end diff --git a/actionwebservice/test/ws/soap_rpc_encoding_test.rb b/actionwebservice/test/ws/soap_rpc_encoding_test.rb new file mode 100644 index 0000000000..e5dcbfeb1b --- /dev/null +++ b/actionwebservice/test/ws/soap_rpc_encoding_test.rb @@ -0,0 +1,47 @@ +require File.dirname(__FILE__) + '/abstract_encoding' +require 'time' + +class SoapRpcEncodingTest < Test::Unit::TestCase + include EncodingTest + + def test_setup + @encoder = WS::Encoding::SoapRpcEncoding.new + @marshaler = WS::Marshaling::SoapMarshaler.new + end + + def test_call_encoding_and_decoding + obj = encode_rpc_call('DecodeMe', @call_signature, @call_params) + method_name, decoded_params = decode_rpc_call(obj) + params = decoded_params.map{|x| @marshaler.unmarshal(x).value} + assert_equal(method_name, 'DecodeMe') + assert_equal(@call_params[0..3], params[0..3]) + # XXX: DateTime not marshaled correctly yet + assert_equal(@call_params[5..-1], params[5..-1]) + end + + def test_response_encoding_and_decoding_simple + obj = encode_rpc_response('DecodeMe', @response_signature, @response_param) + method_name, return_value = decode_rpc_response(obj) + return_value = @marshaler.unmarshal(return_value).value + assert_equal('DecodeMe', method_name) + assert_equal(@response_param, return_value) + end + + def test_response_encoding_and_decoding_struct + struct = Nested::StructClass.new + obj = encode_rpc_response('DecodeMe', [Nested::StructClass], struct) + method_name, return_value = decode_rpc_response(obj) + return_value = @marshaler.unmarshal(return_value).value + assert_equal('DecodeMe', method_name) + assert_equal(struct, return_value) + end + + def test_response_encoding_and_decoding_array + struct = Nested::StructClass.new + obj = encode_rpc_response('DecodeMe', [[Nested::StructClass]], [struct]) + method_name, return_value = decode_rpc_response(obj) + return_value = @marshaler.unmarshal(return_value).value + assert_equal('DecodeMe', method_name) + assert_equal([struct], return_value) + end +end diff --git a/actionwebservice/test/ws/types_test.rb b/actionwebservice/test/ws/types_test.rb new file mode 100644 index 0000000000..649fdbad7c --- /dev/null +++ b/actionwebservice/test/ws/types_test.rb @@ -0,0 +1,41 @@ +require File.dirname(__FILE__) + '/abstract_unit' + +class TypesTest < Test::Unit::TestCase + include WS + + def setup + @caster = BaseTypeCaster.new + end + + def test_base_types + assert_equal(:int, BaseTypes.canonical_type_name(:integer)) + assert_equal(:int, BaseTypes.canonical_type_name(:fixnum)) + assert_equal(Integer, BaseTypes.type_name_to_class(:bignum)) + assert_equal(Date, BaseTypes.type_name_to_class(:date)) + assert_equal(Time, BaseTypes.type_name_to_class(:timestamp)) + assert_equal(TrueClass, BaseTypes.type_name_to_class(:bool)) + assert_equal(:int, BaseTypes.class_to_type_name(Bignum)) + assert_equal(:bool, BaseTypes.class_to_type_name(FalseClass)) + assert_equal(Integer, BaseTypes.canonical_type_class(Fixnum)) + assert_raises(TypeError) do + BaseTypes.canonical_type_name(:fake) + end + end + + def test_casting + assert_equal(5, @caster.cast("5", Fixnum)) + assert_equal('50.0', @caster.cast(50.0, String)) + assert_equal(true, @caster.cast('true', FalseClass)) + assert_equal(false, @caster.cast('false', TrueClass)) + assert_raises(TypeError) do + @caster.cast('yes', FalseClass) + end + assert_equal(3.14159, @caster.cast('3.14159', Float)) + now1 = Time.new + now2 = @caster.cast("#{now1}", Time) + assert_equal(now1.tv_sec, now2.tv_sec) + date1 = Date.parse('2004-01-01') + date2 = @caster.cast("#{date1}", Date) + assert_equal(date1, date2) + end +end diff --git a/actionwebservice/test/ws/xmlrpc_encoding_test.rb b/actionwebservice/test/ws/xmlrpc_encoding_test.rb new file mode 100644 index 0000000000..45aaa901bd --- /dev/null +++ b/actionwebservice/test/ws/xmlrpc_encoding_test.rb @@ -0,0 +1,34 @@ +require File.dirname(__FILE__) + '/abstract_encoding' +require 'time' + +class XmlRpcEncodingTest < Test::Unit::TestCase + include EncodingTest + + def test_setup + @encoder = WS::Encoding::XmlRpcEncoding.new + @marshaler = WS::Marshaling::XmlRpcMarshaler.new + end + + def test_typed_call_encoding_and_decoding + obj = encode_rpc_call('DecodeMe', @call_signature, @call_params) + method_name, params = decode_rpc_call(obj) + (0..(@call_signature.length-1)).each do |i| + params[i] = @marshaler.typed_unmarshal(params[i], @call_signature[i]).value + end + assert_equal(method_name, 'DecodeMe') + assert_equal(@call_params[0..3], params[0..3]) + assert_equal(@call_params[5..-1], params[5..-1]) + end + + def test_untyped_call_encoding_and_decoding + obj = encode_rpc_call('DecodeMe', @call_signature, @call_params) + method_name, params = decode_rpc_call(obj) + (0..(@call_signature.length-1)).each do |i| + params[i] = @marshaler.unmarshal(params[i]).value + end + assert_equal(method_name, 'DecodeMe') + assert_equal(@call_params[0..3], params[0..3]) + assert_equal(@call_params[5].name, params[5]['name']) + assert_equal(@call_params[5].version, params[5]['version']) + end +end -- cgit v1.2.3