Go Interop Tests¶
The Go binding test suite is tiered by dependency level. Each tier is independent — you can run pure tests without any system dependencies and add heavier tiers as the environment allows.
Test Tiers¶
| Tier | Build tag | What it tests | Requires |
|---|---|---|---|
| pure | (none) | CDR serialization correctness, codegen output | Nothing |
| ffi | (none) | hiroz package: context, pub/sub, service, action APIs |
libhiroz.a |
| integration | integration |
Full end-to-end with live Zenoh sessions | zenohd, libhiroz.a |
Running Tests¶
# Pure tests — no external dependencies
just -f crates/hiroz-go/justfile test-go-pure
# FFI unit tests — requires libhiroz.a
just -f crates/hiroz-go/justfile build-rust
just -f crates/hiroz-go/justfile test-go-ffi
# Integration tests — requires zenohd running on PATH
just -f crates/hiroz-go/justfile build-rust
just -f crates/hiroz-go/justfile test-integration
# Go↔Rust interop tests — also requires compiled Rust example binaries
just -f crates/hiroz-go/justfile build-rust-examples
just -f crates/hiroz-go/justfile test-integration
# Run with race detector
cd crates/hiroz-go
CGO_LDFLAGS="-L../../target/release" go test -race -tags integration ./interop_tests/...
# Everything
just -f crates/hiroz-go/justfile test-all
Integration Test Structure¶
Integration tests live in crates/hiroz-go/interop_tests/ and use the Go integration build tag so they are excluded from normal go test ./... runs.
Common Infrastructure (common_test.go)¶
ZenohRouter manages a per-test isolated Zenoh router:
- Starts
zenohdon a PID-derived port (7447 + pid % 1000) to avoid conflicts when tests run in parallel - Stops the process via
t.Cleanup— no manual teardown needed router.Config()returns theZENOH_CONFIG_OVERRIDE-format string for Go contextsgetROS2Env(router)returns env vars for ROS 2 processes:RMW_IMPLEMENTATION=rmw_zenoh_cppand the matchingZENOH_CONFIG_OVERRIDErustEnv(router)returns env vars for Rust hiroz processes:ZENOH_CONFIG_OVERRIDEpointing at the test router
Availability checks run before tests that need external tools:
checkROS2Available()— verifiesros2CLI is on PATHrustExampleBinary(name)— returns the binary path iftarget/release/examples/<name>exists, or("", false)to skip gracefully
Go ↔ ROS 2 Tests (pubsub_test.go, service_test.go, action_test.go)¶
These tests verify that Go nodes communicate with standard ROS 2 nodes running via rmw_zenoh_cpp.
| Test | Direction | Status |
|---|---|---|
TestGoPublisherToROS2Subscriber |
Go pub → ROS 2 sub | Pass |
TestROS2PublisherToGoSubscriber |
ROS 2 pub → Go sub | Pass |
TestGoPublisherToGoSubscriber |
Go pub → Go sub | Pass |
TestGoServiceServerToROS2Client |
Go server ← ROS 2 client | Pass |
TestROS2ServiceServerToGoClient |
ROS 2 server → Go client | Pass |
TestGoServiceServerToGoClient |
Go server ↔ Go client | Pass |
TestGoActionServerToROS2Client |
Go server ← ROS 2 client | Pass |
TestROS2ActionServerToGoClient |
ROS 2 server → Go client | Pass |
TestGoActionServerToGoClient |
Go server ↔ Go client | Pass |
TestActionFeedbackMonitoring |
Server publishes feedback | Pass |
TestActionGoalCancellation |
Cooperative cancel stops execution early | Pass |
TestActionWithCustomTypes |
Custom action types | Skipped — needs fixture |
Tests that require ROS 2 skip automatically when ros2 is not on PATH.
Go ↔ Rust hiroz Tests (hiroz_rust_test.go)¶
These tests spawn compiled Rust hiroz example binaries and verify that the Go binding interoperates correctly with the native Rust implementation — without going through the ROS 2 rmw layer.
This matters because Go↔Go tests use the same FFI library on both sides; a bug that affects both paths symmetrically could go undetected. Go↔Rust tests exercise the full serialization and protocol stack between two independent implementations.
| Test | Direction | Binary |
|---|---|---|
TestGoPublisherToRustSubscriber |
Go pub → Rust sub | z_pubsub --role listener |
TestRustPublisherToGoSubscriber |
Rust pub → Go sub | z_pubsub --role talker |
TestGoServiceClientToRustServer |
Go client → Rust server | z_srvcli --mode server |
TestRustServiceClientToGoServer |
Rust client → Go server | z_srvcli --mode client |
Tests skip gracefully when the Rust example binary is missing — build it first:
How Rust processes are configured: ZContextBuilder in the Rust examples reads ZENOH_CONFIG_OVERRIDE (same key=value;key=value format as ZENOH_CONFIG_OVERRIDE for rmw) and applies those keys on top of the default ROS session config. The test injects this variable to point the Rust process at the per-test router.
Adding a New Integration Test¶
Create or add to a _test.go file in crates/hiroz-go/interop_tests/. Add the build tag at the top:
Start a per-test router:
router := startZenohRouter(t)
os.Setenv("ZENOH_CONFIG_OVERRIDE", router.Config())
defer os.Unsetenv("ZENOH_CONFIG_OVERRIDE")
If your test needs ROS 2:
if !checkROS2Available() {
t.Skip("ROS2 not available")
}
// Pass getROS2Env(router) to exec.Command env
If your test needs a Rust binary: