Skip to content
Snippets Groups Projects
protocol_unit.cpp 3.49 KiB
Newer Older
#include "catch.hpp"
#include <ftl/net/protocol.hpp>

using ftl::net::Protocol;

// --- Mock --------------------------------------------------------------------

#define _FTL_NET_SOCKET_HPP_ // Prevent include

namespace ftl {
namespace net {
class Socket {
	public:
	std::string getURI() { return "mock://"; }
	int send(int msg, const std::string &d) { return 0; }
};
};
};

using ftl::net::Socket;

class MockProtocol : public Protocol {
	public:
	MockProtocol() : Protocol(33) {}
	void mock_dispatchRPC(Socket &s, const std::string &d) { dispatchRPC(s,d); }
	void mock_dispatchReturn(Socket &s, const std::string &d) { dispatchReturn(s,d); }
	void mock_dispatchRaw(uint32_t msg, Socket &s) { dispatchRaw(msg,s); }
};

// --- Support -----------------------------------------------------------------

// --- Files to test -----------------------------------------------------------

#include "../src/protocol.cpp"
#include "../src/dispatcher.cpp"

// --- Tests -------------------------------------------------------------------

TEST_CASE("Protocol::bind(int,...)", "[proto]") {
	MockProtocol p;
	Socket s;
	
	SECTION("a valid bind and dispatch") {
		bool msg = false;

		p.bind(5, [&](uint32_t m, Socket &s) {
			msg = true;	
		});
		
		p.mock_dispatchRaw(5, s);
		REQUIRE(msg);
	}
	
	SECTION("an invalid dispatch") {
		bool msg = false;

		p.bind(5, [&](uint32_t m, Socket &s) {
			msg = true;	
		});
		
		p.mock_dispatchRaw(6, s);
		REQUIRE( !msg );
		// TODO How is failure reported?
	}
}

TEST_CASE("Protocol::bind(string,...)", "[proto]") {
	MockProtocol p;
	Socket s;
	
	SECTION("no argument bind with valid dispatch") {
		bool called = false;
		
		p.bind("test1", [&]() {
			called = true;
		});
		
		auto args_obj = std::make_tuple();
		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 );
	}
	
	SECTION("multiple bindings") {
		bool called1 = false;
		bool called2 = false;
		
		p.bind("test1", [&]() {
			called1 = true;
		});
		p.bind("test2", [&]() {
			called2 = true;
		});
		
		auto args_obj = std::make_tuple();
		auto call_obj = std::make_tuple(0,0,"test2",args_obj);
		std::stringstream buf;
		msgpack::pack(buf, call_obj);
		
		p.mock_dispatchRPC(s, buf.str());
		REQUIRE( !called1 );
		REQUIRE( called2 );
	}
	
	SECTION("one argument bind with valid dispatch") {
		bool called = false;
		
		p.bind("test1", [&](int a) {
			called = true;
			REQUIRE( a == 5 );
		});
		
		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 );
	}
	
	SECTION("two argument bind fake dispatch") {
		bool called = false;
		
		p.bind("test1", [&](int a, float b) {
			called = true;
			REQUIRE( a == 5 );
			REQUIRE( b == 5.4f ); // Danger
		});
		
		auto args_obj = std::make_tuple(5, 5.4f);
		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 );
	}
	
	SECTION("non-void bind no arguments") {
		bool called = false;
		
		p.bind("test1", [&]() -> int {
			called = true;
			return 55;
		});
		
		auto args_obj = std::make_tuple();
		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 );
		
		// TODO Require that a writev occurred with result value
	}
}