add oneshot tests
Tests inspired by tests in the `oneshot` third-party crate.
This commit is contained in:
parent
9ba5b5e7f7
commit
b481ecd8b5
2 changed files with 345 additions and 0 deletions
|
|
@ -1,5 +1,6 @@
|
|||
#![feature(mapped_lock_guards)]
|
||||
#![feature(mpmc_channel)]
|
||||
#![feature(oneshot_channel)]
|
||||
#![feature(once_cell_try)]
|
||||
#![feature(lock_value_accessors)]
|
||||
#![feature(reentrant_lock)]
|
||||
|
|
@ -26,6 +27,8 @@ mod mutex;
|
|||
mod once;
|
||||
mod once_lock;
|
||||
#[cfg(not(any(target_os = "emscripten", target_os = "wasi")))]
|
||||
mod oneshot;
|
||||
#[cfg(not(any(target_os = "emscripten", target_os = "wasi")))]
|
||||
mod reentrant_lock;
|
||||
#[cfg(not(any(target_os = "emscripten", target_os = "wasi")))]
|
||||
mod rwlock;
|
||||
|
|
|
|||
342
library/std/tests/sync/oneshot.rs
Normal file
342
library/std/tests/sync/oneshot.rs
Normal file
|
|
@ -0,0 +1,342 @@
|
|||
//! Inspired by tests from <https://github.com/faern/oneshot/blob/main/tests/sync.rs>
|
||||
|
||||
use std::sync::mpsc::RecvError;
|
||||
use std::sync::oneshot;
|
||||
use std::sync::oneshot::{RecvTimeoutError, TryRecvError};
|
||||
use std::time::{Duration, Instant};
|
||||
use std::{mem, thread};
|
||||
|
||||
#[test]
|
||||
fn send_before_try_recv() {
|
||||
let (sender, receiver) = oneshot::channel();
|
||||
|
||||
assert!(sender.send(19i128).is_ok());
|
||||
|
||||
match receiver.try_recv() {
|
||||
Ok(19) => {}
|
||||
_ => panic!("expected Ok(19)"),
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn send_before_recv() {
|
||||
let (sender, receiver) = oneshot::channel::<()>();
|
||||
|
||||
assert!(sender.send(()).is_ok());
|
||||
assert_eq!(receiver.recv(), Ok(()));
|
||||
|
||||
let (sender, receiver) = oneshot::channel::<u64>();
|
||||
|
||||
assert!(sender.send(42).is_ok());
|
||||
assert_eq!(receiver.recv(), Ok(42));
|
||||
|
||||
let (sender, receiver) = oneshot::channel::<[u8; 4096]>();
|
||||
|
||||
assert!(sender.send([0b10101010; 4096]).is_ok());
|
||||
assert!(receiver.recv().unwrap()[..] == [0b10101010; 4096][..]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn sender_drop() {
|
||||
{
|
||||
let (sender, receiver) = oneshot::channel::<u128>();
|
||||
|
||||
mem::drop(sender);
|
||||
|
||||
match receiver.recv() {
|
||||
Err(RecvError) => {}
|
||||
_ => panic!("expected recv error"),
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
let (sender, receiver) = oneshot::channel::<i32>();
|
||||
|
||||
mem::drop(sender);
|
||||
|
||||
match receiver.try_recv() {
|
||||
Err(TryRecvError::Disconnected) => {}
|
||||
_ => panic!("expected disconnected error"),
|
||||
}
|
||||
}
|
||||
{
|
||||
let (sender, receiver) = oneshot::channel::<i32>();
|
||||
|
||||
mem::drop(sender);
|
||||
|
||||
match receiver.recv_timeout(Duration::from_secs(1)) {
|
||||
Err(RecvTimeoutError::Disconnected) => {}
|
||||
_ => panic!("expected disconnected error"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn send_never_deadline() {
|
||||
let (sender, receiver) = oneshot::channel::<i32>();
|
||||
|
||||
mem::drop(sender);
|
||||
|
||||
match receiver.recv_deadline(Instant::now()) {
|
||||
Err(RecvTimeoutError::Disconnected) => {}
|
||||
_ => panic!("expected disconnected error"),
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn send_before_recv_timeout() {
|
||||
let (sender, receiver) = oneshot::channel();
|
||||
|
||||
assert!(sender.send(22i128).is_ok());
|
||||
|
||||
let start = Instant::now();
|
||||
|
||||
let timeout = Duration::from_secs(1);
|
||||
match receiver.recv_timeout(timeout) {
|
||||
Ok(22) => {}
|
||||
_ => panic!("expected Ok(22)"),
|
||||
}
|
||||
|
||||
assert!(start.elapsed() < timeout);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn send_error() {
|
||||
let (sender, receiver) = oneshot::channel();
|
||||
|
||||
mem::drop(receiver);
|
||||
|
||||
let send_error = sender.send(32u128).unwrap_err();
|
||||
assert_eq!(send_error.0, 32);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn recv_before_send() {
|
||||
let (sender, receiver) = oneshot::channel();
|
||||
|
||||
let t1 = thread::spawn(move || {
|
||||
thread::sleep(Duration::from_millis(10));
|
||||
sender.send(9u128).unwrap();
|
||||
});
|
||||
let t2 = thread::spawn(move || {
|
||||
assert_eq!(receiver.recv(), Ok(9));
|
||||
});
|
||||
|
||||
t1.join().unwrap();
|
||||
t2.join().unwrap();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn recv_timeout_before_send() {
|
||||
let (sender, receiver) = oneshot::channel();
|
||||
|
||||
let t = thread::spawn(move || {
|
||||
thread::sleep(Duration::from_millis(100));
|
||||
sender.send(99u128).unwrap();
|
||||
});
|
||||
|
||||
match receiver.recv_timeout(Duration::from_secs(1)) {
|
||||
Ok(99) => {}
|
||||
_ => panic!("expected Ok(99)"),
|
||||
}
|
||||
|
||||
t.join().unwrap();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn recv_then_drop_sender() {
|
||||
let (sender, receiver) = oneshot::channel::<u128>();
|
||||
|
||||
let t1 = thread::spawn(move || match receiver.recv() {
|
||||
Err(RecvError) => {}
|
||||
_ => panic!("expected recv error"),
|
||||
});
|
||||
|
||||
let t2 = thread::spawn(move || {
|
||||
thread::sleep(Duration::from_millis(10));
|
||||
mem::drop(sender);
|
||||
});
|
||||
|
||||
t1.join().unwrap();
|
||||
t2.join().unwrap();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn drop_sender_then_recv() {
|
||||
let (sender, receiver) = oneshot::channel::<u128>();
|
||||
|
||||
let t1 = thread::spawn(move || {
|
||||
thread::sleep(Duration::from_millis(10));
|
||||
mem::drop(sender);
|
||||
});
|
||||
|
||||
let t2 = thread::spawn(move || match receiver.recv() {
|
||||
Err(RecvError) => {}
|
||||
_ => panic!("expected disconnected error"),
|
||||
});
|
||||
|
||||
t1.join().unwrap();
|
||||
t2.join().unwrap();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn try_recv_empty() {
|
||||
let (sender, receiver) = oneshot::channel::<u128>();
|
||||
match receiver.try_recv() {
|
||||
Err(TryRecvError::Empty(_)) => {}
|
||||
_ => panic!("expected empty error"),
|
||||
}
|
||||
mem::drop(sender);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn try_recv_then_drop_receiver() {
|
||||
let (sender, receiver) = oneshot::channel::<u128>();
|
||||
|
||||
let t1 = thread::spawn(move || {
|
||||
thread::sleep(Duration::from_millis(100));
|
||||
let _ = sender.send(42);
|
||||
});
|
||||
|
||||
let t2 = thread::spawn(move || match receiver.try_recv() {
|
||||
Ok(_) => {}
|
||||
Err(TryRecvError::Empty(r)) => {
|
||||
mem::drop(r);
|
||||
}
|
||||
Err(TryRecvError::Disconnected) => {}
|
||||
});
|
||||
|
||||
t2.join().unwrap();
|
||||
t1.join().unwrap();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn recv_no_time() {
|
||||
let (_sender, receiver) = oneshot::channel::<u128>();
|
||||
|
||||
let start = Instant::now();
|
||||
match receiver.recv_deadline(start) {
|
||||
Err(RecvTimeoutError::Timeout(_)) => {}
|
||||
_ => panic!("expected timeout error"),
|
||||
}
|
||||
|
||||
let (_sender, receiver) = oneshot::channel::<u128>();
|
||||
match receiver.recv_timeout(Duration::from_millis(0)) {
|
||||
Err(RecvTimeoutError::Timeout(_)) => {}
|
||||
_ => panic!("expected timeout error"),
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn recv_deadline_passed() {
|
||||
let (_sender, receiver) = oneshot::channel::<u128>();
|
||||
|
||||
let start = Instant::now();
|
||||
let timeout = Duration::from_millis(100);
|
||||
|
||||
match receiver.recv_deadline(start + timeout) {
|
||||
Err(RecvTimeoutError::Timeout(_)) => {}
|
||||
_ => panic!("expected timeout error"),
|
||||
}
|
||||
|
||||
assert!(start.elapsed() >= timeout);
|
||||
assert!(start.elapsed() < timeout * 3);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn recv_time_passed() {
|
||||
let (_sender, receiver) = oneshot::channel::<u128>();
|
||||
|
||||
let start = Instant::now();
|
||||
let timeout = Duration::from_millis(100);
|
||||
match receiver.recv_timeout(timeout) {
|
||||
Err(RecvTimeoutError::Timeout(_)) => {}
|
||||
_ => panic!("expected timeout error"),
|
||||
}
|
||||
assert!(start.elapsed() >= timeout);
|
||||
assert!(start.elapsed() < timeout * 3);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn non_send_type_can_be_used_on_same_thread() {
|
||||
use std::ptr;
|
||||
|
||||
#[derive(Debug, Eq, PartialEq)]
|
||||
struct NotSend(*mut ());
|
||||
|
||||
let (sender, receiver) = oneshot::channel();
|
||||
sender.send(NotSend(ptr::null_mut())).unwrap();
|
||||
let reply = receiver.try_recv().unwrap();
|
||||
assert_eq!(reply, NotSend(ptr::null_mut()));
|
||||
}
|
||||
|
||||
/// Helper for testing drop behavior (taken directly from the `oneshot` crate).
|
||||
struct DropCounter {
|
||||
count: std::rc::Rc<std::cell::RefCell<usize>>,
|
||||
}
|
||||
|
||||
impl DropCounter {
|
||||
fn new() -> (DropTracker, DropCounter) {
|
||||
let count = std::rc::Rc::new(std::cell::RefCell::new(0));
|
||||
(DropTracker { count: count.clone() }, DropCounter { count })
|
||||
}
|
||||
|
||||
fn count(&self) -> usize {
|
||||
*self.count.borrow()
|
||||
}
|
||||
}
|
||||
|
||||
struct DropTracker {
|
||||
count: std::rc::Rc<std::cell::RefCell<usize>>,
|
||||
}
|
||||
|
||||
impl Drop for DropTracker {
|
||||
fn drop(&mut self) {
|
||||
*self.count.borrow_mut() += 1;
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn message_in_channel_dropped_on_receiver_drop() {
|
||||
let (sender, receiver) = oneshot::channel();
|
||||
|
||||
let (message, counter) = DropCounter::new();
|
||||
assert_eq!(counter.count(), 0);
|
||||
|
||||
sender.send(message).unwrap();
|
||||
assert_eq!(counter.count(), 0);
|
||||
|
||||
mem::drop(receiver);
|
||||
assert_eq!(counter.count(), 1);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn send_error_drops_message_correctly() {
|
||||
let (sender, receiver) = oneshot::channel();
|
||||
mem::drop(receiver);
|
||||
|
||||
let (message, counter) = DropCounter::new();
|
||||
|
||||
let send_error = sender.send(message).unwrap_err();
|
||||
assert_eq!(counter.count(), 0);
|
||||
|
||||
mem::drop(send_error);
|
||||
assert_eq!(counter.count(), 1);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn send_error_drops_message_correctly_on_extract() {
|
||||
let (sender, receiver) = oneshot::channel();
|
||||
mem::drop(receiver);
|
||||
|
||||
let (message, counter) = DropCounter::new();
|
||||
|
||||
let send_error = sender.send(message).unwrap_err();
|
||||
assert_eq!(counter.count(), 0);
|
||||
|
||||
let message = send_error.0; // Access the inner value directly
|
||||
assert_eq!(counter.count(), 0);
|
||||
|
||||
mem::drop(message);
|
||||
assert_eq!(counter.count(), 1);
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue