#include "assert_def.h" #include "rpc_core.hpp" #include "serialize/CustomType.h" #include "test.h" namespace rpc_core_test { void test_rpc() { using namespace rpc_core; // 此示例使用回环连接 实际使用时需自定义连接 auto connection = std::make_shared(); // 创建rpc 收发消息 auto rpc = rpc::create(connection); // 定时器实现 应配合当前应用的事件循环 以确保消息收发和超时回调在同一个线程 // 此示例使用回环连接 不做超时测试 rpc->set_timer([](uint32_t ms, const rpc::timeout_cb& cb) { RPC_CORE_UNUSED(ms); RPC_CORE_UNUSED(cb); }); // 已连接时设置ready rpc->set_ready(true); /** * 简单示例 * 以收发`std::string`为例,支持结构体和绝大多数STL容器(见序列化章节)。 */ { // The Receiver rpc->subscribe("cmd", [](const std::string& msg) -> std::string { assert(msg == "hello"); return "world"; }); // The Sender rpc->cmd("cmd") ->msg(std::string("hello")) ->rsp([](const std::string& rsp) { assert(rsp == "world"); }) ->call(); } /** * 详细测试 * 根据使用场景不同 提供以下几种方式 */ { RPC_CORE_LOG("1. 收发消息完整测试"); // 注册监听 rpc->subscribe("cmd1", [&](const std::string& msg) -> std::string { RPC_CORE_LOGI("get cmd1: %s", msg.c_str()); ASSERT(msg == "test"); return "ok"; }); // 请求支持很多方法 可根据需求使用所需部分 bool pass = false; auto request = rpc->cmd("cmd1") ->msg(std::string("test")) ->rsp([&](const std::string& rsp) { RPC_CORE_LOGI("get rsp from cmd1: %s", rsp.c_str()); ASSERT(rsp == "ok"); pass = true; }) ->timeout([] { RPC_CORE_LOGI("timeout"); }) ->finally([](finally_t type) { RPC_CORE_LOGI("finally: type:%s", rpc_core::request::finally_t_str(type)); }); RPC_CORE_LOGI("执行请求"); ASSERT(!pass); request->call(); ASSERT(pass); /// 其他功能测试 RPC_CORE_LOGI("多次调用"); pass = false; request->call(); ASSERT(pass); RPC_CORE_LOGI("测试取消"); pass = false; request->cancel(); request->call(); ASSERT(!pass); RPC_CORE_LOGI("恢复取消"); request->reset_cancel(); request->call(); ASSERT(pass); RPC_CORE_LOGI("添加到dispose"); pass = false; { // RAII dispose dispose dispose; request->add_to(dispose); } request->call(); ASSERT(!pass); RPC_CORE_LOGI("先创建request"); pass = false; request::create() ->cmd("cmd1") ->msg(std::string("test")) ->rsp([&](const std::string& rsp) { ASSERT(rsp == "ok"); pass = true; }) ->call(rpc); ASSERT(pass); RPC_CORE_LOGI("no_such_cmd"); pass = false; request::create() ->cmd("cmd_xx") ->msg(std::string("test")) ->rsp([] { ASSERT(false); }) ->finally([&](finally_t type) { ASSERT(type == finally_t::no_such_cmd); pass = true; }) ->call(rpc); ASSERT(pass); } RPC_CORE_LOG("2. 复杂结构体类型测试(包含STL容器)"); { bool pass = false; CustomType customType; customType.id = 1; customType.ids = {1, 2, 3}; customType.name = "test"; rpc->subscribe("cmd2", [&](const CustomType& msg) -> CustomType { RPC_CORE_LOGI("get cmd2"); ASSERT(msg == customType); return customType; }); rpc->cmd("cmd2") ->msg(customType) ->rsp([&](const CustomType& rsp) { RPC_CORE_LOGI("get rsp from cmd2"); ASSERT(rsp == customType); pass = true; }) ->call(); ASSERT(pass); } RPC_CORE_LOG("3. finally测试"); { bool pass = false; bool pass_finally = false; rpc->subscribe("cmd3", [&](const std::string& msg) { return msg; }); rpc->cmd("cmd3") ->msg(std::string("test")) ->rsp([&](const std::string& rsp) { ASSERT(rsp == "test"); pass = true; }) ->finally([&](finally_t type) { ASSERT(type == finally_t::normal); ASSERT(!pass_finally); pass_finally = true; }) ->call(); ASSERT(pass); ASSERT(pass_finally); pass_finally = false; rpc->cmd("cmd3") ->msg(std::string("test")) ->finally([&](finally_t type) { ASSERT(type == finally_t::no_need_rsp); ASSERT(!pass_finally); pass_finally = true; }) ->call(); ASSERT(pass_finally); } RPC_CORE_LOG("4. 多种使用场景测试"); { RPC_CORE_LOG("4.1 有参数 有返回"); { bool pass_cmd = false; bool pass_rsp = false; rpc->subscribe("cmd4", [&](const std::string& msg) -> std::string { ASSERT(msg == "test"); pass_cmd = true; return "test"; }); rpc->cmd("cmd4") ->msg(std::string("test")) ->rsp([&](const std::string& msg) { ASSERT(msg == "test"); pass_rsp = true; }) ->call(); ASSERT(pass_cmd); ASSERT(pass_rsp); } RPC_CORE_LOG("4.2 有参数 无返回"); { bool pass_cmd = false; rpc->subscribe("cmd4", [&](const std::string& msg) { ASSERT(msg == "test"); pass_cmd = true; }); rpc->cmd("cmd4")->msg(std::string("test"))->call(); ASSERT(pass_cmd); } RPC_CORE_LOG("4.3 无参数 有返回"); { bool pass_cmd = false; bool pass_rsp = false; rpc->subscribe("cmd4", [&]() -> std::string { pass_cmd = true; return "test"; }); rpc->cmd("cmd4") ->rsp([&](const std::string& msg) { pass_rsp = true; ASSERT(msg == "test"); }) ->call(); ASSERT(pass_cmd); ASSERT(pass_rsp); } RPC_CORE_LOG("4.4 无参数 无返回"); { bool pass_cmd = false; rpc->subscribe("cmd4", [&]() { pass_cmd = true; }); rpc->cmd("cmd4")->call(); ASSERT(pass_cmd); } } RPC_CORE_LOG("5. ping pong测试"); { bool pass = false; rpc->ping("test") ->rsp([&](const std::string& payload) { RPC_CORE_LOGI("get rsp from ping: %s", payload.c_str()); ASSERT(payload == "test"); pass = true; }) ->call(); ASSERT(pass); } RPC_CORE_LOG("6. dispose测试"); { bool pass = false; auto request = rpc->ping("test") ->rsp([&](const std::string& payload) { RPC_CORE_UNUSED(payload); ASSERT(false); }) ->finally([&](finally_t type) { ASSERT(type == finally_t::canceled); pass = true; }); { dispose dispose; request->add_to(dispose); } request->call(); ASSERT(pass); } #ifndef RPC_CORE_FEATURE_DISABLE_FUTURE RPC_CORE_LOG("7. future模式测试"); { { auto result = rpc->ping("test")->future().get(); ASSERT(result.type == finally_t::normal); ASSERT(result.data == "test"); } { auto result = rpc->ping()->future().get(); ASSERT(result.type == finally_t::normal); } } #endif RPC_CORE_LOG("8. 未ready的rpc对象"); { bool pass = false; auto rpc_tmp = rpc::create(connection); rpc_tmp->cmd("cmd")->call(); // should not crash rpc_tmp->cmd("cmd") ->finally([&](finally_t type) { RPC_CORE_LOG("finally: %d", (int)type); ASSERT(type == finally_t::rpc_not_ready); pass = true; }) ->call(); ASSERT(pass); } } } // namespace rpc_core_test