C++ Testing Guide
Building Test Binaries
# Build the shared library
cargo build --no-default-features -p horus_cpp
# Compile a C++ test
g++ -std=c++17 -fext-numeric-literals \
-I horus_cpp/include \
-o my_test tests/my_test.cpp \
-L target/debug -lhorus_cpp -lpthread -ldl -lm
# Run
LD_LIBRARY_PATH=target/debug ./my_test
Writing C++ Tests
Use a simple CHECK macro pattern:
#include <horus/horus.hpp>
static int pass = 0, fail = 0;
#define CHECK(cond, name) do { \
if (cond) { printf("[PASS] %s\n", name); pass++; } \
else { printf("[FAIL] %s\n", name); fail++; } \
} while(0)
void test_pubsub() {
horus::Publisher<horus::msg::CmdVel> pub("test.cmd");
horus::Subscriber<horus::msg::CmdVel> sub("test.cmd");
horus::msg::CmdVel msg{}; msg.linear = 1.5f;
pub.send(msg);
auto recv = sub.recv();
CHECK(recv.has_value(), "message received");
CHECK(recv->get()->linear == 1.5f, "field preserved");
}
int main() {
test_pubsub();
printf("Results: %d passed, %d failed\n", pass, fail);
return fail > 0 ? 1 : 0;
}
AddressSanitizer
Compile with ASAN to detect memory errors:
g++ -std=c++17 -fsanitize=address -fno-omit-frame-pointer \
-I horus_cpp/include \
-o my_test_asan tests/my_test.cpp \
-L target/debug -lhorus_cpp -lpthread -ldl -lm
LD_LIBRARY_PATH=target/debug ASAN_OPTIONS=detect_leaks=0 ./my_test_asan
Stress Testing
Test stability under load:
// 1000 scheduler create/destroy cycles
for (int i = 0; i < 1000; i++) {
horus::Scheduler sched;
sched.add("node").tick([]{ }).build();
sched.tick_once();
}
// 50 nodes with 100 ticks each
{
horus::Scheduler sched;
for (int i = 0; i < 50; i++) {
sched.add(("node_" + std::to_string(i)).c_str())
.tick([]{ }).build();
}
for (int i = 0; i < 100; i++) sched.tick_once();
}
Cross-Process Testing
Test IPC between separate processes:
# Terminal 1: subscriber (start first)
LD_LIBRARY_PATH=target/debug ./cross_process_sub "test.topic"
# Terminal 2: publisher
LD_LIBRARY_PATH=target/debug ./cross_process_pub "test.topic"
The subscriber must start first — it creates the SHM ring buffer that both processes share.
CI Integration
The .github/workflows/cpp-bindings.yml pipeline runs:
- Rust FFI tests (139 tests)
- C++ compilation (15 binaries)
- C++ unit tests (e2e, ergonomic, full API, user API, stress)
- Cross-process IPC (CmdVel, JSON, Service, Action)
- ASAN (stress + full API under AddressSanitizer)
- Benchmarks (release-mode performance)