rubyjedi-actionwebservice 2.3.5.20100615120735
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 +335 -0
- data/MIT-LICENSE +21 -0
- data/README +381 -0
- data/Rakefile +180 -0
- data/TODO +32 -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 +17 -0
- data/examples/metaWeblog/apis/blogger_api.rb +60 -0
- data/examples/metaWeblog/apis/blogger_service.rb +34 -0
- data/examples/metaWeblog/apis/meta_weblog_api.rb +67 -0
- data/examples/metaWeblog/apis/meta_weblog_service.rb +48 -0
- data/examples/metaWeblog/controllers/xmlrpc_controller.rb +16 -0
- data/generators/web_service/USAGE +28 -0
- data/generators/web_service/templates/api_definition.rb +5 -0
- data/generators/web_service/templates/controller.rb +8 -0
- data/generators/web_service/templates/functional_test.rb +19 -0
- data/generators/web_service/web_service_generator.rb +29 -0
- data/lib/action_web_service/acts_as_web_service.rb +24 -0
- data/lib/action_web_service/api.rb +297 -0
- data/lib/action_web_service/base.rb +38 -0
- data/lib/action_web_service/casting.rb +151 -0
- data/lib/action_web_service/client/base.rb +28 -0
- data/lib/action_web_service/client/soap_client.rb +113 -0
- data/lib/action_web_service/client/xmlrpc_client.rb +58 -0
- data/lib/action_web_service/client.rb +3 -0
- data/lib/action_web_service/container/action_controller_container.rb +93 -0
- data/lib/action_web_service/container/delegated_container.rb +86 -0
- data/lib/action_web_service/container/direct_container.rb +69 -0
- data/lib/action_web_service/container.rb +3 -0
- data/lib/action_web_service/dispatcher/abstract.rb +208 -0
- data/lib/action_web_service/dispatcher/action_controller_dispatcher.rb +396 -0
- data/lib/action_web_service/dispatcher.rb +2 -0
- data/lib/action_web_service/invocation.rb +202 -0
- data/lib/action_web_service/protocol/abstract.rb +112 -0
- data/lib/action_web_service/protocol/discovery.rb +37 -0
- data/lib/action_web_service/protocol/soap_protocol/marshaler.rb +242 -0
- data/lib/action_web_service/protocol/soap_protocol.rb +176 -0
- data/lib/action_web_service/protocol/xmlrpc_protocol.rb +123 -0
- data/lib/action_web_service/protocol.rb +4 -0
- data/lib/action_web_service/scaffolding.rb +281 -0
- data/lib/action_web_service/simple.rb +53 -0
- data/lib/action_web_service/string_to_datetime_for_soap.rb +16 -0
- data/lib/action_web_service/struct.rb +68 -0
- data/lib/action_web_service/support/class_inheritable_options.rb +26 -0
- data/lib/action_web_service/support/signature_types.rb +261 -0
- data/lib/action_web_service/templates/scaffolds/layout.html.erb +65 -0
- data/lib/action_web_service/templates/scaffolds/methods.html.erb +6 -0
- data/lib/action_web_service/templates/scaffolds/parameters.html.erb +29 -0
- data/lib/action_web_service/templates/scaffolds/result.html.erb +30 -0
- data/lib/action_web_service/test_invoke.rb +110 -0
- data/lib/action_web_service/version.rb +9 -0
- data/lib/action_web_service.rb +60 -0
- data/lib/actionwebservice.rb +1 -0
- data/setup.rb +1379 -0
- data/test/abstract_client.rb +184 -0
- data/test/abstract_dispatcher.rb +549 -0
- data/test/abstract_unit.rb +43 -0
- data/test/actionwebservice_unittest.db +0 -0
- data/test/api_test.rb +102 -0
- data/test/apis/auto_load_api.rb +3 -0
- data/test/apis/broken_auto_load_api.rb +2 -0
- data/test/base_test.rb +42 -0
- data/test/casting_test.rb +95 -0
- data/test/client_soap_test.rb +156 -0
- data/test/client_xmlrpc_test.rb +154 -0
- data/test/container_test.rb +75 -0
- data/test/debug.log +12305 -0
- data/test/dispatcher_action_controller_soap_test.rb +139 -0
- data/test/dispatcher_action_controller_xmlrpc_test.rb +59 -0
- data/test/fixtures/db_definitions/mysql.sql +8 -0
- data/test/fixtures/db_definitions/sqlite3.sql +8 -0
- data/test/fixtures/users.yml +12 -0
- data/test/gencov +3 -0
- data/test/invocation_test.rb +186 -0
- data/test/run +6 -0
- data/test/scaffolded_controller_test.rb +147 -0
- data/test/struct_test.rb +84 -0
- data/test/test_invoke_test.rb +113 -0
- metadata +182 -0
@@ -0,0 +1,549 @@
|
|
1
|
+
require 'abstract_unit'
|
2
|
+
require 'stringio'
|
3
|
+
|
4
|
+
class ActionController::Base; def rescue_action(e) raise e end; end
|
5
|
+
|
6
|
+
module DispatcherTest
|
7
|
+
Utf8String = "One World Caf\303\251"
|
8
|
+
WsdlNamespace = 'http://rubyonrails.com/some/namespace'
|
9
|
+
|
10
|
+
class Node < ActiveRecord::Base
|
11
|
+
def initialize(*args)
|
12
|
+
super(*args)
|
13
|
+
@new_record = false
|
14
|
+
end
|
15
|
+
|
16
|
+
class << self
|
17
|
+
def name
|
18
|
+
"DispatcherTest::Node"
|
19
|
+
end
|
20
|
+
|
21
|
+
def columns(*args)
|
22
|
+
[
|
23
|
+
ActiveRecord::ConnectionAdapters::Column.new('id', 0, 'int'),
|
24
|
+
ActiveRecord::ConnectionAdapters::Column.new('name', nil, 'string'),
|
25
|
+
ActiveRecord::ConnectionAdapters::Column.new('description', nil, 'string'),
|
26
|
+
]
|
27
|
+
end
|
28
|
+
|
29
|
+
def connection
|
30
|
+
self
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
class Person < ActionWebService::Struct
|
36
|
+
member :id, :int
|
37
|
+
member :name, :string
|
38
|
+
|
39
|
+
def ==(other)
|
40
|
+
self.id == other.id && self.name == other.name
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
class API < ActionWebService::API::Base
|
45
|
+
api_method :add, :expects => [:int, :int], :returns => [:int]
|
46
|
+
api_method :interceptee
|
47
|
+
api_method :struct_return, :returns => [[Node]]
|
48
|
+
api_method :void
|
49
|
+
end
|
50
|
+
|
51
|
+
class DirectAPI < ActionWebService::API::Base
|
52
|
+
api_method :add, :expects => [{:a=>:int}, {:b=>:int}], :returns => [:int]
|
53
|
+
api_method :add2, :expects => [{:a=>:int}, {:b=>:int}], :returns => [:int]
|
54
|
+
api_method :before_filtered
|
55
|
+
api_method :after_filtered, :returns => [[:int]]
|
56
|
+
api_method :struct_return, :returns => [[Node]]
|
57
|
+
api_method :struct_pass, :expects => [{:person => Person}]
|
58
|
+
api_method :base_struct_return, :returns => [[Person]]
|
59
|
+
api_method :hash_struct_return, :returns => [[Person]]
|
60
|
+
api_method :thrower
|
61
|
+
api_method :void
|
62
|
+
api_method :test_utf8, :returns => [:string]
|
63
|
+
api_method :hex, :expects => [:base64], :returns => [:string]
|
64
|
+
api_method :unhex, :expects => [:string], :returns => [:base64]
|
65
|
+
api_method :time, :expects => [:time], :returns => [:time]
|
66
|
+
end
|
67
|
+
|
68
|
+
class VirtualAPI < ActionWebService::API::Base
|
69
|
+
default_api_method :fallback
|
70
|
+
end
|
71
|
+
|
72
|
+
class Service < ActionWebService::Base
|
73
|
+
web_service_api API
|
74
|
+
|
75
|
+
before_invocation :do_intercept, :only => [:interceptee]
|
76
|
+
|
77
|
+
attr :added
|
78
|
+
attr :intercepted
|
79
|
+
attr :void_called
|
80
|
+
|
81
|
+
def initialize
|
82
|
+
@void_called = false
|
83
|
+
end
|
84
|
+
|
85
|
+
def add(a, b)
|
86
|
+
@added = a + b
|
87
|
+
end
|
88
|
+
|
89
|
+
def interceptee
|
90
|
+
@intercepted = false
|
91
|
+
end
|
92
|
+
|
93
|
+
def struct_return
|
94
|
+
n1 = Node.new('id' => 1, 'name' => 'node1', 'description' => 'Node 1')
|
95
|
+
n2 = Node.new('id' => 2, 'name' => 'node2', 'description' => 'Node 2')
|
96
|
+
[n1, n2]
|
97
|
+
end
|
98
|
+
|
99
|
+
def void(*args)
|
100
|
+
@void_called = args
|
101
|
+
end
|
102
|
+
|
103
|
+
def do_intercept(name, args)
|
104
|
+
[false, "permission denied"]
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
class MTAPI < ActionWebService::API::Base
|
109
|
+
inflect_names false
|
110
|
+
api_method :getCategories, :returns => [[:string]]
|
111
|
+
api_method :bool, :returns => [:bool]
|
112
|
+
api_method :alwaysFail
|
113
|
+
api_method :person, :returns => [Person]
|
114
|
+
end
|
115
|
+
|
116
|
+
class BloggerAPI < ActionWebService::API::Base
|
117
|
+
inflect_names false
|
118
|
+
api_method :getCategories, :returns => [[:string]]
|
119
|
+
api_method :str, :expects => [:int], :returns => [:string]
|
120
|
+
api_method :alwaysFail
|
121
|
+
end
|
122
|
+
|
123
|
+
class MTService < ActionWebService::Base
|
124
|
+
web_service_api MTAPI
|
125
|
+
|
126
|
+
def getCategories
|
127
|
+
["mtCat1", "mtCat2"]
|
128
|
+
end
|
129
|
+
|
130
|
+
def bool
|
131
|
+
'y'
|
132
|
+
end
|
133
|
+
|
134
|
+
def alwaysFail
|
135
|
+
raise "MT AlwaysFail"
|
136
|
+
end
|
137
|
+
|
138
|
+
def person
|
139
|
+
Person.new('id' => 1, 'name' => 'person1')
|
140
|
+
end
|
141
|
+
end
|
142
|
+
|
143
|
+
class BloggerService < ActionWebService::Base
|
144
|
+
web_service_api BloggerAPI
|
145
|
+
|
146
|
+
def getCategories
|
147
|
+
["bloggerCat1", "bloggerCat2"]
|
148
|
+
end
|
149
|
+
|
150
|
+
def str(int)
|
151
|
+
unless int.is_a?(Integer)
|
152
|
+
raise "Not an integer!"
|
153
|
+
end
|
154
|
+
500 + int
|
155
|
+
end
|
156
|
+
|
157
|
+
def alwaysFail
|
158
|
+
raise "Blogger AlwaysFail"
|
159
|
+
end
|
160
|
+
end
|
161
|
+
|
162
|
+
class AbstractController < ActionController::Base
|
163
|
+
acts_as_web_service
|
164
|
+
def generate_wsdl
|
165
|
+
self.request ||= ::ActionController::TestRequest.new
|
166
|
+
to_wsdl
|
167
|
+
end
|
168
|
+
end
|
169
|
+
|
170
|
+
class DelegatedController < AbstractController
|
171
|
+
web_service_dispatching_mode :delegated
|
172
|
+
wsdl_namespace WsdlNamespace
|
173
|
+
|
174
|
+
web_service(:test_service) { @service ||= Service.new; @service }
|
175
|
+
end
|
176
|
+
|
177
|
+
class LayeredController < AbstractController
|
178
|
+
web_service_dispatching_mode :layered
|
179
|
+
wsdl_namespace WsdlNamespace
|
180
|
+
|
181
|
+
web_service(:mt) { @mt_service ||= MTService.new; @mt_service }
|
182
|
+
web_service(:blogger) { @blogger_service ||= BloggerService.new; @blogger_service }
|
183
|
+
end
|
184
|
+
|
185
|
+
class DirectController < AbstractController
|
186
|
+
web_service_api DirectAPI
|
187
|
+
web_service_dispatching_mode :direct
|
188
|
+
wsdl_namespace WsdlNamespace
|
189
|
+
|
190
|
+
before_invocation :alwaysfail, :only => [:before_filtered]
|
191
|
+
after_invocation :alwaysok, :only => [:after_filtered]
|
192
|
+
|
193
|
+
attr :added
|
194
|
+
attr :added2
|
195
|
+
attr :before_filter_called
|
196
|
+
attr :before_filter_target_called
|
197
|
+
attr :after_filter_called
|
198
|
+
attr :after_filter_target_called
|
199
|
+
attr :void_called
|
200
|
+
attr :struct_pass_value
|
201
|
+
|
202
|
+
def initialize
|
203
|
+
@before_filter_called = false
|
204
|
+
@before_filter_target_called = false
|
205
|
+
@after_filter_called = false
|
206
|
+
@after_filter_target_called = false
|
207
|
+
@void_called = false
|
208
|
+
@struct_pass_value = false
|
209
|
+
end
|
210
|
+
|
211
|
+
def add
|
212
|
+
@added = params['a'] + params['b']
|
213
|
+
end
|
214
|
+
|
215
|
+
def add2(a, b)
|
216
|
+
@added2 = a + b
|
217
|
+
end
|
218
|
+
|
219
|
+
def before_filtered
|
220
|
+
@before_filter_target_called = true
|
221
|
+
end
|
222
|
+
|
223
|
+
def after_filtered
|
224
|
+
@after_filter_target_called = true
|
225
|
+
[5, 6, 7]
|
226
|
+
end
|
227
|
+
|
228
|
+
def thrower
|
229
|
+
raise "Hi, I'm an exception"
|
230
|
+
end
|
231
|
+
|
232
|
+
def struct_return
|
233
|
+
n1 = Node.new('id' => 1, 'name' => 'node1', 'description' => 'Node 1')
|
234
|
+
n2 = Node.new('id' => 2, 'name' => 'node2', 'description' => 'Node 2')
|
235
|
+
[n1, n2]
|
236
|
+
end
|
237
|
+
|
238
|
+
def struct_pass(person)
|
239
|
+
@struct_pass_value = person
|
240
|
+
end
|
241
|
+
|
242
|
+
def base_struct_return
|
243
|
+
p1 = Person.new('id' => 1, 'name' => 'person1')
|
244
|
+
p2 = Person.new('id' => 2, 'name' => 'person2')
|
245
|
+
[p1, p2]
|
246
|
+
end
|
247
|
+
|
248
|
+
def hash_struct_return
|
249
|
+
p1 = { :id => '1', 'name' => 'test' }
|
250
|
+
p2 = { 'id' => '2', :name => 'person2' }
|
251
|
+
[p1, p2]
|
252
|
+
end
|
253
|
+
|
254
|
+
def void
|
255
|
+
@void_called = @method_params
|
256
|
+
end
|
257
|
+
|
258
|
+
def test_utf8
|
259
|
+
Utf8String
|
260
|
+
end
|
261
|
+
|
262
|
+
def hex(s)
|
263
|
+
return s.unpack("H*")[0]
|
264
|
+
end
|
265
|
+
|
266
|
+
def unhex(s)
|
267
|
+
return [s].pack("H*")
|
268
|
+
end
|
269
|
+
|
270
|
+
def time(t)
|
271
|
+
t
|
272
|
+
end
|
273
|
+
|
274
|
+
protected
|
275
|
+
def alwaysfail(method_name, params)
|
276
|
+
@before_filter_called = true
|
277
|
+
false
|
278
|
+
end
|
279
|
+
|
280
|
+
def alwaysok(method_name, params, return_value)
|
281
|
+
@after_filter_called = true
|
282
|
+
end
|
283
|
+
end
|
284
|
+
|
285
|
+
class VirtualController < AbstractController
|
286
|
+
web_service_api VirtualAPI
|
287
|
+
wsdl_namespace WsdlNamespace
|
288
|
+
|
289
|
+
def fallback
|
290
|
+
"fallback!"
|
291
|
+
end
|
292
|
+
end
|
293
|
+
end
|
294
|
+
|
295
|
+
module DispatcherCommonTests
|
296
|
+
def test_direct_dispatching
|
297
|
+
assert_equal(70, do_method_call(@direct_controller, 'Add', 20, 50))
|
298
|
+
assert_equal(70, @direct_controller.added)
|
299
|
+
assert_equal(50, do_method_call(@direct_controller, 'Add2', 25, 25))
|
300
|
+
assert_equal(50, @direct_controller.added2)
|
301
|
+
assert(@direct_controller.void_called == false)
|
302
|
+
assert(do_method_call(@direct_controller, 'Void', 3, 4, 5).nil?)
|
303
|
+
assert(@direct_controller.void_called == [])
|
304
|
+
result = do_method_call(@direct_controller, 'BaseStructReturn')
|
305
|
+
assert(result[0].is_a?(DispatcherTest::Person))
|
306
|
+
assert(result[1].is_a?(DispatcherTest::Person))
|
307
|
+
assert_equal("cafe", do_method_call(@direct_controller, 'Hex', "\xca\xfe"))
|
308
|
+
assert_equal("\xca\xfe", do_method_call(@direct_controller, 'Unhex', "cafe"))
|
309
|
+
time = Time.gm(1998, "Feb", 02, 15, 12, 01)
|
310
|
+
assert_equal(time, do_method_call(@direct_controller, 'Time', time))
|
311
|
+
end
|
312
|
+
|
313
|
+
def test_direct_entrypoint
|
314
|
+
assert(@direct_controller.respond_to?(:api))
|
315
|
+
end
|
316
|
+
|
317
|
+
def test_virtual_dispatching
|
318
|
+
assert_equal("fallback!", do_method_call(@virtual_controller, 'VirtualOne'))
|
319
|
+
assert_equal("fallback!", do_method_call(@virtual_controller, 'VirtualTwo'))
|
320
|
+
end
|
321
|
+
|
322
|
+
def test_direct_filtering
|
323
|
+
assert_equal(false, @direct_controller.before_filter_called)
|
324
|
+
assert_equal(false, @direct_controller.before_filter_target_called)
|
325
|
+
do_method_call(@direct_controller, 'BeforeFiltered')
|
326
|
+
assert_equal(true, @direct_controller.before_filter_called)
|
327
|
+
assert_equal(false, @direct_controller.before_filter_target_called)
|
328
|
+
assert_equal(false, @direct_controller.after_filter_called)
|
329
|
+
assert_equal(false, @direct_controller.after_filter_target_called)
|
330
|
+
assert_equal([5, 6, 7], do_method_call(@direct_controller, 'AfterFiltered'))
|
331
|
+
assert_equal(true, @direct_controller.after_filter_called)
|
332
|
+
assert_equal(true, @direct_controller.after_filter_target_called)
|
333
|
+
end
|
334
|
+
|
335
|
+
def test_delegated_dispatching
|
336
|
+
assert_equal(130, do_method_call(@delegated_controller, 'Add', 50, 80))
|
337
|
+
service = @delegated_controller.web_service_object(:test_service)
|
338
|
+
assert_equal(130, service.added)
|
339
|
+
@delegated_controller.web_service_exception_reporting = true
|
340
|
+
assert(service.intercepted.nil?)
|
341
|
+
result = do_method_call(@delegated_controller, 'Interceptee')
|
342
|
+
assert(service.intercepted.nil?)
|
343
|
+
assert(is_exception?(result))
|
344
|
+
assert_match(/permission denied/, exception_message(result))
|
345
|
+
result = do_method_call(@delegated_controller, 'NonExistentMethod')
|
346
|
+
assert(is_exception?(result))
|
347
|
+
assert_match(/NonExistentMethod/, exception_message(result))
|
348
|
+
assert(service.void_called == false)
|
349
|
+
assert(do_method_call(@delegated_controller, 'Void', 3, 4, 5).nil?)
|
350
|
+
assert(service.void_called == [])
|
351
|
+
end
|
352
|
+
|
353
|
+
def test_garbage_request
|
354
|
+
[@direct_controller, @delegated_controller].each do |controller|
|
355
|
+
controller.class.web_service_exception_reporting = true
|
356
|
+
send_garbage_request = lambda do
|
357
|
+
service_name = service_name(controller)
|
358
|
+
request = protocol.encode_action_pack_request(service_name, 'broken, method, name!', 'broken request body', :request_class => ActionController::TestRequest)
|
359
|
+
response = ActionController::TestResponse.new
|
360
|
+
controller.process(request, response)
|
361
|
+
# puts response.body
|
362
|
+
assert(response.status =~ /^500/)
|
363
|
+
end
|
364
|
+
send_garbage_request.call
|
365
|
+
controller.class.web_service_exception_reporting = false
|
366
|
+
send_garbage_request.call
|
367
|
+
end
|
368
|
+
end
|
369
|
+
|
370
|
+
def test_exception_marshaling
|
371
|
+
@direct_controller.web_service_exception_reporting = true
|
372
|
+
result = do_method_call(@direct_controller, 'Thrower')
|
373
|
+
assert(is_exception?(result))
|
374
|
+
assert_equal("Hi, I'm an exception", exception_message(result))
|
375
|
+
@direct_controller.web_service_exception_reporting = false
|
376
|
+
result = do_method_call(@direct_controller, 'Thrower')
|
377
|
+
assert(exception_message(result) != "Hi, I'm an exception")
|
378
|
+
end
|
379
|
+
|
380
|
+
def test_ar_struct_return
|
381
|
+
[@direct_controller, @delegated_controller].each do |controller|
|
382
|
+
result = do_method_call(controller, 'StructReturn')
|
383
|
+
assert(result[0].is_a?(DispatcherTest::Node))
|
384
|
+
assert(result[1].is_a?(DispatcherTest::Node))
|
385
|
+
assert_equal('node1', result[0].name)
|
386
|
+
assert_equal('node2', result[1].name)
|
387
|
+
end
|
388
|
+
end
|
389
|
+
|
390
|
+
def test_casting
|
391
|
+
assert_equal 70, do_method_call(@direct_controller, 'Add', "50", "20")
|
392
|
+
assert_equal false, @direct_controller.struct_pass_value
|
393
|
+
person = DispatcherTest::Person.new(:id => 1, :name => 'test')
|
394
|
+
result = do_method_call(@direct_controller, 'StructPass', person)
|
395
|
+
assert(nil == result || true == result)
|
396
|
+
assert_equal person, @direct_controller.struct_pass_value
|
397
|
+
assert !person.equal?(@direct_controller.struct_pass_value)
|
398
|
+
result = do_method_call(@direct_controller, 'StructPass', {'id' => '1', 'name' => 'test'})
|
399
|
+
case
|
400
|
+
when soap?
|
401
|
+
assert_equal(person, @direct_controller.struct_pass_value)
|
402
|
+
assert !person.equal?(@direct_controller.struct_pass_value)
|
403
|
+
when xmlrpc?
|
404
|
+
assert_equal(person, @direct_controller.struct_pass_value)
|
405
|
+
assert !person.equal?(@direct_controller.struct_pass_value)
|
406
|
+
end
|
407
|
+
assert_equal person, do_method_call(@direct_controller, 'HashStructReturn')[0]
|
408
|
+
result = do_method_call(@direct_controller, 'StructPass', {'id' => '1', 'name' => 'test', 'nonexistent_attribute' => 'value'})
|
409
|
+
case
|
410
|
+
when soap?
|
411
|
+
assert_equal(person, @direct_controller.struct_pass_value)
|
412
|
+
assert !person.equal?(@direct_controller.struct_pass_value)
|
413
|
+
when xmlrpc?
|
414
|
+
assert_equal(person, @direct_controller.struct_pass_value)
|
415
|
+
assert !person.equal?(@direct_controller.struct_pass_value)
|
416
|
+
end
|
417
|
+
end
|
418
|
+
|
419
|
+
def test_logging
|
420
|
+
buf = ""
|
421
|
+
ActionController::Base.logger = Logger.new(StringIO.new(buf))
|
422
|
+
test_casting
|
423
|
+
test_garbage_request
|
424
|
+
test_exception_marshaling
|
425
|
+
ActionController::Base.logger = nil
|
426
|
+
assert_match /Web Service Response/, buf
|
427
|
+
assert_match /Web Service Request/, buf
|
428
|
+
end
|
429
|
+
|
430
|
+
def test_allowed_http_methods
|
431
|
+
webservice_api = @direct_controller.class.web_service_api
|
432
|
+
original_allowed_http_methods = webservice_api.allowed_http_methods
|
433
|
+
|
434
|
+
# check defaults
|
435
|
+
assert_equal false, http_method_allowed?(:get)
|
436
|
+
assert_equal false, http_method_allowed?(:head)
|
437
|
+
assert_equal false, http_method_allowed?(:put)
|
438
|
+
assert_equal false, http_method_allowed?(:delete)
|
439
|
+
assert_equal true, http_method_allowed?(:post)
|
440
|
+
|
441
|
+
# allow get and post
|
442
|
+
webservice_api.allowed_http_methods = [ :get, :post ]
|
443
|
+
assert_equal true, http_method_allowed?(:get)
|
444
|
+
assert_equal true, http_method_allowed?(:post)
|
445
|
+
|
446
|
+
# allow get only
|
447
|
+
webservice_api.allowed_http_methods = [ :get ]
|
448
|
+
assert_equal true, http_method_allowed?(:get)
|
449
|
+
assert_equal false, http_method_allowed?(:post)
|
450
|
+
|
451
|
+
# allow delete only
|
452
|
+
webservice_api.allowed_http_methods = [ 'DELETE' ]
|
453
|
+
assert_equal false, http_method_allowed?(:get)
|
454
|
+
assert_equal false, http_method_allowed?(:head)
|
455
|
+
assert_equal false, http_method_allowed?(:post)
|
456
|
+
assert_equal false, http_method_allowed?(:put)
|
457
|
+
assert_equal true, http_method_allowed?(:delete)
|
458
|
+
|
459
|
+
ensure
|
460
|
+
webservice_api.allowed_http_methods = original_allowed_http_methods
|
461
|
+
end
|
462
|
+
|
463
|
+
protected
|
464
|
+
def service_name(container)
|
465
|
+
raise NotImplementedError
|
466
|
+
end
|
467
|
+
|
468
|
+
def exception_message(obj)
|
469
|
+
raise NotImplementedError
|
470
|
+
end
|
471
|
+
|
472
|
+
def is_exception?(obj)
|
473
|
+
raise NotImplementedError
|
474
|
+
end
|
475
|
+
|
476
|
+
def protocol
|
477
|
+
@protocol
|
478
|
+
end
|
479
|
+
|
480
|
+
def soap?
|
481
|
+
protocol.is_a? ActionWebService::Protocol::Soap::SoapProtocol
|
482
|
+
end
|
483
|
+
|
484
|
+
def xmlrpc?
|
485
|
+
protocol.is_a? ActionWebService::Protocol::XmlRpc::XmlRpcProtocol
|
486
|
+
end
|
487
|
+
|
488
|
+
def do_method_call(container, public_method_name, *params)
|
489
|
+
request_env = {}
|
490
|
+
mode = container.web_service_dispatching_mode
|
491
|
+
case mode
|
492
|
+
when :direct
|
493
|
+
service_name = service_name(container)
|
494
|
+
api = container.class.web_service_api
|
495
|
+
method = api.public_api_method_instance(public_method_name)
|
496
|
+
when :delegated
|
497
|
+
service_name = service_name(container)
|
498
|
+
api = container.web_service_object(service_name).class.web_service_api
|
499
|
+
method = api.public_api_method_instance(public_method_name)
|
500
|
+
when :layered
|
501
|
+
service_name = nil
|
502
|
+
real_method_name = nil
|
503
|
+
if public_method_name =~ /^([^\.]+)\.(.*)$/
|
504
|
+
service_name = $1
|
505
|
+
real_method_name = $2
|
506
|
+
end
|
507
|
+
if soap?
|
508
|
+
public_method_name = real_method_name
|
509
|
+
request_env['HTTP_SOAPACTION'] = "/soap/#{service_name}/#{real_method_name}"
|
510
|
+
end
|
511
|
+
api = container.web_service_object(service_name.to_sym).class.web_service_api rescue nil
|
512
|
+
method = api.public_api_method_instance(real_method_name) rescue nil
|
513
|
+
service_name = self.service_name(container)
|
514
|
+
end
|
515
|
+
protocol.register_api(api)
|
516
|
+
virtual = false
|
517
|
+
unless method
|
518
|
+
virtual = true
|
519
|
+
method ||= ActionWebService::API::Method.new(public_method_name.underscore.to_sym, public_method_name, nil, nil)
|
520
|
+
end
|
521
|
+
body = protocol.encode_request(public_method_name, params.dup, method.expects)
|
522
|
+
# puts body
|
523
|
+
ap_request = protocol.encode_action_pack_request(service_name, public_method_name, body, :request_class => ActionController::TestRequest)
|
524
|
+
ap_request.env.update(request_env)
|
525
|
+
ap_response = ActionController::TestResponse.new
|
526
|
+
container.process(ap_request, ap_response)
|
527
|
+
# puts ap_response.body
|
528
|
+
@response_body = ap_response.body
|
529
|
+
public_method_name, return_value = protocol.decode_response(ap_response.body)
|
530
|
+
unless is_exception?(return_value) || virtual
|
531
|
+
return_value = method.cast_returns(return_value)
|
532
|
+
end
|
533
|
+
if soap?
|
534
|
+
# http://dev.rubyonrails.com/changeset/920
|
535
|
+
assert_match(/Response$/, public_method_name) unless public_method_name == "fault"
|
536
|
+
end
|
537
|
+
return_value
|
538
|
+
end
|
539
|
+
|
540
|
+
def http_method_allowed?(method)
|
541
|
+
method = method.to_s.upcase
|
542
|
+
test_request = ActionController::TestRequest.new
|
543
|
+
test_request.action = 'api'
|
544
|
+
test_response = ActionController::TestResponse.new
|
545
|
+
test_request.env['REQUEST_METHOD'] = method
|
546
|
+
result = @direct_controller.process(test_request, test_response)
|
547
|
+
result.body =~ /(GET|POST|PUT|DELETE|TRACE|CONNECT) not supported/ ? false : true
|
548
|
+
end
|
549
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
$: << "#{File.dirname(__FILE__)}/../lib"
|
2
|
+
ENV["RAILS_ENV"] = "test"
|
3
|
+
require 'rubygems'
|
4
|
+
require 'test/unit'
|
5
|
+
require 'action_web_service'
|
6
|
+
require 'action_controller'
|
7
|
+
require 'action_controller/test_case'
|
8
|
+
require 'action_view'
|
9
|
+
require 'action_view/test_case'
|
10
|
+
|
11
|
+
# Show backtraces for deprecated behavior for quicker cleanup.
|
12
|
+
ActiveSupport::Deprecation.debug = true
|
13
|
+
|
14
|
+
|
15
|
+
ActiveRecord::Base.logger = ActionController::Base.logger = Logger.new("debug.log")
|
16
|
+
|
17
|
+
begin
|
18
|
+
require 'active_record'
|
19
|
+
require "active_record/test_case"
|
20
|
+
require "active_record/fixtures" unless Object.const_defined?(:Fixtures)
|
21
|
+
rescue LoadError => e
|
22
|
+
fail "\nFailed to load activerecord: #{e}"
|
23
|
+
end
|
24
|
+
|
25
|
+
ActiveRecord::Base.configurations = {
|
26
|
+
'mysql' => {
|
27
|
+
:adapter => "mysql",
|
28
|
+
:username => "unit_tester",
|
29
|
+
:encoding => "utf8",
|
30
|
+
:database => "actionwebservice_unittest"
|
31
|
+
},
|
32
|
+
'sqlite3' => {
|
33
|
+
:adapter => "sqlite3",
|
34
|
+
:database => "actionwebservice_unittest.db"
|
35
|
+
}
|
36
|
+
}
|
37
|
+
|
38
|
+
ActiveRecord::Base.establish_connection 'sqlite3'
|
39
|
+
|
40
|
+
class ActiveSupport::TestCase
|
41
|
+
include ActiveRecord::TestFixtures
|
42
|
+
self.fixture_path = "#{File.dirname(__FILE__)}/fixtures/"
|
43
|
+
end
|
Binary file
|
data/test/api_test.rb
ADDED
@@ -0,0 +1,102 @@
|
|
1
|
+
require 'abstract_unit'
|
2
|
+
|
3
|
+
module APITest
|
4
|
+
class API < ActionWebService::API::Base
|
5
|
+
api_method :void
|
6
|
+
api_method :expects_and_returns, :expects_and_returns => [:string]
|
7
|
+
api_method :expects, :expects => [:int, :bool]
|
8
|
+
api_method :returns, :returns => [:int, [:string]]
|
9
|
+
api_method :named_signature, :expects => [{:appkey=>:int}, {:publish=>:bool}]
|
10
|
+
api_method :string_types, :expects => ['int', 'string', 'bool', 'base64']
|
11
|
+
api_method :class_types, :expects => [TrueClass, Bignum, String]
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
class TC_API < ActiveSupport::TestCase
|
16
|
+
API = APITest::API
|
17
|
+
|
18
|
+
def test_api_method_declaration
|
19
|
+
%w(
|
20
|
+
void
|
21
|
+
expects_and_returns
|
22
|
+
expects
|
23
|
+
returns
|
24
|
+
named_signature
|
25
|
+
string_types
|
26
|
+
class_types
|
27
|
+
).each do |name|
|
28
|
+
name = name.to_sym
|
29
|
+
public_name = API.public_api_method_name(name)
|
30
|
+
assert(API.has_api_method?(name))
|
31
|
+
assert(API.has_public_api_method?(public_name))
|
32
|
+
assert(API.api_method_name(public_name) == name)
|
33
|
+
assert(API.api_methods.has_key?(name))
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def test_signature_canonicalization
|
38
|
+
assert_equal(nil, API.api_methods[:void].expects)
|
39
|
+
assert_equal(nil, API.api_methods[:void].returns)
|
40
|
+
assert_equal([String], API.api_methods[:expects_and_returns].expects.map{|x| x.type_class})
|
41
|
+
assert_equal([String], API.api_methods[:expects_and_returns].returns.map{|x| x.type_class})
|
42
|
+
assert_equal([Integer, TrueClass], API.api_methods[:expects].expects.map{|x| x.type_class})
|
43
|
+
assert_equal(nil, API.api_methods[:expects].returns)
|
44
|
+
assert_equal(nil, API.api_methods[:returns].expects)
|
45
|
+
assert_equal([Integer, [String]], API.api_methods[:returns].returns.map{|x| x.array?? [x.element_type.type_class] : x.type_class})
|
46
|
+
assert_equal([[:appkey, Integer], [:publish, TrueClass]], API.api_methods[:named_signature].expects.map{|x| [x.name, x.type_class]})
|
47
|
+
assert_equal(nil, API.api_methods[:named_signature].returns)
|
48
|
+
assert_equal([Integer, String, TrueClass, ActionWebService::Base64], API.api_methods[:string_types].expects.map{|x| x.type_class})
|
49
|
+
assert_equal(nil, API.api_methods[:string_types].returns)
|
50
|
+
assert_equal([TrueClass, Integer, String], API.api_methods[:class_types].expects.map{|x| x.type_class})
|
51
|
+
assert_equal(nil, API.api_methods[:class_types].returns)
|
52
|
+
end
|
53
|
+
|
54
|
+
def test_not_instantiable
|
55
|
+
assert_raises(NoMethodError) do
|
56
|
+
API.new
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
def test_api_errors
|
61
|
+
assert_raises(ActionWebService::ActionWebServiceError) do
|
62
|
+
klass = Class.new(ActionWebService::API::Base) do
|
63
|
+
api_method :test, :expects => [ActiveRecord::Base]
|
64
|
+
end
|
65
|
+
end
|
66
|
+
klass = Class.new(ActionWebService::API::Base) do
|
67
|
+
allow_active_record_expects true
|
68
|
+
api_method :test2, :expects => [ActiveRecord::Base]
|
69
|
+
end
|
70
|
+
assert_raises(ActionWebService::ActionWebServiceError) do
|
71
|
+
klass = Class.new(ActionWebService::API::Base) do
|
72
|
+
api_method :test, :invalid => [:int]
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
def test_parameter_names
|
78
|
+
method = API.api_methods[:named_signature]
|
79
|
+
assert_equal 0, method.expects_index_of(:appkey)
|
80
|
+
assert_equal 1, method.expects_index_of(:publish)
|
81
|
+
assert_equal 1, method.expects_index_of('publish')
|
82
|
+
assert_equal 0, method.expects_index_of('appkey')
|
83
|
+
assert_equal -1, method.expects_index_of('blah')
|
84
|
+
assert_equal -1, method.expects_index_of(:missing)
|
85
|
+
assert_equal -1, API.api_methods[:void].expects_index_of('test')
|
86
|
+
end
|
87
|
+
|
88
|
+
def test_parameter_hash
|
89
|
+
method = API.api_methods[:named_signature]
|
90
|
+
hash = method.expects_to_hash([5, false])
|
91
|
+
assert_equal({:appkey => 5, :publish => false}, hash)
|
92
|
+
end
|
93
|
+
|
94
|
+
def test_api_methods_compat
|
95
|
+
sig = API.api_methods[:named_signature][:expects]
|
96
|
+
assert_equal [{:appkey=>Integer}, {:publish=>TrueClass}], sig
|
97
|
+
end
|
98
|
+
|
99
|
+
def test_to_s
|
100
|
+
assert_equal 'void Expects(int param0, bool param1)', APITest::API.api_methods[:expects].to_s
|
101
|
+
end
|
102
|
+
end
|