Skip to content
Snippets Groups Projects
Commit 48ed2181 authored by Nicolas Pope's avatar Nicolas Pope
Browse files

Add exception handling and reporting in RPC code

parent d1289122
No related branches found
No related tags found
No related merge requests found
...@@ -69,7 +69,7 @@ class Protocol { ...@@ -69,7 +69,7 @@ class Protocol {
static Protocol *find(const std::string &id); static Protocol *find(const std::string &id);
protected: //protected:
void dispatchRPC(Socket &, const std::string &d); void dispatchRPC(Socket &, const std::string &d);
void dispatchReturn(Socket &, const std::string &d); void dispatchReturn(Socket &, const std::string &d);
void dispatchRaw(uint32_t service, Socket &); void dispatchRaw(uint32_t service, Socket &);
......
...@@ -55,14 +55,22 @@ void ftl::net::Dispatcher::dispatch_call(Socket &s, const msgpack::object &msg) ...@@ -55,14 +55,22 @@ void ftl::net::Dispatcher::dispatch_call(Socket &s, const msgpack::object &msg)
auto result = (it_func->second)(args); //->get(); auto result = (it_func->second)(args); //->get();
response_t res_obj = std::make_tuple(1,id,msgpack::object(),result->get()); response_t res_obj = std::make_tuple(1,id,msgpack::object(),result->get());
std::stringstream buf; std::stringstream buf;
msgpack::pack(buf, res_obj); msgpack::pack(buf, res_obj);
//std::cout << " RESULT " << result.as<std::string>() << std::endl;
s.send(FTL_PROTOCOL_RPCRETURN, buf.str()); s.send(FTL_PROTOCOL_RPCRETURN, buf.str());
} catch (int e) { } catch (const std::exception &e) {
//throw;
//LOG(ERROR) << "Exception when attempting to call RPC (" << e << ")";
response_t res_obj = std::make_tuple(1,id,msgpack::object(e.what()),msgpack::object());
std::stringstream buf;
msgpack::pack(buf, res_obj);
s.send(FTL_PROTOCOL_RPCRETURN, buf.str());
} catch (int e) {
//throw; //throw;
LOG(ERROR) << "Exception when attempting to call RPC (" << e << ")"; //LOG(ERROR) << "Exception when attempting to call RPC (" << e << ")";
response_t res_obj = std::make_tuple(1,id,msgpack::object(e),msgpack::object());
std::stringstream buf;
msgpack::pack(buf, res_obj);
s.send(FTL_PROTOCOL_RPCRETURN, buf.str());
} }
} }
} }
......
...@@ -11,7 +11,7 @@ using namespace std::chrono; ...@@ -11,7 +11,7 @@ using namespace std::chrono;
using ftl::net::Listener; using ftl::net::Listener;
using ftl::net::Socket; using ftl::net::Socket;
static std::vector<shared_ptr<ftl::net::Socket>> sockets; std::vector<shared_ptr<ftl::net::Socket>> sockets;
static std::vector<shared_ptr<ftl::net::Listener>> listeners; static std::vector<shared_ptr<ftl::net::Listener>> listeners;
static fd_set sfdread; static fd_set sfdread;
static fd_set sfderror; static fd_set sfderror;
......
#include "catch.hpp" #include "catch.hpp"
#include <ftl/net/protocol.hpp> #include <ftl/net/protocol.hpp>
#include <ftl/net/dispatcher.hpp>
using ftl::net::Protocol; using ftl::net::Protocol;
using ftl::net::Dispatcher;
// --- Mock -------------------------------------------------------------------- // --- Mock --------------------------------------------------------------------
#define _FTL_NET_SOCKET_HPP_ // Prevent include #define _FTL_NET_SOCKET_HPP_ // Prevent include
static std::string last_send;
namespace ftl { namespace ftl {
namespace net { namespace net {
class Socket { class Socket {
public: public:
std::string getURI() { return "mock://"; } std::string getURI() { return "mock://"; }
int send(int msg, const std::string &d) { return 0; } int send(int msg, const std::string &d) { last_send = d; return 0; }
}; };
}; };
}; };
...@@ -29,6 +33,13 @@ class MockProtocol : public Protocol { ...@@ -29,6 +33,13 @@ class MockProtocol : public Protocol {
// --- Support ----------------------------------------------------------------- // --- Support -----------------------------------------------------------------
Dispatcher::response_t get_response() {
auto unpacked = msgpack::unpack(last_send.data(), last_send.size());
Dispatcher::response_t the_result;
unpacked.get().convert(the_result);
return the_result;
}
// --- Files to test ----------------------------------------------------------- // --- Files to test -----------------------------------------------------------
#include "../src/protocol.cpp" #include "../src/protocol.cpp"
...@@ -64,11 +75,11 @@ TEST_CASE("Protocol::bind(int,...)", "[proto]") { ...@@ -64,11 +75,11 @@ TEST_CASE("Protocol::bind(int,...)", "[proto]") {
} }
} }
TEST_CASE("Protocol::bind(string,...)", "[proto]") { SCENARIO("Protocol::bind(string,...)", "[proto]") {
MockProtocol p; MockProtocol p;
Socket s; Socket s;
SECTION("no argument bind with valid dispatch") { GIVEN("no arguments and no return") {
bool called = false; bool called = false;
p.bind("test1", [&]() { p.bind("test1", [&]() {
...@@ -84,7 +95,7 @@ TEST_CASE("Protocol::bind(string,...)", "[proto]") { ...@@ -84,7 +95,7 @@ TEST_CASE("Protocol::bind(string,...)", "[proto]") {
REQUIRE( called ); REQUIRE( called );
} }
SECTION("multiple bindings") { GIVEN("multiple no argument bindings") {
bool called1 = false; bool called1 = false;
bool called2 = false; bool called2 = false;
...@@ -105,7 +116,7 @@ TEST_CASE("Protocol::bind(string,...)", "[proto]") { ...@@ -105,7 +116,7 @@ TEST_CASE("Protocol::bind(string,...)", "[proto]") {
REQUIRE( called2 ); REQUIRE( called2 );
} }
SECTION("one argument bind with valid dispatch") { GIVEN("one argument") {
bool called = false; bool called = false;
p.bind("test1", [&](int a) { p.bind("test1", [&](int a) {
...@@ -122,7 +133,7 @@ TEST_CASE("Protocol::bind(string,...)", "[proto]") { ...@@ -122,7 +133,7 @@ TEST_CASE("Protocol::bind(string,...)", "[proto]") {
REQUIRE( called ); REQUIRE( called );
} }
SECTION("two argument bind fake dispatch") { GIVEN("two arguments no return") {
bool called = false; bool called = false;
p.bind("test1", [&](int a, float b) { p.bind("test1", [&](int a, float b) {
...@@ -140,7 +151,7 @@ TEST_CASE("Protocol::bind(string,...)", "[proto]") { ...@@ -140,7 +151,7 @@ TEST_CASE("Protocol::bind(string,...)", "[proto]") {
REQUIRE( called ); REQUIRE( called );
} }
SECTION("non-void bind no arguments") { GIVEN("integer return, no arguments") {
bool called = false; bool called = false;
p.bind("test1", [&]() -> int { p.bind("test1", [&]() -> int {
...@@ -156,7 +167,85 @@ TEST_CASE("Protocol::bind(string,...)", "[proto]") { ...@@ -156,7 +167,85 @@ TEST_CASE("Protocol::bind(string,...)", "[proto]") {
p.mock_dispatchRPC(s, buf.str()); p.mock_dispatchRPC(s, buf.str());
REQUIRE( called ); REQUIRE( called );
// TODO Require that a writev occurred with result value auto [kind,id,err,res] = get_response();
REQUIRE( res.as<int>() == 55 );
REQUIRE( kind == 1 );
REQUIRE( id == 0 );
REQUIRE( err.type == 0 );
}
GIVEN("integer return and one argument") {
bool called = false;
p.bind("test1", [&](int a) -> int {
called = true;
return a+2;
});
auto args_obj = std::make_tuple(12);
auto call_obj = std::make_tuple(0,0,"test1",args_obj);
std::stringstream buf;
msgpack::pack(buf, call_obj);
p.mock_dispatchRPC(s, buf.str());
REQUIRE( called );
auto [kind,id,err,res] = get_response();
REQUIRE( res.as<int>() == 14 );
REQUIRE( kind == 1 );
REQUIRE( id == 0 );
REQUIRE( err.type == 0 );
}
GIVEN("an integer exception in bound function") {
bool called = false;
p.bind("test1", [&](int a) {
called = true;
throw -1;
});
auto args_obj = std::make_tuple(5);
auto call_obj = std::make_tuple(0,0,"test1",args_obj);
std::stringstream buf;
msgpack::pack(buf, call_obj);
p.mock_dispatchRPC(s, buf.str());
REQUIRE( called );
auto [kind,id,err,res] = get_response();
REQUIRE( res.type == 0 );
REQUIRE( kind == 1 );
REQUIRE( id == 0 );
REQUIRE( err.as<int>() == -1 );
}
GIVEN("a custom std::exception in bound function") {
bool called = false;
struct CustExcept : public std::exception {
const char *what() const noexcept { return "My exception"; }
};
p.bind("test1", [&](int a) {
called = true;
throw CustExcept();
});
auto args_obj = std::make_tuple(5);
auto call_obj = std::make_tuple(0,0,"test1",args_obj);
std::stringstream buf;
msgpack::pack(buf, call_obj);
p.mock_dispatchRPC(s, buf.str());
REQUIRE( called );
auto [kind,id,err,res] = get_response();
REQUIRE( res.type == 0 );
REQUIRE( kind == 1 );
REQUIRE( id == 0 );
REQUIRE( err.type == 5 );
REQUIRE( err.as<std::string>() == "My exception" );
} }
} }
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment