diff --git a/lib/rjr/messages.rb b/lib/rjr/messages.rb index 2f7ea2d..86f044e 100644 --- a/lib/rjr/messages.rb +++ b/lib/rjr/messages.rb @@ -6,3 +6,4 @@ require 'rjr/messages/request' require 'rjr/messages/response' require 'rjr/messages/notification' +require 'rjr/messages/intermediate' diff --git a/lib/rjr/messages/intermediate.rb b/lib/rjr/messages/intermediate.rb new file mode 100644 index 0000000..bd9d760 --- /dev/null +++ b/lib/rjr/messages/intermediate.rb @@ -0,0 +1,50 @@ +# RJR Request Message +# +# Copyright (C) 2012-2014 Mohammed Morsi +# Licensed under the Apache License, Version 2.0 + +require 'json' +require 'rjr/util/json_parser' + +module RJR +module Messages + +# Intermediate representation of a JSON-RPC data containing +# extracted/parsed data which has not been analysed. +class Intermediate + # JSON from which data is extracted from + attr_accessor :json + + # Data extracted from message + attr_accessor :data + + def initialize(args = {}) + @json = args[:json] || nil + @data = args[:data] || {} + end + + def keys + data.keys + end + + def [](key) + data[key.to_s] + end + + def has?(key) + data.key?(key) + end + + def self.parse(json) + parsed = nil + + #allow parsing errs to propagate up + parsed = JSONParser.parse(json) + + self.new :json => json, + :data => parsed + end + +end # class Intermediate +end # module Messages +end # module RJR diff --git a/lib/rjr/messages/notification.rb b/lib/rjr/messages/notification.rb index 32834a9..00d5714 100644 --- a/lib/rjr/messages/notification.rb +++ b/lib/rjr/messages/notification.rb @@ -13,7 +13,7 @@ module Messages # indicate the result should _not_ be returned class Notification # Message string received from the source - attr_accessor :json_message + attr_accessor :message # Method source is invoking on the destination attr_accessor :jr_method @@ -48,18 +48,17 @@ def parse_args(args) end def parse_message(message) - @json_message = message - notification = JSONParser.parse(@json_message) - @jr_method = notification['method'] - @jr_args = notification['params'] + @message = message + @jr_method = message['method'] + @jr_args = message['params'] - parse_headers(notification) + parse_headers(message) end - def parse_headers(notification) - notification.keys.select { |k| + def parse_headers(message) + message.keys.select { |k| !['jsonrpc', 'method', 'params'].include?(k) - }.each { |k| @headers[k] = notification[k] } + }.each { |k| @headers[k] = message[k] } end public @@ -70,13 +69,7 @@ def parse_headers(notification) # @param [String] message string message to check # @return [true,false] indicating if message is a notification message def self.is_notification_message?(message) - begin - # FIXME log error - parsed = JSONParser.parse(message) - parsed.has_key?('method') && !parsed.has_key?('id') - rescue Exception => e - false - end + message.has?('method') && !message.has?('id') end # Convert notification message to json diff --git a/lib/rjr/messages/request.rb b/lib/rjr/messages/request.rb index 4921a39..cac7ec6 100644 --- a/lib/rjr/messages/request.rb +++ b/lib/rjr/messages/request.rb @@ -12,7 +12,7 @@ module Messages # Message sent from client to server to invoke a JSON-RPC method class Request # Message string received from the source - attr_accessor :json_message + attr_accessor :message # Method source is invoking on the destination attr_accessor :jr_method @@ -51,35 +51,29 @@ def parse_args(args) end def parse_message(message) - @json_message = message - request = JSONParser.parse(@json_message) - @jr_method = request['method'] - @jr_args = request['params'] - @msg_id = request['id'] + @message = message + @jr_method = message['method'] + @jr_args = message['params'] + @msg_id = message['id'] - parse_headers(request) + parse_headers(message) end - def parse_headers(request) - request.keys.select { |k| + def parse_headers(message) + message.keys.select { |k| !['jsonrpc', 'id', 'method', 'params'].include?(k) - }.each { |k| @headers[k] = request[k] } + }.each { |k| @headers[k] = message[k] } end public - # Class helper to determine if the specified string is a valid json-rpc - # method request - # @param [String] message string message to check + # Class helper to determine if the specified message is a valid + # json-rpc method request message. + # + # @param [Message] message to check # @return [true,false] indicating if message is request message def self.is_request_message?(message) - begin - # FIXME log error - parsed = JSONParser.parse(message) - parsed.has_key?('method') && parsed.has_key?('id') - rescue Exception => e - false - end + message.has?('method') && message.has?('id') end # Convert request message to json diff --git a/lib/rjr/messages/response.rb b/lib/rjr/messages/response.rb index 6a13699..e4535a7 100644 --- a/lib/rjr/messages/response.rb +++ b/lib/rjr/messages/response.rb @@ -13,7 +13,7 @@ module Messages # Message sent from server to client in response to a JSON-RPC request class Response # Message string received from the source - attr_accessor :json_message + attr_accessor :message # ID of the message in accordance w/ json-rpc specification attr_accessor :msg_id @@ -49,54 +49,47 @@ def parse_args(args) end def parse_message(message) - @json_message = message - response = JSONParser.parse(@json_message) - @msg_id = response['id'] + @message = message + @msg_id = message['id'] - parse_result(response) - parse_headers(response) + parse_result(message) + parse_headers(message) end - def parse_result(response) + def parse_result(message) @result = Result.new - @result.success = response.has_key?('result') + @result.success = message.has?('result') @result.failed = !@result.success if @result.success - @result.result = response['result'] + @result.result = message['result'] - elsif response.has_key?('error') - @result.error_code = response['error']['code'] - @result.error_msg = response['error']['message'] + elsif message.has?('error') + @result.error_code = message['error']['code'] + @result.error_msg = message['error']['message'] # TODO can we safely constantize this ? - @result.error_class = response['error']['class'] + @result.error_class = message['error']['class'] end @result end - def parse_headers(request) - request.keys.select { |k| + def parse_headers(message) + message.keys.select { |k| !['jsonrpc', 'id', 'method', 'result', 'error'].include?(k) - }.each { |k| @headers[k] = request[k] } + }.each { |k| @headers[k] = message[k] } end public - # Class helper to determine if the specified string is a valid json-rpc - # method response + # Class helper to determine if the specified string is a + # valid json-rpc method response + # # @param [String] message string message to check # @return [true,false] indicating if message is response message def self.is_response_message?(message) - begin - # FIXME log error - json = JSONParser.parse(message) - json.has_key?('result') || json.has_key?('error') - rescue Exception => e - puts e.to_s - false - end + message.has?('result') || message.has?('error') end def success_json diff --git a/lib/rjr/node.rb b/lib/rjr/node.rb index f6ec8a9..d3fd7c8 100644 --- a/lib/rjr/node.rb +++ b/lib/rjr/node.rb @@ -183,28 +183,36 @@ def client_for(connection) # Internal helper, handle message received def handle_message(msg, connection = {}) - if Messages::Request.is_request_message?(msg) - tp << ThreadPoolJob.new(msg) { |m| handle_request(m, false, connection) } + intermediate = Messages::Intermediate.parse(msg) - elsif Messages::Notification.is_notification_message?(msg) - tp << ThreadPoolJob.new(msg) { |m| handle_request(m, true, connection) } + if Messages::Request.is_request_message?(intermediate) + tp << ThreadPoolJob.new(intermediate) { |i| + handle_request(i, false, connection) + } - elsif Messages::Response.is_response_message?(msg) - handle_response(msg) + elsif Messages::Notification.is_notification_message?(intermediate) + tp << ThreadPoolJob.new(intermediate) { |i| + handle_request(i, true, connection) + } + + elsif Messages::Response.is_response_message?(intermediate) + handle_response(intermediate) end + + intermediate end # Internal helper, handle request message received - def handle_request(data, notification=false, connection={}) + def handle_request(message, notification=false, connection={}) # get client for the specified connection # TODO should grap port/ip immediately on connection and use that client_port,client_ip = client_for(connection) msg = notification ? - Messages::Notification.new(:message => data, + Messages::Notification.new(:message => message, :headers => @message_headers) : - Messages::Request.new(:message => data, + Messages::Request.new(:message => message, :headers => @message_headers) callback = NodeCallback.new(:node => self, @@ -233,8 +241,8 @@ def handle_request(data, notification=false, connection={}) end # Internal helper, handle response message received - def handle_response(data) - msg = Messages::Response.new(:message => data, + def handle_response(message) + msg = Messages::Response.new(:message => message, :headers => self.message_headers) res = err = nil begin diff --git a/lib/rjr/nodes/local.rb b/lib/rjr/nodes/local.rb index 08ff04b..94277f9 100644 --- a/lib/rjr/nodes/local.rb +++ b/lib/rjr/nodes/local.rb @@ -61,8 +61,9 @@ def to_s # Implementation of RJR::Node#send_msg def send_msg(msg, connection) # ignore response message - unless Messages::Response.is_response_message?(msg) - launch_request(msg, true) # .join? + inter = Messages::Intermediate.parse(msg) + unless Messages::Response.is_response_message?(inter) + launch_request(inter, true) # .join? end end @@ -80,9 +81,15 @@ def listen # (or close to it, globals will still be available, but locks will # not be locally held, etc) def launch_request(req, notification) - Thread.new(req,notification) { |req,notification| - res = handle_request(req, notification, nil) - handle_response(res.to_s) unless res.nil? + Thread.new(req, notification) { |req, notification| + inter = req.is_a?(Messages::Intermediate) ? req : + Messages::Intermediate.parse(req) + res = handle_request(inter, notification, nil) + + unless res.nil? + inter = Messages::Intermediate.parse(res.to_s) + handle_response(inter) + end } end diff --git a/lib/rjr/nodes/web.rb b/lib/rjr/nodes/web.rb index 1f4535e..765c76b 100644 --- a/lib/rjr/nodes/web.rb +++ b/lib/rjr/nodes/web.rb @@ -52,12 +52,13 @@ def initialize(args = {}) def process_http_request # TODO support http protocols other than POST msg = @http_post_content.nil? ? '' : @http_post_content - @rjr_node.send(:handle_message, msg, self) # XXX private method + inter = @rjr_node.send(:handle_message, msg, self) # XXX private method # XXX we still have to send a response back to client to satisfy # the http standard, even if this is a notification. handle_message # does not do this. - @rjr_node.send_msg "", self if Messages::Notification.is_notification_message?(msg) + notification = Messages::Notification.is_notification_message?(inter) + @rjr_node.send_msg "", self if notification end end diff --git a/lib/rjr/util/json_parser.rb b/lib/rjr/util/json_parser.rb index b9b808c..c0c3d17 100644 --- a/lib/rjr/util/json_parser.rb +++ b/lib/rjr/util/json_parser.rb @@ -16,11 +16,11 @@ class JSONParser # Returns the message and remaining portion of the data string, # if message is found, else nil # - # TODO efficiency can probably be optimized in the case closing '}' - # hasn't arrived yet - # - # FIXME if uneven brackets appears in string data (such as in params) - # this will break, detect when in string and ignore in counts +# TODO efficiency can probably be optimized in the case closing '}' +# hasn't arrived yet +# +# FIXME if uneven brackets appears in string data (such as in params) +# this will break, detect when in string and ignore in counts def self.extract_json_from(data) return nil if data.nil? || data.empty? start = 0 diff --git a/specs/messages/intermediate_spec.rb b/specs/messages/intermediate_spec.rb new file mode 100644 index 0000000..e91001d --- /dev/null +++ b/specs/messages/intermediate_spec.rb @@ -0,0 +1,58 @@ +require 'rjr/common' +require 'rjr/messages/intermediate' + +module RJR +module Messages + describe Intermediate do + describe "#keys" do + it "returns extracted data keys" do + msg = Intermediate.new :data => {:foo => :bar, :mo => :money} + msg.keys.should == [:foo, :mo] + end + end + + describe "#[]" do + it "returns value from extracted data" do + msg = Intermediate.new :data => {'foo' => 'bar'} + msg['foo'].should == 'bar' + msg[:foo].should == 'bar' + end + end + + describe "#has?" do + context "data has key" do + it "returns true" do + msg = Intermediate.new :data => {'foo' => 'bar'} + msg.has?('foo').should be_true + end + end + + context "data does not have key" do + it "returns false" do + msg = Intermediate.new + msg.has?('foo').should be_false + end + end + end + + describe "::parse" do + it "returns new intermediate instance with original message and parsed data" do + json = '{"foo":"bar"}' + msg = Intermediate.parse json + msg.json.should == json + msg.data.should == {"foo" => "bar"} + end + + describe "error parsing json" do + it "propagates err" do + json = '{"foo":"bar"}' + JSONParser.should_receive(:parse).with(json).and_raise(RuntimeError) + lambda { + Intermediate.parse json + }.should raise_error(RuntimeError) + end + end + end + end # describe Intermediate +end # module Messages +end # module RJR diff --git a/specs/messages/notification_spec.rb b/specs/messages/notification_spec.rb index af1664b..cd47622 100644 --- a/specs/messages/notification_spec.rb +++ b/specs/messages/notification_spec.rb @@ -1,4 +1,5 @@ require 'rjr/messages/notification' +require 'rjr/messages/intermediate' module RJR module Messages @@ -16,9 +17,9 @@ module Messages it "should return bool indicating if string is a notification msg" it "should produce valid json" do - msg = Notification.new :method => 'test', - :args => ['a', 1], - :headers => {:h => 2} + msg = Notification.new :method => 'test', + :args => ['a', 1], + :headers => {:h => 2} msg_string = msg.to_s msg_string.should include('"h":2') @@ -31,8 +32,10 @@ module Messages it "should parse notification message string" do msg_string = '{"jsonrpc": "2.0", ' + '"method": "test", "params": ["a", 1]}' - msg = Notification.new :message => msg_string - msg.json_message.should == msg_string + inter = Intermediate.parse msg_string + + msg = Notification.new :message => inter + msg.message.should == inter msg.jr_method.should == 'test' msg.jr_args.should =~ ['a', 1] end @@ -41,19 +44,15 @@ module Messages msg_string = '{"jsonrpc": "2.0", ' + '"method": "test", "params": ["a", 1], ' + '"h": 2}' - msg = Notification.new :message => msg_string, :headers => {'f' => 'g'} - msg.json_message.should == msg_string + inter = Intermediate.parse msg_string + + msg = Notification.new :message => inter, :headers => {'f' => 'g'} + msg.message.should == inter msg.headers.should have_key 'h' msg.headers.should have_key 'f' msg.headers['h'].should == 2 msg.headers['f'].should == 'g' end - - it "should fail if parsing invalid message string" do - lambda { - msg = Notification.new :message => 'foobar' - }.should raise_error JSON::ParserError - end end # describe Notification end # module Messages end # module RJR diff --git a/specs/messages/request_spec.rb b/specs/messages/request_spec.rb index 409fdea..ad9ff30 100644 --- a/specs/messages/request_spec.rb +++ b/specs/messages/request_spec.rb @@ -1,13 +1,15 @@ require 'rjr/common' require 'rjr/messages/request' +require 'rjr/messages/intermediate' module RJR module Messages describe Request do it "should accept request parameters" do - msg = Request.new :method => 'test', - :args => ['a', 1], - :headers => {:h => 2} + msg = Request.new :method => 'test', + :args => ['a', 1], + :headers => {:h => 2} + msg.jr_method.should == "test" msg.jr_args.should =~ ['a', 1] msg.headers.should have_key(:h) @@ -18,9 +20,9 @@ module Messages it "should return bool indicating if string is a request msg" it "should produce valid json" do - msg = Request.new :method => 'test', - :args => ['a', 1], - :headers => {:h => 2} + msg = Request.new :method => 'test', + :args => ['a', 1], + :headers => {:h => 2} msg_string = msg.to_s msg_string.should include('"h":2') @@ -35,8 +37,10 @@ module Messages msg_string = '{"jsonrpc": "2.0", ' + '"id": "' + msg_uuid + '", ' + '"method": "test", "params": ["a", 1]}' - msg = Request.new :message => msg_string - msg.json_message.should == msg_string + inter = Intermediate.parse msg_string + + msg = Request.new :message => inter + msg.message.should == inter msg.jr_method.should == 'test' msg.jr_args.should =~ ['a', 1] msg.msg_id.should == msg_uuid @@ -48,19 +52,15 @@ module Messages '"id": "' + msg_uuid + '", ' + '"method": "test", "params": ["a", 1], ' + '"h": 2}' - msg = Request.new :message => msg_string, :headers => {'f' => 'g'} - msg.json_message.should == msg_string + inter = Intermediate.parse msg_string + + msg = Request.new :message => inter, :headers => {'f' => 'g'} + msg.message.should == inter msg.headers.should have_key 'h' msg.headers.should have_key 'f' msg.headers['h'].should == 2 msg.headers['f'].should == 'g' end - - it "should fail if parsing invalid message string" do - lambda { - msg = Request.new :message => 'foobar' - }.should raise_error JSON::ParserError - end end # describe Request end # module Messages end # module RJR diff --git a/specs/messages/response_spec.rb b/specs/messages/response_spec.rb index 076626b..7284cf2 100644 --- a/specs/messages/response_spec.rb +++ b/specs/messages/response_spec.rb @@ -1,6 +1,7 @@ require 'rjr/common' require 'rjr/result' require 'rjr/messages/response' +require 'rjr/messages/intermediate' module RJR module Messages @@ -21,8 +22,8 @@ module Messages it "should produce valid result response json" do msg_id = gen_uuid msg = Response.new :id => msg_id, - :result => RJR::Result.new(:result => 'success'), - :headers => {:h => 2} + :result => RJR::Result.new(:result => 'success'), + :headers => {:h => 2} msg_string = msg.to_s msg_string.should include('"id":"'+msg_id+'"') msg_string.should include('"result":"success"') @@ -52,8 +53,10 @@ module Messages msg_id = gen_uuid msg_string = '{"id":"' + msg_id + '", ' + '"result":"success","jsonrpc":"2.0"}' - msg = Response.new :message => msg_string - msg.json_message.should == msg_string + inter = Intermediate.parse msg_string + + msg = Response.new :message => inter + msg.message.should == inter msg.msg_id.should == msg_id msg.result.success.should == true msg.result.failed.should == false @@ -64,8 +67,10 @@ module Messages msg_id = gen_uuid msg_string = '{"id":"' + msg_id + '", ' + '"error":{"code":404,"message":"not found","class":"ArgumentError"}, "jsonrpc":"2.0"}' - msg = Response.new :message => msg_string - msg.json_message.should == msg_string + inter = Intermediate.parse msg_string + + msg = Response.new :message => inter + msg.message.should == inter msg.msg_id.should == msg_id msg.result.success.should == false msg.result.failed.should == true @@ -78,17 +83,13 @@ module Messages msg_id = gen_uuid msg_string = '{"id":"' + msg_id + '", ' + '"result":"success","h":2,"jsonrpc":"2.0"}' - msg = Response.new :message => msg_string - msg.json_message.should == msg_string + inter = Intermediate.parse msg_string + + msg = Response.new :message => inter + msg.message.should == inter msg.headers.should have_key 'h' msg.headers['h'].should == 2 end - - it "should fail if parsing invalid message string" do - lambda { - msg = Response.new :message => 'foobar' - }.should raise_error JSON::ParserError - end end # describe Response end # module Messages end # module RJR diff --git a/specs/node_spec.rb b/specs/node_spec.rb index 7697936..256b79d 100644 --- a/specs/node_spec.rb +++ b/specs/node_spec.rb @@ -247,6 +247,10 @@ module RJR connection = Object.new request = Messages::Request.new :id => 1, :method => 'foo' request_str = request.to_s + inter = Messages::Intermediate.parse request_str + Messages::Intermediate.should_receive(:parse). + with(request_str). + and_return(inter) node = Node.new node.tp.should_receive(:<<) { |job| @@ -254,7 +258,7 @@ module RJR job.exec Mutex.new } - node.should_receive(:handle_request).with(request_str, false, connection) + node.should_receive(:handle_request).with(inter, false, connection) node.send :handle_message, request_str, connection end end @@ -264,6 +268,10 @@ module RJR connection = Object.new notification = Messages::Notification.new :method => 'foo' notification_str = notification.to_s + inter = Messages::Intermediate.parse notification_str + Messages::Intermediate.should_receive(:parse). + with(notification_str). + and_return(inter) node = Node.new node.tp.should_receive(:<<) { |job| @@ -271,8 +279,7 @@ module RJR job.exec Mutex.new } - node.should_receive(:handle_request). - with(notification_str, true, connection) + node.should_receive(:handle_request).with(inter, true, connection) node.send :handle_message, notification_str, connection end end @@ -281,9 +288,13 @@ module RJR it "handles response" do response = Messages::Response.new :result => Result.new response_str = response.to_s + inter = Messages::Intermediate.parse response_str + Messages::Intermediate.should_receive(:parse). + with(response_str). + and_return(inter) node = Node.new - node.should_receive(:handle_response).with(response_str) + node.should_receive(:handle_response).with(inter) node.send :handle_message, response_str end end @@ -297,6 +308,14 @@ module RJR node.send :handle_message, "{}" end end + + it "returns intermediate message" do + node = Node.new + connection = Object.new + inter = Messages::Intermediate.new + Messages::Intermediate.should_receive(:parse).and_return(inter) + node.send(:handle_message, '', connection).should == inter + end end describe "#handle_request" do @@ -305,13 +324,14 @@ module RJR Messages::Notification.new :method => 'rjr_method1', :args => ['method', 'args'], :headers => {'msg' => 'headers'} - @notification = notification.to_s + notification_str = notification.to_s + @intermediate = Messages::Intermediate.parse notification_str @node = Node.new end it "invokes dispatcher.dispatch" do @node.dispatcher.should_receive(:dispatch) - @node.send :handle_request, @notification, true + @node.send :handle_request, @intermediate, true end describe "dispatcher.dispatch args" do @@ -319,21 +339,21 @@ module RJR @node.dispatcher.should_receive(:dispatch) { |args| args[:rjr_method].should == 'rjr_method1' } - @node.send :handle_request, @notification, true + @node.send :handle_request, @intermediate, true end it "includes :rjr_method_args => msg.jr_args" do @node.dispatcher.should_receive(:dispatch) { |args| args[:rjr_method_args].should == ['method', 'args'] } - @node.send :handle_request, @notification, true + @node.send :handle_request, @intermediate, true end it "includes :rjr_headers => msg.headers" do @node.dispatcher.should_receive(:dispatch) { |args| args[:rjr_headers].should == {'msg' => 'headers'} } - @node.send :handle_request, @notification, true + @node.send :handle_request, @intermediate, true end it "includes :rjr_client_ip => extracted client ip" do @@ -343,7 +363,7 @@ module RJR @node.dispatcher.should_receive(:dispatch) { |args| args[:rjr_client_ip].should == '127.0.0.1' } - @node.send :handle_request, @notification, true, connection + @node.send :handle_request, @intermediate, true, connection end it "includes :rjr_client_port => extracted client port" do @@ -353,14 +373,14 @@ module RJR @node.dispatcher.should_receive(:dispatch) { |args| args[:rjr_client_port].should == 9999 } - @node.send :handle_request, @notification, true, connection + @node.send :handle_request, @intermediate, true, connection end it "includes :rjr_node => self" do @node.dispatcher.should_receive(:dispatch) { |args| args[:rjr_node].should == @node } - @node.send :handle_request, @notification, true + @node.send :handle_request, @intermediate, true end it "includes :rjr_node_id => self.node_id" do @@ -368,7 +388,7 @@ module RJR @node.dispatcher.should_receive(:dispatch) { |args| args[:rjr_node_id].should == 'node_id' } - @node.send :handle_request, @notification, true + @node.send :handle_request, @intermediate, true end it "includes :rjr_node_type => self.node_type" do @@ -376,14 +396,14 @@ module RJR @node.dispatcher.should_receive(:dispatch) { |args| args[:rjr_node_type].should == :nt } - @node.send :handle_request, @notification, true + @node.send :handle_request, @intermediate, true end it "includes :rjr_callback => constructed node callback" do @node.dispatcher.should_receive(:dispatch) { |args| args[:rjr_callback].should be_an_instance_of(NodeCallback) } - @node.send :handle_request, @notification, true + @node.send :handle_request, @intermediate, true end describe "specified node callback" do @@ -391,7 +411,7 @@ module RJR @node.dispatcher.should_receive(:dispatch) { |args| args[:rjr_callback].node.should == @node } - @node.send :handle_request, @notification, true + @node.send :handle_request, @intermediate, true end it "has a handle to the connection" do @@ -399,17 +419,18 @@ module RJR @node.dispatcher.should_receive(:dispatch) { |args| args[:rjr_callback].connection.should == connection } - @node.send :handle_request, @notification, true, connection + @node.send :handle_request, @intermediate, true, connection end end end context "handling request / not a notification" do before(:each) do - request = Messages::Request.new :method => 'method1', - :args => ['method', 'args'], - :headers => {'msg' => 'headers'} - @request = request.to_s + request = Messages::Request.new :method => 'method1', + :args => ['method', 'args'], + :headers => {'msg' => 'headers'} + request_str = request.to_s + @intermediate = Messages::Intermediate.parse request_str result = Result.new @expected = Messages::Response.new :result => result, @@ -426,19 +447,19 @@ module RJR response.should == @expected.to_s econnection.should == connection } - @node.send :handle_request, @request, false, connection + @node.send :handle_request, @intermediate, false, connection end it "returns response" do @node.should_receive(:send_msg) # stub out - response = @node.send(:handle_request, @request, false) + response = @node.send(:handle_request, @intermediate, false) response.should be_an_instance_of(Messages::Response) response.to_s.should == @expected.to_s end end it "returns nil" do - @node.send(:handle_request, @notification, true).should be_nil + @node.send(:handle_request, @intermediate, true).should be_nil end end @@ -448,7 +469,8 @@ module RJR @result = Result.new :result => 42 response = Messages::Response.new :id => 'msg1', :result => @result - @response = response.to_s + response = response.to_s + @intermediate = Messages::Intermediate.parse response end it "invokes dispatcher.handle_response with response result" do @@ -456,11 +478,11 @@ module RJR r.should be_an_instance_of(Result) r.result.should == 42 } - @node.send :handle_response, @response + @node.send :handle_response, @intermediate end it "adds response msg_id and result to response queue" do - @node.send :handle_response, @response + @node.send :handle_response, @intermediate responses = @node.instance_variable_get(:@responses) responses.size.should == 1 responses.first[0].should == 'msg1' @@ -470,7 +492,7 @@ module RJR context "response contains error" do it "adds response error to response queue" do @node.dispatcher.should_receive(:handle_response).and_raise(Exception) - @node.send :handle_response, @response + @node.send :handle_response, @intermediate responses = @node.instance_variable_get(:@responses) responses.first[2].should be_an_instance_of(Exception) end @@ -478,7 +500,7 @@ module RJR it "signals response cv" do @node.instance_variable_get(:@response_cv).should_receive(:broadcast) - @node.send :handle_response, @response + @node.send :handle_response, @intermediate end end