diff options
| author | datdenkikniet <jcdra1@gmail.com> | 2025-03-14 22:34:42 +0100 |
|---|---|---|
| committer | Emil Fresk <emil.fresk@gmail.com> | 2025-03-16 11:19:22 +0000 |
| commit | 4d58d2bcd5e08f0123d2f3ac39c6a090dfee23d6 (patch) | |
| tree | 602d1de26ca0c742c5b6fd200dea85c2e6014b3b /rtic-sync | |
| parent | 36c574019f36074737637d9c0d8129d9f0e6dc59 (diff) | |
rtic-sync: add test validating that free queue slots are not lost on drop
Diffstat (limited to 'rtic-sync')
| -rw-r--r-- | rtic-sync/Cargo.toml | 1 | ||||
| -rw-r--r-- | rtic-sync/src/channel.rs | 41 |
2 files changed, 42 insertions, 0 deletions
diff --git a/rtic-sync/Cargo.toml b/rtic-sync/Cargo.toml index a522c16..220f831 100644 --- a/rtic-sync/Cargo.toml +++ b/rtic-sync/Cargo.toml @@ -29,6 +29,7 @@ embedded-hal-bus = { version = "0.2.0", features = ["async"] } defmt-03 = { package = "defmt", version = "0.3", optional = true } [dev-dependencies] +cassette = "0.3.0" static_cell = "2.1.0" tokio = { version = "1", features = ["rt", "macros", "time"] } diff --git a/rtic-sync/src/channel.rs b/rtic-sync/src/channel.rs index e4dc835..17fd50a 100644 --- a/rtic-sync/src/channel.rs +++ b/rtic-sync/src/channel.rs @@ -559,6 +559,8 @@ impl<T, const N: usize> Drop for Receiver<'_, T, N> { #[cfg(test)] mod tests { + use cassette::Cassette; + use super::*; #[test] @@ -684,4 +686,43 @@ mod tests { fn tuple_channel() { let _ = make_channel!((i32, u32), 10); } + + fn freeq<const N: usize, T, F, R>(channel: &Channel<T, N>, f: F) -> R + where + F: FnOnce(&mut Deque<u8, N>) -> R, + { + critical_section::with(|cs| f(channel.access(cs).freeq)) + } + + #[test] + fn dropping_waked_send_returns_freeq_item() { + let (mut tx, mut rx) = make_channel!(u8, 1); + + tx.try_send(0).unwrap(); + assert!(freeq(&rx.0, |q| q.is_empty())); + + // Running this in a separate thread scope to ensure that `pinned_future` is dropped fully. + // + // Calling drop explicitly gets hairy because dropping things behind a `Pin` is not easy. + std::thread::scope(|scope| { + scope.spawn(|| { + let pinned_future = core::pin::pin!(tx.send(1)); + let mut future = Cassette::new(pinned_future); + + future.poll_on(); + + assert!(freeq(&rx.0, |q| q.is_empty())); + assert!(!rx.0.wait_queue.is_empty()); + + assert_eq!(rx.try_recv(), Ok(0)); + + assert!(freeq(&rx.0, |q| q.is_empty())); + }); + }); + + assert!(!freeq(&rx.0, |q| q.is_empty())); + + // Make sure that rx & tx are alive until here for good measure. + drop((tx, rx)); + } } |
