1 //! Mock version of std::fs::File;
2 use mockall::mock;
3 
4 use crate::sync::oneshot;
5 use std::{
6     cell::RefCell,
7     collections::VecDeque,
8     fs::{Metadata, Permissions},
9     future::Future,
10     io::{self, Read, Seek, SeekFrom, Write},
11     path::PathBuf,
12     pin::Pin,
13     task::{Context, Poll},
14 };
15 
16 mock! {
17     #[derive(Debug)]
18     pub File {
19         pub fn create(pb: PathBuf) -> io::Result<Self>;
20         // These inner_ methods exist because std::fs::File has two
21         // implementations for each of these methods: one on "&mut self" and
22         // one on "&&self".  Defining both of those in terms of an inner_ method
23         // allows us to specify the expectation the same way, regardless of
24         // which method is used.
25         pub fn inner_flush(&self) -> io::Result<()>;
26         pub fn inner_read(&self, dst: &mut [u8]) -> io::Result<usize>;
27         pub fn inner_seek(&self, pos: SeekFrom) -> io::Result<u64>;
28         pub fn inner_write(&self, src: &[u8]) -> io::Result<usize>;
29         pub fn metadata(&self) -> io::Result<Metadata>;
30         pub fn open(pb: PathBuf) -> io::Result<Self>;
31         pub fn set_len(&self, size: u64) -> io::Result<()>;
32         pub fn set_permissions(&self, _perm: Permissions) -> io::Result<()>;
33         pub fn set_max_buf_size(&self, max_buf_size: usize);
34         pub fn sync_all(&self) -> io::Result<()>;
35         pub fn sync_data(&self) -> io::Result<()>;
36         pub fn try_clone(&self) -> io::Result<Self>;
37     }
38     #[cfg(windows)]
39     impl std::os::windows::io::AsRawHandle for File {
40         fn as_raw_handle(&self) -> std::os::windows::io::RawHandle;
41     }
42     #[cfg(windows)]
43     impl std::os::windows::io::FromRawHandle for File {
44         unsafe fn from_raw_handle(h: std::os::windows::io::RawHandle) -> Self;
45     }
46     #[cfg(unix)]
47     impl std::os::unix::io::AsRawFd for File {
48         fn as_raw_fd(&self) -> std::os::unix::io::RawFd;
49     }
50 
51     #[cfg(unix)]
52     impl std::os::unix::io::FromRawFd for File {
53         unsafe fn from_raw_fd(h: std::os::unix::io::RawFd) -> Self;
54     }
55 }
56 
57 impl Read for MockFile {
read(&mut self, dst: &mut [u8]) -> io::Result<usize>58     fn read(&mut self, dst: &mut [u8]) -> io::Result<usize> {
59         self.inner_read(dst)
60     }
61 }
62 
63 impl Read for &'_ MockFile {
read(&mut self, dst: &mut [u8]) -> io::Result<usize>64     fn read(&mut self, dst: &mut [u8]) -> io::Result<usize> {
65         self.inner_read(dst)
66     }
67 }
68 
69 impl Seek for &'_ MockFile {
seek(&mut self, pos: SeekFrom) -> io::Result<u64>70     fn seek(&mut self, pos: SeekFrom) -> io::Result<u64> {
71         self.inner_seek(pos)
72     }
73 }
74 
75 impl Write for &'_ MockFile {
write(&mut self, src: &[u8]) -> io::Result<usize>76     fn write(&mut self, src: &[u8]) -> io::Result<usize> {
77         self.inner_write(src)
78     }
79 
flush(&mut self) -> io::Result<()>80     fn flush(&mut self) -> io::Result<()> {
81         self.inner_flush()
82     }
83 }
84 
85 tokio_thread_local! {
86     static QUEUE: RefCell<VecDeque<Box<dyn FnOnce() + Send>>> = RefCell::new(VecDeque::new())
87 }
88 
89 #[derive(Debug)]
90 pub(super) struct JoinHandle<T> {
91     rx: oneshot::Receiver<T>,
92 }
93 
spawn_blocking<F, R>(f: F) -> JoinHandle<R> where F: FnOnce() -> R + Send + 'static, R: Send + 'static,94 pub(super) fn spawn_blocking<F, R>(f: F) -> JoinHandle<R>
95 where
96     F: FnOnce() -> R + Send + 'static,
97     R: Send + 'static,
98 {
99     let (tx, rx) = oneshot::channel();
100     let task = Box::new(move || {
101         let _ = tx.send(f());
102     });
103 
104     QUEUE.with(|cell| cell.borrow_mut().push_back(task));
105 
106     JoinHandle { rx }
107 }
108 
spawn_mandatory_blocking<F, R>(f: F) -> Option<JoinHandle<R>> where F: FnOnce() -> R + Send + 'static, R: Send + 'static,109 pub(super) fn spawn_mandatory_blocking<F, R>(f: F) -> Option<JoinHandle<R>>
110 where
111     F: FnOnce() -> R + Send + 'static,
112     R: Send + 'static,
113 {
114     let (tx, rx) = oneshot::channel();
115     let task = Box::new(move || {
116         let _ = tx.send(f());
117     });
118 
119     QUEUE.with(|cell| cell.borrow_mut().push_back(task));
120 
121     Some(JoinHandle { rx })
122 }
123 
124 impl<T> Future for JoinHandle<T> {
125     type Output = Result<T, io::Error>;
126 
poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output>127     fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
128         use std::task::Poll;
129 
130         match Pin::new(&mut self.rx).poll(cx) {
131             Poll::Ready(Ok(v)) => Poll::Ready(Ok(v)),
132             Poll::Ready(Err(e)) => panic!("error = {e:?}"),
133             Poll::Pending => Poll::Pending,
134         }
135     }
136 }
137 
138 pub(super) mod pool {
139     use super::*;
140 
len() -> usize141     pub(in super::super) fn len() -> usize {
142         QUEUE.with(|cell| cell.borrow().len())
143     }
144 
run_one()145     pub(in super::super) fn run_one() {
146         let task = QUEUE
147             .with(|cell| cell.borrow_mut().pop_front())
148             .expect("expected task to run, but none ready");
149 
150         task();
151     }
152 }
153