axtro-actionwebservice 2.3.5.1.20101118142125

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