From 19d21ec47d7f17acef9089bb5591da3488781dfd Mon Sep 17 00:00:00 2001 From: Artur Mukhamadiev Date: Sat, 7 Feb 2026 15:43:12 +0300 Subject: [PATCH] stale --- config.yaml | 9 +- include/cloud_point_rpc/rpc_client.hpp | 110 ++++++++++++------------ src/cli.cpp | 112 ++++++++++++++++--------- tests/test_integration.cpp | 76 ++++++++--------- tests/test_rpc.cpp | 32 +++---- 5 files changed, 186 insertions(+), 153 deletions(-) diff --git a/config.yaml b/config.yaml index 7d95af4..0e0eef9 100644 --- a/config.yaml +++ b/config.yaml @@ -1,11 +1,8 @@ server: ip: "127.0.0.1" - port: 8085 - + port: 9095 test_data: - intrinsic_params: [1.1, 0.0, 0.0, 0.0, 1.1, 0.0, 0.0, 0.0, 1.0] - extrinsic_params: [1.0, 0.0, 0.0, 0.5, 0.0, 1.0, 0.0, 0.5, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0] + intrinsic_params: [1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0] + extrinsic_params: [1,0,0,0, 0,1,0,0, 0,0,1,0, 0,0,0,1] cloud_point: - [0.1, 0.2, 0.3] - - [1.1, 1.2, 1.3] - - [5.5, 6.6, 7.7] diff --git a/include/cloud_point_rpc/rpc_client.hpp b/include/cloud_point_rpc/rpc_client.hpp index 0a23508..11b5800 100644 --- a/include/cloud_point_rpc/rpc_client.hpp +++ b/include/cloud_point_rpc/rpc_client.hpp @@ -1,82 +1,88 @@ #pragma once +#include "jsonrpccxx/iclientconnector.hpp" +#include +#include #include +#include +#include +#include #include #include -#include -#include -#include namespace cloud_point_rpc { -class RpcClient { - public: - RpcClient() : socket_(io_context_) {} - - void connect(const std::string& ip, int port) { +class TCPConnector : public jsonrpccxx::IClientConnector { +public: + TCPConnector(const std::string &ip, size_t port) noexcept(false) + : io_context_(), socket_(io_context_) { try { LOG(INFO) << "Client connecting to " << ip << ":" << port; asio::ip::tcp::endpoint endpoint(asio::ip::make_address(ip), port); socket_.connect(endpoint); LOG(INFO) << "Client connected"; - } catch (const std::exception& e) { + } catch (const std::exception &e) { throw std::runtime_error(std::string("Connection Failed: ") + e.what()); } } + std::string Send(const std::string &request) override { + // Send + LOG(INFO) << "Client sending: " << request; + asio::write(socket_, asio::buffer(request)); + return read(); + } + +protected: + std::string read() { + std::string result; + std::array header; + LOG(INFO) << "trying to read"; + + size_t len = asio::read(socket_, asio::buffer(header)); + if (len != sizeof(uint64_t)) { + LOG(ERROR) << "failed to read header"; + return result; + } + + uint64_t packet_size = reinterpret_cast(header.data()); + + std::vector payload(packet_size); + len = asio::read(socket_, asio::buffer(payload)); + + LOG(INFO) << std::format("read len={}", len); + + result = payload.data(); + return result; + } + +private: + asio::io_context io_context_; + asio::ip::tcp::socket socket_; +}; + +class RpcClient : public jsonrpccxx::JsonRpcClient { +public: + RpcClient(TCPConnector &connector) + : jsonrpccxx::JsonRpcClient(connector, jsonrpccxx::version::v2) {} + [[nodiscard]] std::vector get_intrinsic_params() { - return call("get-intrinsic-params")["result"].get>(); + return this->CallMethod>(id++, "get-intrinsic-params"); } [[nodiscard]] std::vector get_extrinsic_params() { - return call("get-extrinsic-params")["result"].get>(); + return this->CallMethod>(id++, "get-extrinsic-params"); } [[nodiscard]] std::vector> get_cloud_point() { - return call("get-cloud-point")["result"].get>>(); + return this->CallMethod>>( + id++, "get-cloud-point"); } - [[nodiscard]] nlohmann::json call(const std::string& method, const nlohmann::json& params = nlohmann::json::object()) { - using json = nlohmann::json; - - // Create Request - json request = { - {"jsonrpc", "2.0"}, - {"method", method}, - {"params", params}, - {"id", ++id_counter_} - }; - std::string request_str = request.dump(); + ~RpcClient() = default; - // Send - LOG(INFO) << "Client sending: " << request_str; - asio::write(socket_, asio::buffer(request_str)); - - // Read Response - LOG(INFO) << "Client reading response..."; - std::vector buffer(65536); - asio::error_code ec; - size_t len = socket_.read_some(asio::buffer(buffer), ec); - if (ec) throw std::system_error(ec); - - LOG(INFO) << "Client read " << len << " bytes"; - json response = json::parse(std::string(buffer.data(), len)); - - if (response.contains("error")) { - throw std::runtime_error(response["error"]["message"].get()); - } - - return response; - } - - ~RpcClient() { - // Socket closes automatically - } - - private: - asio::io_context io_context_; - asio::ip::tcp::socket socket_; - int id_counter_ = 0; +private: + int id{0}; }; } // namespace cloud_point_rpc diff --git a/src/cli.cpp b/src/cli.cpp index c7067a8..56938fc 100644 --- a/src/cli.cpp +++ b/src/cli.cpp @@ -2,57 +2,89 @@ #include "cloud_point_rpc/rpc_client.hpp" #include #include +#include namespace cloud_point_rpc { -void print_menu(std::ostream& output) { - output << "\n=== Cloud Point RPC CLI ===" << std::endl; - output << "1. get-intrinsic-params" << std::endl; - output << "2. get-extrinsic-params" << std::endl; - output << "3. get-cloud-point" << std::endl; - output << "0. Exit" << std::endl; - output << "Select an option: "; +void print_menu(std::ostream &output) { + output << "\n=== Cloud Point RPC CLI ===" << std::endl; + output << "1. get-intrinsic-params" << std::endl; + output << "2. get-extrinsic-params" << std::endl; + output << "3. get-cloud-point" << std::endl; + output << "0. Exit" << std::endl; + output << "Select an option: "; } -int run_cli(std::istream& input, std::ostream& output, const std::string& ip, int port) { - try { - RpcClient client; - client.connect(ip, port); - - output << "Connected to " << ip << ":" << port << std::endl; +template std::string vector_to_string(const std::vector &v) { + std::string result; + for (auto &el : v) { + result += std::to_string(el) + " "; + } + return result; +} - std::string choice; - while (true) { - print_menu(output); - if (!(input >> choice)) break; +template +std::string vector_to_string(const std::vector> &v) { + std::string result; + for (auto &el : v) { + result += vector_to_string(el) + "\n"; + } + return result; +} - if (choice == "0") break; +int run_cli(std::istream &input, std::ostream &output, const std::string &ip, + int port) { + try { + TCPConnector connector(ip, port); + RpcClient client(connector); - std::string method; - if (choice == "1") { - method = "get-intrinsic-params"; - } else if (choice == "2") { - method = "get-extrinsic-params"; - } else if (choice == "3") { - method = "get-cloud-point"; - } else { - output << "Invalid option: " << choice << std::endl; - continue; - } + output << "Connected to " << ip << ":" << port << std::endl; - try { - auto response = client.call(method); - output << "\nResponse:\n" << response.dump(4) << std::endl; - } catch (const std::exception& e) { - output << "\nRPC Error: " << e.what() << std::endl; - } + std::string choice; + while (true) { + print_menu(output); + if (!(input >> choice)) + break; + + if (choice == "0") + break; + + std::string method; + if (choice == "1") { + method = "get-intrinsic-params"; + } else if (choice == "2") { + method = "get-extrinsic-params"; + } else if (choice == "3") { + method = "get-cloud-point"; + } else { + output << "Invalid option: " << choice << std::endl; + continue; + } + + try { + + if (method == "get-intrinsic-params") { + auto response = client.get_intrinsic_params(); + LOG(INFO) << vector_to_string(response); } - } catch (const std::exception& e) { - LOG(ERROR) << "CLI Error: " << e.what(); - output << "Error: " << e.what() << std::endl; - return 1; + if (method == "get-extrinsic-params") { + auto response = client.get_extrinsic_params(); + LOG(INFO) << vector_to_string(response); + } + if (method == "get-cloud-point") { + auto response = client.get_cloud_point(); + LOG(INFO) << vector_to_string(response); + } + } catch (const std::exception &e) { + output << "\nRPC Error: " << e.what() << std::endl; + } } - return 0; + } catch (const std::exception &e) { + LOG(ERROR) << "CLI Error: " << e.what(); + output << "Error: " << e.what() << std::endl; + return 1; + } + return 0; } } // namespace cloud_point_rpc diff --git a/tests/test_integration.cpp b/tests/test_integration.cpp index b21c960..ae2fc9a 100644 --- a/tests/test_integration.cpp +++ b/tests/test_integration.cpp @@ -1,58 +1,57 @@ -#include -#include -#include #include +#include +#include +#include #include "cloud_point_rpc/config.hpp" +#include "cloud_point_rpc/rpc_client.hpp" #include "cloud_point_rpc/rpc_server.hpp" #include "cloud_point_rpc/service.hpp" #include "cloud_point_rpc/tcp_server.hpp" -#include "cloud_point_rpc/rpc_client.hpp" #include using namespace cloud_point_rpc; class IntegrationTest : public ::testing::Test { - protected: +protected: void SetUp() override { // Create a temporary config file for testing std::ofstream config_file("config.yaml"); - config_file << "server:\n" - << " ip: \"127.0.0.1\"\n" - << " port: 9095\n" - << "test_data:\n" - << " intrinsic_params: [1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0]\n" - << " extrinsic_params: [1,0,0,0, 0,1,0,0, 0,0,1,0, 0,0,0,1]\n" - << " cloud_point:\n" - << " - [0.1, 0.2, 0.3]\n"; + config_file + << "server:\n" + << " ip: \"127.0.0.1\"\n" + << " port: 9095\n" + << "test_data:\n" + << " intrinsic_params: [1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0]\n" + << " extrinsic_params: [1,0,0,0, 0,1,0,0, 0,0,1,0, 0,0,0,1]\n" + << " cloud_point:\n" + << " - [0.1, 0.2, 0.3]\n"; config_file.close(); // Setup Mock Server try { - config_ = ConfigLoader::load("config.yaml"); + config_ = ConfigLoader::load("config.yaml"); } catch (...) { - // If config fails, we can't proceed, but we should avoid crashing in TearDown - throw; + // If config fails, we can't proceed, but we should avoid crashing in + // TearDown + throw; } - + service_ = std::make_unique(config_.test_data); rpc_server_ = std::make_unique(); - rpc_server_->register_method("get-intrinsic-params", [&](const nlohmann::json&) { - return service_->get_intrinsic_params(); - }); - + rpc_server_->register_method("get-intrinsic-params", + [&](const nlohmann::json &) { + return service_->get_intrinsic_params(); + }); + // Start Server Thread - tcp_server_ = std::make_unique(config_.server.ip, config_.server.port, - [&](const std::string& req) { - return rpc_server_->process(req); - } - ); - - server_thread_ = std::thread([&]() { - tcp_server_->start(); - }); + tcp_server_ = std::make_unique( + config_.server.ip, config_.server.port, + [&](const std::string &req) { return rpc_server_->process(req); }); + + server_thread_ = std::thread([&]() { tcp_server_->start(); }); // Give server time to start std::this_thread::sleep_for(std::chrono::milliseconds(200)); @@ -60,7 +59,7 @@ class IntegrationTest : public ::testing::Test { void TearDown() override { if (tcp_server_) { - tcp_server_->stop(); + tcp_server_->stop(); } if (server_thread_.joinable()) { server_thread_.join(); @@ -77,16 +76,15 @@ class IntegrationTest : public ::testing::Test { }; TEST_F(IntegrationTest, ClientCanConnectAndRetrieveValues) { - RpcClient client; - - // Act: Connect - ASSERT_NO_THROW(client.connect(config_.server.ip, config_.server.port)); + TCPConnector connector(config_.server.ip, config_.server.port); + RpcClient client(connector); // Act: Call Method - auto params = client.get_intrinsic_params(); + std::vector params; + EXPECT_NO_THROW(params = client.get_intrinsic_params()); // Assert: Values match config - const auto& expected = config_.test_data.intrinsic_params; + const auto &expected = config_.test_data.intrinsic_params; ASSERT_EQ(params.size(), expected.size()); for (size_t i = 0; i < params.size(); ++i) { EXPECT_DOUBLE_EQ(params[i], expected[i]); @@ -94,7 +92,5 @@ TEST_F(IntegrationTest, ClientCanConnectAndRetrieveValues) { } TEST_F(IntegrationTest, ClientHandlesConnectionError) { - RpcClient client; - // Try connecting to a closed port - EXPECT_THROW(client.connect("127.0.0.1", 9999), std::runtime_error); + EXPECT_THROW(TCPConnector connector("127.0.0.1", 9999), std::runtime_error); } diff --git a/tests/test_rpc.cpp b/tests/test_rpc.cpp index b687fe3..d3f871f 100644 --- a/tests/test_rpc.cpp +++ b/tests/test_rpc.cpp @@ -1,36 +1,37 @@ -#include -#include -#include -#include #include "cloud_point_rpc/rpc_server.hpp" #include "cloud_point_rpc/service.hpp" +#include +#include #include +#include +#include using json = nlohmann::json; using namespace cloud_point_rpc; class RpcServerTest : public ::testing::Test { - protected: +protected: RpcServer server; Service service; void SetUp() override { - server.register_method("get-intrinsic-params", [&](const json&) { + server.register_method("get-intrinsic-params", [&](const json &) { return service.get_intrinsic_params(); }); } }; TEST_F(RpcServerTest, GetIntrinsicParamsReturnsMatrix) { - std::string request = R"({"jsonrpc": "2.0", "method": "get-intrinsic-params", "id": 1})"; + std::string request = + R"({"jsonrpc": "2.0", "method": "get-intrinsic-params", "id": 1})"; std::string response_str = server.process(request); - + json response = json::parse(response_str); - + ASSERT_EQ(response["jsonrpc"], "2.0"); ASSERT_EQ(response["id"], 1); ASSERT_TRUE(response.contains("result")); - + auto result = response["result"].get>(); EXPECT_EQ(result.size(), 9); // Verify Identity Matrix @@ -40,11 +41,12 @@ TEST_F(RpcServerTest, GetIntrinsicParamsReturnsMatrix) { } TEST_F(RpcServerTest, MethodNotFoundReturnsError) { - std::string request = R"({"jsonrpc": "2.0", "method": "unknown-method", "id": 99})"; + std::string request = + R"({"jsonrpc": "2.0", "method": "unknown-method", "id": 99})"; std::string response_str = server.process(request); - + json response = json::parse(response_str); - + ASSERT_TRUE(response.contains("error")); EXPECT_EQ(response["error"]["code"], -32601); EXPECT_EQ(response["error"]["message"], "Method not found"); @@ -53,9 +55,9 @@ TEST_F(RpcServerTest, MethodNotFoundReturnsError) { TEST_F(RpcServerTest, InvalidJsonReturnsParseError) { std::string request = R"({"jsonrpc": "2.0", "method": "broken-json...)"; std::string response_str = server.process(request); - + json response = json::parse(response_str); - + ASSERT_TRUE(response.contains("error")); EXPECT_EQ(response["error"]["code"], -32700); }