Skip to content

Commit 346e2b5

Browse files
estevejhdcs
andauthored
Add unit testing (#84)
* Copied tests from jhdcs' fork * Ran cargo fmt * Run clippy on tests as well * Make Clippy happy * Fix rustfmt warning * Added std_msgs to package.xml * Disable deref_nullptr warning for generated code * Include Soya-Onishi's changes * Fix Node::new call * Fix spelling mistakes Co-authored-by: jhdcs <[email protected]> * Fix spelling mistakes Co-authored-by: jhdcs <[email protected]> * Fix spelling mistakes Co-authored-by: jhdcs <[email protected]> * Fix formatting Co-authored-by: jhdcs <[email protected]>
1 parent df78ac7 commit 346e2b5

File tree

10 files changed

+165
-3
lines changed

10 files changed

+165
-3
lines changed

.github/workflows/rust.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,7 @@ jobs:
9191
for path in $(colcon list | awk '$3 == "(ament_cargo)" { print $2 }'); do
9292
cd $path
9393
echo "Running clippy in $path"
94-
cargo clippy -- -D warnings
94+
cargo clippy --all-targets --all-features -- -D warnings
9595
cd -
9696
done
9797

rclrs/Cargo.toml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,9 @@ rosidl_runtime_rs = "*"
2222
# Needed for e.g. writing yaml files in tests
2323
tempfile = "3.3.0"
2424

25+
[dev-dependencies.std_msgs]
26+
version = "*"
27+
2528
[build-dependencies]
2629
# Needed for FFI
2730
bindgen = "0.59.1"

rclrs/package.xml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@
1717
<build_depend>rosidl_runtime_rs</build_depend>
1818
<build_depend>rcl</build_depend>
1919

20+
<test_depend>std_msgs</test_depend>
21+
2022
<export>
2123
<build_type>ament_cargo</build_type>
2224
</export>

rclrs/src/context.rs

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -158,3 +158,24 @@ impl Context {
158158
unsafe { rcl_context_is_valid(rcl_context) }
159159
}
160160
}
161+
162+
#[cfg(test)]
163+
mod tests {
164+
use super::*;
165+
166+
#[test]
167+
fn test_create_context() -> Result<(), RclrsError> {
168+
// If the context fails to be created, this will cause a panic
169+
let _ = Context::new(vec![])?;
170+
Ok(())
171+
}
172+
173+
#[test]
174+
fn test_context_ok() -> Result<(), RclrsError> {
175+
// If the context fails to be created, this will cause a panic
176+
let created_context = Context::new(vec![]).unwrap();
177+
assert!(created_context.ok());
178+
179+
Ok(())
180+
}
181+
}

rclrs/src/lib.rs

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,3 +77,44 @@ pub fn spin(node: &Node) -> Result<(), RclrsError> {
7777

7878
Ok(())
7979
}
80+
81+
#[cfg(test)]
82+
mod tests {
83+
use super::*;
84+
use std::sync::{Arc, Mutex};
85+
use std::time::Duration;
86+
87+
#[test]
88+
fn test_spin_once() -> Result<(), RclrsError> {
89+
let context = Context::new(vec![]).unwrap();
90+
let mut subscriber_node = context.create_node("minimal_subscriber")?;
91+
let num_messages = Arc::new(Mutex::new(0));
92+
let received_msg = Arc::new(Mutex::new(String::new()));
93+
let n = num_messages.clone();
94+
let m = received_msg.clone();
95+
let publisher = subscriber_node
96+
.create_publisher::<std_msgs::msg::String>("topic", QOS_PROFILE_DEFAULT)?;
97+
let _subscription = subscriber_node.create_subscription::<std_msgs::msg::String, _>(
98+
"topic",
99+
QOS_PROFILE_DEFAULT,
100+
move |msg: std_msgs::msg::String| {
101+
let mut num_messages = n.lock().unwrap();
102+
let mut received_msg = m.lock().unwrap();
103+
104+
*num_messages += 1;
105+
*received_msg = msg.data;
106+
},
107+
)?;
108+
109+
let message = std_msgs::msg::String {
110+
data: String::from("Hello World"),
111+
};
112+
publisher.publish(message)?;
113+
spin_once(&subscriber_node, Some(Duration::from_millis(500)))?;
114+
115+
assert_eq!(*num_messages.lock().unwrap(), 1);
116+
assert_eq!(&*received_msg.lock().unwrap().as_str(), "Hello World");
117+
118+
Ok(())
119+
}
120+
}

rclrs/src/node.rs

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -286,3 +286,41 @@ unsafe fn call_string_getter_with_handle(
286286
let cstr = CStr::from_ptr(char_ptr);
287287
cstr.to_string_lossy().into_owned()
288288
}
289+
290+
#[cfg(test)]
291+
mod tests {
292+
use super::*;
293+
use crate::{Context, Node, QOS_PROFILE_DEFAULT};
294+
295+
#[test]
296+
fn test_new() -> Result<(), RclrsError> {
297+
let context =
298+
Context::new(vec![]).expect("Context instantiation is expected to be a success");
299+
let _ = Node::new(&context, "Bob")?;
300+
301+
Ok(())
302+
}
303+
304+
#[test]
305+
fn test_create_subscription() -> Result<(), RclrsError> {
306+
let context =
307+
Context::new(vec![]).expect("Context instantiation is expected to be a success");
308+
let mut node = context.create_node("test_create_subscription")?;
309+
let _subscription = node.create_subscription::<std_msgs::msg::String, _>(
310+
"topic",
311+
QOS_PROFILE_DEFAULT,
312+
move |_: std_msgs::msg::String| {},
313+
)?;
314+
Ok(())
315+
}
316+
317+
#[test]
318+
fn test_create_publisher() -> Result<(), RclrsError> {
319+
let context =
320+
Context::new(vec![]).expect("Context instantiation is expected to be a success");
321+
let node = context.create_node("test_create_publisher")?;
322+
let _publisher =
323+
node.create_publisher::<std_msgs::msg::String>("topic", QOS_PROFILE_DEFAULT)?;
324+
Ok(())
325+
}
326+
}

rclrs/src/node/publisher.rs

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -163,3 +163,38 @@ impl<'a, T: Message> MessageCow<'a, T> for &'a T {
163163
Cow::Borrowed(self)
164164
}
165165
}
166+
167+
#[cfg(test)]
168+
mod tests {
169+
use super::*;
170+
use crate::{Context, Publisher, QOS_PROFILE_DEFAULT};
171+
172+
fn create_fixture(name: &str) -> (Context, Node) {
173+
let context =
174+
Context::new(vec![]).expect("Context instantiation is expected to be a success");
175+
let node = context
176+
.create_node(name)
177+
.expect("Node instantiation is expected to be a success");
178+
179+
(context, node)
180+
}
181+
182+
#[test]
183+
fn test_new_publisher() -> Result<(), RclrsError> {
184+
let (_, node) = create_fixture("test_new_publisher");
185+
let _ = Publisher::<std_msgs::msg::String>::new(&node, "test", QOS_PROFILE_DEFAULT)?;
186+
187+
Ok(())
188+
}
189+
190+
#[test]
191+
fn test_publish_message() -> Result<(), RclrsError> {
192+
let (_, node) = create_fixture("test_publish_message");
193+
let publisher =
194+
Publisher::<std_msgs::msg::String>::new(&node, "test", QOS_PROFILE_DEFAULT)?;
195+
let message = std_msgs::msg::String {
196+
data: "Hello world!".to_owned(),
197+
};
198+
publisher.publish(&message)
199+
}
200+
}

rclrs/src/node/subscription.rs

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -206,3 +206,24 @@ where
206206
Ok(())
207207
}
208208
}
209+
210+
#[cfg(test)]
211+
mod tests {
212+
use super::*;
213+
use crate::{Context, Subscription, QOS_PROFILE_DEFAULT};
214+
215+
#[test]
216+
fn test_instantiate_subscriber() -> Result<(), RclrsError> {
217+
let context =
218+
Context::new(vec![]).expect("Context instantiation is expected to be a success");
219+
let node = context.create_node("test_new_subscriber")?;
220+
let _subscriber = Subscription::<std_msgs::msg::String>::new(
221+
&node,
222+
"test",
223+
QOS_PROFILE_DEFAULT,
224+
move |_: std_msgs::msg::String| {},
225+
)?;
226+
227+
Ok(())
228+
}
229+
}

rclrs/src/rcl_bindings.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
#![allow(dead_code)]
2+
#![allow(deref_nullptr)]
23
#![allow(non_upper_case_globals)]
34
#![allow(non_camel_case_types)]
45
#![allow(non_snake_case)]

rosidl_runtime_rs/src/sequence.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -705,10 +705,10 @@ mod tests {
705705
if xs_seq.len() != xs.len() + ys.len() {
706706
return false;
707707
}
708-
if &xs_seq[..xs.len()] != &xs[..] {
708+
if xs_seq[..xs.len()] != xs[..] {
709709
return false;
710710
}
711-
if &xs_seq[xs.len()..] != &ys[..] {
711+
if xs_seq[xs.len()..] != ys[..] {
712712
return false;
713713
}
714714
true

0 commit comments

Comments
 (0)