rtic-sync: add test validating that free queue slots are not lost on drop

This commit is contained in:
datdenkikniet 2025-03-14 22:34:42 +01:00 committed by Emil Fresk
parent 36c574019f
commit 4d58d2bcd5
2 changed files with 42 additions and 0 deletions

View file

@ -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"] }

View file

@ -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));
}
}