Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -297,9 +297,12 @@ jobs:
- name: Run coverage
run: |
source /tmp/nix-dev-env.sh
# Without its features hiroz-tests compiles to empty binaries, so
# coverage taken blind under-reports the paths they exercise.
cargo llvm-cov \
-p hiroz -p hiroz-codegen -p hiroz-cdr -p hiroz-protocol -p hiroz-schema \
-p hiroz-tests \
--features hiroz-tests/ros-msgs,hiroz-tests/jazzy \
-j4 \
--lcov --output-path lcov.info
shell: bash
Expand Down
20 changes: 20 additions & 0 deletions crates/hiroz-tests/build.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,26 @@
use std::{env, path::PathBuf};

fn main() {
// Package-wide enforcement of the feature requirement.
//
// `tests/feature_gate.rs` only fires if Cargo selects that target.
// `cargo test -p hiroz-tests --test cache` with no features builds only
// `cache`, which the crate-level `cfg` compiles to an empty binary --
// `0 passed`, guard never run. A build script runs for every build of the
// package regardless of target selection, so this is the one place the
// requirement holds everywhere.
if std::env::var_os("CARGO_FEATURE_ROS_MSGS").is_none() {
panic!(
"\n\nhiroz-tests requires the `ros-msgs` feature.\n\n\
Without it the suites gated on it compile to empty test binaries \n\
that report `0 passed`, which reads as green but is no coverage.\n\n\
Build it as:\n\n \
cargo test -p hiroz-tests --features ros-msgs,jazzy\n\n\
Suites that drive a real ROS 2 installation need \n \
--features ros-interop,<distro> instead.\n"
);
}

// Declare custom cfg for ROS version detection
println!("cargo::rustc-check-cfg=cfg(ros_humble)");

Expand Down
46 changes: 46 additions & 0 deletions crates/hiroz-tests/tests/feature_gate.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
//! Fails loudly when `hiroz-tests` is built without the features its suites need.
//!
//! Several suites carry a crate-level `#![cfg(feature = "ros-msgs")]`. An
//! unsatisfied crate-level `cfg` neither errors nor warns — the file compiles to
//! an empty test binary reporting `0 passed`, indistinguishable from green.
//!
//! This file is deliberately ungated, so a featureless build cannot compile it
//! away. `build.rs` covers the narrower `--test <name>` invocations that never
//! select this target.
//!
//! `hiroz-tests` therefore has no supported featureless configuration: run it as
//! `cargo test -p hiroz-tests --features ros-msgs,jazzy`, or with
//! `ros-interop,<distro>` for suites that drive a real ROS installation.
//!
//! Selection is a separate failure mode from compilation: this crate is not in
//! `default-members`, so a bare `cargo nextest run` skips it rather than
//! building it empty. `scripts/test-pure-rust.nu` names it explicitly.

/// Without `ros-msgs`, the gated suites are silently absent — fail instead.
#[test]
#[cfg(not(feature = "ros-msgs"))]
fn ros_msgs_gated_suites_must_not_be_silently_skipped() {
Comment thread
YuanYuYuan marked this conversation as resolved.
panic!(
"hiroz-tests was built without the `ros-msgs` feature.\n\
\n\
The suites gated on it — `cache.rs`, `subscriber_timeout.rs`, \
`service_schema_discovery.rs`, the `z_*_example` suites and others — \
have been compiled to empty test binaries and will report `0 passed`, \
which reads as green. That is not a pass; it is no coverage.\n\
\n\
Build the crate with its features:\n\
\n\
cargo test -p hiroz-tests --features ros-msgs,jazzy\n\
\n\
Suites that additionally drive a real ROS 2 installation need \
`--features ros-interop,<distro>` instead."
);
}

/// With `ros-msgs`, record that the gate was satisfied.
///
/// Present so the guard is visible in the test list in *both* configurations —
/// a check whose only evidence is the absence of a failure is not a check.
#[test]
#[cfg(feature = "ros-msgs")]
fn ros_msgs_gated_suites_are_compiled_in() {}
2 changes: 2 additions & 0 deletions crates/hiroz/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,8 @@ pub mod python_bridge;
pub mod qos;
/// Internal message queues.
pub mod queue;
/// Debug-time enforcement of "no user callback under a hiroz lock guard".
pub mod reentrancy;
/// Message type metadata traits (`WithTypeInfo`, etc.).
pub mod ros_msg;
/// ROS 2 service client and server.
Expand Down
Loading
Loading