| #![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(); |
| }) |
| } |