saorin 0.1.4 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- data/lib/saorin/adapters/clients/base.rb +25 -21
- data/lib/saorin/adapters/servers/base.rb +13 -12
- data/lib/saorin/error.rb +21 -10
- data/lib/saorin/request.rb +22 -5
- data/lib/saorin/response.rb +8 -7
- data/lib/saorin/test.rb +128 -0
- data/lib/saorin/utility.rb +15 -0
- data/lib/saorin/version.rb +1 -1
- data/saorin.gemspec +3 -0
- data/server.rb +1 -1
- data/spec/adapter/base_spec.rb +1 -1
- data/spec/adapter/servers/rack_spec.rb +11 -0
- data/spec/adapter/servers/reel_spec.rb +11 -0
- data/spec/request_spec.rb +3 -1
- data/spec/response_spec.rb +25 -18
- data/spec/support/{shared_examples.rb → rpc_call.rb} +4 -53
- data/spec/support/utils.rb +13 -0
- metadata +62 -6
@@ -12,25 +12,22 @@ module Saorin
|
|
12
12
|
def initialize(options = {})
|
13
13
|
end
|
14
14
|
|
15
|
-
def
|
16
|
-
|
15
|
+
def call(method, *args)
|
16
|
+
apply Saorin::Request.new(method, args, :id => seqid!)
|
17
|
+
end
|
18
|
+
|
19
|
+
def notify(method, *args)
|
20
|
+
apply Saorin::Request.new(method, args)
|
21
|
+
end
|
22
|
+
|
23
|
+
def apply(request)
|
17
24
|
response = send_request request.to_json
|
18
25
|
content = process_response response
|
19
26
|
raise content if content.is_a?(Saorin::RPCError)
|
20
27
|
content
|
21
28
|
end
|
22
29
|
|
23
|
-
|
24
|
-
|
25
|
-
def call_multi(*args)
|
26
|
-
requests = args.map do |arg|
|
27
|
-
request_args = arg.to_a.flatten
|
28
|
-
method = request_args.shift
|
29
|
-
Saorin::Request.new method, request_args, seqid!
|
30
|
-
end
|
31
|
-
response = send_request requests.to_json
|
32
|
-
process_response response
|
33
|
-
end
|
30
|
+
protected
|
34
31
|
|
35
32
|
def send_request(content)
|
36
33
|
raise NotImplementedError
|
@@ -39,11 +36,15 @@ module Saorin
|
|
39
36
|
def process_response(content)
|
40
37
|
response = parse_response content
|
41
38
|
if response.is_a?(::Array)
|
42
|
-
response.map { |res|
|
39
|
+
response.map { |res| handle_response res }
|
43
40
|
else
|
44
|
-
|
41
|
+
handle_response response
|
45
42
|
end
|
43
|
+
rescue Saorin::InvalidResponse => e
|
44
|
+
raise e
|
46
45
|
rescue => e
|
46
|
+
p e
|
47
|
+
print e.backtrace.join("\t\n")
|
47
48
|
raise Saorin::InvalidResponse, e.to_s
|
48
49
|
end
|
49
50
|
|
@@ -53,20 +54,23 @@ module Saorin
|
|
53
54
|
raise Saorin::InvalidResponse, e.to_s
|
54
55
|
end
|
55
56
|
|
56
|
-
def to_content(
|
57
|
-
if
|
58
|
-
|
57
|
+
def to_content(response)
|
58
|
+
return nil if response.nil?
|
59
|
+
if response.error?
|
60
|
+
code, message, data = response.error.values_at('code', 'message', 'data')
|
59
61
|
error_class = Saorin.code_to_error code
|
60
|
-
error_class
|
62
|
+
raise Error, 'unknown error code' unless error_class
|
63
|
+
error_class.new message, :code => code, :data => data
|
61
64
|
else
|
62
|
-
|
65
|
+
response.result
|
63
66
|
end
|
64
67
|
end
|
65
68
|
|
66
69
|
def handle_response(hash)
|
70
|
+
return nil if hash.nil?
|
67
71
|
response = Response.from_hash(hash)
|
68
72
|
response.validate
|
69
|
-
response
|
73
|
+
to_content response
|
70
74
|
end
|
71
75
|
|
72
76
|
def seqid
|
@@ -27,7 +27,7 @@ module Saorin
|
|
27
27
|
handle_request(request)
|
28
28
|
end
|
29
29
|
rescue Saorin::Error => e
|
30
|
-
Response.new(
|
30
|
+
Response.new(:error => e)
|
31
31
|
end
|
32
32
|
|
33
33
|
response && MultiJson.dump(response)
|
@@ -43,29 +43,30 @@ module Saorin
|
|
43
43
|
begin
|
44
44
|
request = Request.from_hash(hash)
|
45
45
|
request.validate
|
46
|
-
|
47
|
-
response = Response.new(result, nil, request.id)
|
48
|
-
notify?(hash) ? nil : response
|
46
|
+
dispatch_request_with_trap_notification request
|
49
47
|
rescue Saorin::InvalidRequest => e
|
50
|
-
Response.new(
|
48
|
+
Response.new(:error => e)
|
51
49
|
rescue Saorin::Error => e
|
52
|
-
Response.new(
|
50
|
+
Response.new(:error => e, :id => request.id)
|
53
51
|
rescue Exception => e
|
54
|
-
|
55
|
-
|
52
|
+
options = {:error => Saorin::InternalError.new}
|
53
|
+
options[:id] = request.id if request
|
54
|
+
Response.new(options)
|
56
55
|
end
|
57
56
|
end
|
58
57
|
|
59
|
-
def
|
60
|
-
|
58
|
+
def dispatch_request_with_trap_notification(request)
|
59
|
+
result = dispatch_request request
|
60
|
+
Response.new(:result => result, :id => request.id)
|
61
|
+
ensure
|
62
|
+
return nil if request.notify?
|
61
63
|
end
|
62
64
|
|
63
65
|
def dispatch_request(request)
|
64
66
|
method = request.method.to_s
|
65
67
|
params = request.params || []
|
66
68
|
|
67
|
-
unless @allowed_methods.include?(method) &&
|
68
|
-
@handler.respond_to?(method)
|
69
|
+
unless @allowed_methods.include?(method) && @handler.respond_to?(method)
|
69
70
|
raise Saorin::MethodNotFound
|
70
71
|
end
|
71
72
|
|
data/lib/saorin/error.rb
CHANGED
@@ -5,15 +5,20 @@ module Saorin
|
|
5
5
|
end
|
6
6
|
|
7
7
|
class RPCError < Error
|
8
|
-
attr_reader :code
|
8
|
+
attr_reader :code, :data
|
9
9
|
|
10
|
-
def initialize(
|
11
|
-
@code = code
|
10
|
+
def initialize(message, options = {})
|
12
11
|
super message
|
12
|
+
@code = options[:code]
|
13
|
+
@data = options[:data]
|
13
14
|
end
|
14
15
|
|
15
16
|
def to_h
|
16
|
-
|
17
|
+
h = {}
|
18
|
+
h['code'] = code
|
19
|
+
h['message'] = message
|
20
|
+
h['data'] = data if data
|
21
|
+
h
|
17
22
|
end
|
18
23
|
|
19
24
|
def to_json(*args)
|
@@ -41,23 +46,29 @@ module Saorin
|
|
41
46
|
JSON_RPC_ERRORS.each do |code, name, message|
|
42
47
|
class_eval <<-EOS
|
43
48
|
class #{name} < RPCError
|
44
|
-
def initialize
|
45
|
-
|
49
|
+
def initialize(message = nil, options = {})
|
50
|
+
options[:code] = #{code}
|
51
|
+
super message || '#{message}', options
|
46
52
|
end
|
47
53
|
end
|
48
54
|
EOS
|
49
55
|
end
|
50
56
|
|
51
57
|
class ServerError < RPCError
|
52
|
-
def initialize(
|
53
|
-
|
58
|
+
def initialize(message, options = {})
|
59
|
+
options[:code] ||= -32000
|
60
|
+
super message, options
|
54
61
|
end
|
55
62
|
end
|
56
63
|
|
57
64
|
class << self
|
58
65
|
def code_to_error(code)
|
59
|
-
|
60
|
-
|
66
|
+
if (-32099..-32000).include?(code)
|
67
|
+
ServerError
|
68
|
+
else
|
69
|
+
@map ||= Hash[JSON_RPC_ERRORS.map { |c, n, m| [c, const_get(n)] }]
|
70
|
+
@map[code]
|
71
|
+
end
|
61
72
|
end
|
62
73
|
end
|
63
74
|
|
data/lib/saorin/request.rb
CHANGED
@@ -1,16 +1,22 @@
|
|
1
1
|
require 'saorin'
|
2
2
|
require 'saorin/error'
|
3
|
+
require 'saorin/utility'
|
3
4
|
require 'multi_json'
|
4
5
|
|
5
6
|
module Saorin
|
6
7
|
class Request
|
7
8
|
attr_accessor :version, :method, :params, :id
|
8
9
|
|
9
|
-
def initialize(method, params,
|
10
|
-
@version = version
|
10
|
+
def initialize(method, params, options = {})
|
11
|
+
@version = options[:version] || Saorin::JSON_RPC_VERSION
|
11
12
|
@method = method
|
12
13
|
@params = params
|
13
|
-
@id = id
|
14
|
+
@id = options[:id]
|
15
|
+
@notify = !options.has_key?(:id)
|
16
|
+
end
|
17
|
+
|
18
|
+
def notify?
|
19
|
+
@notify
|
14
20
|
end
|
15
21
|
|
16
22
|
def valid?
|
@@ -33,7 +39,7 @@ module Saorin
|
|
33
39
|
h['jsonrpc'] = @version
|
34
40
|
h['method'] = @method
|
35
41
|
h['params'] = @params if @params && !@params.empty?
|
36
|
-
h['id'] = @id
|
42
|
+
h['id'] = @id unless notify?
|
37
43
|
h
|
38
44
|
end
|
39
45
|
|
@@ -42,9 +48,20 @@ module Saorin
|
|
42
48
|
MultiJson.dump to_h, options
|
43
49
|
end
|
44
50
|
|
51
|
+
def self.symbolized_keys(hash)
|
52
|
+
hash.each do |k, v|
|
53
|
+
if k.is_a? ::String
|
54
|
+
hash[k.to_sym] = v
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
45
59
|
def self.from_hash(hash)
|
46
60
|
raise Saorin::InvalidRequest unless hash.is_a?(::Hash)
|
47
|
-
|
61
|
+
options = hash.dup
|
62
|
+
method = options.delete('method')
|
63
|
+
params = options.delete('params')
|
64
|
+
new method, params, Saorin::Utility.symbolized_keys(options)
|
48
65
|
end
|
49
66
|
end
|
50
67
|
end
|
data/lib/saorin/response.rb
CHANGED
@@ -1,16 +1,17 @@
|
|
1
1
|
require 'saorin'
|
2
2
|
require 'saorin/error'
|
3
|
+
require 'saorin/utility'
|
3
4
|
require 'multi_json'
|
4
5
|
|
5
6
|
module Saorin
|
6
7
|
class Response
|
7
8
|
attr_accessor :version, :result, :error, :id
|
8
9
|
|
9
|
-
def initialize(
|
10
|
-
@version = version
|
11
|
-
@result = result
|
12
|
-
@error = error
|
13
|
-
@id = id
|
10
|
+
def initialize(options = {})
|
11
|
+
@version = options[:version] || Saorin::JSON_RPC_VERSION
|
12
|
+
@result = options[:result]
|
13
|
+
@error = options[:error]
|
14
|
+
@id = options[:id]
|
14
15
|
end
|
15
16
|
|
16
17
|
def error?
|
@@ -20,7 +21,7 @@ module Saorin
|
|
20
21
|
def valid?
|
21
22
|
return false unless !(@result && @error)
|
22
23
|
return false unless [String].any? { |type| @version.is_a? type }
|
23
|
-
return false unless [
|
24
|
+
return false unless [Object].any? { |type| @result.is_a? type }
|
24
25
|
return false unless [Saorin::Error, Hash, NilClass].any? { |type| @error.is_a? type }
|
25
26
|
return false unless [String, Numeric, NilClass].any? { |type| @id.is_a? type }
|
26
27
|
return false unless @version == JSON_RPC_VERSION
|
@@ -47,7 +48,7 @@ module Saorin
|
|
47
48
|
|
48
49
|
def self.from_hash(hash)
|
49
50
|
raise Saorin::InvalidResponse unless hash.is_a?(::Hash)
|
50
|
-
new
|
51
|
+
new Saorin::Utility.symbolized_keys(hash)
|
51
52
|
end
|
52
53
|
end
|
53
54
|
end
|
data/lib/saorin/test.rb
ADDED
@@ -0,0 +1,128 @@
|
|
1
|
+
require 'saorin/server'
|
2
|
+
require 'saorin/client'
|
3
|
+
require 'thread'
|
4
|
+
require 'logger'
|
5
|
+
require 'rspec'
|
6
|
+
|
7
|
+
module Saorin
|
8
|
+
module Test
|
9
|
+
class Handler
|
10
|
+
def identity(value)
|
11
|
+
value
|
12
|
+
end
|
13
|
+
|
14
|
+
def subtract1(a, b)
|
15
|
+
a - b
|
16
|
+
end
|
17
|
+
|
18
|
+
def subtract2(options)
|
19
|
+
options['minuend'] - options['subtrahend']
|
20
|
+
end
|
21
|
+
|
22
|
+
def update(a, b, c, d, e)
|
23
|
+
'OK'
|
24
|
+
end
|
25
|
+
|
26
|
+
def sum(a, b, c)
|
27
|
+
a + b + c
|
28
|
+
end
|
29
|
+
|
30
|
+
def notify_hello(a)
|
31
|
+
'OK'
|
32
|
+
end
|
33
|
+
|
34
|
+
def get_data
|
35
|
+
['hello', 5]
|
36
|
+
end
|
37
|
+
|
38
|
+
def notify_sum(a, b, c)
|
39
|
+
a + b + c
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
HOST = '127.0.0.1'
|
44
|
+
PORT = 45339
|
45
|
+
|
46
|
+
attr_reader :pid
|
47
|
+
attr_reader :server
|
48
|
+
attr_reader :client
|
49
|
+
|
50
|
+
def create_test_server(options = {})
|
51
|
+
@pid = Process.fork do
|
52
|
+
@server = Saorin::Server.start(Handler.new, {
|
53
|
+
:host => HOST,
|
54
|
+
:port => PORT,
|
55
|
+
:Logger => Logger.new('/dev/null'),
|
56
|
+
:AccessLog => [],
|
57
|
+
}.merge(options))
|
58
|
+
end
|
59
|
+
sleep 3
|
60
|
+
end
|
61
|
+
|
62
|
+
def shutdown_test_server
|
63
|
+
Process.kill :INT, @pid
|
64
|
+
sleep 3
|
65
|
+
end
|
66
|
+
|
67
|
+
def create_test_client(options = {})
|
68
|
+
@client = Saorin::Client.new({
|
69
|
+
:url => "http://127.0.0.1:#{PORT}"
|
70
|
+
}.merge(options))
|
71
|
+
end
|
72
|
+
|
73
|
+
def test_call(*args)
|
74
|
+
@client.call *args
|
75
|
+
end
|
76
|
+
|
77
|
+
def test_notify(*args)
|
78
|
+
@client.notify *args
|
79
|
+
end
|
80
|
+
|
81
|
+
shared_context 'setup rpc server client' do
|
82
|
+
let(:server_adapter) {}
|
83
|
+
let(:client_adapter) {}
|
84
|
+
before(:all) do
|
85
|
+
create_test_server :adapter => server_adapter
|
86
|
+
create_test_client :adapter => client_adapter
|
87
|
+
end
|
88
|
+
after(:all) do
|
89
|
+
shutdown_test_server
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
shared_examples 'rpc server client' do
|
94
|
+
it 'string' do
|
95
|
+
value = '123'
|
96
|
+
test_call('identity', value).should eq value
|
97
|
+
end
|
98
|
+
|
99
|
+
it 'number' do
|
100
|
+
value = 123
|
101
|
+
test_call('identity', value).should eq value
|
102
|
+
end
|
103
|
+
|
104
|
+
it 'array' do
|
105
|
+
value = [1, 2, 3]
|
106
|
+
test_call('identity', value).should eq value
|
107
|
+
end
|
108
|
+
|
109
|
+
it 'hash' do
|
110
|
+
value = {'foo' => 1, 'bar' => 2}
|
111
|
+
test_call('identity', value).should eq value
|
112
|
+
end
|
113
|
+
|
114
|
+
it 'nil' do
|
115
|
+
value = nil
|
116
|
+
test_call('identity', value).should eq value
|
117
|
+
end
|
118
|
+
|
119
|
+
it 'not found' do
|
120
|
+
lambda { test_call('xxx') }.should raise_error MethodNotFound
|
121
|
+
end
|
122
|
+
|
123
|
+
it 'invalid params' do
|
124
|
+
lambda { test_call('identity', 1, 2, 3, 4, 5) }.should raise_error InvalidParams
|
125
|
+
end
|
126
|
+
end
|
127
|
+
end
|
128
|
+
end
|
data/lib/saorin/version.rb
CHANGED
data/saorin.gemspec
CHANGED
@@ -20,4 +20,7 @@ Gem::Specification.new do |gem|
|
|
20
20
|
gem.add_dependency 'multi_json'
|
21
21
|
gem.add_development_dependency 'rake'
|
22
22
|
gem.add_development_dependency 'rspec'
|
23
|
+
gem.add_development_dependency 'rack'
|
24
|
+
gem.add_development_dependency 'reel'
|
25
|
+
gem.add_development_dependency 'faraday'
|
23
26
|
end
|
data/server.rb
CHANGED
data/spec/adapter/base_spec.rb
CHANGED
@@ -4,7 +4,7 @@ require 'saorin/adapters/servers/base'
|
|
4
4
|
describe Saorin::Adapters::Servers::Base do
|
5
5
|
it_should_behave_like 'rpc call' do
|
6
6
|
let(:process) do
|
7
|
-
handler = Handler.new
|
7
|
+
handler = Saorin::Test::Handler.new
|
8
8
|
server = Saorin::Adapters::Servers::Base.new handler
|
9
9
|
proc do |input|
|
10
10
|
server.process_request input
|
@@ -0,0 +1,11 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'saorin/test'
|
3
|
+
require 'saorin/adapters/servers/rack'
|
4
|
+
|
5
|
+
describe Saorin::Adapters::Servers::Rack do
|
6
|
+
include Saorin::Test
|
7
|
+
|
8
|
+
let(:server_adapter) { :rack }
|
9
|
+
include_context 'setup rpc server client'
|
10
|
+
it_should_behave_like 'rpc server client'
|
11
|
+
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'saorin/test'
|
3
|
+
require 'saorin/adapters/servers/reel'
|
4
|
+
|
5
|
+
describe Saorin::Adapters::Servers::Reel do
|
6
|
+
include Saorin::Test
|
7
|
+
|
8
|
+
let(:server_adapter) { :reel }
|
9
|
+
include_context 'setup rpc server client'
|
10
|
+
it_should_behave_like 'rpc server client'
|
11
|
+
end
|
data/spec/request_spec.rb
CHANGED
@@ -9,7 +9,9 @@ describe Saorin::Request do
|
|
9
9
|
:id => rand(1 << 31),
|
10
10
|
}
|
11
11
|
options = default_options.merge(options)
|
12
|
-
|
12
|
+
method = options.delete(:method)
|
13
|
+
params = options.delete(:params)
|
14
|
+
Saorin::Request.new method, params, options
|
13
15
|
end
|
14
16
|
|
15
17
|
describe '#initialize' do
|
data/spec/response_spec.rb
CHANGED
@@ -9,12 +9,12 @@ describe Saorin::Response do
|
|
9
9
|
:id => rand(1 << 31),
|
10
10
|
}
|
11
11
|
options = default_options.merge(options)
|
12
|
-
Saorin::Response.new
|
12
|
+
Saorin::Response.new options
|
13
13
|
end
|
14
14
|
|
15
15
|
describe '#initialize' do
|
16
16
|
context 'success' do
|
17
|
-
before { @r =
|
17
|
+
before { @r = Saorin::Response.new :result => '123', :id => 123 }
|
18
18
|
subject { @r }
|
19
19
|
its(:version) { should eq Saorin::JSON_RPC_VERSION }
|
20
20
|
its(:result) { should eq '123' }
|
@@ -23,10 +23,10 @@ describe Saorin::Response do
|
|
23
23
|
its(:error?) { should be_false }
|
24
24
|
end
|
25
25
|
|
26
|
-
context '
|
26
|
+
context 'error' do
|
27
27
|
before do
|
28
28
|
@e = Saorin::InvalidRequest.new
|
29
|
-
@r =
|
29
|
+
@r = Saorin::Response.new :error => @e, :id => 123
|
30
30
|
end
|
31
31
|
subject { @r }
|
32
32
|
its(:version) { should eq Saorin::JSON_RPC_VERSION }
|
@@ -44,21 +44,28 @@ describe Saorin::Response do
|
|
44
44
|
create_response(:version => 2).should_not be_valid
|
45
45
|
end
|
46
46
|
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
47
|
+
context 'result' do
|
48
|
+
def create_success_response(result)
|
49
|
+
create_response(:result => result, :error => nil)
|
50
|
+
end
|
51
|
+
|
52
|
+
it('number') { create_success_response(123).should be_valid }
|
53
|
+
it('string') { create_success_response('123').should be_valid }
|
54
|
+
it('nil') { create_success_response(nil).should be_valid }
|
55
|
+
it('array') { create_success_response([]).should be_valid }
|
56
|
+
it('hash') { create_success_response({}).should be_valid }
|
57
|
+
end
|
52
58
|
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
create_response(:result => nil, :error => {}).should be_valid
|
58
|
-
create_response(:result => nil, :error => Saorin::InvalidResponse.new).should be_valid
|
59
|
+
context 'error' do
|
60
|
+
def create_fail_response(error)
|
61
|
+
create_response(:result => nil, :error => error)
|
62
|
+
end
|
59
63
|
|
60
|
-
|
61
|
-
|
64
|
+
it('number') { create_fail_response(123).should_not be_valid }
|
65
|
+
it('string') { create_fail_response('123').should_not be_valid }
|
66
|
+
it('array') { create_fail_response([]).should_not be_valid }
|
67
|
+
it('hash') { create_fail_response({}).should be_valid }
|
68
|
+
it('exception') { create_fail_response(Saorin::InvalidResponse.new).should be_valid }
|
62
69
|
end
|
63
70
|
|
64
71
|
it 'id' do
|
@@ -95,7 +102,7 @@ describe Saorin::Response do
|
|
95
102
|
h.should_not include('result')
|
96
103
|
h.should include('error')
|
97
104
|
end
|
98
|
-
it '
|
105
|
+
it 'error' do
|
99
106
|
h = create_response(:error => nil).to_h
|
100
107
|
h.should include('result')
|
101
108
|
h.should_not include('error')
|
@@ -1,55 +1,6 @@
|
|
1
|
+
require 'support/utils'
|
1
2
|
require 'json'
|
2
3
|
|
3
|
-
class Handler
|
4
|
-
def subtract1(a, b)
|
5
|
-
a - b
|
6
|
-
end
|
7
|
-
|
8
|
-
def subtract2(options)
|
9
|
-
options['minuend'] - options['subtrahend']
|
10
|
-
end
|
11
|
-
|
12
|
-
def update(a, b, c, d, e)
|
13
|
-
'OK'
|
14
|
-
end
|
15
|
-
|
16
|
-
def foobar1
|
17
|
-
'OK'
|
18
|
-
end
|
19
|
-
|
20
|
-
def foobar3(a, b)
|
21
|
-
'OK'
|
22
|
-
end
|
23
|
-
|
24
|
-
def sum(a, b, c)
|
25
|
-
a + b + c
|
26
|
-
end
|
27
|
-
|
28
|
-
def notify_hello(a)
|
29
|
-
'OK'
|
30
|
-
end
|
31
|
-
|
32
|
-
def get_data
|
33
|
-
['hello', 5]
|
34
|
-
end
|
35
|
-
|
36
|
-
def notify_sum(a, b, c)
|
37
|
-
a + b + c
|
38
|
-
end
|
39
|
-
end
|
40
|
-
|
41
|
-
def deserialize(data)
|
42
|
-
data && JSON.load(data)
|
43
|
-
end
|
44
|
-
|
45
|
-
def validates(process, inputs, answers)
|
46
|
-
inputs.zip(answers).each do |input, answer|
|
47
|
-
output = deserialize process.call(input)
|
48
|
-
answer = deserialize answer
|
49
|
-
output.should eq answer
|
50
|
-
end
|
51
|
-
end
|
52
|
-
|
53
4
|
shared_examples 'rpc call with positional parameters' do
|
54
5
|
it 'rpc call with positional parameters' do
|
55
6
|
inputs << %({"jsonrpc": "2.0", "method": "subtract1", "params": [42, 23], "id": 1})
|
@@ -74,7 +25,7 @@ shared_examples 'a Notification' do
|
|
74
25
|
it 'a Notification' do
|
75
26
|
inputs << %({"jsonrpc": "2.0", "method": "update", "params": [1,2,3,4,5]})
|
76
27
|
answers << nil
|
77
|
-
inputs << %({"jsonrpc": "2.0", "method": "
|
28
|
+
inputs << %({"jsonrpc": "2.0", "method": "foobar"})
|
78
29
|
answers << nil
|
79
30
|
validates process, inputs, answers
|
80
31
|
end
|
@@ -82,7 +33,7 @@ end
|
|
82
33
|
|
83
34
|
shared_examples 'rpc call of non-existent method' do
|
84
35
|
it 'rpc call of non-existent method' do
|
85
|
-
inputs << %({"jsonrpc": "2.0", "method": "
|
36
|
+
inputs << %({"jsonrpc": "2.0", "method": "foobar", "id": "1"})
|
86
37
|
answers << %({"jsonrpc": "2.0", "error": {"code": -32601, "message": "Method not found"}, "id": "1"})
|
87
38
|
validates process, inputs, answers
|
88
39
|
end
|
@@ -90,7 +41,7 @@ end
|
|
90
41
|
|
91
42
|
shared_examples 'rpc call with invalid JSON' do
|
92
43
|
it 'rpc call with invalid JSON' do
|
93
|
-
inputs << %({"jsonrpc": "2.0", "method": "
|
44
|
+
inputs << %({"jsonrpc": "2.0", "method": "foobar, "params": "bar", "baz])
|
94
45
|
answers << %({"jsonrpc": "2.0", "error": {"code": -32700, "message": "Parse error"}, "id": null})
|
95
46
|
validates process, inputs, answers
|
96
47
|
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
require 'saorin/test'
|
2
|
+
|
3
|
+
def deserialize(data)
|
4
|
+
data && JSON.load(data)
|
5
|
+
end
|
6
|
+
|
7
|
+
def validates(process, inputs, answers)
|
8
|
+
inputs.zip(answers).each do |input, answer|
|
9
|
+
output = deserialize process.call(input)
|
10
|
+
answer = deserialize answer
|
11
|
+
output.should eq answer
|
12
|
+
end
|
13
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: saorin
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2013-03-
|
12
|
+
date: 2013-03-09 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: multi_json
|
@@ -59,6 +59,54 @@ dependencies:
|
|
59
59
|
- - ! '>='
|
60
60
|
- !ruby/object:Gem::Version
|
61
61
|
version: '0'
|
62
|
+
- !ruby/object:Gem::Dependency
|
63
|
+
name: rack
|
64
|
+
requirement: !ruby/object:Gem::Requirement
|
65
|
+
none: false
|
66
|
+
requirements:
|
67
|
+
- - ! '>='
|
68
|
+
- !ruby/object:Gem::Version
|
69
|
+
version: '0'
|
70
|
+
type: :development
|
71
|
+
prerelease: false
|
72
|
+
version_requirements: !ruby/object:Gem::Requirement
|
73
|
+
none: false
|
74
|
+
requirements:
|
75
|
+
- - ! '>='
|
76
|
+
- !ruby/object:Gem::Version
|
77
|
+
version: '0'
|
78
|
+
- !ruby/object:Gem::Dependency
|
79
|
+
name: reel
|
80
|
+
requirement: !ruby/object:Gem::Requirement
|
81
|
+
none: false
|
82
|
+
requirements:
|
83
|
+
- - ! '>='
|
84
|
+
- !ruby/object:Gem::Version
|
85
|
+
version: '0'
|
86
|
+
type: :development
|
87
|
+
prerelease: false
|
88
|
+
version_requirements: !ruby/object:Gem::Requirement
|
89
|
+
none: false
|
90
|
+
requirements:
|
91
|
+
- - ! '>='
|
92
|
+
- !ruby/object:Gem::Version
|
93
|
+
version: '0'
|
94
|
+
- !ruby/object:Gem::Dependency
|
95
|
+
name: faraday
|
96
|
+
requirement: !ruby/object:Gem::Requirement
|
97
|
+
none: false
|
98
|
+
requirements:
|
99
|
+
- - ! '>='
|
100
|
+
- !ruby/object:Gem::Version
|
101
|
+
version: '0'
|
102
|
+
type: :development
|
103
|
+
prerelease: false
|
104
|
+
version_requirements: !ruby/object:Gem::Requirement
|
105
|
+
none: false
|
106
|
+
requirements:
|
107
|
+
- - ! '>='
|
108
|
+
- !ruby/object:Gem::Version
|
109
|
+
version: '0'
|
62
110
|
description: JSON-RPC 2.0 implementation
|
63
111
|
email:
|
64
112
|
- mail@mashiro.org
|
@@ -87,14 +135,19 @@ files:
|
|
87
135
|
- lib/saorin/request.rb
|
88
136
|
- lib/saorin/response.rb
|
89
137
|
- lib/saorin/server.rb
|
138
|
+
- lib/saorin/test.rb
|
139
|
+
- lib/saorin/utility.rb
|
90
140
|
- lib/saorin/version.rb
|
91
141
|
- saorin.gemspec
|
92
142
|
- server.rb
|
93
143
|
- spec/adapter/base_spec.rb
|
144
|
+
- spec/adapter/servers/rack_spec.rb
|
145
|
+
- spec/adapter/servers/reel_spec.rb
|
94
146
|
- spec/request_spec.rb
|
95
147
|
- spec/response_spec.rb
|
96
148
|
- spec/spec_helper.rb
|
97
|
-
- spec/support/
|
149
|
+
- spec/support/rpc_call.rb
|
150
|
+
- spec/support/utils.rb
|
98
151
|
homepage: ''
|
99
152
|
licenses: []
|
100
153
|
post_install_message:
|
@@ -109,7 +162,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
109
162
|
version: '0'
|
110
163
|
segments:
|
111
164
|
- 0
|
112
|
-
hash:
|
165
|
+
hash: -2145368172034945708
|
113
166
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
114
167
|
none: false
|
115
168
|
requirements:
|
@@ -118,7 +171,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
118
171
|
version: '0'
|
119
172
|
segments:
|
120
173
|
- 0
|
121
|
-
hash:
|
174
|
+
hash: -2145368172034945708
|
122
175
|
requirements: []
|
123
176
|
rubyforge_project:
|
124
177
|
rubygems_version: 1.8.24
|
@@ -127,7 +180,10 @@ specification_version: 3
|
|
127
180
|
summary: JSON-RPC 2.0 server and client implementation for any protocols
|
128
181
|
test_files:
|
129
182
|
- spec/adapter/base_spec.rb
|
183
|
+
- spec/adapter/servers/rack_spec.rb
|
184
|
+
- spec/adapter/servers/reel_spec.rb
|
130
185
|
- spec/request_spec.rb
|
131
186
|
- spec/response_spec.rb
|
132
187
|
- spec/spec_helper.rb
|
133
|
-
- spec/support/
|
188
|
+
- spec/support/rpc_call.rb
|
189
|
+
- spec/support/utils.rb
|