223 lines
6.8 KiB
Rust
223 lines
6.8 KiB
Rust
#![cfg(loom)]
|
|
|
|
use oneshot::TryRecvError;
|
|
|
|
use loom::hint;
|
|
use loom::thread;
|
|
#[cfg(feature = "async")]
|
|
use std::future::Future;
|
|
#[cfg(feature = "async")]
|
|
use std::pin::Pin;
|
|
#[cfg(feature = "async")]
|
|
use std::task::{self, Poll};
|
|
#[cfg(feature = "std")]
|
|
use std::time::Duration;
|
|
|
|
mod helpers;
|
|
|
|
#[test]
|
|
fn try_recv() {
|
|
loom::model(|| {
|
|
let (sender, receiver) = oneshot::channel::<u128>();
|
|
|
|
let t = thread::spawn(move || loop {
|
|
match receiver.try_recv() {
|
|
Ok(msg) => break msg,
|
|
Err(TryRecvError::Empty) => hint::spin_loop(),
|
|
Err(TryRecvError::Disconnected) => panic!("Should not be disconnected"),
|
|
}
|
|
});
|
|
|
|
assert!(sender.send(19).is_ok());
|
|
assert_eq!(t.join().unwrap(), 19);
|
|
})
|
|
}
|
|
|
|
#[cfg(feature = "std")]
|
|
#[test]
|
|
fn send_recv_different_threads() {
|
|
loom::model(|| {
|
|
let (sender, receiver) = oneshot::channel();
|
|
let t2 = thread::spawn(move || {
|
|
assert_eq!(receiver.recv_timeout(Duration::from_millis(1)), Ok(9));
|
|
});
|
|
let t1 = thread::spawn(move || {
|
|
sender.send(9u128).unwrap();
|
|
});
|
|
t1.join().unwrap();
|
|
t2.join().unwrap();
|
|
})
|
|
}
|
|
|
|
#[cfg(feature = "std")]
|
|
#[test]
|
|
fn recv_drop_sender_different_threads() {
|
|
loom::model(|| {
|
|
let (sender, receiver) = oneshot::channel::<u128>();
|
|
let t2 = thread::spawn(move || {
|
|
assert!(receiver.recv_timeout(Duration::from_millis(0)).is_err());
|
|
});
|
|
let t1 = thread::spawn(move || {
|
|
drop(sender);
|
|
});
|
|
t1.join().unwrap();
|
|
t2.join().unwrap();
|
|
})
|
|
}
|
|
|
|
#[cfg(feature = "async")]
|
|
#[test]
|
|
fn async_recv() {
|
|
loom::model(|| {
|
|
let (sender, receiver) = oneshot::channel::<u128>();
|
|
let t1 = thread::spawn(move || {
|
|
sender.send(987).unwrap();
|
|
});
|
|
assert_eq!(loom::future::block_on(receiver), Ok(987));
|
|
t1.join().unwrap();
|
|
})
|
|
}
|
|
|
|
#[cfg(feature = "async")]
|
|
#[test]
|
|
fn send_then_poll() {
|
|
loom::model(|| {
|
|
let (sender, mut receiver) = oneshot::channel::<u128>();
|
|
sender.send(1234).unwrap();
|
|
|
|
let (waker, waker_handle) = helpers::waker::waker();
|
|
let mut context = task::Context::from_waker(&waker);
|
|
|
|
assert_eq!(
|
|
Pin::new(&mut receiver).poll(&mut context),
|
|
Poll::Ready(Ok(1234))
|
|
);
|
|
assert_eq!(waker_handle.clone_count(), 0);
|
|
assert_eq!(waker_handle.drop_count(), 0);
|
|
assert_eq!(waker_handle.wake_count(), 0);
|
|
})
|
|
}
|
|
|
|
#[cfg(feature = "async")]
|
|
#[test]
|
|
fn poll_then_send() {
|
|
loom::model(|| {
|
|
let (sender, mut receiver) = oneshot::channel::<u128>();
|
|
|
|
let (waker, waker_handle) = helpers::waker::waker();
|
|
let mut context = task::Context::from_waker(&waker);
|
|
|
|
assert_eq!(Pin::new(&mut receiver).poll(&mut context), Poll::Pending);
|
|
assert_eq!(waker_handle.clone_count(), 1);
|
|
assert_eq!(waker_handle.drop_count(), 0);
|
|
assert_eq!(waker_handle.wake_count(), 0);
|
|
|
|
sender.send(1234).unwrap();
|
|
assert_eq!(waker_handle.clone_count(), 1);
|
|
assert_eq!(waker_handle.drop_count(), 1);
|
|
assert_eq!(waker_handle.wake_count(), 1);
|
|
|
|
assert_eq!(
|
|
Pin::new(&mut receiver).poll(&mut context),
|
|
Poll::Ready(Ok(1234))
|
|
);
|
|
assert_eq!(waker_handle.clone_count(), 1);
|
|
assert_eq!(waker_handle.drop_count(), 1);
|
|
assert_eq!(waker_handle.wake_count(), 1);
|
|
})
|
|
}
|
|
|
|
#[cfg(feature = "async")]
|
|
#[test]
|
|
fn poll_with_different_wakers() {
|
|
loom::model(|| {
|
|
let (sender, mut receiver) = oneshot::channel::<u128>();
|
|
|
|
let (waker1, waker_handle1) = helpers::waker::waker();
|
|
let mut context1 = task::Context::from_waker(&waker1);
|
|
|
|
assert_eq!(Pin::new(&mut receiver).poll(&mut context1), Poll::Pending);
|
|
assert_eq!(waker_handle1.clone_count(), 1);
|
|
assert_eq!(waker_handle1.drop_count(), 0);
|
|
assert_eq!(waker_handle1.wake_count(), 0);
|
|
|
|
let (waker2, waker_handle2) = helpers::waker::waker();
|
|
let mut context2 = task::Context::from_waker(&waker2);
|
|
|
|
assert_eq!(Pin::new(&mut receiver).poll(&mut context2), Poll::Pending);
|
|
assert_eq!(waker_handle1.clone_count(), 1);
|
|
assert_eq!(waker_handle1.drop_count(), 1);
|
|
assert_eq!(waker_handle1.wake_count(), 0);
|
|
|
|
assert_eq!(waker_handle2.clone_count(), 1);
|
|
assert_eq!(waker_handle2.drop_count(), 0);
|
|
assert_eq!(waker_handle2.wake_count(), 0);
|
|
|
|
// Sending should cause the waker from the latest poll to be woken up
|
|
sender.send(1234).unwrap();
|
|
assert_eq!(waker_handle1.clone_count(), 1);
|
|
assert_eq!(waker_handle1.drop_count(), 1);
|
|
assert_eq!(waker_handle1.wake_count(), 0);
|
|
|
|
assert_eq!(waker_handle2.clone_count(), 1);
|
|
assert_eq!(waker_handle2.drop_count(), 1);
|
|
assert_eq!(waker_handle2.wake_count(), 1);
|
|
})
|
|
}
|
|
|
|
#[cfg(feature = "async")]
|
|
#[test]
|
|
fn poll_then_try_recv() {
|
|
loom::model(|| {
|
|
let (_sender, mut receiver) = oneshot::channel::<u128>();
|
|
|
|
let (waker, waker_handle) = helpers::waker::waker();
|
|
let mut context = task::Context::from_waker(&waker);
|
|
|
|
assert_eq!(Pin::new(&mut receiver).poll(&mut context), Poll::Pending);
|
|
assert_eq!(waker_handle.clone_count(), 1);
|
|
assert_eq!(waker_handle.drop_count(), 0);
|
|
assert_eq!(waker_handle.wake_count(), 0);
|
|
|
|
assert_eq!(receiver.try_recv(), Err(TryRecvError::Empty));
|
|
|
|
assert_eq!(Pin::new(&mut receiver).poll(&mut context), Poll::Pending);
|
|
assert_eq!(waker_handle.clone_count(), 2);
|
|
assert_eq!(waker_handle.drop_count(), 1);
|
|
assert_eq!(waker_handle.wake_count(), 0);
|
|
})
|
|
}
|
|
|
|
#[cfg(feature = "async")]
|
|
#[test]
|
|
fn poll_then_try_recv_while_sending() {
|
|
loom::model(|| {
|
|
let (sender, mut receiver) = oneshot::channel::<u128>();
|
|
|
|
let (waker, waker_handle) = helpers::waker::waker();
|
|
let mut context = task::Context::from_waker(&waker);
|
|
|
|
assert_eq!(Pin::new(&mut receiver).poll(&mut context), Poll::Pending);
|
|
assert_eq!(waker_handle.clone_count(), 1);
|
|
assert_eq!(waker_handle.drop_count(), 0);
|
|
assert_eq!(waker_handle.wake_count(), 0);
|
|
|
|
let t = thread::spawn(move || {
|
|
sender.send(1234).unwrap();
|
|
});
|
|
|
|
let msg = loop {
|
|
match receiver.try_recv() {
|
|
Ok(msg) => break msg,
|
|
Err(TryRecvError::Empty) => hint::spin_loop(),
|
|
Err(TryRecvError::Disconnected) => panic!("Should not be disconnected"),
|
|
}
|
|
};
|
|
assert_eq!(msg, 1234);
|
|
assert_eq!(waker_handle.clone_count(), 1);
|
|
assert_eq!(waker_handle.drop_count(), 1);
|
|
assert_eq!(waker_handle.wake_count(), 1);
|
|
|
|
t.join().unwrap();
|
|
})
|
|
}
|