actionwebservice 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/ChangeLog +47 -0
- data/MIT-LICENSE +21 -0
- data/README +238 -0
- data/Rakefile +144 -0
- data/TODO +13 -0
- data/examples/googlesearch/README +143 -0
- data/examples/googlesearch/autoloading/google_search_api.rb +50 -0
- data/examples/googlesearch/autoloading/google_search_controller.rb +57 -0
- data/examples/googlesearch/delegated/google_search_service.rb +108 -0
- data/examples/googlesearch/delegated/search_controller.rb +7 -0
- data/examples/googlesearch/direct/google_search_api.rb +50 -0
- data/examples/googlesearch/direct/search_controller.rb +58 -0
- data/examples/metaWeblog/README +16 -0
- data/examples/metaWeblog/blog_controller.rb +127 -0
- data/lib/action_web_service.rb +60 -0
- data/lib/action_web_service/api.rb +2 -0
- data/lib/action_web_service/api/abstract.rb +192 -0
- data/lib/action_web_service/api/action_controller.rb +92 -0
- data/lib/action_web_service/base.rb +41 -0
- data/lib/action_web_service/client.rb +3 -0
- data/lib/action_web_service/client/base.rb +39 -0
- data/lib/action_web_service/client/soap_client.rb +88 -0
- data/lib/action_web_service/client/xmlrpc_client.rb +77 -0
- data/lib/action_web_service/container.rb +85 -0
- data/lib/action_web_service/dispatcher.rb +2 -0
- data/lib/action_web_service/dispatcher/abstract.rb +150 -0
- data/lib/action_web_service/dispatcher/action_controller_dispatcher.rb +299 -0
- data/lib/action_web_service/invocation.rb +205 -0
- data/lib/action_web_service/protocol.rb +4 -0
- data/lib/action_web_service/protocol/abstract.rb +128 -0
- data/lib/action_web_service/protocol/registry.rb +55 -0
- data/lib/action_web_service/protocol/soap_protocol.rb +484 -0
- data/lib/action_web_service/protocol/xmlrpc_protocol.rb +168 -0
- data/lib/action_web_service/struct.rb +55 -0
- data/lib/action_web_service/support/class_inheritable_options.rb +26 -0
- data/lib/action_web_service/support/signature.rb +100 -0
- data/setup.rb +1360 -0
- data/test/abstract_client.rb +131 -0
- data/test/abstract_soap.rb +58 -0
- data/test/abstract_unit.rb +9 -0
- data/test/api_test.rb +52 -0
- data/test/base_test.rb +42 -0
- data/test/client_soap_test.rb +93 -0
- data/test/client_xmlrpc_test.rb +92 -0
- data/test/container_test.rb +53 -0
- data/test/dispatcher_action_controller_test.rb +186 -0
- data/test/gencov +3 -0
- data/test/invocation_test.rb +149 -0
- data/test/protocol_registry_test.rb +53 -0
- data/test/protocol_soap_test.rb +252 -0
- data/test/protocol_xmlrpc_test.rb +147 -0
- data/test/run +5 -0
- data/test/struct_test.rb +40 -0
- metadata +131 -0
@@ -0,0 +1,53 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/abstract_unit'
|
2
|
+
|
3
|
+
module ContainerTest
|
4
|
+
|
5
|
+
$immediate_service = Object.new
|
6
|
+
$deferred_service = Object.new
|
7
|
+
|
8
|
+
class DelegateContainer < ActionController::Base
|
9
|
+
web_service_dispatching_mode :delegated
|
10
|
+
|
11
|
+
attr :flag
|
12
|
+
attr :previous_flag
|
13
|
+
|
14
|
+
def initialize
|
15
|
+
@previous_flag = nil
|
16
|
+
@flag = true
|
17
|
+
end
|
18
|
+
|
19
|
+
web_service :immediate_service, $immediate_service
|
20
|
+
web_service(:deferred_service) { @previous_flag = @flag; @flag = false; $deferred_service }
|
21
|
+
end
|
22
|
+
|
23
|
+
class DirectContainer < ActionController::Base
|
24
|
+
web_service_dispatching_mode :direct
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
class TC_Container < Test::Unit::TestCase
|
29
|
+
def setup
|
30
|
+
@delegate_container = ContainerTest::DelegateContainer.new
|
31
|
+
@direct_container = ContainerTest::DirectContainer.new
|
32
|
+
end
|
33
|
+
|
34
|
+
def test_registration
|
35
|
+
assert(ContainerTest::DelegateContainer.has_web_service?(:immediate_service))
|
36
|
+
assert(ContainerTest::DelegateContainer.has_web_service?(:deferred_service))
|
37
|
+
assert(!ContainerTest::DelegateContainer.has_web_service?(:fake_service))
|
38
|
+
end
|
39
|
+
|
40
|
+
def test_service_object
|
41
|
+
assert(@delegate_container.flag == true)
|
42
|
+
assert(@delegate_container.web_service_object(:immediate_service) == $immediate_service)
|
43
|
+
assert(@delegate_container.previous_flag.nil?)
|
44
|
+
assert(@delegate_container.flag == true)
|
45
|
+
assert(@delegate_container.web_service_object(:deferred_service) == $deferred_service)
|
46
|
+
assert(@delegate_container.previous_flag == true)
|
47
|
+
assert(@delegate_container.flag == false)
|
48
|
+
end
|
49
|
+
|
50
|
+
def test_direct_container
|
51
|
+
assert(ContainerTest::DirectContainer.web_service_dispatching_mode == :direct)
|
52
|
+
end
|
53
|
+
end
|
@@ -0,0 +1,186 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/abstract_soap'
|
2
|
+
require 'wsdl/parser'
|
3
|
+
|
4
|
+
module DispatcherActionControllerTest
|
5
|
+
class API < ActionWebService::API::Base
|
6
|
+
api_method :add, :expects => [:int, :int], :returns => [:int]
|
7
|
+
end
|
8
|
+
|
9
|
+
class DirectAPI < ActionWebService::API::Base
|
10
|
+
api_method :add, :expects => [{:a=>:int}, {:b=>:int}], :returns => [:int]
|
11
|
+
api_method :before_filtered
|
12
|
+
api_method :after_filtered, :returns => [:int]
|
13
|
+
api_method :thrower
|
14
|
+
end
|
15
|
+
|
16
|
+
class Service < ActionWebService::Base
|
17
|
+
web_service_api API
|
18
|
+
|
19
|
+
attr :added
|
20
|
+
|
21
|
+
def add(a, b)
|
22
|
+
@added = a + b
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
class AbstractController < ActionController::Base
|
27
|
+
def generate_wsdl(container, uri, soap_action_base)
|
28
|
+
to_wsdl(container, uri, soap_action_base)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
class DelegatedController < AbstractController
|
33
|
+
web_service_dispatching_mode :delegated
|
34
|
+
|
35
|
+
web_service(:test_service) { @service ||= Service.new; @service }
|
36
|
+
end
|
37
|
+
|
38
|
+
class DirectController < AbstractController
|
39
|
+
web_service_api DirectAPI
|
40
|
+
web_service_dispatching_mode :direct
|
41
|
+
|
42
|
+
before_filter :alwaysfail, :only => [:before_filtered]
|
43
|
+
after_filter :alwaysok, :only => [:after_filtered]
|
44
|
+
|
45
|
+
attr :added
|
46
|
+
attr :before_filter_called
|
47
|
+
attr :before_filter_target_called
|
48
|
+
attr :after_filter_called
|
49
|
+
attr :after_filter_target_called
|
50
|
+
|
51
|
+
def initialize
|
52
|
+
@before_filter_called = false
|
53
|
+
@before_filter_target_called = false
|
54
|
+
@after_filter_called = false
|
55
|
+
@after_filter_target_called = false
|
56
|
+
end
|
57
|
+
|
58
|
+
def add
|
59
|
+
@added = @params['a'] + @params['b']
|
60
|
+
end
|
61
|
+
|
62
|
+
def before_filtered
|
63
|
+
@before_filter_target_called = true
|
64
|
+
end
|
65
|
+
|
66
|
+
def after_filtered
|
67
|
+
@after_filter_target_called = true
|
68
|
+
5
|
69
|
+
end
|
70
|
+
|
71
|
+
def thrower
|
72
|
+
raise "Hi, I'm a SOAP exception"
|
73
|
+
end
|
74
|
+
|
75
|
+
protected
|
76
|
+
def alwaysfail
|
77
|
+
@before_filter_called = true
|
78
|
+
false
|
79
|
+
end
|
80
|
+
|
81
|
+
def alwaysok
|
82
|
+
@after_filter_called = true
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
class TC_DispatcherActionController < AbstractSoapTest
|
88
|
+
include DispatcherActionControllerTest
|
89
|
+
|
90
|
+
def test_direct_dispatching
|
91
|
+
@container = DirectController.new
|
92
|
+
assert(do_soap_call('Add', 20, 50) == 70)
|
93
|
+
assert(@container.added == 70)
|
94
|
+
end
|
95
|
+
|
96
|
+
def test_direct_entrypoint
|
97
|
+
@container = DirectController.new
|
98
|
+
assert(@container.respond_to?(:api))
|
99
|
+
end
|
100
|
+
|
101
|
+
def test_direct_filtering
|
102
|
+
@container = DirectController.new
|
103
|
+
assert(@container.before_filter_called == false)
|
104
|
+
assert(@container.before_filter_target_called == false)
|
105
|
+
assert(do_soap_call('BeforeFiltered').nil?)
|
106
|
+
assert(@container.before_filter_called == true)
|
107
|
+
assert(@container.before_filter_target_called == false)
|
108
|
+
assert(@container.after_filter_called == false)
|
109
|
+
assert(@container.after_filter_target_called == false)
|
110
|
+
assert(do_soap_call('AfterFiltered') == 5)
|
111
|
+
assert(@container.after_filter_called == true)
|
112
|
+
assert(@container.after_filter_target_called == true)
|
113
|
+
end
|
114
|
+
|
115
|
+
def test_delegated_dispatching
|
116
|
+
@container = DelegatedController.new
|
117
|
+
assert(do_soap_call('Add', 50, 80) == 130)
|
118
|
+
assert(service.added == 130)
|
119
|
+
end
|
120
|
+
|
121
|
+
def test_exception_marshaling
|
122
|
+
@container = DirectController.new
|
123
|
+
result = do_soap_call('Thrower')
|
124
|
+
exception = result.detail
|
125
|
+
assert(exception.cause.is_a?(RuntimeError))
|
126
|
+
assert_equal("Hi, I'm a SOAP exception", exception.cause.message)
|
127
|
+
@container.web_service_exception_reporting = false
|
128
|
+
assert_raises(SoapTestError) do
|
129
|
+
do_soap_call('Thrower')
|
130
|
+
end
|
131
|
+
end
|
132
|
+
|
133
|
+
def test_wsdl_generation
|
134
|
+
ensure_valid_wsdl_generation DelegatedController.new
|
135
|
+
ensure_valid_wsdl_generation DirectController.new
|
136
|
+
end
|
137
|
+
|
138
|
+
def
|
139
|
+
|
140
|
+
def test_wsdl_action
|
141
|
+
ensure_valid_wsdl_action DelegatedController.new
|
142
|
+
ensure_valid_wsdl_action DirectController.new
|
143
|
+
end
|
144
|
+
|
145
|
+
protected
|
146
|
+
def service_name
|
147
|
+
@container.is_a?(DelegatedController) ? 'test_service' : 'api'
|
148
|
+
end
|
149
|
+
|
150
|
+
def service
|
151
|
+
@container.web_service_object(:test_service)
|
152
|
+
end
|
153
|
+
|
154
|
+
def do_soap_call(public_method_name, *args)
|
155
|
+
super(public_method_name, *args) do |test_request, test_response|
|
156
|
+
response = @container.process(test_request, test_response)
|
157
|
+
end
|
158
|
+
end
|
159
|
+
|
160
|
+
def ensure_valid_wsdl_generation(controller)
|
161
|
+
wsdl = controller.generate_wsdl(controller, 'http://localhost:3000/test/', '/test')
|
162
|
+
ensure_valid_wsdl(wsdl)
|
163
|
+
end
|
164
|
+
|
165
|
+
def ensure_valid_wsdl(wsdl)
|
166
|
+
definitions = WSDL::Parser.new.parse(wsdl)
|
167
|
+
assert(definitions.is_a?(WSDL::Definitions))
|
168
|
+
definitions.bindings.each do |binding|
|
169
|
+
assert(binding.name.name.index(':').nil?)
|
170
|
+
end
|
171
|
+
definitions.services.each do |service|
|
172
|
+
service.ports.each do |port|
|
173
|
+
assert(port.name.name.index(':').nil?)
|
174
|
+
end
|
175
|
+
end
|
176
|
+
end
|
177
|
+
|
178
|
+
def ensure_valid_wsdl_action(controller)
|
179
|
+
test_request = ActionController::TestRequest.new({ 'action' => 'wsdl' })
|
180
|
+
test_request.env['REQUEST_METHOD'] = 'GET'
|
181
|
+
test_request.env['HTTP_HOST'] = 'localhost:3000'
|
182
|
+
test_response = ActionController::TestResponse.new
|
183
|
+
wsdl = controller.process(test_request, test_response).body
|
184
|
+
ensure_valid_wsdl(wsdl)
|
185
|
+
end
|
186
|
+
end
|
data/test/gencov
ADDED
@@ -0,0 +1,149 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/abstract_unit'
|
2
|
+
|
3
|
+
module InvocationTest
|
4
|
+
class API < ActionWebService::API::Base
|
5
|
+
api_method :add, :expects => [:int, :int], :returns => [:int]
|
6
|
+
api_method :transmogrify, :expects_and_returns => [:string]
|
7
|
+
api_method :fail_with_reason
|
8
|
+
api_method :fail_generic
|
9
|
+
api_method :no_before
|
10
|
+
api_method :no_after
|
11
|
+
api_method :only_one
|
12
|
+
api_method :only_two
|
13
|
+
end
|
14
|
+
|
15
|
+
class Service < ActionWebService::Base
|
16
|
+
web_service_api API
|
17
|
+
|
18
|
+
before_invocation :intercept_before, :except => [:no_before]
|
19
|
+
after_invocation :intercept_after, :except => [:no_after]
|
20
|
+
before_invocation :intercept_only, :only => [:only_one, :only_two]
|
21
|
+
|
22
|
+
attr_accessor :before_invoked
|
23
|
+
attr_accessor :after_invoked
|
24
|
+
attr_accessor :only_invoked
|
25
|
+
attr_accessor :invocation_result
|
26
|
+
|
27
|
+
def initialize
|
28
|
+
@before_invoked = nil
|
29
|
+
@after_invoked = nil
|
30
|
+
@only_invoked = nil
|
31
|
+
@invocation_result = nil
|
32
|
+
end
|
33
|
+
|
34
|
+
def add(a, b)
|
35
|
+
a + b
|
36
|
+
end
|
37
|
+
|
38
|
+
def transmogrify(str)
|
39
|
+
str.upcase
|
40
|
+
end
|
41
|
+
|
42
|
+
def fail_with_reason
|
43
|
+
end
|
44
|
+
|
45
|
+
def fail_generic
|
46
|
+
end
|
47
|
+
|
48
|
+
def no_before
|
49
|
+
5
|
50
|
+
end
|
51
|
+
|
52
|
+
def no_after
|
53
|
+
end
|
54
|
+
|
55
|
+
def only_one
|
56
|
+
end
|
57
|
+
|
58
|
+
def only_two
|
59
|
+
end
|
60
|
+
|
61
|
+
protected
|
62
|
+
def intercept_before(name, args)
|
63
|
+
@before_invoked = name
|
64
|
+
return [false, "permission denied"] if name == :fail_with_reason
|
65
|
+
return false if name == :fail_generic
|
66
|
+
end
|
67
|
+
|
68
|
+
def intercept_after(name, args, result)
|
69
|
+
@after_invoked = name
|
70
|
+
@invocation_result = result
|
71
|
+
end
|
72
|
+
|
73
|
+
def intercept_only(name, args)
|
74
|
+
raise "Interception error" unless name == :only_one || name == :only_two
|
75
|
+
@only_invoked = name
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
class TC_Invocation < Test::Unit::TestCase
|
81
|
+
include ActionWebService::Invocation
|
82
|
+
|
83
|
+
def setup
|
84
|
+
@service = InvocationTest::Service.new
|
85
|
+
end
|
86
|
+
|
87
|
+
def test_invocation
|
88
|
+
assert(perform_invocation(:add, 5, 10) == 15)
|
89
|
+
assert(perform_invocation(:transmogrify, "hello") == "HELLO")
|
90
|
+
assert_raises(NoMethodError) do
|
91
|
+
perform_invocation(:nonexistent_method_xyzzy)
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
def test_interceptor_registration
|
96
|
+
assert(InvocationTest::Service.before_invocation_interceptors.length == 2)
|
97
|
+
assert(InvocationTest::Service.after_invocation_interceptors.length == 1)
|
98
|
+
end
|
99
|
+
|
100
|
+
def test_interception
|
101
|
+
assert(@service.before_invoked.nil? && @service.after_invoked.nil? && @service.only_invoked.nil? && @service.invocation_result.nil?)
|
102
|
+
perform_invocation(:add, 20, 50)
|
103
|
+
assert(@service.before_invoked == :add)
|
104
|
+
assert(@service.after_invoked == :add)
|
105
|
+
assert(@service.invocation_result == 70)
|
106
|
+
end
|
107
|
+
|
108
|
+
def test_interception_canceling
|
109
|
+
reason = nil
|
110
|
+
perform_invocation(:fail_with_reason){|r| reason = r}
|
111
|
+
assert(@service.before_invoked == :fail_with_reason)
|
112
|
+
assert(@service.after_invoked.nil?)
|
113
|
+
assert(@service.invocation_result.nil?)
|
114
|
+
assert(reason == "permission denied")
|
115
|
+
reason = true
|
116
|
+
@service.before_invoked = @service.after_invoked = @service.invocation_result = nil
|
117
|
+
perform_invocation(:fail_generic){|r| reason = r}
|
118
|
+
assert(@service.before_invoked == :fail_generic)
|
119
|
+
assert(@service.after_invoked.nil?)
|
120
|
+
assert(@service.invocation_result.nil?)
|
121
|
+
assert(reason == true)
|
122
|
+
end
|
123
|
+
|
124
|
+
def test_interception_except_conditions
|
125
|
+
perform_invocation(:no_before)
|
126
|
+
assert(@service.before_invoked.nil?)
|
127
|
+
assert(@service.after_invoked == :no_before)
|
128
|
+
assert(@service.invocation_result == 5)
|
129
|
+
@service.before_invoked = @service.after_invoked = @service.invocation_result = nil
|
130
|
+
perform_invocation(:no_after)
|
131
|
+
assert(@service.before_invoked == :no_after)
|
132
|
+
assert(@service.after_invoked.nil?)
|
133
|
+
assert(@service.invocation_result.nil?)
|
134
|
+
end
|
135
|
+
|
136
|
+
def test_interception_only_conditions
|
137
|
+
assert(@service.only_invoked.nil?)
|
138
|
+
perform_invocation(:only_one)
|
139
|
+
assert(@service.only_invoked == :only_one)
|
140
|
+
@service.only_invoked = nil
|
141
|
+
perform_invocation(:only_two)
|
142
|
+
assert(@service.only_invoked == :only_two)
|
143
|
+
end
|
144
|
+
|
145
|
+
private
|
146
|
+
def perform_invocation(method_name, *args, &block)
|
147
|
+
@service.perform_invocation(method_name, args, &block)
|
148
|
+
end
|
149
|
+
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/abstract_unit'
|
2
|
+
|
3
|
+
|
4
|
+
module Foo
|
5
|
+
include ActionWebService::Protocol
|
6
|
+
|
7
|
+
def self.append_features(base)
|
8
|
+
super
|
9
|
+
base.register_protocol(BodyOnly, FooMinimalProtocol)
|
10
|
+
base.register_protocol(HeaderAndBody, FooMinimalProtocolTwo)
|
11
|
+
base.register_protocol(HeaderAndBody, FooMinimalProtocolTwo)
|
12
|
+
base.register_protocol(HeaderAndBody, FooFullProtocol)
|
13
|
+
end
|
14
|
+
|
15
|
+
class FooFullProtocol < AbstractProtocol
|
16
|
+
def self.create_protocol_request(klass, request)
|
17
|
+
protocol = FooFullProtocol.new klass
|
18
|
+
ActionWebService::Protocol::ProtocolRequest.new(protocol, '', '', '', '')
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
class FooMinimalProtocol < AbstractProtocol
|
23
|
+
def self.create_protocol_request(klass, request)
|
24
|
+
protocol = FooMinimalProtocol.new klass
|
25
|
+
ActionWebService::Protocol::ProtocolRequest.new(protocol, '', '', '', '')
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
class FooMinimalProtocolTwo < AbstractProtocol
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
class ProtocolRegistry
|
34
|
+
include ActionWebService::Protocol::Registry
|
35
|
+
include Foo
|
36
|
+
|
37
|
+
def all_protocols
|
38
|
+
header_and_body_protocols + body_only_protocols
|
39
|
+
end
|
40
|
+
|
41
|
+
def protocol_request
|
42
|
+
probe_request_protocol(nil)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
|
47
|
+
class TC_ProtocolRegistry < Test::Unit::TestCase
|
48
|
+
def test_registration
|
49
|
+
registry = ProtocolRegistry.new
|
50
|
+
assert(registry.all_protocols.length == 4)
|
51
|
+
assert(registry.protocol_request.protocol.is_a?(Foo::FooFullProtocol))
|
52
|
+
end
|
53
|
+
end
|