fdv-actionwebservice 2.3.8

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 (79) hide show
  1. data/CHANGELOG +320 -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.rb +66 -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 +149 -0
  28. data/lib/action_web_service/client.rb +3 -0
  29. data/lib/action_web_service/client/base.rb +28 -0
  30. data/lib/action_web_service/client/soap_client.rb +113 -0
  31. data/lib/action_web_service/client/xmlrpc_client.rb +58 -0
  32. data/lib/action_web_service/container.rb +3 -0
  33. data/lib/action_web_service/container/action_controller_container.rb +93 -0
  34. data/lib/action_web_service/container/delegated_container.rb +86 -0
  35. data/lib/action_web_service/container/direct_container.rb +69 -0
  36. data/lib/action_web_service/dispatcher.rb +2 -0
  37. data/lib/action_web_service/dispatcher/abstract.rb +207 -0
  38. data/lib/action_web_service/dispatcher/action_controller_dispatcher.rb +379 -0
  39. data/lib/action_web_service/invocation.rb +202 -0
  40. data/lib/action_web_service/protocol.rb +4 -0
  41. data/lib/action_web_service/protocol/abstract.rb +112 -0
  42. data/lib/action_web_service/protocol/discovery.rb +37 -0
  43. data/lib/action_web_service/protocol/soap_protocol.rb +176 -0
  44. data/lib/action_web_service/protocol/soap_protocol/marshaler.rb +242 -0
  45. data/lib/action_web_service/protocol/xmlrpc_protocol.rb +122 -0
  46. data/lib/action_web_service/scaffolding.rb +281 -0
  47. data/lib/action_web_service/struct.rb +64 -0
  48. data/lib/action_web_service/support/class_inheritable_options.rb +26 -0
  49. data/lib/action_web_service/support/signature_types.rb +226 -0
  50. data/lib/action_web_service/templates/scaffolds/layout.html.erb +65 -0
  51. data/lib/action_web_service/templates/scaffolds/methods.html.erb +6 -0
  52. data/lib/action_web_service/templates/scaffolds/parameters.html.erb +29 -0
  53. data/lib/action_web_service/templates/scaffolds/result.html.erb +30 -0
  54. data/lib/action_web_service/test_invoke.rb +110 -0
  55. data/lib/action_web_service/version.rb +9 -0
  56. data/lib/actionwebservice.rb +1 -0
  57. data/setup.rb +1379 -0
  58. data/test/abstract_client.rb +183 -0
  59. data/test/abstract_dispatcher.rb +548 -0
  60. data/test/abstract_unit.rb +43 -0
  61. data/test/api_test.rb +102 -0
  62. data/test/apis/auto_load_api.rb +3 -0
  63. data/test/apis/broken_auto_load_api.rb +2 -0
  64. data/test/base_test.rb +42 -0
  65. data/test/casting_test.rb +95 -0
  66. data/test/client_soap_test.rb +155 -0
  67. data/test/client_xmlrpc_test.rb +153 -0
  68. data/test/container_test.rb +73 -0
  69. data/test/dispatcher_action_controller_soap_test.rb +139 -0
  70. data/test/dispatcher_action_controller_xmlrpc_test.rb +59 -0
  71. data/test/fixtures/db_definitions/mysql.sql +8 -0
  72. data/test/fixtures/users.yml +12 -0
  73. data/test/gencov +3 -0
  74. data/test/invocation_test.rb +185 -0
  75. data/test/run +6 -0
  76. data/test/scaffolded_controller_test.rb +146 -0
  77. data/test/struct_test.rb +52 -0
  78. data/test/test_invoke_test.rb +112 -0
  79. metadata +166 -0
@@ -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 'activerecord'
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 => "root",
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
@@ -0,0 +1,102 @@
1
+ require File.dirname(__FILE__) + '/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,42 @@
1
+ require File.dirname(__FILE__) + '/abstract_unit'
2
+
3
+ module BaseTest
4
+ class API < ActionWebService::API::Base
5
+ api_method :add, :expects => [:int, :int], :returns => [:int]
6
+ api_method :void
7
+ end
8
+
9
+ class PristineAPI < ActionWebService::API::Base
10
+ inflect_names false
11
+
12
+ api_method :add
13
+ api_method :under_score
14
+ end
15
+
16
+ class Service < ActionWebService::Base
17
+ web_service_api API
18
+
19
+ def add(a, b)
20
+ end
21
+
22
+ def void
23
+ end
24
+ end
25
+
26
+ class PristineService < ActionWebService::Base
27
+ web_service_api PristineAPI
28
+
29
+ def add
30
+ end
31
+
32
+ def under_score
33
+ end
34
+ end
35
+ end
36
+
37
+ class TC_Base < ActiveSupport::TestCase
38
+ def test_options
39
+ assert(BaseTest::PristineService.web_service_api.inflect_names == false)
40
+ assert(BaseTest::Service.web_service_api.inflect_names == true)
41
+ end
42
+ end
@@ -0,0 +1,95 @@
1
+ require File.dirname(__FILE__) + '/abstract_unit'
2
+
3
+ module CastingTest
4
+ class A < ActionWebService::Struct; end
5
+ class B < A; end
6
+ class API < ActionWebService::API::Base
7
+ api_method :int, :expects => [:int]
8
+ api_method :str, :expects => [:string]
9
+ api_method :base64, :expects => [:base64]
10
+ api_method :bool, :expects => [:bool]
11
+ api_method :float, :expects => [:float]
12
+ api_method :time, :expects => [:time]
13
+ api_method :datetime, :expects => [:datetime]
14
+ api_method :date, :expects => [:date]
15
+
16
+ api_method :int_array, :expects => [[:int]]
17
+ api_method :str_array, :expects => [[:string]]
18
+ api_method :bool_array, :expects => [[:bool]]
19
+
20
+ api_method :a, :expects => [A]
21
+ end
22
+ end
23
+
24
+ class TC_Casting < Test::Unit::TestCase
25
+ include CastingTest
26
+
27
+ def test_base_type_casting_valid
28
+ assert_equal 10000, cast_expects(:int, '10000')[0]
29
+ assert_equal '10000', cast_expects(:str, 10000)[0]
30
+ base64 = cast_expects(:base64, 10000)[0]
31
+ assert_equal '10000', base64
32
+ assert_instance_of ActionWebService::Base64, base64
33
+ [1, '1', 'true', 'y', 'yes'].each do |val|
34
+ assert_equal true, cast_expects(:bool, val)[0]
35
+ end
36
+ [0, '0', 'false', 'n', 'no'].each do |val|
37
+ assert_equal false, cast_expects(:bool, val)[0]
38
+ end
39
+ assert_equal 3.14159, cast_expects(:float, '3.14159')[0]
40
+ now = Time.at(Time.now.tv_sec)
41
+ casted = cast_expects(:time, now.to_s)[0]
42
+ assert_equal now, casted
43
+ now = DateTime.now
44
+ assert_equal now.to_s, cast_expects(:datetime, now.to_s)[0].to_s
45
+ today = Date.today
46
+ assert_equal today, cast_expects(:date, today.to_s)[0]
47
+ end
48
+
49
+ def test_base_type_casting_invalid
50
+ assert_raises ArgumentError do
51
+ cast_expects(:int, 'this is not a number')
52
+ end
53
+ assert_raises ActionWebService::Casting::CastingError do
54
+ # neither true or false ;)
55
+ cast_expects(:bool, 'i always lie')
56
+ end
57
+ assert_raises ArgumentError do
58
+ cast_expects(:float, 'not a float')
59
+ end
60
+ # not sure why this test fails but too lazy to find out why :-(
61
+ # assert_raises ArgumentError do
62
+ # cast_expects(:time, '111111111111111111111111111111111')
63
+ # end
64
+ assert_raises ArgumentError do
65
+ cast_expects(:datetime, '-1')
66
+ end
67
+ assert_raises ArgumentError do
68
+ cast_expects(:date, '')
69
+ end
70
+ end
71
+
72
+ def test_array_type_casting
73
+ assert_equal [1, 2, 3213992, 4], cast_expects(:int_array, ['1', '2', '3213992', '4'])[0]
74
+ assert_equal ['one', 'two', '5.0', '200', nil, 'true'], cast_expects(:str_array, [:one, 'two', 5.0, 200, nil, true])[0]
75
+ assert_equal [true, nil, true, true, false], cast_expects(:bool_array, ['1', nil, 'y', true, 'false'])[0]
76
+ end
77
+
78
+ def test_array_type_casting_failure
79
+ assert_raises ActionWebService::Casting::CastingError do
80
+ cast_expects(:bool_array, ['false', 'blahblah'])
81
+ end
82
+ assert_raises ArgumentError do
83
+ cast_expects(:int_array, ['1', '2.021', '4'])
84
+ end
85
+ end
86
+
87
+ def test_structured_type_casting_with_polymorphism
88
+ assert cast_expects(:a, B.new)[0].is_a?(B)
89
+ end
90
+
91
+ private
92
+ def cast_expects(method_name, *args)
93
+ API.api_method_instance(method_name.to_sym).cast_expects([*args])
94
+ end
95
+ end
@@ -0,0 +1,155 @@
1
+ require File.dirname(__FILE__) + '/abstract_client'
2
+
3
+
4
+ module ClientSoapTest
5
+ PORT = 8998
6
+
7
+ class SoapClientLet < ClientTest::AbstractClientLet
8
+ def do_POST(req, res)
9
+ test_request = ActionController::TestRequest.new
10
+ test_request.request_parameters['action'] = req.path.gsub(/^\//, '').split(/\//)[1]
11
+ test_request.env['REQUEST_METHOD'] = "POST"
12
+ test_request.env['HTTP_CONTENTTYPE'] = 'text/xml'
13
+ test_request.env['HTTP_SOAPACTION'] = req.header['soapaction'][0]
14
+ test_request.env['RAW_POST_DATA'] = req.body
15
+ response = ActionController::TestResponse.new
16
+ @controller.process(test_request, response)
17
+ res.header['content-type'] = 'text/xml'
18
+ res.body = response.body
19
+ rescue Exception => e
20
+ $stderr.puts e.message
21
+ $stderr.puts e.backtrace.join("\n")
22
+ ensure
23
+ ActiveRecord::Base.clear_active_connections!
24
+ end
25
+ end
26
+
27
+ class ClientContainer < ActionController::Base
28
+ web_client_api :client, :soap, "http://localhost:#{PORT}/client/api", :api => ClientTest::API
29
+ web_client_api :invalid, :null, "", :api => true
30
+
31
+ def get_client
32
+ client
33
+ end
34
+
35
+ def get_invalid
36
+ invalid
37
+ end
38
+ end
39
+
40
+ class SoapServer < ClientTest::AbstractServer
41
+ def create_clientlet(controller)
42
+ SoapClientLet.new(controller)
43
+ end
44
+
45
+ def server_port
46
+ PORT
47
+ end
48
+ end
49
+ end
50
+
51
+ class TC_ClientSoap < ActiveSupport::TestCase
52
+ include ClientTest
53
+ include ClientSoapTest
54
+
55
+ fixtures :users
56
+
57
+ def setup
58
+ @server = SoapServer.instance
59
+ @container = @server.container
60
+ @client = ActionWebService::Client::Soap.new(API, "http://localhost:#{@server.server_port}/client/api")
61
+ end
62
+
63
+ def test_void
64
+ assert(@container.value_void.nil?)
65
+ @client.void
66
+ assert(!@container.value_void.nil?)
67
+ end
68
+
69
+ def test_normal
70
+ assert(@container.value_normal.nil?)
71
+ assert_equal(5, @client.normal(5, 6))
72
+ assert_equal([5, 6], @container.value_normal)
73
+ assert_equal(5, @client.normal("7", "8"))
74
+ assert_equal([7, 8], @container.value_normal)
75
+ assert_equal(5, @client.normal(true, false))
76
+ end
77
+
78
+ def test_array_return
79
+ assert(@container.value_array_return.nil?)
80
+ new_person = Person.new
81
+ new_person.firstnames = ["one", "two"]
82
+ new_person.lastname = "last"
83
+ assert_equal([new_person], @client.array_return)
84
+ assert_equal([new_person], @container.value_array_return)
85
+ end
86
+
87
+ def test_struct_pass
88
+ assert(@container.value_struct_pass.nil?)
89
+ new_person = Person.new
90
+ new_person.firstnames = ["one", "two"]
91
+ new_person.lastname = "last"
92
+ assert_equal(true, @client.struct_pass([new_person]))
93
+ assert_equal([[new_person]], @container.value_struct_pass)
94
+ end
95
+
96
+ def test_nil_struct_return
97
+ assert_nil @client.nil_struct_return
98
+ end
99
+
100
+ def test_inner_nil
101
+ outer = @client.inner_nil
102
+ assert_equal 'outer', outer.name
103
+ assert_nil outer.inner
104
+ end
105
+
106
+ def test_client_container
107
+ assert_equal(50, ClientContainer.new.get_client.client_container)
108
+ assert(ClientContainer.new.get_invalid.nil?)
109
+ end
110
+
111
+ def test_named_parameters
112
+ assert(@container.value_named_parameters.nil?)
113
+ assert(@client.named_parameters("key", 5).nil?)
114
+ assert_equal(["key", 5], @container.value_named_parameters)
115
+ end
116
+
117
+ def test_capitalized_method_name
118
+ @container.value_normal = nil
119
+ assert_equal(5, @client.Normal(5, 6))
120
+ assert_equal([5, 6], @container.value_normal)
121
+ @container.value_normal = nil
122
+ end
123
+
124
+ def test_model_return
125
+ user = @client.user_return
126
+ assert_equal 1, user.id
127
+ assert_equal 'Kent', user.name
128
+ assert user.active?
129
+ assert_kind_of Date, user.created_on
130
+ assert_equal Date.today, user.created_on
131
+ assert_equal BigDecimal('12.2'), user.balance
132
+ end
133
+
134
+ def test_with_model
135
+ with_model = @client.with_model_return
136
+ assert_equal 'Kent', with_model.user.name
137
+ assert_equal 2, with_model.users.size
138
+ with_model.users.each do |user|
139
+ assert_kind_of User, user
140
+ end
141
+ end
142
+
143
+ def test_scoped_model_return
144
+ scoped_model = @client.scoped_model_return
145
+ assert_kind_of Accounting::User, scoped_model
146
+ assert_equal 'Kent', scoped_model.name
147
+ end
148
+
149
+ def test_multi_dim_return
150
+ md_struct = @client.multi_dim_return
151
+ assert_kind_of Array, md_struct.pref
152
+ assert_equal 2, md_struct.pref.size
153
+ assert_kind_of Array, md_struct.pref[0]
154
+ end
155
+ end