diff options
Diffstat (limited to 'third_party/rust/tokio/tests/support')
-rw-r--r-- | third_party/rust/tokio/tests/support/mock_file.rs | 281 | ||||
-rw-r--r-- | third_party/rust/tokio/tests/support/mock_pool.rs | 66 | ||||
-rw-r--r-- | third_party/rust/tokio/tests/support/signal.rs | 7 |
3 files changed, 354 insertions, 0 deletions
diff --git a/third_party/rust/tokio/tests/support/mock_file.rs b/third_party/rust/tokio/tests/support/mock_file.rs new file mode 100644 index 0000000000..9895f835e6 --- /dev/null +++ b/third_party/rust/tokio/tests/support/mock_file.rs @@ -0,0 +1,281 @@ +#![allow(clippy::unnecessary_operation)] + +use std::collections::VecDeque; +use std::fmt; +use std::fs::{Metadata, Permissions}; +use std::io; +use std::io::prelude::*; +use std::io::SeekFrom; +use std::path::PathBuf; +use std::sync::{Arc, Mutex}; + +pub struct File { + shared: Arc<Mutex<Shared>>, +} + +pub struct Handle { + shared: Arc<Mutex<Shared>>, +} + +struct Shared { + calls: VecDeque<Call>, +} + +#[derive(Debug)] +enum Call { + Read(io::Result<Vec<u8>>), + Write(io::Result<Vec<u8>>), + Seek(SeekFrom, io::Result<u64>), + SyncAll(io::Result<()>), + SyncData(io::Result<()>), + SetLen(u64, io::Result<()>), +} + +impl Handle { + pub fn read(&self, data: &[u8]) -> &Self { + let mut s = self.shared.lock().unwrap(); + s.calls.push_back(Call::Read(Ok(data.to_owned()))); + self + } + + pub fn read_err(&self) -> &Self { + let mut s = self.shared.lock().unwrap(); + s.calls + .push_back(Call::Read(Err(io::ErrorKind::Other.into()))); + self + } + + pub fn write(&self, data: &[u8]) -> &Self { + let mut s = self.shared.lock().unwrap(); + s.calls.push_back(Call::Write(Ok(data.to_owned()))); + self + } + + pub fn write_err(&self) -> &Self { + let mut s = self.shared.lock().unwrap(); + s.calls + .push_back(Call::Write(Err(io::ErrorKind::Other.into()))); + self + } + + pub fn seek_start_ok(&self, offset: u64) -> &Self { + let mut s = self.shared.lock().unwrap(); + s.calls + .push_back(Call::Seek(SeekFrom::Start(offset), Ok(offset))); + self + } + + pub fn seek_current_ok(&self, offset: i64, ret: u64) -> &Self { + let mut s = self.shared.lock().unwrap(); + s.calls + .push_back(Call::Seek(SeekFrom::Current(offset), Ok(ret))); + self + } + + pub fn sync_all(&self) -> &Self { + let mut s = self.shared.lock().unwrap(); + s.calls.push_back(Call::SyncAll(Ok(()))); + self + } + + pub fn sync_all_err(&self) -> &Self { + let mut s = self.shared.lock().unwrap(); + s.calls + .push_back(Call::SyncAll(Err(io::ErrorKind::Other.into()))); + self + } + + pub fn sync_data(&self) -> &Self { + let mut s = self.shared.lock().unwrap(); + s.calls.push_back(Call::SyncData(Ok(()))); + self + } + + pub fn sync_data_err(&self) -> &Self { + let mut s = self.shared.lock().unwrap(); + s.calls + .push_back(Call::SyncData(Err(io::ErrorKind::Other.into()))); + self + } + + pub fn set_len(&self, size: u64) -> &Self { + let mut s = self.shared.lock().unwrap(); + s.calls.push_back(Call::SetLen(size, Ok(()))); + self + } + + pub fn set_len_err(&self, size: u64) -> &Self { + let mut s = self.shared.lock().unwrap(); + s.calls + .push_back(Call::SetLen(size, Err(io::ErrorKind::Other.into()))); + self + } + + pub fn remaining(&self) -> usize { + let s = self.shared.lock().unwrap(); + s.calls.len() + } +} + +impl Drop for Handle { + fn drop(&mut self) { + if !std::thread::panicking() { + let s = self.shared.lock().unwrap(); + assert_eq!(0, s.calls.len()); + } + } +} + +impl File { + pub fn open(_: PathBuf) -> io::Result<File> { + unimplemented!(); + } + + pub fn create(_: PathBuf) -> io::Result<File> { + unimplemented!(); + } + + pub fn mock() -> (Handle, File) { + let shared = Arc::new(Mutex::new(Shared { + calls: VecDeque::new(), + })); + + let handle = Handle { + shared: shared.clone(), + }; + let file = File { shared }; + + (handle, file) + } + + pub fn sync_all(&self) -> io::Result<()> { + use self::Call::*; + + let mut s = self.shared.lock().unwrap(); + + match s.calls.pop_front() { + Some(SyncAll(ret)) => ret, + Some(op) => panic!("expected next call to be {:?}; was sync_all", op), + None => panic!("did not expect call"), + } + } + + pub fn sync_data(&self) -> io::Result<()> { + use self::Call::*; + + let mut s = self.shared.lock().unwrap(); + + match s.calls.pop_front() { + Some(SyncData(ret)) => ret, + Some(op) => panic!("expected next call to be {:?}; was sync_all", op), + None => panic!("did not expect call"), + } + } + + pub fn set_len(&self, size: u64) -> io::Result<()> { + use self::Call::*; + + let mut s = self.shared.lock().unwrap(); + + match s.calls.pop_front() { + Some(SetLen(arg, ret)) => { + assert_eq!(arg, size); + ret + } + Some(op) => panic!("expected next call to be {:?}; was sync_all", op), + None => panic!("did not expect call"), + } + } + + pub fn metadata(&self) -> io::Result<Metadata> { + unimplemented!(); + } + + pub fn set_permissions(&self, _perm: Permissions) -> io::Result<()> { + unimplemented!(); + } + + pub fn try_clone(&self) -> io::Result<Self> { + unimplemented!(); + } +} + +impl Read for &'_ File { + fn read(&mut self, dst: &mut [u8]) -> io::Result<usize> { + use self::Call::*; + + let mut s = self.shared.lock().unwrap(); + + match s.calls.pop_front() { + Some(Read(Ok(data))) => { + assert!(dst.len() >= data.len()); + assert!(dst.len() <= 16 * 1024, "actual = {}", dst.len()); // max buffer + + &mut dst[..data.len()].copy_from_slice(&data); + Ok(data.len()) + } + Some(Read(Err(e))) => Err(e), + Some(op) => panic!("expected next call to be {:?}; was a read", op), + None => panic!("did not expect call"), + } + } +} + +impl Write for &'_ File { + fn write(&mut self, src: &[u8]) -> io::Result<usize> { + use self::Call::*; + + let mut s = self.shared.lock().unwrap(); + + match s.calls.pop_front() { + Some(Write(Ok(data))) => { + assert_eq!(src, &data[..]); + Ok(src.len()) + } + Some(Write(Err(e))) => Err(e), + Some(op) => panic!("expected next call to be {:?}; was write", op), + None => panic!("did not expect call"), + } + } + + fn flush(&mut self) -> io::Result<()> { + Ok(()) + } +} + +impl Seek for &'_ File { + fn seek(&mut self, pos: SeekFrom) -> io::Result<u64> { + use self::Call::*; + + let mut s = self.shared.lock().unwrap(); + + match s.calls.pop_front() { + Some(Seek(expect, res)) => { + assert_eq!(expect, pos); + res + } + Some(op) => panic!("expected call {:?}; was `seek`", op), + None => panic!("did not expect call; was `seek`"), + } + } +} + +impl fmt::Debug for File { + fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { + fmt.debug_struct("mock::File").finish() + } +} + +#[cfg(unix)] +impl std::os::unix::io::AsRawFd for File { + fn as_raw_fd(&self) -> std::os::unix::io::RawFd { + unimplemented!(); + } +} + +#[cfg(windows)] +impl std::os::windows::io::AsRawHandle for File { + fn as_raw_handle(&self) -> std::os::windows::io::RawHandle { + unimplemented!(); + } +} diff --git a/third_party/rust/tokio/tests/support/mock_pool.rs b/third_party/rust/tokio/tests/support/mock_pool.rs new file mode 100644 index 0000000000..e1fdb42641 --- /dev/null +++ b/third_party/rust/tokio/tests/support/mock_pool.rs @@ -0,0 +1,66 @@ +use tokio::sync::oneshot; + +use std::cell::RefCell; +use std::collections::VecDeque; +use std::future::Future; +use std::io; +use std::pin::Pin; +use std::task::{Context, Poll}; + +thread_local! { + static QUEUE: RefCell<VecDeque<Box<dyn FnOnce() + Send>>> = RefCell::new(VecDeque::new()) +} + +#[derive(Debug)] +pub(crate) struct Blocking<T> { + rx: oneshot::Receiver<T>, +} + +pub(crate) fn run<F, R>(f: F) -> Blocking<R> +where + F: FnOnce() -> R + Send + 'static, + R: Send + 'static, +{ + let (tx, rx) = oneshot::channel(); + let task = Box::new(move || { + let _ = tx.send(f()); + }); + + QUEUE.with(|cell| cell.borrow_mut().push_back(task)); + + Blocking { rx } +} + +impl<T> Future for Blocking<T> { + type Output = Result<T, io::Error>; + + fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> { + use std::task::Poll::*; + + match Pin::new(&mut self.rx).poll(cx) { + Ready(Ok(v)) => Ready(Ok(v)), + Ready(Err(e)) => panic!("error = {:?}", e), + Pending => Pending, + } + } +} + +pub(crate) async fn asyncify<F, T>(f: F) -> io::Result<T> +where + F: FnOnce() -> io::Result<T> + Send + 'static, + T: Send + 'static, +{ + run(f).await? +} + +pub(crate) fn len() -> usize { + QUEUE.with(|cell| cell.borrow().len()) +} + +pub(crate) fn run_one() { + let task = QUEUE + .with(|cell| cell.borrow_mut().pop_front()) + .expect("expected task to run, but none ready"); + + task(); +} diff --git a/third_party/rust/tokio/tests/support/signal.rs b/third_party/rust/tokio/tests/support/signal.rs new file mode 100644 index 0000000000..ea06058764 --- /dev/null +++ b/third_party/rust/tokio/tests/support/signal.rs @@ -0,0 +1,7 @@ +pub fn send_signal(signal: libc::c_int) { + use libc::{getpid, kill}; + + unsafe { + assert_eq!(kill(getpid(), signal), 0); + } +} |