Skip to content

Commit d5c3e71

Browse files
committed
Add a test that spins Timers created from a Node
Signed-off-by: Michael X. Grey <[email protected]>
1 parent 9e28ee7 commit d5c3e71

File tree

1 file changed

+52
-3
lines changed

1 file changed

+52
-3
lines changed

rclrs/src/node.rs

Lines changed: 52 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -576,7 +576,10 @@ mod tests {
576576
use super::*;
577577
use crate::test_helpers::*;
578578

579-
use std::time::Duration;
579+
use std::{
580+
time::{Duration, Instant},
581+
sync::{Arc, atomic::{AtomicU64, Ordering}},
582+
};
580583

581584
#[test]
582585
fn traits() {
@@ -630,18 +633,64 @@ mod tests {
630633
}
631634

632635
#[test]
633-
fn test_create_timer_without_clock_source() -> Result<(), RclrsError> {
636+
fn test_create_timer() -> Result<(), RclrsError> {
634637
let context = Context::new([])?;
635638
let node = NodeBuilder::new(&context, "node_with_timer")
636639
.namespace("test_create_timer")
637640
.build()?;
638641

639-
let _timer = node.create_timer_repeating(Duration::from_millis(1), || {})?;
642+
let repeat_counter = Arc::new(AtomicU64::new(0));
643+
let repeat_counter_check = Arc::clone(&repeat_counter);
644+
let _repeating_timer = node.create_timer_repeating(
645+
Duration::from_millis(1),
646+
move || { repeat_counter.fetch_add(1, Ordering::AcqRel); },
647+
)?;
640648
assert_eq!(node.live_timers().len(), 1);
641649

650+
let oneshot_counter = Arc::new(AtomicU64::new(0));
651+
let oneshot_counter_check = Arc::clone(&oneshot_counter);
652+
let _oneshot_timer = node.create_timer_oneshot(
653+
Duration::from_millis(1)
654+
.node_time(),
655+
move || { oneshot_counter.fetch_add(1, Ordering::AcqRel); },
656+
)?;
657+
658+
let oneshot_resetting_counter = Arc::new(AtomicU64::new(0));
659+
let oneshot_resetting_counter_check = Arc::clone(&oneshot_resetting_counter);
660+
let _oneshot_resetting_timer = node.create_timer_oneshot(
661+
Duration::from_millis(1),
662+
move |timer: &Timer| {
663+
recursive_oneshot(timer, oneshot_resetting_counter);
664+
},
665+
);
666+
667+
let start = Instant::now();
668+
while start.elapsed() < Duration::from_millis(10) {
669+
crate::spin_once(Arc::clone(&node), Some(Duration::from_millis(10)))?;
670+
}
671+
672+
// We give a little leeway to the exact count since timers won't always
673+
// be triggered perfectly. The important thing is that it was
674+
// successfully called repeatedly.
675+
assert!(repeat_counter_check.load(Ordering::Acquire) > 5);
676+
assert!(oneshot_resetting_counter_check.load(Ordering::Acquire) > 5);
677+
678+
// This should only have been triggered exactly once
679+
assert_eq!(oneshot_counter_check.load(Ordering::Acquire), 1);
680+
642681
Ok(())
643682
}
644683

684+
fn recursive_oneshot(
685+
timer: &Timer,
686+
counter: Arc<AtomicU64>,
687+
) {
688+
counter.fetch_add(1, Ordering::AcqRel);
689+
timer.set_oneshot(move |timer: &Timer| {
690+
recursive_oneshot(timer, counter);
691+
});
692+
}
693+
645694
#[test]
646695
fn test_logger_name() -> Result<(), RclrsError> {
647696
// Use helper to create 2 nodes for us

0 commit comments

Comments
 (0)