# Build & Testing ## Build system The project uses **Meson** with **Ninja** and requires a **C++20** compiler (GCC or Clang). The root `meson.build` declares the project and dependencies; `src/meson.build` and `tests/meson.build` define build targets. ### Dependencies All dependencies are resolved via Meson wrap files in `subprojects/` or system packages: | Dependency | Wrap file | Purpose | |---|---|---| | nlohmann_json | `nlohmann_json.wrap` | JSON parsing | | asio | `asio.wrap` | TCP networking (header-only) | | glog | `glog.wrap` (CMake subproject) | Logging | | yaml-cpp | `yaml-cpp.wrap` | Config file parsing | | aklomp-base64 | `aklomp-base64.wrap` | Base64 encode/decode | | GoogleTest | `gtest.wrap` | Unit testing (gtest + gmock) | The `rpc/` directory is a git submodule pointing to [json-rpc-cxx](https://github.com/jsonrpcx/json-rpc-cxx), providing `jsonrpccxx/` headers used by the client. It is included via `include_directories` in the root `meson.build`. ### Build targets Defined in `src/meson.build`: **Shared libraries:** | Library | Sources | Notes | |---|---|---| | `libcloud_point_rpc` | `rpc_coder.cpp`, `rpc_server.cpp`, `server_api.cpp`, `service.cpp` | Core library, installed with `install_rpath: '$ORIGIN'` | | `libcloud_point_rpc_cli` | `cli.cpp` | CLI client logic | | `test_cloud_point` | `test_api.cpp` | Test API library | **Executables:** | Executable | Source | Description | |---|---|---| | `cloud_point_rpc_server` | `server_main.cpp` | Standalone mock server | | `cloud_point_rpc_cli` | `main.cpp` | Interactive CLI client | | `minimal_client` | `minimal_client.cpp` | Minimal client sending a hardcoded `ping` | ### Linux build ```bash git submodule init && git submodule update meson setup build meson compile -C build ``` Run the server: ```bash ./build/src/cloud_point_rpc_server config.yaml ``` Run the CLI client: ```bash ./build/src/cloud_point_rpc_cli config.yaml ``` ### Windows build Windows requires static linking and a Python venv for Meson: ```powershell git submodule init git submodule update python3 -m venv .\venv .\venv\Scripts\Activate.ps1 pip install meson cmake meson setup -Ddefault_library=static build meson compile -C build # To get DLLs on PATH: meson devenv -C build ``` The root `meson.build` adds a `devenv` on Windows that appends subproject DLL directories to `PATH` when `default_library=shared`. When building static, the build defines `BASE64_STATIC_DEFINE` and `YAML_CPP_STATIC_DEFINE`. ### Clean build ```bash meson compile --clean -C build ``` ## Configuration The server reads a YAML config file. Sample: `config.yml`: ```yaml server: ip: "127.0.0.1" port: 9095 ``` Full config schema (parsed by `ConfigLoader` in `include/cloud_point_rpc/config.hpp`): | Section | Field | Type | Default | Description | |---|---|---|---|---| | `server.ip` | string | `127.0.0.1` | Server bind address | | `server.port` | int | `8080` | Server listen port | | `test_data.intrinsic_params` | list of double | empty (fallback to identity 3×3) | Camera intrinsic parameters | | `test_data.extrinsic_params` | list of double | empty (fallback to identity 4×4) | Camera extrinsic parameters | | `test_data.cloud_point` | list of lists of double | empty (fallback to 3 sample points) | Point cloud data | The `test_data` section is only used by the standalone mock server (`server_main.cpp`). The C API path (`crpc_init`) loads config for server address but does not use `test_data` — Unity provides its own handlers. ## Docker The `Dockerfile` uses Ubuntu 24.04 and builds the CLI client. It installs build dependencies, copies the project, runs `meson setup build && meson compile -C build`, and starts the CLI by default. ```bash docker build -t cloud-point-rpc . docker run --network=host -it cloud-point-rpc ``` Mount a custom config: ```bash docker run --network=host -it -v $(pwd)/my_config.yaml:/app/config.yaml cloud-point-rpc ``` > The server is not configured to run inside Docker — only the CLI client. The `--network=host` flag simplifies connectivity to a server running on the host. ## CI `.gitea/workflows/test.yaml` defines a Gitea Actions workflow named "Verification" that runs on push to `master`: 1. Install build tools (cmake, make, ninja, gcc) 2. Install Meson via pip in a venv 3. Checkout with submodules 4. `meson setup build && meson compile -C build -j2` 5. `meson test -C build` ## Testing All tests are in `tests/` and compiled into a single `unit_tests` executable (defined in `tests/meson.build`) linked against `cloud_point_rpc_dep`, `cloud_point_rpc_cli_dep`, `cloud_point_rpc_test_dep`, and GoogleTest/GMock. ### Run tests ```bash meson test -C build # all tests meson test -C build -v # verbose meson test -C build unit_tests # explicit ``` ### Test suites | File | Area | Description | |---|---|---| | `test_rpc.cpp` | RPC server | Basic request/response, method dispatch | | `test_rpc_edge_cases.cpp` | RPC server | Edge cases: invalid JSON, missing fields, non-object requests | | `test_tcp.cpp` | TCP server | TCP connection and message round-trip | | `test_tcp_edge_cases.cpp` | TCP server | TCP edge cases | | `test_integration.cpp` | Integration | Full server+client stack with mock data, real TCP | | `test_cli.cpp` | CLI | CLI client menu and output | | `test_c_api.cpp` | C API | `crpc_test_*` functions, callback registration, auto-call | | `test_c_api_edge_cases.cpp` | C API | Multiple methods, removal, scheduling | | `test_base64.cpp` | Base64 | Encode/decode round-trip | | `test_base64_edge_cases.cpp` | Base64 | Edge cases (empty input, binary with nulls) | | `test_serialize.cpp` | Serialization | `serialize`/`deserialize` for numeric types, `inplace_size_embedding` | | `test_service.cpp` | Service | Default fallbacks, configured data, empty data | ### Test conventions - All test fixtures initialize Google Logging in `SetUp()` with `FLAGS_logtostderr = true`. - Integration tests (`test_integration.cpp`) create a temporary `config.yaml`, start a real `TcpServer` in a thread, and connect via `TCPConnector`/`RpcClient`. - C API tests use `crpc_test_init()` / `crpc_test_deinit()` and verify callback invocation via `std::promise`/`std::future`. - The latest commit (`9de6f5a`) added `google::InitGoogleLogging` calls in test files to ensure logging is initialized before glog macros are used. ### Linting The project uses clang-format with LLVM base style and 4-space indent (`.clang-format`): ```bash ninja -C build clang-format # or find src include tests -name "*.cpp" -o -name "*.hpp" | xargs clang-format -i ``` ## Source references - `meson.build` — Root build config, dependency declarations - `src/meson.build` — Library and executable targets - `tests/meson.build` — Test executable definition - `config.yml` — Sample config - `Dockerfile` — Container build - `.gitea/workflows/test.yaml` — CI pipeline - `.clang-format` — Code formatting config