From 4b28d2e785949216b1958211533a6eb77da47156 Mon Sep 17 00:00:00 2001 From: carter Date: Sun, 17 May 2026 16:44:47 -0600 Subject: [PATCH] Enable the ros2 integration tests and clean them up --- roslibrust_ros2/src/lib.rs | 176 ------------------ roslibrust_ros2/tests/common/mod.rs | 11 ++ roslibrust_ros2/tests/test_pubsub_basic.rs | 37 ++++ .../tests/test_service_server_callable.rs | 52 ++++++ .../tests/test_service_zenoh_to_zenoh.rs | 47 +++++ roslibrust_ros2/tests/test_subscribe_basic.rs | 39 ++++ 6 files changed, 186 insertions(+), 176 deletions(-) create mode 100644 roslibrust_ros2/tests/common/mod.rs create mode 100644 roslibrust_ros2/tests/test_pubsub_basic.rs create mode 100644 roslibrust_ros2/tests/test_service_server_callable.rs create mode 100644 roslibrust_ros2/tests/test_service_zenoh_to_zenoh.rs create mode 100644 roslibrust_ros2/tests/test_subscribe_basic.rs diff --git a/roslibrust_ros2/src/lib.rs b/roslibrust_ros2/src/lib.rs index 4b7277c..092117b 100644 --- a/roslibrust_ros2/src/lib.rs +++ b/roslibrust_ros2/src/lib.rs @@ -264,179 +264,3 @@ impl roslibrust_common::ServiceProvider for ZenohClient { Ok(ZenohServiceServer { cancellation_token }) } } - -#[cfg(test)] -mod tests { - - #[cfg(feature = "ros2_zenoh_test")] - mod integration_tests { - use crate::ZenohClient; - use ros_z::context::ZContext; - use roslibrust_common::traits::*; - - fn make_test_context() -> ZContext { - use ros_z::context::ZContextBuilder; - use ros_z::Builder; - - ZContextBuilder::default() - .with_domain_id(0) - .with_connect_endpoints(["tcp/[::]:7447"]) - .build() - .unwrap() - } - - #[ignore] - #[tokio::test(flavor = "multi_thread")] - async fn test_subscribe_basic() { - let ctx = make_test_context(); - let client = ZenohClient::new(&ctx, "test_subscribe_basic_node") - .await - .unwrap(); - let mut subscriber = client - .subscribe::("/chatter") - .await - .unwrap(); - - #[allow(clippy::zombie_processes)] - let mut pub_cmd = std::process::Command::new("ros2") - .arg("topic") - .arg("pub") - .arg("-t") - .arg("10") - .arg("/chatter") - .arg("std_msgs/msg/String") - .arg("data: Hello World") - .spawn() - .unwrap(); - - tokio::time::timeout(tokio::time::Duration::from_secs(2), async { - let msg = subscriber.next().await.unwrap(); - assert_eq!(msg.data, "Hello World"); - }) - .await - .unwrap(); - - pub_cmd.kill().unwrap(); - } - - #[tokio::test(flavor = "multi_thread")] - async fn test_pubsub_basic() { - let ctx = make_test_context(); - let client = ZenohClient::new(&ctx, "test_publish_basic_node") - .await - .unwrap(); - - let publisher = client - .advertise::("/chatter") - .await - .unwrap(); - - let mut subscriber = client - .subscribe::("/chatter") - .await - .unwrap(); - - let msg = roslibrust_test::ros2::std_msgs::String { - data: "Hello World".to_string(), - }; - - publisher.publish(&msg).await.unwrap(); - - tokio::time::timeout(tokio::time::Duration::from_secs(2), async { - let msg = subscriber.next().await.unwrap(); - assert_eq!(msg.data, "Hello World"); - }) - .await - .expect("Failed to receive message within 2 seconds"); - } - - #[ignore] - #[tokio::test(flavor = "multi_thread")] - async fn test_service_server_callable() { - let ctx = make_test_context(); - let client = ZenohClient::new(&ctx, "test_service_server_callable_node") - .await - .unwrap(); - - let state = std::sync::Arc::new(std::sync::atomic::AtomicBool::new(false)); - let state_copy = state.clone(); - let server_fn = move |request: roslibrust_test::ros2::std_srvs::SetBoolRequest| { - state_copy.store(request.data, std::sync::atomic::Ordering::SeqCst); - Ok(roslibrust_test::ros2::std_srvs::SetBoolResponse { - message: "You set my bool!".to_string(), - success: request.data, - }) - }; - - let _service = client - .advertise_service::( - "/test_service_server_callable_node/set_bool", - server_fn, - ) - .await - .unwrap(); - - #[allow(clippy::zombie_processes)] - let mut srv_call_cmd = std::process::Command::new("ros2") - .arg("service") - .arg("call") - .arg("/test_service_server_callable_node/set_bool") - .arg("std_srvs/srv/SetBool") - .arg("data: true") - .spawn() - .unwrap(); - - tokio::time::timeout(tokio::time::Duration::from_secs(2), async { - while !state.load(std::sync::atomic::Ordering::SeqCst) { - tokio::time::sleep(tokio::time::Duration::from_millis(100)).await; - } - }) - .await - .expect("Bool should be set true within 2 seconds"); - - srv_call_cmd.kill().unwrap() - } - - #[ignore] - #[tokio::test(flavor = "multi_thread")] - async fn test_service_zenoh_to_zenoh() { - let ctx = make_test_context(); - let node = ZenohClient::new(&ctx, "test_service_server_zenoh") - .await - .unwrap(); - - let state = std::sync::Arc::new(std::sync::atomic::AtomicBool::new(false)); - let state_copy = state.clone(); - - let server_fn = move |request: roslibrust_test::ros2::std_srvs::SetBoolRequest| { - state_copy.store(request.data, std::sync::atomic::Ordering::SeqCst); - Ok(roslibrust_test::ros2::std_srvs::SetBoolResponse { - message: "You set my bool!".to_string(), - success: request.data, - }) - }; - - let _service = node - .advertise_service::( - "/test_service_zenoh_to_zenoh_set_bool", - server_fn, - ) - .await - .unwrap(); - - tokio::time::sleep(tokio::time::Duration::from_millis(100)).await; - - let response = node - .call_service::( - "/test_service_zenoh_to_zenoh_set_bool", - roslibrust_test::ros2::std_srvs::SetBoolRequest { data: true }, - ) - .await - .expect("Service call should succeed"); - - assert!(response.success); - assert_eq!(response.message, "You set my bool!"); - assert!(state.load(std::sync::atomic::Ordering::SeqCst)); - } - } -} diff --git a/roslibrust_ros2/tests/common/mod.rs b/roslibrust_ros2/tests/common/mod.rs new file mode 100644 index 0000000..5254be7 --- /dev/null +++ b/roslibrust_ros2/tests/common/mod.rs @@ -0,0 +1,11 @@ +use ros_z::context::ZContext; +use ros_z::context::ZContextBuilder; +use ros_z::Builder; + +pub fn make_test_context() -> ZContext { + ZContextBuilder::default() + .with_domain_id(0) + .with_connect_endpoints(["tcp/[::]:7447"]) + .build() + .unwrap() +} diff --git a/roslibrust_ros2/tests/test_pubsub_basic.rs b/roslibrust_ros2/tests/test_pubsub_basic.rs new file mode 100644 index 0000000..609c319 --- /dev/null +++ b/roslibrust_ros2/tests/test_pubsub_basic.rs @@ -0,0 +1,37 @@ +#![cfg(feature = "ros2_zenoh_test")] + +mod common; + +use roslibrust_common::traits::*; +use roslibrust_ros2::ZenohClient; + +#[tokio::test(flavor = "multi_thread")] +async fn test_pubsub_basic() { + let ctx = common::make_test_context(); + let client = ZenohClient::new(&ctx, "test_publish_basic_node") + .await + .unwrap(); + + let publisher = client + .advertise::("/chatter") + .await + .unwrap(); + + let mut subscriber = client + .subscribe::("/chatter") + .await + .unwrap(); + + let msg = roslibrust_test::ros2::std_msgs::String { + data: "Hello World".to_string(), + }; + + publisher.publish(&msg).await.unwrap(); + + tokio::time::timeout(tokio::time::Duration::from_secs(2), async { + let msg = subscriber.next().await.unwrap(); + assert_eq!(msg.data, "Hello World"); + }) + .await + .expect("Failed to receive message within 2 seconds"); +} diff --git a/roslibrust_ros2/tests/test_service_server_callable.rs b/roslibrust_ros2/tests/test_service_server_callable.rs new file mode 100644 index 0000000..c02bc2b --- /dev/null +++ b/roslibrust_ros2/tests/test_service_server_callable.rs @@ -0,0 +1,52 @@ +#![cfg(feature = "ros2_zenoh_test")] + +mod common; + +use roslibrust_common::traits::*; +use roslibrust_ros2::ZenohClient; + +#[tokio::test(flavor = "multi_thread")] +async fn test_service_server_callable() { + let ctx = common::make_test_context(); + let client = ZenohClient::new(&ctx, "test_service_server_callable_node") + .await + .unwrap(); + + let state = std::sync::Arc::new(std::sync::atomic::AtomicBool::new(false)); + let state_copy = state.clone(); + let server_fn = move |request: roslibrust_test::ros2::std_srvs::SetBoolRequest| { + state_copy.store(request.data, std::sync::atomic::Ordering::SeqCst); + Ok(roslibrust_test::ros2::std_srvs::SetBoolResponse { + message: "You set my bool!".to_string(), + success: request.data, + }) + }; + + let _service = client + .advertise_service::( + "/test_service_server_callable_node/set_bool", + server_fn, + ) + .await + .unwrap(); + + #[allow(clippy::zombie_processes)] + let mut srv_call_cmd = std::process::Command::new("ros2") + .arg("service") + .arg("call") + .arg("/test_service_server_callable_node/set_bool") + .arg("std_srvs/srv/SetBool") + .arg("data: true") + .spawn() + .unwrap(); + + tokio::time::timeout(tokio::time::Duration::from_secs(2), async { + while !state.load(std::sync::atomic::Ordering::SeqCst) { + tokio::time::sleep(tokio::time::Duration::from_millis(100)).await; + } + }) + .await + .expect("Bool should be set true within 2 seconds"); + + srv_call_cmd.kill().unwrap() +} diff --git a/roslibrust_ros2/tests/test_service_zenoh_to_zenoh.rs b/roslibrust_ros2/tests/test_service_zenoh_to_zenoh.rs new file mode 100644 index 0000000..96b8bcc --- /dev/null +++ b/roslibrust_ros2/tests/test_service_zenoh_to_zenoh.rs @@ -0,0 +1,47 @@ +#![cfg(feature = "ros2_zenoh_test")] + +mod common; + +use roslibrust_common::traits::*; +use roslibrust_ros2::ZenohClient; + +#[tokio::test(flavor = "multi_thread")] +async fn test_service_zenoh_to_zenoh() { + let ctx = common::make_test_context(); + let node = ZenohClient::new(&ctx, "test_service_server_zenoh") + .await + .unwrap(); + + let state = std::sync::Arc::new(std::sync::atomic::AtomicBool::new(false)); + let state_copy = state.clone(); + + let server_fn = move |request: roslibrust_test::ros2::std_srvs::SetBoolRequest| { + state_copy.store(request.data, std::sync::atomic::Ordering::SeqCst); + Ok(roslibrust_test::ros2::std_srvs::SetBoolResponse { + message: "You set my bool!".to_string(), + success: request.data, + }) + }; + + let _service = node + .advertise_service::( + "/test_service_zenoh_to_zenoh_set_bool", + server_fn, + ) + .await + .unwrap(); + + tokio::time::sleep(tokio::time::Duration::from_millis(100)).await; + + let response = node + .call_service::( + "/test_service_zenoh_to_zenoh_set_bool", + roslibrust_test::ros2::std_srvs::SetBoolRequest { data: true }, + ) + .await + .expect("Service call should succeed"); + + assert!(response.success); + assert_eq!(response.message, "You set my bool!"); + assert!(state.load(std::sync::atomic::Ordering::SeqCst)); +} diff --git a/roslibrust_ros2/tests/test_subscribe_basic.rs b/roslibrust_ros2/tests/test_subscribe_basic.rs new file mode 100644 index 0000000..5e5f13e --- /dev/null +++ b/roslibrust_ros2/tests/test_subscribe_basic.rs @@ -0,0 +1,39 @@ +#![cfg(feature = "ros2_zenoh_test")] + +mod common; + +use roslibrust_common::traits::*; +use roslibrust_ros2::ZenohClient; + +#[tokio::test(flavor = "multi_thread")] +async fn test_subscribe_basic() { + let ctx = common::make_test_context(); + let client = ZenohClient::new(&ctx, "test_subscribe_basic_node") + .await + .unwrap(); + let mut subscriber = client + .subscribe::("/chatter") + .await + .unwrap(); + + #[allow(clippy::zombie_processes)] + let mut pub_cmd = std::process::Command::new("ros2") + .arg("topic") + .arg("pub") + .arg("-t") + .arg("10") + .arg("/chatter") + .arg("std_msgs/msg/String") + .arg("data: Hello World") + .spawn() + .unwrap(); + + tokio::time::timeout(tokio::time::Duration::from_secs(2), async { + let msg = subscriber.next().await.unwrap(); + assert_eq!(msg.data, "Hello World"); + }) + .await + .unwrap(); + + pub_cmd.kill().unwrap(); +}