sinatra-rpc 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,50 @@
1
+ require 'spec_helper'
2
+
3
+ describe Sinatra::RPC::Serializer::Base do
4
+
5
+ before(:all) do
6
+ @registry = Sinatra::RPC::Serializer.instance_variable_get('@registry').dup
7
+ end
8
+
9
+ after(:all) do
10
+ Sinatra::RPC::Serializer.instance_variable_set('@registry', @registry)
11
+ end
12
+
13
+ it 'should set the correct response content type' do
14
+ class B64Serializer < Sinatra::RPC::Serializer::Base
15
+ content_types 'text/base64'
16
+ end
17
+
18
+ B64Serializer.new.content_type.should == 'text/base64'
19
+ end
20
+
21
+ it 'should set the response content type of the default serializer' do
22
+ class DefaultSerializer < Sinatra::RPC::Serializer::Base
23
+ content_types nil, 'application/x-default'
24
+ end
25
+
26
+ class AnotherDefaultSerializer < Sinatra::RPC::Serializer::Base
27
+ content_types 'application/x-another-default', nil
28
+ end
29
+
30
+ DefaultSerializer.new.content_type.should == 'application/x-default'
31
+ AnotherDefaultSerializer.new.content_type.should == 'application/x-another-default'
32
+ end
33
+
34
+ it 'should set default content type options' do
35
+ class OptionsSerializer < Sinatra::RPC::Serializer::Base
36
+ content_types 'application/x-opt'
37
+ end
38
+ OptionsSerializer.new.content_type_options.should == {}
39
+ end
40
+
41
+ it 'should raise an exception if the dump or parse methods are not implemented' do
42
+ class DummySerializer < Sinatra::RPC::Serializer::Base
43
+ content_types 'application/x-no-parse'
44
+ end
45
+
46
+ expect { DummySerializer.new.dump(Object.new) }.to raise_error(NotImplementedError)
47
+ expect { DummySerializer.new.parse("request") }.to raise_error(NotImplementedError)
48
+ end
49
+
50
+ end
@@ -0,0 +1,20 @@
1
+ require 'spec_helper'
2
+
3
+ describe Sinatra::RPC::Serializer::XMLRPC do
4
+
5
+ before(:each) do
6
+ @xmlrpc = Sinatra::RPC::Serializer.find('text/xml').new
7
+ end
8
+
9
+ it 'should parse requests correctly' do
10
+ req = XMLRPC::Marshal.dump_call('handler.myMethod', 'arg1', 42)
11
+ @xmlrpc.parse(req).should == ['handler.myMethod', ['arg1', 42]]
12
+ req = XMLRPC::Marshal.dump_call('simpleMethod', false, 1, 2, 'string')
13
+ @xmlrpc.parse(req).should == ['simpleMethod', [false, 1, 2, 'string']]
14
+ end
15
+
16
+ it 'should dump responses correctly' do
17
+ XMLRPC::Marshal.load_response(@xmlrpc.dump('result')).should == 'result'
18
+ XMLRPC::Marshal.load_response(@xmlrpc.dump([1, 'array'])).should == [1, 'array']
19
+ end
20
+ end
@@ -0,0 +1,47 @@
1
+ require 'spec_helper'
2
+
3
+ describe Sinatra::RPC::Serializer do
4
+
5
+ before(:all) do
6
+ @registry = Sinatra::RPC::Serializer.instance_variable_get('@registry').dup
7
+ end
8
+
9
+ after(:all) do
10
+ Sinatra::RPC::Serializer.instance_variable_set('@registry', @registry)
11
+ end
12
+
13
+ it 'should allow registering new classes' do
14
+ class B64Serializer < Sinatra::RPC::Serializer::Base
15
+ content_types 'text/base64'
16
+ end
17
+
18
+ Sinatra::RPC::Serializer.find('text/base64').should == B64Serializer
19
+ end
20
+
21
+ it 'should allow registering more than 1 content type' do
22
+ class MultiSerializer < Sinatra::RPC::Serializer::Base
23
+ content_types 'application/x-app1', 'application/x-app2'
24
+ end
25
+
26
+ Sinatra::RPC::Serializer.find('application/x-app1').should == MultiSerializer
27
+ Sinatra::RPC::Serializer.find('application/x-app2').should == MultiSerializer
28
+ end
29
+
30
+ it 'should allow registering a default Serializer' do
31
+ class DefaultSerializer < Sinatra::RPC::Serializer::Base
32
+ content_types nil, 'application/x-default'
33
+ end
34
+
35
+ Sinatra::RPC::Serializer.find('application/x-default').should == DefaultSerializer
36
+ Sinatra::RPC::Serializer.find(nil).should == DefaultSerializer
37
+ end
38
+
39
+ it 'should select the default Serializer when an unsupported content type is specified' do
40
+ class DefaultSerializer < Sinatra::RPC::Serializer::Base
41
+ content_types nil, 'application/x-default'
42
+ end
43
+
44
+ Sinatra::RPC::Serializer.find('application/x-unsupported').should == DefaultSerializer
45
+ end
46
+
47
+ end
@@ -0,0 +1,166 @@
1
+ require 'spec_helper'
2
+
3
+ module UtilsTest
4
+ class MyClass
5
+ # This is a test method.
6
+ def my_method; end
7
+
8
+ # Full method doc for greet.
9
+ # @param folks [String] people to greet
10
+ # @return [String] the greeting
11
+ def greet(folks); "Hi, #{folks}!"; end
12
+
13
+ # Partially documented.
14
+ # @param people [String] the people
15
+ def bye(people); "Bye, #{people}!"; end
16
+
17
+ # Partially documented.
18
+ # @return [String] the result
19
+ def so_long(people); "So long, #{people}!"; end
20
+
21
+ # Multiple types.
22
+ # @param arg [String, Class] the arg
23
+ # @return [Array] the result
24
+ def multi(arg); ["The argument is #{arg}!"]; end
25
+ end
26
+
27
+ class SimpleClass
28
+ # This is a test method.
29
+ def my_method; end
30
+ end
31
+
32
+ end
33
+
34
+ def m(name)
35
+ UtilsTest::MyClass.instance_method name
36
+ end
37
+
38
+ describe Sinatra::RPC::Utils do
39
+
40
+ context '.camelize' do
41
+ it 'should convert underscored strings' do
42
+ Sinatra::RPC::Utils.camelize('my_test_string').should == 'MyTestString'
43
+ Sinatra::RPC::Utils.camelize('_starts_with_underscore').should == 'StartsWithUnderscore'
44
+ Sinatra::RPC::Utils.camelize('ends_with_underscore_').should == 'EndsWithUnderscore'
45
+ end
46
+
47
+ it 'should generate strings starting with a lowercase letter' do
48
+ Sinatra::RPC::Utils.camelize('my_test_string', false).should == 'myTestString'
49
+ end
50
+
51
+ it 'should convert symbols' do
52
+ Sinatra::RPC::Utils.camelize(:my_test_sym, false).should == 'myTestSym'
53
+ end
54
+ end
55
+
56
+ context '.underscore' do
57
+ it 'should convert camelcase strings' do
58
+ Sinatra::RPC::Utils.underscore('MyTestString').should == 'my_test_string'
59
+ end
60
+
61
+ it 'should convert string starting with a lowercase letter' do
62
+ Sinatra::RPC::Utils.underscore('myTestString').should == 'my_test_string'
63
+ end
64
+ end
65
+
66
+ context '.method_help' do
67
+ it 'should generate a simple help string' do
68
+ doc = "This is a test method."
69
+ Sinatra::RPC::Utils.method_help(m(:my_method)).should == doc
70
+ end
71
+
72
+ it 'should include tags in the help string' do
73
+ doc = %q{
74
+ Full method doc for greet.
75
+ @param folks [String] people to greet
76
+ @return [String] the greeting
77
+ }.strip
78
+ Sinatra::RPC::Utils.method_help(m(:greet)).should == doc
79
+ end
80
+ end
81
+
82
+ context '.method_signature' do
83
+ it 'should extract a valid signature from the documentation' do
84
+ Sinatra::RPC::Utils.method_signature(m(:greet)).should == [['string', 'string']]
85
+ end
86
+
87
+ it 'should return an empty string if the signature is invalid' do
88
+ Sinatra::RPC::Utils.method_signature(m(:my_method)).should == [['nil']]
89
+ end
90
+
91
+ it 'should handle partially documented methods' do
92
+ Sinatra::RPC::Utils.method_signature(m(:bye)).should == [['nil', 'string']]
93
+ Sinatra::RPC::Utils.method_signature(m(:so_long)).should == [['string']]
94
+ end
95
+
96
+ it 'should handle multiple argument types' do
97
+ Sinatra::RPC::Utils.method_signature(m(:multi)).should == [['array', 'string']]
98
+ end
99
+ end
100
+
101
+ context '.rpc_methods' do
102
+ it 'should correctly generate the RPC method index' do
103
+ c = UtilsTest::MyClass.new
104
+ index = {
105
+ 'ns.myMethod' => {
106
+ handler: c,
107
+ method: :my_method,
108
+ help: "This is a test method.",
109
+ signature: [['nil']]
110
+ },
111
+ 'ns.greet' => {
112
+ handler: c,
113
+ method: :greet,
114
+ help: %q{
115
+ Full method doc for greet.
116
+ @param folks [String] people to greet
117
+ @return [String] the greeting
118
+ }.strip,
119
+ signature: [['string', 'string']]
120
+ },
121
+ 'ns.bye' => {
122
+ handler: c,
123
+ method: :bye,
124
+ help: %q{
125
+ Partially documented.
126
+ @param people [String] the people
127
+ }.strip,
128
+ signature: [['nil', 'string']]
129
+ },
130
+ 'ns.soLong' => {
131
+ handler: c,
132
+ method: :so_long,
133
+ help: %q{
134
+ Partially documented.
135
+ @return [String] the result
136
+ }.strip,
137
+ signature: [['string']]
138
+ },
139
+ 'ns.multi' => {
140
+ handler: c,
141
+ method: :multi,
142
+ help: %q{
143
+ Multiple types.
144
+ @param arg [String, Class] the arg
145
+ @return [Array] the result
146
+ }.strip,
147
+ signature: [['array', 'string']]
148
+ },
149
+ }
150
+ Sinatra::RPC::Utils.rpc_methods('ns', c).should == index
151
+ end
152
+
153
+ it 'should work without specifying a namespace' do
154
+ c = UtilsTest::SimpleClass.new
155
+ index = {
156
+ 'myMethod' => {
157
+ handler: c,
158
+ method: :my_method,
159
+ help: "This is a test method.",
160
+ signature: [['nil']]
161
+ }
162
+ }
163
+ Sinatra::RPC::Utils.rpc_methods(c).should == index
164
+ end
165
+ end
166
+ end
@@ -0,0 +1,115 @@
1
+ require 'spec_helper'
2
+ require 'sinatra/base'
3
+
4
+ describe Sinatra::RPC do
5
+
6
+ module RpcTest
7
+
8
+ class MyHandler
9
+ # A greeting method.
10
+ # @param people [String] the people to greet
11
+ # @return [String] the greeting
12
+ def hello(people)
13
+ raise Sinatra::RPC::NoPeopleFault, "No people!" if people.nil? or people.empty?
14
+ "Hello, #{people}!"
15
+ end
16
+ end
17
+
18
+ class MyApp < Sinatra::Base
19
+ register Sinatra::RPC
20
+ register_rpc_fault :no_people, 211
21
+ add_rpc_handler MyHandler
22
+
23
+ post '/RPC2' do
24
+ handle_rpc request
25
+ end
26
+ end
27
+ end
28
+
29
+ def app
30
+ RpcTest::MyApp
31
+ end
32
+
33
+ # This method calls the RPC endpoint.
34
+ def call(method, *params)
35
+ request('/RPC2',
36
+ :method => 'post',
37
+ :params => XMLRPC::Marshal.dump_call(method, *params)
38
+ )
39
+ end
40
+
41
+ # Unmarshals the response coming from the RPC endpoint.
42
+ def parse(response)
43
+ XMLRPC::Marshal.load_response(response.body)
44
+ end
45
+
46
+ it 'should have a version number' do
47
+ Sinatra::RPC::VERSION.should_not be_nil
48
+ end
49
+
50
+ context 'using XMLRPC' do
51
+
52
+ it 'should reply to RPC requests' do
53
+ call('system.listMethods')
54
+ #puts last_response.body
55
+ last_response.should be_ok
56
+ end
57
+
58
+ it 'should return a 404 error if the method does not exist' do
59
+ call('fake.method', 'an argument')
60
+ last_response.status.should == 404
61
+ end
62
+
63
+ context 'with introspection' do
64
+
65
+ it 'should have an echo method' do
66
+ call('test.echo', 'a test string')
67
+ last_response.should be_ok
68
+ parse(last_response).should == 'a test string'
69
+ end
70
+
71
+ it 'should list RPC methods' do
72
+ call('system.listMethods')
73
+ last_response.should be_ok
74
+ parse(last_response).should == %w{
75
+ hello
76
+ system.listMethods
77
+ system.methodHelp
78
+ system.methodSignature
79
+ test.echo
80
+ }
81
+ end
82
+
83
+ it 'should show the method help' do
84
+ call('system.methodHelp', 'hello')
85
+ last_response.should be_ok
86
+ parse(last_response).should == %q{
87
+ A greeting method.
88
+ @param people [String] the people to greet
89
+ @return [String] the greeting
90
+ }.strip
91
+ end
92
+
93
+ it 'should show method signatures' do
94
+ call('system.methodSignature', 'hello')
95
+ last_response.should be_ok
96
+ parse(last_response).should == [['string', 'string']]
97
+ end
98
+ end
99
+
100
+ context 'with a custom handler' do
101
+ it 'should handle RPC requests' do
102
+ call('hello', 'World')
103
+ last_response.should be_ok
104
+ parse(last_response).should == 'Hello, World!'
105
+ end
106
+
107
+ it 'should handle RPC faults' do
108
+ call('hello', '')
109
+ err = parse(last_response)
110
+ err.faultCode.should == 211
111
+ end
112
+ end
113
+ end
114
+
115
+ end
@@ -0,0 +1,12 @@
1
+ require 'coveralls'
2
+ Coveralls.wear!
3
+ #require 'simplecov'
4
+ #SimpleCov.start
5
+
6
+ $LOAD_PATH.unshift File.expand_path('../../lib', __FILE__)
7
+ require 'rack/test'
8
+ require 'sinatra/rpc'
9
+
10
+ RSpec.configure do |config|
11
+ config.include Rack::Test::Methods
12
+ end
metadata ADDED
@@ -0,0 +1,198 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: sinatra-rpc
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Andrea Bernardo Ciddio
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2014-03-10 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: method_source
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ~>
18
+ - !ruby/object:Gem::Version
19
+ version: 0.8.0
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ~>
25
+ - !ruby/object:Gem::Version
26
+ version: 0.8.0
27
+ - !ruby/object:Gem::Dependency
28
+ name: bundler
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ~>
32
+ - !ruby/object:Gem::Version
33
+ version: '1.3'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ~>
39
+ - !ruby/object:Gem::Version
40
+ version: '1.3'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rake
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - '>='
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - '>='
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: rspec
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - '>='
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - '>='
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: yard
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - '>='
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - '>='
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: coveralls
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - '>='
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - '>='
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
97
+ - !ruby/object:Gem::Dependency
98
+ name: rack-test
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - '>='
102
+ - !ruby/object:Gem::Version
103
+ version: '0'
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - '>='
109
+ - !ruby/object:Gem::Version
110
+ version: '0'
111
+ - !ruby/object:Gem::Dependency
112
+ name: sinatra
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - '>='
116
+ - !ruby/object:Gem::Version
117
+ version: '0'
118
+ type: :development
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - '>='
123
+ - !ruby/object:Gem::Version
124
+ version: '0'
125
+ description: A Sinatra extension module providing RPC server functionality
126
+ email:
127
+ - bcandrea@gmail.com
128
+ executables: []
129
+ extensions: []
130
+ extra_rdoc_files: []
131
+ files:
132
+ - .gitignore
133
+ - .rspec
134
+ - .ruby-version
135
+ - .travis.yml
136
+ - .yardopts
137
+ - Gemfile
138
+ - LICENSE.txt
139
+ - README.md
140
+ - Rakefile
141
+ - lib/sinatra/rpc.rb
142
+ - lib/sinatra/rpc/fault.rb
143
+ - lib/sinatra/rpc/handler/echo.rb
144
+ - lib/sinatra/rpc/handler/introspection.rb
145
+ - lib/sinatra/rpc/helpers.rb
146
+ - lib/sinatra/rpc/serializer.rb
147
+ - lib/sinatra/rpc/serializer/base.rb
148
+ - lib/sinatra/rpc/serializer/xmlrpc.rb
149
+ - lib/sinatra/rpc/utils.rb
150
+ - lib/sinatra/rpc/version.rb
151
+ - sinatra-rpc.gemspec
152
+ - spec/sinatra/rpc/fault_spec.rb
153
+ - spec/sinatra/rpc/handler/echo_spec.rb
154
+ - spec/sinatra/rpc/handler/introspection_spec.rb
155
+ - spec/sinatra/rpc/helpers_spec.rb
156
+ - spec/sinatra/rpc/serializer/base_spec.rb
157
+ - spec/sinatra/rpc/serializer/xmlrpc_spec.rb
158
+ - spec/sinatra/rpc/serializer_spec.rb
159
+ - spec/sinatra/rpc/utils_spec.rb
160
+ - spec/sinatra/rpc_spec.rb
161
+ - spec/spec_helper.rb
162
+ homepage: https://github.com/bcandrea/sinatra-rpc
163
+ licenses:
164
+ - MIT
165
+ metadata: {}
166
+ post_install_message:
167
+ rdoc_options: []
168
+ require_paths:
169
+ - lib
170
+ required_ruby_version: !ruby/object:Gem::Requirement
171
+ requirements:
172
+ - - '>='
173
+ - !ruby/object:Gem::Version
174
+ version: '0'
175
+ required_rubygems_version: !ruby/object:Gem::Requirement
176
+ requirements:
177
+ - - '>='
178
+ - !ruby/object:Gem::Version
179
+ version: '0'
180
+ requirements: []
181
+ rubyforge_project:
182
+ rubygems_version: 2.0.3
183
+ signing_key:
184
+ specification_version: 4
185
+ summary: The Sinatra::RPC module provides an extension that can be used to build RPC
186
+ endpoints.
187
+ test_files:
188
+ - spec/sinatra/rpc/fault_spec.rb
189
+ - spec/sinatra/rpc/handler/echo_spec.rb
190
+ - spec/sinatra/rpc/handler/introspection_spec.rb
191
+ - spec/sinatra/rpc/helpers_spec.rb
192
+ - spec/sinatra/rpc/serializer/base_spec.rb
193
+ - spec/sinatra/rpc/serializer/xmlrpc_spec.rb
194
+ - spec/sinatra/rpc/serializer_spec.rb
195
+ - spec/sinatra/rpc/utils_spec.rb
196
+ - spec/sinatra/rpc_spec.rb
197
+ - spec/spec_helper.rb
198
+ has_rdoc: