actionwebservice 0.5.0 → 0.6.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 → CHANGELOG} +20 -0
- data/README +45 -1
- data/Rakefile +12 -10
- data/TODO +8 -9
- data/lib/action_web_service.rb +10 -6
- data/lib/action_web_service/api.rb +1 -2
- data/lib/action_web_service/api/{abstract.rb → base.rb} +14 -71
- data/lib/action_web_service/base.rb +0 -3
- data/lib/action_web_service/client/base.rb +1 -12
- data/lib/action_web_service/client/soap_client.rb +49 -17
- data/lib/action_web_service/client/xmlrpc_client.rb +20 -15
- data/lib/action_web_service/container.rb +3 -85
- data/lib/action_web_service/{api/action_controller.rb → container/action_controller_container.rb} +2 -2
- data/lib/action_web_service/container/delegated_container.rb +87 -0
- data/lib/action_web_service/container/direct_container.rb +70 -0
- data/lib/action_web_service/dispatcher/abstract.rb +100 -102
- data/lib/action_web_service/dispatcher/action_controller_dispatcher.rb +199 -137
- data/lib/action_web_service/protocol.rb +1 -1
- data/lib/action_web_service/protocol/abstract.rb +14 -112
- data/lib/action_web_service/protocol/discovery.rb +37 -0
- data/lib/action_web_service/protocol/soap_protocol.rb +32 -458
- data/lib/action_web_service/protocol/xmlrpc_protocol.rb +29 -149
- data/lib/action_web_service/struct.rb +2 -5
- data/lib/action_web_service/test_invoke.rb +130 -0
- data/lib/action_web_service/vendor/ws.rb +4 -0
- data/lib/action_web_service/vendor/ws/common.rb +8 -0
- data/lib/action_web_service/vendor/ws/encoding.rb +3 -0
- data/lib/action_web_service/vendor/ws/encoding/abstract.rb +26 -0
- data/lib/action_web_service/vendor/ws/encoding/soap_rpc_encoding.rb +90 -0
- data/lib/action_web_service/vendor/ws/encoding/xmlrpc_encoding.rb +53 -0
- data/lib/action_web_service/vendor/ws/marshaling.rb +3 -0
- data/lib/action_web_service/vendor/ws/marshaling/abstract.rb +17 -0
- data/lib/action_web_service/vendor/ws/marshaling/soap_marshaling.rb +277 -0
- data/lib/action_web_service/vendor/ws/marshaling/xmlrpc_marshaling.rb +116 -0
- data/lib/action_web_service/vendor/ws/types.rb +162 -0
- data/test/abstract_client.rb +8 -11
- data/test/abstract_dispatcher.rb +370 -0
- data/test/abstract_unit.rb +1 -0
- data/test/api_test.rb +18 -1
- data/test/apis/auto_load_api.rb +3 -0
- data/test/apis/broken_auto_load_api.rb +2 -0
- data/test/client_soap_test.rb +16 -3
- data/test/client_xmlrpc_test.rb +16 -4
- data/test/container_test.rb +28 -8
- data/test/dispatcher_action_controller_soap_test.rb +106 -0
- data/test/dispatcher_action_controller_xmlrpc_test.rb +44 -0
- data/test/gencov +1 -1
- data/test/invocation_test.rb +39 -3
- data/test/run +4 -4
- data/test/test_invoke_test.rb +77 -0
- data/test/ws/abstract_encoding.rb +68 -0
- data/test/ws/abstract_unit.rb +13 -0
- data/test/ws/gencov +3 -0
- data/test/ws/run +5 -0
- data/test/ws/soap_marshaling_test.rb +91 -0
- data/test/ws/soap_rpc_encoding_test.rb +47 -0
- data/test/ws/types_test.rb +41 -0
- data/test/ws/xmlrpc_encoding_test.rb +34 -0
- metadata +48 -19
- data/lib/action_web_service/protocol/registry.rb +0 -55
- data/lib/action_web_service/support/signature.rb +0 -100
- data/test/abstract_soap.rb +0 -58
- data/test/dispatcher_action_controller_test.rb +0 -186
- data/test/protocol_registry_test.rb +0 -53
- data/test/protocol_soap_test.rb +0 -252
- data/test/protocol_xmlrpc_test.rb +0 -147
@@ -0,0 +1,162 @@
|
|
1
|
+
require 'time'
|
2
|
+
require 'date'
|
3
|
+
|
4
|
+
module WS
|
5
|
+
module BaseTypes
|
6
|
+
class << self
|
7
|
+
def type_name_to_class(name)
|
8
|
+
case canonical_type_name(name)
|
9
|
+
when :int
|
10
|
+
Integer
|
11
|
+
when :string
|
12
|
+
String
|
13
|
+
when :bool
|
14
|
+
TrueClass
|
15
|
+
when :float
|
16
|
+
Float
|
17
|
+
when :time
|
18
|
+
Time
|
19
|
+
when :date
|
20
|
+
Date
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def class_to_type_name(klass)
|
25
|
+
if WS.derived_from?(Integer, klass) || WS.derived_from?(Fixnum, klass) || WS.derived_from?(Bignum, klass)
|
26
|
+
:int
|
27
|
+
elsif klass == String
|
28
|
+
:string
|
29
|
+
elsif klass == TrueClass || klass == FalseClass
|
30
|
+
:bool
|
31
|
+
elsif WS.derived_from?(Float, klass) || WS.derived_from?(Precision, klass) || WS.derived_from?(Numeric, klass)
|
32
|
+
:float
|
33
|
+
elsif klass == Time || klass == DateTime
|
34
|
+
:time
|
35
|
+
elsif klass == Date
|
36
|
+
:date
|
37
|
+
else
|
38
|
+
raise(TypeError, "#{klass} is not a valid base type")
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def base_type?(klass)
|
43
|
+
!(canonical_type_class(klass) rescue nil).nil?
|
44
|
+
end
|
45
|
+
|
46
|
+
def canonical_type_class(klass)
|
47
|
+
type_name_to_class(class_to_type_name(klass))
|
48
|
+
end
|
49
|
+
|
50
|
+
def canonical_param_type_class(spec)
|
51
|
+
klass = spec.is_a?(Hash) ? spec.values[0] : spec
|
52
|
+
array_element_class = klass.is_a?(Array) ? klass[0] : nil
|
53
|
+
klass = array_element_class ? array_element_class : klass
|
54
|
+
klass = type_name_to_class(klass) if klass.is_a?(Symbol) || klass.is_a?(String)
|
55
|
+
base_class = canonical_type_class(klass) rescue nil
|
56
|
+
klass = base_class unless base_class.nil?
|
57
|
+
array_element_class ? [klass] : klass
|
58
|
+
end
|
59
|
+
|
60
|
+
def canonical_param_type_spec(spec)
|
61
|
+
klass = canonical_param_type_class(spec)
|
62
|
+
spec.is_a?(Hash) ? {spec.keys[0]=>klass} : klass
|
63
|
+
end
|
64
|
+
|
65
|
+
def canonical_type_name(name)
|
66
|
+
name = name.to_sym
|
67
|
+
case name
|
68
|
+
when :int, :integer, :fixnum, :bignum
|
69
|
+
:int
|
70
|
+
when :string, :base64
|
71
|
+
:string
|
72
|
+
when :bool, :boolean
|
73
|
+
:bool
|
74
|
+
when :float, :double
|
75
|
+
:float
|
76
|
+
when :time, :datetime, :timestamp
|
77
|
+
:time
|
78
|
+
when :date
|
79
|
+
:date
|
80
|
+
else
|
81
|
+
raise(TypeError, "#{name} is not a valid base type")
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
class Param
|
88
|
+
attr_accessor :value
|
89
|
+
attr_accessor :info
|
90
|
+
|
91
|
+
def initialize(value, info)
|
92
|
+
@value = value
|
93
|
+
@info = info
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
class ParamInfo
|
98
|
+
attr_accessor :name
|
99
|
+
attr_accessor :type
|
100
|
+
attr_accessor :data
|
101
|
+
|
102
|
+
def initialize(name, type, data=nil)
|
103
|
+
@name = name
|
104
|
+
@type = type
|
105
|
+
@data = data
|
106
|
+
end
|
107
|
+
|
108
|
+
def self.create(spec, data, index=nil)
|
109
|
+
name = spec.is_a?(Hash) ? spec.keys[0].to_s : (index ? "param#{index}" : nil)
|
110
|
+
type = BaseTypes.canonical_param_type_class(spec)
|
111
|
+
ParamInfo.new(name, type, data)
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
class BaseTypeCaster
|
116
|
+
def initialize
|
117
|
+
@handlers = {}
|
118
|
+
install_handlers
|
119
|
+
end
|
120
|
+
|
121
|
+
def cast(value, klass)
|
122
|
+
type_class = BaseTypes.canonical_type_class(klass)
|
123
|
+
return value unless type_class
|
124
|
+
@handlers[type_class].call(value, type_class)
|
125
|
+
end
|
126
|
+
|
127
|
+
protected
|
128
|
+
def install_handlers
|
129
|
+
handler = method(:cast_base_type)
|
130
|
+
[:int, :string, :bool, :float, :time, :date].each do |name|
|
131
|
+
type = BaseTypes.type_name_to_class(name)
|
132
|
+
@handlers[type] = handler
|
133
|
+
end
|
134
|
+
@handlers[Fixnum] = handler
|
135
|
+
end
|
136
|
+
|
137
|
+
def cast_base_type(value, type_class)
|
138
|
+
desired_class = BaseTypes.canonical_type_class(type_class)
|
139
|
+
value_class = BaseTypes.canonical_type_class(value.class)
|
140
|
+
return value if desired_class == value_class
|
141
|
+
desired_name = BaseTypes.class_to_type_name(desired_class)
|
142
|
+
case desired_name
|
143
|
+
when :int
|
144
|
+
Integer(value)
|
145
|
+
when :string
|
146
|
+
value.to_s
|
147
|
+
when :bool
|
148
|
+
return false if value.nil?
|
149
|
+
value = value.to_s
|
150
|
+
return true if value == 'true'
|
151
|
+
return false if value == 'false'
|
152
|
+
raise(TypeError, "can't convert #{value} to boolean")
|
153
|
+
when :float
|
154
|
+
Float(value)
|
155
|
+
when :time
|
156
|
+
Time.parse(value.to_s)
|
157
|
+
when :date
|
158
|
+
Date.parse(value.to_s)
|
159
|
+
end
|
160
|
+
end
|
161
|
+
end
|
162
|
+
end
|
data/test/abstract_client.rb
CHANGED
@@ -20,6 +20,7 @@ module ClientTest
|
|
20
20
|
api_method :struct_pass, :expects => [[Person]], :returns => [:bool]
|
21
21
|
api_method :client_container, :returns => [:int]
|
22
22
|
api_method :named_parameters, :expects => [{:key=>:string}, {:id=>:int}]
|
23
|
+
api_method :thrower
|
23
24
|
end
|
24
25
|
|
25
26
|
class NullLogOut
|
@@ -29,11 +30,11 @@ module ClientTest
|
|
29
30
|
class Container < ActionController::Base
|
30
31
|
web_service_api API
|
31
32
|
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
33
|
+
attr_accessor :value_void
|
34
|
+
attr_accessor :value_normal
|
35
|
+
attr_accessor :value_array_return
|
36
|
+
attr_accessor :value_struct_pass
|
37
|
+
attr_accessor :value_named_parameters
|
37
38
|
|
38
39
|
def initialize
|
39
40
|
@session = @assigns = {}
|
@@ -73,12 +74,8 @@ module ClientTest
|
|
73
74
|
@value_named_parameters = @method_params
|
74
75
|
end
|
75
76
|
|
76
|
-
def
|
77
|
-
|
78
|
-
end
|
79
|
-
|
80
|
-
def dispatch_request(protocol_request)
|
81
|
-
dispatch_protocol_request(protocol_request)
|
77
|
+
def thrower
|
78
|
+
raise "Hi"
|
82
79
|
end
|
83
80
|
end
|
84
81
|
|
@@ -0,0 +1,370 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/abstract_unit'
|
2
|
+
|
3
|
+
module DispatcherTest
|
4
|
+
class Node < ActiveRecord::Base
|
5
|
+
def initialize(*args)
|
6
|
+
super(*args)
|
7
|
+
@new_record = false
|
8
|
+
end
|
9
|
+
|
10
|
+
class << self
|
11
|
+
def name
|
12
|
+
"DispatcherTest::Node"
|
13
|
+
end
|
14
|
+
|
15
|
+
def columns(*args)
|
16
|
+
[
|
17
|
+
ActiveRecord::ConnectionAdapters::Column.new('id', 0, 'int'),
|
18
|
+
ActiveRecord::ConnectionAdapters::Column.new('name', nil, 'string'),
|
19
|
+
ActiveRecord::ConnectionAdapters::Column.new('description', nil, 'string'),
|
20
|
+
]
|
21
|
+
end
|
22
|
+
|
23
|
+
def connection
|
24
|
+
self
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
class Person < ActionWebService::Struct
|
30
|
+
member :id, :int
|
31
|
+
member :name, :string
|
32
|
+
end
|
33
|
+
|
34
|
+
class API < ActionWebService::API::Base
|
35
|
+
api_method :add, :expects => [:int, :int], :returns => [:int]
|
36
|
+
api_method :interceptee
|
37
|
+
api_method :struct_return, :returns => [[Node]]
|
38
|
+
api_method :void
|
39
|
+
end
|
40
|
+
|
41
|
+
class DirectAPI < ActionWebService::API::Base
|
42
|
+
api_method :add, :expects => [{:a=>:int}, {:b=>:int}], :returns => [:int]
|
43
|
+
api_method :before_filtered
|
44
|
+
api_method :after_filtered, :returns => [[:int]]
|
45
|
+
api_method :struct_return, :returns => [[Node]]
|
46
|
+
api_method :base_struct_return, :returns => [[Person]]
|
47
|
+
api_method :thrower
|
48
|
+
api_method :void
|
49
|
+
end
|
50
|
+
|
51
|
+
class VirtualAPI < ActionWebService::API::Base
|
52
|
+
default_api_method :fallback
|
53
|
+
end
|
54
|
+
|
55
|
+
class Service < ActionWebService::Base
|
56
|
+
web_service_api API
|
57
|
+
|
58
|
+
before_invocation :do_intercept, :only => [:interceptee]
|
59
|
+
|
60
|
+
attr :added
|
61
|
+
attr :intercepted
|
62
|
+
attr :void_called
|
63
|
+
|
64
|
+
def initialize
|
65
|
+
@void_called = false
|
66
|
+
end
|
67
|
+
|
68
|
+
def add(a, b)
|
69
|
+
@added = a + b
|
70
|
+
end
|
71
|
+
|
72
|
+
def interceptee
|
73
|
+
@intercepted = false
|
74
|
+
end
|
75
|
+
|
76
|
+
def struct_return
|
77
|
+
n1 = Node.new('id' => 1, 'name' => 'node1', 'description' => 'Node 1')
|
78
|
+
n2 = Node.new('id' => 2, 'name' => 'node2', 'description' => 'Node 2')
|
79
|
+
[n1, n2]
|
80
|
+
end
|
81
|
+
|
82
|
+
def void(*args)
|
83
|
+
@void_called = args
|
84
|
+
end
|
85
|
+
|
86
|
+
def do_intercept(name, args)
|
87
|
+
[false, "permission denied"]
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
class MTAPI < ActionWebService::API::Base
|
92
|
+
inflect_names false
|
93
|
+
api_method :getCategories, :returns => [[:string]]
|
94
|
+
end
|
95
|
+
|
96
|
+
class BloggerAPI < ActionWebService::API::Base
|
97
|
+
inflect_names false
|
98
|
+
api_method :getCategories, :returns => [[:string]]
|
99
|
+
end
|
100
|
+
|
101
|
+
class MTService < ActionWebService::Base
|
102
|
+
web_service_api MTAPI
|
103
|
+
|
104
|
+
def getCategories
|
105
|
+
["mtCat1", "mtCat2"]
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
class BloggerService < ActionWebService::Base
|
110
|
+
web_service_api BloggerAPI
|
111
|
+
|
112
|
+
def getCategories
|
113
|
+
["bloggerCat1", "bloggerCat2"]
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
class AbstractController < ActionController::Base
|
118
|
+
def generate_wsdl
|
119
|
+
to_wsdl
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
123
|
+
class DelegatedController < AbstractController
|
124
|
+
web_service_dispatching_mode :delegated
|
125
|
+
|
126
|
+
web_service(:test_service) { @service ||= Service.new; @service }
|
127
|
+
end
|
128
|
+
|
129
|
+
class LayeredController < AbstractController
|
130
|
+
web_service_dispatching_mode :layered
|
131
|
+
|
132
|
+
web_service(:mt) { @mt_service ||= MTService.new; @mt_service }
|
133
|
+
web_service(:blogger) { @blogger_service ||= BloggerService.new; @blogger_service }
|
134
|
+
end
|
135
|
+
|
136
|
+
class DirectController < AbstractController
|
137
|
+
web_service_api DirectAPI
|
138
|
+
web_service_dispatching_mode :direct
|
139
|
+
|
140
|
+
before_filter :alwaysfail, :only => [:before_filtered]
|
141
|
+
after_filter :alwaysok, :only => [:after_filtered]
|
142
|
+
|
143
|
+
attr :added
|
144
|
+
attr :before_filter_called
|
145
|
+
attr :before_filter_target_called
|
146
|
+
attr :after_filter_called
|
147
|
+
attr :after_filter_target_called
|
148
|
+
attr :void_called
|
149
|
+
|
150
|
+
def initialize
|
151
|
+
@before_filter_called = false
|
152
|
+
@before_filter_target_called = false
|
153
|
+
@after_filter_called = false
|
154
|
+
@after_filter_target_called = false
|
155
|
+
@void_called = false
|
156
|
+
end
|
157
|
+
|
158
|
+
def add
|
159
|
+
@added = @params['a'] + @params['b']
|
160
|
+
end
|
161
|
+
|
162
|
+
def before_filtered
|
163
|
+
@before_filter_target_called = true
|
164
|
+
end
|
165
|
+
|
166
|
+
def after_filtered
|
167
|
+
@after_filter_target_called = true
|
168
|
+
[5, 6, 7]
|
169
|
+
end
|
170
|
+
|
171
|
+
def thrower
|
172
|
+
raise "Hi, I'm an exception"
|
173
|
+
end
|
174
|
+
|
175
|
+
def struct_return
|
176
|
+
n1 = Node.new('id' => 1, 'name' => 'node1', 'description' => 'Node 1')
|
177
|
+
n2 = Node.new('id' => 2, 'name' => 'node2', 'description' => 'Node 2')
|
178
|
+
[n1, n2]
|
179
|
+
end
|
180
|
+
|
181
|
+
def base_struct_return
|
182
|
+
p1 = Person.new('id' => 1, 'name' => 'person1')
|
183
|
+
p2 = Person.new('id' => 2, 'name' => 'person2')
|
184
|
+
[p1, p2]
|
185
|
+
end
|
186
|
+
|
187
|
+
def void
|
188
|
+
@void_called = @method_params
|
189
|
+
end
|
190
|
+
|
191
|
+
protected
|
192
|
+
def alwaysfail
|
193
|
+
@before_filter_called = true
|
194
|
+
false
|
195
|
+
end
|
196
|
+
|
197
|
+
def alwaysok
|
198
|
+
@after_filter_called = true
|
199
|
+
end
|
200
|
+
end
|
201
|
+
|
202
|
+
class VirtualController < AbstractController
|
203
|
+
web_service_api VirtualAPI
|
204
|
+
|
205
|
+
def fallback
|
206
|
+
"fallback!"
|
207
|
+
end
|
208
|
+
end
|
209
|
+
end
|
210
|
+
|
211
|
+
module DispatcherCommonTests
|
212
|
+
def test_direct_dispatching
|
213
|
+
assert_equal(70, do_method_call(@direct_controller, 'Add', 20, 50))
|
214
|
+
assert_equal(70, @direct_controller.added)
|
215
|
+
assert(@direct_controller.void_called == false)
|
216
|
+
case @encoder
|
217
|
+
when WS::Encoding::SoapRpcEncoding
|
218
|
+
assert(do_method_call(@direct_controller, 'Void', 3, 4, 5).nil?)
|
219
|
+
when WS::Encoding::XmlRpcEncoding
|
220
|
+
assert(do_method_call(@direct_controller, 'Void', 3, 4, 5) == true)
|
221
|
+
end
|
222
|
+
assert(@direct_controller.void_called == [])
|
223
|
+
result = do_method_call(@direct_controller, 'BaseStructReturn')
|
224
|
+
case @encoder
|
225
|
+
when WS::Encoding::SoapRpcEncoding
|
226
|
+
assert(result[0].is_a?(DispatcherTest::Person))
|
227
|
+
assert(result[1].is_a?(DispatcherTest::Person))
|
228
|
+
when WS::Encoding::XmlRpcEncoding
|
229
|
+
assert(result[0].is_a?(Hash))
|
230
|
+
assert(result[1].is_a?(Hash))
|
231
|
+
end
|
232
|
+
end
|
233
|
+
|
234
|
+
def test_direct_entrypoint
|
235
|
+
assert(@direct_controller.respond_to?(:api))
|
236
|
+
end
|
237
|
+
|
238
|
+
def test_virtual_dispatching
|
239
|
+
assert_equal("fallback!", do_method_call(@virtual_controller, 'VirtualOne'))
|
240
|
+
assert_equal("fallback!", do_method_call(@virtual_controller, 'VirtualTwo'))
|
241
|
+
end
|
242
|
+
|
243
|
+
def test_direct_filtering
|
244
|
+
assert_equal(false, @direct_controller.before_filter_called)
|
245
|
+
assert_equal(false, @direct_controller.before_filter_target_called)
|
246
|
+
do_method_call(@direct_controller, 'BeforeFiltered')
|
247
|
+
assert_equal(true, @direct_controller.before_filter_called)
|
248
|
+
assert_equal(false, @direct_controller.before_filter_target_called)
|
249
|
+
assert_equal(false, @direct_controller.after_filter_called)
|
250
|
+
assert_equal(false, @direct_controller.after_filter_target_called)
|
251
|
+
assert_equal([5, 6, 7], do_method_call(@direct_controller, 'AfterFiltered'))
|
252
|
+
assert_equal(true, @direct_controller.after_filter_called)
|
253
|
+
assert_equal(true, @direct_controller.after_filter_target_called)
|
254
|
+
end
|
255
|
+
|
256
|
+
def test_delegated_dispatching
|
257
|
+
assert_equal(130, do_method_call(@delegated_controller, 'Add', 50, 80))
|
258
|
+
service = @delegated_controller.web_service_object(:test_service)
|
259
|
+
assert_equal(130, service.added)
|
260
|
+
@delegated_controller.web_service_exception_reporting = true
|
261
|
+
assert(service.intercepted.nil?)
|
262
|
+
result = do_method_call(@delegated_controller, 'Interceptee')
|
263
|
+
assert(service.intercepted.nil?)
|
264
|
+
assert(is_exception?(result))
|
265
|
+
assert_match(/permission denied/, exception_message(result))
|
266
|
+
result = do_method_call(@delegated_controller, 'NonExistentMethod')
|
267
|
+
assert(is_exception?(result))
|
268
|
+
assert_match(/NonExistentMethod/, exception_message(result))
|
269
|
+
assert(service.void_called == false)
|
270
|
+
case @encoder
|
271
|
+
when WS::Encoding::SoapRpcEncoding
|
272
|
+
assert(do_method_call(@delegated_controller, 'Void', 3, 4, 5).nil?)
|
273
|
+
when WS::Encoding::XmlRpcEncoding
|
274
|
+
assert(do_method_call(@delegated_controller, 'Void', 3, 4, 5) == true)
|
275
|
+
end
|
276
|
+
assert(service.void_called == [])
|
277
|
+
end
|
278
|
+
|
279
|
+
def test_garbage_request
|
280
|
+
[@direct_controller, @delegated_controller].each do |controller|
|
281
|
+
controller.class.web_service_exception_reporting = true
|
282
|
+
send_garbage_request = lambda do
|
283
|
+
request = create_ap_request(controller, 'invalid request body', 'xxx')
|
284
|
+
response = ActionController::TestResponse.new
|
285
|
+
controller.process(request, response)
|
286
|
+
# puts response.body
|
287
|
+
assert(response.headers['Status'] =~ /^500/)
|
288
|
+
end
|
289
|
+
send_garbage_request.call
|
290
|
+
controller.class.web_service_exception_reporting = false
|
291
|
+
send_garbage_request.call
|
292
|
+
end
|
293
|
+
end
|
294
|
+
|
295
|
+
def test_exception_marshaling
|
296
|
+
@direct_controller.web_service_exception_reporting = true
|
297
|
+
result = do_method_call(@direct_controller, 'Thrower')
|
298
|
+
assert(is_exception?(result))
|
299
|
+
assert_equal("Hi, I'm an exception", exception_message(result))
|
300
|
+
@direct_controller.web_service_exception_reporting = false
|
301
|
+
result = do_method_call(@direct_controller, 'Thrower')
|
302
|
+
assert(exception_message(result) != "Hi, I'm an exception")
|
303
|
+
end
|
304
|
+
|
305
|
+
def test_ar_struct_return
|
306
|
+
[@direct_controller, @delegated_controller].each do |controller|
|
307
|
+
result = do_method_call(controller, 'StructReturn')
|
308
|
+
case @encoder
|
309
|
+
when WS::Encoding::SoapRpcEncoding
|
310
|
+
assert(result[0].is_a?(DispatcherTest::Node))
|
311
|
+
assert(result[1].is_a?(DispatcherTest::Node))
|
312
|
+
assert_equal('node1', result[0].name)
|
313
|
+
assert_equal('node2', result[1].name)
|
314
|
+
when WS::Encoding::XmlRpcEncoding
|
315
|
+
assert(result[0].is_a?(Hash))
|
316
|
+
assert(result[1].is_a?(Hash))
|
317
|
+
assert_equal('node1', result[0]['name'])
|
318
|
+
assert_equal('node2', result[1]['name'])
|
319
|
+
end
|
320
|
+
end
|
321
|
+
end
|
322
|
+
|
323
|
+
protected
|
324
|
+
def service_name(container)
|
325
|
+
raise NotImplementedError
|
326
|
+
end
|
327
|
+
|
328
|
+
def exception_message(obj)
|
329
|
+
raise NotImplementedError
|
330
|
+
end
|
331
|
+
|
332
|
+
def is_exception?(obj)
|
333
|
+
raise NotImplementedError
|
334
|
+
end
|
335
|
+
|
336
|
+
def do_method_call(container, public_method_name, *params)
|
337
|
+
mode = container.web_service_dispatching_mode
|
338
|
+
case mode
|
339
|
+
when :direct
|
340
|
+
api = container.class.web_service_api
|
341
|
+
when :delegated
|
342
|
+
api = container.web_service_object(service_name(container)).class.web_service_api
|
343
|
+
when :layered
|
344
|
+
service_name = nil
|
345
|
+
if public_method_name =~ /^([^\.]+)\.(.*)$/
|
346
|
+
service_name = $1
|
347
|
+
end
|
348
|
+
api = container.web_service_object(service_name.to_sym).class.web_service_api
|
349
|
+
end
|
350
|
+
info = api.api_methods[method_name] || {}
|
351
|
+
params = params.dup
|
352
|
+
((info[:expects] || []) + (info[:returns] || [])).each do |spec|
|
353
|
+
@marshaler.register_type(spec)
|
354
|
+
end
|
355
|
+
expects = info[:expects]
|
356
|
+
(0..(params.length-1)).each do |i|
|
357
|
+
type_binding = @marshaler.register_type(expects ? expects[i] : params[i].class)
|
358
|
+
info = WS::ParamInfo.create(expects ? expects[i] : params[i].class, type_binding, i)
|
359
|
+
params[i] = @marshaler.marshal(WS::Param.new(params[i], info))
|
360
|
+
end
|
361
|
+
body = @encoder.encode_rpc_call(public_method_name, params)
|
362
|
+
# puts body
|
363
|
+
ap_request = create_ap_request(container, body, public_method_name, *params)
|
364
|
+
ap_response = ActionController::TestResponse.new
|
365
|
+
container.process(ap_request, ap_response)
|
366
|
+
# puts ap_response.body
|
367
|
+
public_method_name, return_value = @encoder.decode_rpc_response(ap_response.body)
|
368
|
+
@marshaler.unmarshal(return_value).value
|
369
|
+
end
|
370
|
+
end
|