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.
Files changed (85) hide show
  1. data/CHANGELOG +335 -0
  2. data/MIT-LICENSE +21 -0
  3. data/README +381 -0
  4. data/Rakefile +180 -0
  5. data/TODO +32 -0
  6. data/examples/googlesearch/README +143 -0
  7. data/examples/googlesearch/autoloading/google_search_api.rb +50 -0
  8. data/examples/googlesearch/autoloading/google_search_controller.rb +57 -0
  9. data/examples/googlesearch/delegated/google_search_service.rb +108 -0
  10. data/examples/googlesearch/delegated/search_controller.rb +7 -0
  11. data/examples/googlesearch/direct/google_search_api.rb +50 -0
  12. data/examples/googlesearch/direct/search_controller.rb +58 -0
  13. data/examples/metaWeblog/README +17 -0
  14. data/examples/metaWeblog/apis/blogger_api.rb +60 -0
  15. data/examples/metaWeblog/apis/blogger_service.rb +34 -0
  16. data/examples/metaWeblog/apis/meta_weblog_api.rb +67 -0
  17. data/examples/metaWeblog/apis/meta_weblog_service.rb +48 -0
  18. data/examples/metaWeblog/controllers/xmlrpc_controller.rb +16 -0
  19. data/generators/web_service/USAGE +28 -0
  20. data/generators/web_service/templates/api_definition.rb +5 -0
  21. data/generators/web_service/templates/controller.rb +8 -0
  22. data/generators/web_service/templates/functional_test.rb +19 -0
  23. data/generators/web_service/web_service_generator.rb +29 -0
  24. data/lib/action_web_service/acts_as_web_service.rb +24 -0
  25. data/lib/action_web_service/api.rb +297 -0
  26. data/lib/action_web_service/base.rb +38 -0
  27. data/lib/action_web_service/casting.rb +151 -0
  28. data/lib/action_web_service/client/base.rb +28 -0
  29. data/lib/action_web_service/client/soap_client.rb +113 -0
  30. data/lib/action_web_service/client/xmlrpc_client.rb +58 -0
  31. data/lib/action_web_service/client.rb +3 -0
  32. data/lib/action_web_service/container/action_controller_container.rb +93 -0
  33. data/lib/action_web_service/container/delegated_container.rb +86 -0
  34. data/lib/action_web_service/container/direct_container.rb +69 -0
  35. data/lib/action_web_service/container.rb +3 -0
  36. data/lib/action_web_service/dispatcher/abstract.rb +208 -0
  37. data/lib/action_web_service/dispatcher/action_controller_dispatcher.rb +396 -0
  38. data/lib/action_web_service/dispatcher.rb +2 -0
  39. data/lib/action_web_service/invocation.rb +202 -0
  40. data/lib/action_web_service/protocol/abstract.rb +112 -0
  41. data/lib/action_web_service/protocol/discovery.rb +37 -0
  42. data/lib/action_web_service/protocol/soap_protocol/marshaler.rb +242 -0
  43. data/lib/action_web_service/protocol/soap_protocol.rb +176 -0
  44. data/lib/action_web_service/protocol/xmlrpc_protocol.rb +123 -0
  45. data/lib/action_web_service/protocol.rb +4 -0
  46. data/lib/action_web_service/scaffolding.rb +281 -0
  47. data/lib/action_web_service/simple.rb +53 -0
  48. data/lib/action_web_service/string_to_datetime_for_soap.rb +16 -0
  49. data/lib/action_web_service/struct.rb +68 -0
  50. data/lib/action_web_service/support/class_inheritable_options.rb +26 -0
  51. data/lib/action_web_service/support/signature_types.rb +261 -0
  52. data/lib/action_web_service/templates/scaffolds/layout.html.erb +65 -0
  53. data/lib/action_web_service/templates/scaffolds/methods.html.erb +6 -0
  54. data/lib/action_web_service/templates/scaffolds/parameters.html.erb +29 -0
  55. data/lib/action_web_service/templates/scaffolds/result.html.erb +30 -0
  56. data/lib/action_web_service/test_invoke.rb +110 -0
  57. data/lib/action_web_service/version.rb +9 -0
  58. data/lib/action_web_service.rb +60 -0
  59. data/lib/actionwebservice.rb +1 -0
  60. data/setup.rb +1379 -0
  61. data/test/abstract_client.rb +184 -0
  62. data/test/abstract_dispatcher.rb +549 -0
  63. data/test/abstract_unit.rb +43 -0
  64. data/test/actionwebservice_unittest.db +0 -0
  65. data/test/api_test.rb +102 -0
  66. data/test/apis/auto_load_api.rb +3 -0
  67. data/test/apis/broken_auto_load_api.rb +2 -0
  68. data/test/base_test.rb +42 -0
  69. data/test/casting_test.rb +95 -0
  70. data/test/client_soap_test.rb +156 -0
  71. data/test/client_xmlrpc_test.rb +154 -0
  72. data/test/container_test.rb +75 -0
  73. data/test/debug.log +12305 -0
  74. data/test/dispatcher_action_controller_soap_test.rb +139 -0
  75. data/test/dispatcher_action_controller_xmlrpc_test.rb +59 -0
  76. data/test/fixtures/db_definitions/mysql.sql +8 -0
  77. data/test/fixtures/db_definitions/sqlite3.sql +8 -0
  78. data/test/fixtures/users.yml +12 -0
  79. data/test/gencov +3 -0
  80. data/test/invocation_test.rb +186 -0
  81. data/test/run +6 -0
  82. data/test/scaffolded_controller_test.rb +147 -0
  83. data/test/struct_test.rb +84 -0
  84. data/test/test_invoke_test.rb +113 -0
  85. 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
@@ -0,0 +1,3 @@
1
+ class AutoLoadAPI < ActionWebService::API::Base
2
+ api_method :void
3
+ end
@@ -0,0 +1,2 @@
1
+
2
+