From 4874355df13d9ac9416fd24cb7f40621515887c4 Mon Sep 17 00:00:00 2001 From: ChenYing Kuo Date: Tue, 3 Dec 2024 14:38:31 +0800 Subject: [PATCH 01/12] Add ROS test with CI. Signed-off-by: ChenYing Kuo --- .github/workflows/ci.yml | 27 +++++ Cargo.lock | 186 ++++++++++++++++++++++++++++- zenoh-plugin-ros2dds/Cargo.toml | 3 + zenoh-plugin-ros2dds/tests/test.rs | 85 +++++++++++++ 4 files changed, 300 insertions(+), 1 deletion(-) create mode 100644 zenoh-plugin-ros2dds/tests/test.rs diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 1fac97d..8905cbf 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -63,6 +63,33 @@ jobs: - name: Run tests run: cargo test --verbose + build_test_ros2: + runs-on: ubuntu-latest + container: + image: rostooling/setup-ros-docker:ubuntu-noble-ros-jazzy-ros-base-latest + steps: + - uses: ros-tooling/setup-ros@v0.7 + with: + required-ros-distributions: jazzy + + - uses: actions/checkout@v4 + + - name: Install ACL + run: sudo apt-get -y install libacl1-dev + + - name: Install Rust toolchain + run: | + rustup show + rustup component add rustfmt clippy + + - name: Code format check + run: cargo fmt --features ros_test --check -- --config "unstable_features=true,imports_granularity=Crate,group_imports=StdExternalCrate" + - name: Clippy + run: cargo clippy --features ros_test --all --examples -- -D warnings + + - name: Run ROS tests (enable feature ros_test) + run: cargo test --features ros_test --verbose + # NOTE: In GitHub repository settings, the "Require status checks to pass # before merging" branch protection rule ensures that commits are only merged # from branches where specific status checks have passed. These checks are diff --git a/Cargo.lock b/Cargo.lock index de2b427..f9259fb 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -570,6 +570,28 @@ dependencies = [ "serde", ] +[[package]] +name = "bindgen" +version = "0.63.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "36d860121800b2a9a94f9b5604b332d5cffb234ce17609ea479d723dbc9d3885" +dependencies = [ + "bitflags 1.3.2", + "cexpr", + "clang-sys", + "lazy_static", + "lazycell", + "log", + "peeking_take_while", + "proc-macro2", + "quote", + "regex", + "rustc-hash 1.1.0", + "shlex", + "syn 1.0.109", + "which", +] + [[package]] name = "bindgen" version = "0.69.5" @@ -956,6 +978,25 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dcb25d077389e53838a8158c8e99174c5a9d902dee4904320db714f3c653ffba" +[[package]] +name = "crossbeam-deque" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "613f8cc01fe9cf1a3eb3d7f488fd2fa8388403e97039e2f73692932e291a770d" +dependencies = [ + "crossbeam-epoch", + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-epoch" +version = "0.9.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e" +dependencies = [ + "crossbeam-utils", +] + [[package]] name = "crossbeam-utils" version = "0.8.20" @@ -1008,7 +1049,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4e085999238629d13a7a19e4dc7a6e61505bcb2033f6a1bed24bff35035c47c4" dependencies = [ "bincode", - "bindgen", + "bindgen 0.69.5", "cmake", "derivative", "libc", @@ -1258,6 +1299,12 @@ version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" +[[package]] +name = "force-send-sync" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32688dcc448aa684426ecc398f9af78c55b0769515ccd12baa565daf6f32feb6" + [[package]] name = "form_urlencoded" version = "1.2.1" @@ -2180,6 +2227,15 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d" +[[package]] +name = "os_str_bytes" +version = "6.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2355d85b9a3786f481747ced0e0ff2ba35213a1f9bd406ed906554d7af805a1" +dependencies = [ + "memchr", +] + [[package]] name = "outref" version = "0.5.1" @@ -2227,6 +2283,12 @@ version = "1.0.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" +[[package]] +name = "peeking_take_while" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19b17cddbe7ec3f8bc800887bab5e717348c95ea2ca0b1bf0837fb964dc67099" + [[package]] name = "pem-rfc7468" version = "0.7.0" @@ -2581,6 +2643,99 @@ dependencies = [ "proc-macro2", ] +[[package]] +name = "r2r" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "82f7b62c21b28403706844629ce89de2869677d83f33bdef615b32de56f0b5a0" +dependencies = [ + "force-send-sync", + "futures", + "indexmap", + "lazy_static", + "log", + "phf", + "prettyplease", + "proc-macro2", + "quote", + "r2r_actions", + "r2r_common", + "r2r_macros", + "r2r_msg_gen", + "r2r_rcl", + "rayon", + "serde", + "serde_json", + "syn 2.0.77", + "thiserror", + "uuid", +] + +[[package]] +name = "r2r_actions" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d4e672304c3e50c75f39b8c97f97b87f7aef89fc43091071d7c9ab2a2ecf057" +dependencies = [ + "bindgen 0.63.0", + "r2r_common", + "r2r_msg_gen", + "r2r_rcl", +] + +[[package]] +name = "r2r_common" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4dee1e660f88ae6f8caf368db2b616f178bb7d57332e4ac157beeb6bbe57fe5" +dependencies = [ + "bindgen 0.63.0", + "os_str_bytes", + "regex", + "sha2 0.10.8", +] + +[[package]] +name = "r2r_macros" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d47d4c56155db63630574a4f0a2426561ff37c18a2021affdf8611b712b7a892" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.77", +] + +[[package]] +name = "r2r_msg_gen" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ec7a0473fa69271526ac1eeb5b1279b94e76cbfccec8ba9e32a18f0fb313de4" +dependencies = [ + "bindgen 0.63.0", + "force-send-sync", + "itertools 0.10.5", + "phf", + "proc-macro2", + "quote", + "r2r_common", + "r2r_rcl", + "rayon", + "syn 2.0.77", +] + +[[package]] +name = "r2r_rcl" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05d79af52bdec385b7b732e78e5b8c20631c8f6968bd37316a84e6adaae41591" +dependencies = [ + "bindgen 0.63.0", + "paste", + "r2r_common", + "widestring", +] + [[package]] name = "rand" version = "0.7.3" @@ -2652,6 +2807,26 @@ dependencies = [ "rand_core 0.5.1", ] +[[package]] +name = "rayon" +version = "1.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b418a60154510ca1a002a752ca9714984e21e4241e804d32555251faf8b78ffa" +dependencies = [ + "either", + "rayon-core", +] + +[[package]] +name = "rayon-core" +version = "1.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1465873a3dfdaa8ae7cb14b4383657caab0b3e8a0aa9ae8e04b044854c8dfce2" +dependencies = [ + "crossbeam-deque", + "crossbeam-utils", +] + [[package]] name = "redox_syscall" version = "0.5.4" @@ -3964,6 +4139,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "81dfa00651efa65069b0b6b651f4aaa31ba9e3c3ce0137aaad053604ee7e0314" dependencies = [ "getrandom 0.2.15", + "serde", ] [[package]] @@ -4189,6 +4365,12 @@ dependencies = [ "rustix 0.38.37", ] +[[package]] +name = "widestring" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7219d36b6eac893fa81e84ebe06485e7dcbb616177469b142df14f1f4deb1311" + [[package]] name = "winapi" version = "0.3.9" @@ -4779,6 +4961,7 @@ dependencies = [ "git-version", "hex", "lazy_static", + "r2r", "regex", "rustc_version 0.4.1", "serde", @@ -4787,6 +4970,7 @@ dependencies = [ "tokio", "tracing", "zenoh", + "zenoh-config", "zenoh-ext", "zenoh-plugin-trait", ] diff --git a/zenoh-plugin-ros2dds/Cargo.toml b/zenoh-plugin-ros2dds/Cargo.toml index 95aae56..ecede8f 100644 --- a/zenoh-plugin-ros2dds/Cargo.toml +++ b/zenoh-plugin-ros2dds/Cargo.toml @@ -31,6 +31,7 @@ default = ["dynamic_plugin"] stats = ["zenoh/stats"] dynamic_plugin = [] dds_shm = ["cyclors/iceoryx"] +ros_test = ["r2r"] [dependencies] async-trait = { workspace = true } @@ -43,6 +44,7 @@ futures = { workspace = true } git-version = { workspace = true } hex = { workspace = true } lazy_static = { workspace = true } +r2r = { version = "0.9", optional = true } regex = { workspace = true } serde = { workspace = true } serde_json = { workspace = true } @@ -50,6 +52,7 @@ test-case = { workspace = true } tokio = { workspace = true } tracing = { workspace = true } zenoh = { workspace = true } +zenoh-config = { workspace = true } zenoh-ext = { workspace = true } zenoh-plugin-trait = { workspace = true } diff --git a/zenoh-plugin-ros2dds/tests/test.rs b/zenoh-plugin-ros2dds/tests/test.rs new file mode 100644 index 0000000..723556c --- /dev/null +++ b/zenoh-plugin-ros2dds/tests/test.rs @@ -0,0 +1,85 @@ +// +// Copyright (c) 2024 ZettaScale Technology +// +// This program and the accompanying materials are made available under the +// terms of the Eclipse Public License 2.0 which is available at +// http://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0 +// which is available at https://www.apache.org/licenses/LICENSE-2.0. +// +// SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 +// +// Contributors: +// ZettaScale Zenoh Team, +// + +#[cfg(feature = "ros_test")] +mod ros_test { + use std::time::Duration; + + use r2r::{self, QosProfile}; + use zenoh::{ + config::Config, + internal::{plugins::PluginsManager, runtime::RuntimeBuilder}, + }; + use zenoh_config::ModeDependentValue; + + async fn create_bridge() { + let mut plugins_mgr = PluginsManager::static_plugins_only(); + plugins_mgr + .declare_static_plugin::("ros2dds", true); + let mut config = Config::default(); + config.insert_json5("plugins/ros2dds", "{}").unwrap(); + config + .timestamping + .set_enabled(Some(ModeDependentValue::Unique(true))) + .unwrap(); + config.adminspace.set_enabled(true).unwrap(); + config.plugins_loading.set_enabled(true).unwrap(); + let mut runtime = RuntimeBuilder::new(config) + .plugins_manager(plugins_mgr) + .build() + .await + .unwrap(); + runtime.start().await.unwrap(); + } + + #[tokio::test(flavor = "multi_thread")] + async fn test_ros_pub_zenoh_sub() { + let topic_name = "mytopic"; + let payload = "hello world"; + + // Create zenoh-bridge-ros2dds + tokio::spawn(create_bridge()); + + // Zenoh subscriber + let session = zenoh::open(zenoh::Config::default()).await.unwrap(); + let subscriber = session.declare_subscriber(topic_name).await.unwrap(); + + // ROS publisher + let ctx = r2r::Context::create().unwrap(); + let mut node = r2r::Node::create(ctx, "testnode", "").unwrap(); + let publisher = node + .create_publisher(&format!("/{}", topic_name), QosProfile::default()) + .unwrap(); + let msg = r2r::std_msgs::msg::String { + data: payload.into(), + }; + + // Wait for the environment to be ready + tokio::time::sleep(Duration::from_secs(1)).await; + + // Publish ROS message + publisher.publish(&msg).unwrap(); + + // Check Zenoh subscriber will receive the data + tokio::time::timeout(Duration::from_secs(3), async { + let sample = subscriber.recv_async().await.unwrap(); + let result: Result = + cdr::deserialize_from(sample.payload().reader(), cdr::size::Infinite); + let recv_data = result.expect("Fail to receive data"); + assert_eq!(recv_data, payload); + }) + .await + .expect("Timeout: Zenoh subscriber didn't receive any ROS message."); + } +} From 646ad6082a3beec9594b0c15d39dec8fa8f1e2b7 Mon Sep 17 00:00:00 2001 From: ChenYing Kuo Date: Tue, 3 Dec 2024 15:03:48 +0800 Subject: [PATCH 02/12] Install rustup in the CI. Signed-off-by: ChenYing Kuo --- .github/workflows/ci.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 8905cbf..68e0804 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -73,6 +73,7 @@ jobs: required-ros-distributions: jazzy - uses: actions/checkout@v4 + - uses: actions-rust-lang/setup-rust-toolchain@v1 - name: Install ACL run: sudo apt-get -y install libacl1-dev From b6846955361a83dbe64b280d55a70f9cf8f3ecd3 Mon Sep 17 00:00:00 2001 From: ChenYing Kuo Date: Tue, 3 Dec 2024 15:08:13 +0800 Subject: [PATCH 03/12] Remove cargo fmt. Signed-off-by: ChenYing Kuo --- .github/workflows/ci.yml | 2 -- 1 file changed, 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 68e0804..b139086 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -83,8 +83,6 @@ jobs: rustup show rustup component add rustfmt clippy - - name: Code format check - run: cargo fmt --features ros_test --check -- --config "unstable_features=true,imports_granularity=Crate,group_imports=StdExternalCrate" - name: Clippy run: cargo clippy --features ros_test --all --examples -- -D warnings From ff733e00aefc705049cb4a51661e9a4d3ff3a0ec Mon Sep 17 00:00:00 2001 From: ChenYing Kuo Date: Tue, 3 Dec 2024 15:16:17 +0800 Subject: [PATCH 04/12] Add source file inside the CI. Signed-off-by: ChenYing Kuo --- .github/workflows/ci.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index b139086..9f89679 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -87,7 +87,9 @@ jobs: run: cargo clippy --features ros_test --all --examples -- -D warnings - name: Run ROS tests (enable feature ros_test) - run: cargo test --features ros_test --verbose + run: | + source /opt/ros/jazzy/setup.sh + cargo test --features ros_test --verbose # NOTE: In GitHub repository settings, the "Require status checks to pass # before merging" branch protection rule ensures that commits are only merged From d79d166e8d9c4cc495173cd832fc29b94b60d9d2 Mon Sep 17 00:00:00 2001 From: ChenYing Kuo Date: Tue, 3 Dec 2024 15:25:15 +0800 Subject: [PATCH 05/12] Use another way to source ROS jazzy Signed-off-by: ChenYing Kuo --- .github/workflows/ci.yml | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 9f89679..07e2314 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -78,18 +78,8 @@ jobs: - name: Install ACL run: sudo apt-get -y install libacl1-dev - - name: Install Rust toolchain - run: | - rustup show - rustup component add rustfmt clippy - - - name: Clippy - run: cargo clippy --features ros_test --all --examples -- -D warnings - - name: Run ROS tests (enable feature ros_test) - run: | - source /opt/ros/jazzy/setup.sh - cargo test --features ros_test --verbose + run: "source /opt/ros/jazzy/setup.bash && cargo test --features ros_test --verbose" # NOTE: In GitHub repository settings, the "Require status checks to pass # before merging" branch protection rule ensures that commits are only merged From f6c8b574232e331cc832b42bfebdd7229681b5fc Mon Sep 17 00:00:00 2001 From: ChenYing Kuo Date: Tue, 3 Dec 2024 15:34:37 +0800 Subject: [PATCH 06/12] Specify the shell we are using. Signed-off-by: ChenYing Kuo --- .github/workflows/ci.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 07e2314..66b1500 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -79,6 +79,7 @@ jobs: run: sudo apt-get -y install libacl1-dev - name: Run ROS tests (enable feature ros_test) + shell: bash run: "source /opt/ros/jazzy/setup.bash && cargo test --features ros_test --verbose" # NOTE: In GitHub repository settings, the "Require status checks to pass From ce2fc0884e8139c9710da9dfb905b1a32e8becd8 Mon Sep 17 00:00:00 2001 From: ChenYing Kuo Date: Wed, 4 Dec 2024 09:38:47 +0800 Subject: [PATCH 07/12] Add Humble test in the CI Signed-off-by: ChenYing Kuo --- .github/workflows/ci.yml | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 66b1500..da35923 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -63,7 +63,26 @@ jobs: - name: Run tests run: cargo test --verbose - build_test_ros2: + build_test_ros2_humble: + runs-on: ubuntu-latest + container: + image: rostooling/setup-ros-docker:ubuntu-jammy-ros-humble-ros-base-latest + steps: + - uses: ros-tooling/setup-ros@v0.7 + with: + required-ros-distributions: humble + + - uses: actions/checkout@v4 + - uses: actions-rust-lang/setup-rust-toolchain@v1 + + - name: Install ACL + run: sudo apt-get -y install libacl1-dev + + - name: Run ROS tests (enable feature ros_test) + shell: bash + run: "source /opt/ros/humble/setup.bash && cargo test --features ros_test --verbose" + + build_test_ros2_jazzy: runs-on: ubuntu-latest container: image: rostooling/setup-ros-docker:ubuntu-noble-ros-jazzy-ros-base-latest From 0e4bd453efb0c4251a9fe40f121504ab11d0a227 Mon Sep 17 00:00:00 2001 From: ChenYing Kuo Date: Wed, 4 Dec 2024 10:01:52 +0800 Subject: [PATCH 08/12] Fix the tests. Signed-off-by: ChenYing Kuo --- zenoh-plugin-ros2dds/src/ros_discovery.rs | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/zenoh-plugin-ros2dds/src/ros_discovery.rs b/zenoh-plugin-ros2dds/src/ros_discovery.rs index 170a538..e279871 100644 --- a/zenoh-plugin-ros2dds/src/ros_discovery.rs +++ b/zenoh-plugin-ros2dds/src/ros_discovery.rs @@ -582,21 +582,23 @@ where mod tests { #[test] - #[ignore] - // Test ignored as it cannot be run at the same time than test_serde_after_iron() - // Both need different ROS_DISTRO env var, that cannot be changed between the 2 tests - // Run this test individually or with `cargo test -- --ignored`` fn test_serde_prior_to_iron() { use std::str::FromStr; use super::*; use crate::ros2_utils::get_ros_distro; + let distro = get_ros_distro(); + println!("ROS_DISTRO={}", distro); + if !ros_distro_is_less_than("iron") { + println!("The current ROS Distro is not prior to iron. Skip the test."); + return; + } + // ros_discovery_message sent by a component_container node on Humble started as such: // - ros2 run rclcpp_components component_container --ros-args --remap __ns:=/TEST // - ros2 component load /TEST/ComponentManager composition composition::Listener // - ros2 component load /TEST/ComponentManager composition composition::Talker - std::env::set_var("ROS_DISTRO", "humble"); let ros_discovery_info_cdr: Vec = hex::decode( "000100000110de17b1eaf995400c9ac8000001c1000000000000000003000000\ 060000002f5445535400000011000000436f6d706f6e656e744d616e61676572\ @@ -636,7 +638,6 @@ mod tests { ) .unwrap(); - println!("ROS_DISTRO={}", get_ros_distro()); let part_info: ParticipantEntitiesInfo = cdr::deserialize(&ros_discovery_info_cdr).unwrap(); println!("{:?}", part_info); @@ -675,11 +676,17 @@ mod tests { use super::*; use crate::ros2_utils::get_ros_distro; + let distro = get_ros_distro(); + println!("ROS_DISTRO={}", distro); + if ros_distro_is_less_than("iron") { + println!("The current ROS Distro is prior to iron. Skip the test."); + return; + } + // ros_discovery_message sent by a component_container node on Iron started as such: // - ros2 run rclcpp_components component_container --ros-args --remap __ns:=/TEST // - ros2 component load /TEST/ComponentManager composition composition::Listener // - ros2 component load /TEST/ComponentManager composition composition::Talker - std::env::set_var("ROS_DISTRO", "iron"); let ros_discovery_info_cdr: Vec = hex::decode( "00010000010f20a26b2fbd8000000000000001c103000000060000002f544553\ 5400000011000000436f6d706f6e656e744d616e616765720000000005000000\ @@ -711,7 +718,6 @@ mod tests { ) .unwrap(); - println!("ROS_DISTRO={}", get_ros_distro()); let part_info: ParticipantEntitiesInfo = cdr::deserialize(&ros_discovery_info_cdr).unwrap(); println!("{:?}", part_info); From 5bb9dd7c0fa1b3eaff2e4af1a74c590a7ad23b04 Mon Sep 17 00:00:00 2001 From: ChenYing Kuo Date: Wed, 4 Dec 2024 17:40:42 +0800 Subject: [PATCH 09/12] Add Zenoh publisher and ROS subscriber. Signed-off-by: ChenYing Kuo --- zenoh-plugin-ros2dds/tests/test.rs | 65 +++++++++++++++++++++++++----- 1 file changed, 56 insertions(+), 9 deletions(-) diff --git a/zenoh-plugin-ros2dds/tests/test.rs b/zenoh-plugin-ros2dds/tests/test.rs index 723556c..dfbb0e2 100644 --- a/zenoh-plugin-ros2dds/tests/test.rs +++ b/zenoh-plugin-ros2dds/tests/test.rs @@ -14,8 +14,9 @@ #[cfg(feature = "ros_test")] mod ros_test { - use std::time::Duration; + use std::{sync::mpsc::channel, time::Duration}; + use futures::StreamExt; use r2r::{self, QosProfile}; use zenoh::{ config::Config, @@ -23,6 +24,11 @@ mod ros_test { }; use zenoh_config::ModeDependentValue; + // The test topic + const TEST_TOPIC: &str = "test_topic"; + // The test TEST_PAYLOAD + const TEST_PAYLOAD: &str = "Hello World"; + async fn create_bridge() { let mut plugins_mgr = PluginsManager::static_plugins_only(); plugins_mgr @@ -44,25 +50,66 @@ mod ros_test { } #[tokio::test(flavor = "multi_thread")] - async fn test_ros_pub_zenoh_sub() { - let topic_name = "mytopic"; - let payload = "hello world"; + async fn test_zenoh_pub_ros_sub() { + let (tx, rx) = channel(); + + // Create zenoh-bridge-ros2dds + tokio::spawn(create_bridge()); + + // ROS subscriber + let ctx = r2r::Context::create().unwrap(); + let mut node = r2r::Node::create(ctx, "ros_sub", "").unwrap(); + let subscriber = node + .subscribe::( + &format!("/{}", TEST_TOPIC), + QosProfile::default(), + ) + .unwrap(); + + // Zenoh publisher + let session = zenoh::open(zenoh::Config::default()).await.unwrap(); + let publisher = session.declare_publisher(TEST_TOPIC).await.unwrap(); + + // Wait for the environment to be ready + tokio::time::sleep(Duration::from_secs(1)).await; + + // Publish Zenoh message + let buf = cdr::serialize::<_, _, cdr::CdrLe>(TEST_PAYLOAD, cdr::size::Infinite).unwrap(); + publisher.put(buf).await.unwrap(); + // Check ROS subscriber will receive the data + tokio::spawn(async move { + subscriber + .for_each(|msg| { + tx.send(msg.data).unwrap(); + futures::future::ready(()) + }) + .await + }); + node.spin_once(std::time::Duration::from_millis(100)); + let data = rx + .recv_timeout(Duration::from_secs(3)) + .expect("Receiver timeout"); + assert_eq!(data, TEST_PAYLOAD); + } + + #[tokio::test(flavor = "multi_thread")] + async fn test_ros_pub_zenoh_sub() { // Create zenoh-bridge-ros2dds tokio::spawn(create_bridge()); // Zenoh subscriber let session = zenoh::open(zenoh::Config::default()).await.unwrap(); - let subscriber = session.declare_subscriber(topic_name).await.unwrap(); + let subscriber = session.declare_subscriber(TEST_TOPIC).await.unwrap(); // ROS publisher let ctx = r2r::Context::create().unwrap(); - let mut node = r2r::Node::create(ctx, "testnode", "").unwrap(); + let mut node = r2r::Node::create(ctx, "ros_pub", "").unwrap(); let publisher = node - .create_publisher(&format!("/{}", topic_name), QosProfile::default()) + .create_publisher(&format!("/{}", TEST_TOPIC), QosProfile::default()) .unwrap(); let msg = r2r::std_msgs::msg::String { - data: payload.into(), + data: TEST_PAYLOAD.into(), }; // Wait for the environment to be ready @@ -77,7 +124,7 @@ mod ros_test { let result: Result = cdr::deserialize_from(sample.payload().reader(), cdr::size::Infinite); let recv_data = result.expect("Fail to receive data"); - assert_eq!(recv_data, payload); + assert_eq!(recv_data, TEST_PAYLOAD); }) .await .expect("Timeout: Zenoh subscriber didn't receive any ROS message."); From a01e1ccd3be9e9dc7e55dcf79313f2f6a57b6e93 Mon Sep 17 00:00:00 2001 From: ChenYing Kuo Date: Thu, 5 Dec 2024 14:28:59 +0800 Subject: [PATCH 10/12] Incorporate the review comments from Julien Signed-off-by: ChenYing Kuo --- .github/workflows/ci.yml | 6 ++++-- Cargo.toml | 1 + zenoh-plugin-ros2dds/Cargo.toml | 2 +- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index da35923..632aabb 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -63,7 +63,8 @@ jobs: - name: Run tests run: cargo test --verbose - build_test_ros2_humble: + system_tests_with_ros2_humble: + name: System tests with ROS 2 Humble runs-on: ubuntu-latest container: image: rostooling/setup-ros-docker:ubuntu-jammy-ros-humble-ros-base-latest @@ -82,7 +83,8 @@ jobs: shell: bash run: "source /opt/ros/humble/setup.bash && cargo test --features ros_test --verbose" - build_test_ros2_jazzy: + system_tests_with_ros2_jazzy: + name: System tests with ROS 2 Jazzy runs-on: ubuntu-latest container: image: rostooling/setup-ros-docker:ubuntu-noble-ros-jazzy-ros-base-latest diff --git a/Cargo.toml b/Cargo.toml index 23ce06a..e813e02 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -36,6 +36,7 @@ futures = "0.3.26" git-version = "0.3.5" hex = "0.4.3" lazy_static = "1.4.0" +r2r = "0.9" regex = "1.7.1" rustc_version = "0.4" serde = "1.0.154" diff --git a/zenoh-plugin-ros2dds/Cargo.toml b/zenoh-plugin-ros2dds/Cargo.toml index ecede8f..5aa5a24 100644 --- a/zenoh-plugin-ros2dds/Cargo.toml +++ b/zenoh-plugin-ros2dds/Cargo.toml @@ -44,7 +44,7 @@ futures = { workspace = true } git-version = { workspace = true } hex = { workspace = true } lazy_static = { workspace = true } -r2r = { version = "0.9", optional = true } +r2r = { workspace = true, optional = true } regex = { workspace = true } serde = { workspace = true } serde_json = { workspace = true } From 417f4a04b6c92343bf7cc388b074e4fbc46ea41e Mon Sep 17 00:00:00 2001 From: ChenYing Kuo Date: Thu, 5 Dec 2024 14:58:02 +0800 Subject: [PATCH 11/12] Speficy the default RMW_IMPLEMENTATION. Signed-off-by: ChenYing Kuo --- zenoh-plugin-ros2dds/tests/test.rs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/zenoh-plugin-ros2dds/tests/test.rs b/zenoh-plugin-ros2dds/tests/test.rs index dfbb0e2..28edbd0 100644 --- a/zenoh-plugin-ros2dds/tests/test.rs +++ b/zenoh-plugin-ros2dds/tests/test.rs @@ -29,6 +29,10 @@ mod ros_test { // The test TEST_PAYLOAD const TEST_PAYLOAD: &str = "Hello World"; + fn init_env() { + std::env::set_var("RMW_IMPLEMENTATION", "rmw_cyclonedds_cpp"); + } + async fn create_bridge() { let mut plugins_mgr = PluginsManager::static_plugins_only(); plugins_mgr @@ -51,6 +55,7 @@ mod ros_test { #[tokio::test(flavor = "multi_thread")] async fn test_zenoh_pub_ros_sub() { + init_env(); let (tx, rx) = channel(); // Create zenoh-bridge-ros2dds @@ -95,6 +100,7 @@ mod ros_test { #[tokio::test(flavor = "multi_thread")] async fn test_ros_pub_zenoh_sub() { + init_env(); // Create zenoh-bridge-ros2dds tokio::spawn(create_bridge()); From 46638aef9c76756900964204862d73e3ff1aa8af Mon Sep 17 00:00:00 2001 From: Julien Enoch Date: Thu, 5 Dec 2024 18:41:23 +0100 Subject: [PATCH 12/12] Add comments about r2r dependency --- Cargo.toml | 4 +++- zenoh-plugin-ros2dds/Cargo.toml | 7 ++++++- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index e813e02..c88085c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -36,7 +36,6 @@ futures = "0.3.26" git-version = "0.3.5" hex = "0.4.3" lazy_static = "1.4.0" -r2r = "0.9" regex = "1.7.1" rustc_version = "0.4" serde = "1.0.154" @@ -56,6 +55,9 @@ zenoh-plugin-ros2dds = { version = "1.0.0-dev", path = "zenoh-plugin-ros2dds/", zenoh-plugin-rest = { version = "1.0.0-dev", git = "https://github.com/eclipse-zenoh/zenoh.git", branch = "main", default-features = false, features=["static_plugin"]} zenoh-plugin-trait = { version = "1.0.0-dev", git = "https://github.com/eclipse-zenoh/zenoh.git", branch = "main", default-features = false } +# r2r is for tests only. See in in zenoh-plugins-ros2dds/Cargo.toml +r2r = "0.9" + [profile.release] codegen-units = 1 diff --git a/zenoh-plugin-ros2dds/Cargo.toml b/zenoh-plugin-ros2dds/Cargo.toml index 5aa5a24..7d12da1 100644 --- a/zenoh-plugin-ros2dds/Cargo.toml +++ b/zenoh-plugin-ros2dds/Cargo.toml @@ -44,7 +44,6 @@ futures = { workspace = true } git-version = { workspace = true } hex = { workspace = true } lazy_static = { workspace = true } -r2r = { workspace = true, optional = true } regex = { workspace = true } serde = { workspace = true } serde_json = { workspace = true } @@ -56,6 +55,12 @@ zenoh-config = { workspace = true } zenoh-ext = { workspace = true } zenoh-plugin-trait = { workspace = true } +# r2r is for tests only. It has to be optional because its building requires a full ROS 2 environement +# However "optional" is not supported for "dev-dependencies". +# Hence it's declared as a dependency but active only with "ros_test" feature +r2r = { workspace = true, optional = true } + + [build-dependencies] rustc_version = { workspace = true }