aboutsummaryrefslogtreecommitdiffstats
path: root/actionwebservice/test/abstract_dispatcher.rb
diff options
context:
space:
mode:
authorLeon Breedt <bitserf@gmail.com>2005-02-25 23:39:39 +0000
committerLeon Breedt <bitserf@gmail.com>2005-02-25 23:39:39 +0000
commit6f5a7b200443baf209d2f33c428ed4a4059782f7 (patch)
tree9c3942fe27be69c102873d9fdaa13f66dc12853d /actionwebservice/test/abstract_dispatcher.rb
parent10faf204b712763f05a2b3155a4fd9c5338f1fb2 (diff)
downloadrails-6f5a7b200443baf209d2f33c428ed4a4059782f7.tar.gz
rails-6f5a7b200443baf209d2f33c428ed4a4059782f7.tar.bz2
rails-6f5a7b200443baf209d2f33c428ed4a4059782f7.zip
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
Diffstat (limited to 'actionwebservice/test/abstract_dispatcher.rb')
-rw-r--r--actionwebservice/test/abstract_dispatcher.rb294
1 files changed, 294 insertions, 0 deletions
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