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 sync_all(&self) -> io::Result<()>;
34         pub fn sync_data(&self) -> io::Result<()>;
35         pub fn try_clone(&self) -> io::Result<Self>;
36     }
37     #[cfg(windows)]
38     impl std::os::windows::io::AsRawHandle for File {
39         fn as_raw_handle(&self) -> std::os::windows::io::RawHandle;
40     }
41     #[cfg(windows)]
42     impl std::os::windows::io::FromRawHandle for File {
43         unsafe fn from_raw_handle(h: std::os::windows::io::RawHandle) -> Self;
44     }
45     #[cfg(unix)]
46     impl std::os::unix::io::AsRawFd for File {
47         fn as_raw_fd(&self) -> std::os::unix::io::RawFd;
48     }
49 
50     #[cfg(unix)]
51     impl std::os::unix::io::FromRawFd for File {
52         unsafe fn from_raw_fd(h: std::os::unix::io::RawFd) -> Self;
53     }
54 }
55 
56 impl Read for MockFile {
read(&mut self, dst: &mut [u8]) -> io::Result<usize>57     fn read(&mut self, dst: &mut [u8]) -> io::Result<usize> {
58         self.inner_read(dst)
59     }
60 }
61 
62 impl Read for &'_ MockFile {
read(&mut self, dst: &mut [u8]) -> io::Result<usize>63     fn read(&mut self, dst: &mut [u8]) -> io::Result<usize> {
64         self.inner_read(dst)
65     }
66 }
67 
68 impl Seek for &'_ MockFile {
seek(&mut self, pos: SeekFrom) -> io::Result<u64>69     fn seek(&mut self, pos: SeekFrom) -> io::Result<u64> {
70         self.inner_seek(pos)
71     }
72 }
73 
74 impl Write for &'_ MockFile {
write(&mut self, src: &[u8]) -> io::Result<usize>75     fn write(&mut self, src: &[u8]) -> io::Result<usize> {
76         self.inner_write(src)
77     }
78 
flush(&mut self) -> io::Result<()>79     fn flush(&mut self) -> io::Result<()> {
80         self.inner_flush()
81     }
82 }
83 
84 thread_local! {
85     static QUEUE: RefCell<VecDeque<Box<dyn FnOnce() + Send>>> = RefCell::new(VecDeque::new())
86 }
87 
88 #[derive(Debug)]
89 pub(super) struct JoinHandle<T> {
90     rx: oneshot::Receiver<T>,
91 }
92 
spawn_blocking<F, R>(f: F) -> JoinHandle<R> where F: FnOnce() -> R + Send + 'static, R: Send + 'static,93 pub(super) fn spawn_blocking<F, R>(f: F) -> JoinHandle<R>
94 where
95     F: FnOnce() -> R + Send + 'static,
96     R: Send + 'static,
97 {
98     let (tx, rx) = oneshot::channel();
99     let task = Box::new(move || {
100         let _ = tx.send(f());
101     });
102 
103     QUEUE.with(|cell| cell.borrow_mut().push_back(task));
104 
105     JoinHandle { rx }
106 }
107 
spawn_mandatory_blocking<F, R>(f: F) -> Option<JoinHandle<R>> where F: FnOnce() -> R + Send + 'static, R: Send + 'static,108 pub(super) fn spawn_mandatory_blocking<F, R>(f: F) -> Option<JoinHandle<R>>
109 where
110     F: FnOnce() -> R + Send + 'static,
111     R: Send + 'static,
112 {
113     let (tx, rx) = oneshot::channel();
114     let task = Box::new(move || {
115         let _ = tx.send(f());
116     });
117 
118     QUEUE.with(|cell| cell.borrow_mut().push_back(task));
119 
120     Some(JoinHandle { rx })
121 }
122 
123 impl<T> Future for JoinHandle<T> {
124     type Output = Result<T, io::Error>;
125 
poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output>126     fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
127         use std::task::Poll::*;
128 
129         match Pin::new(&mut self.rx).poll(cx) {
130             Ready(Ok(v)) => Ready(Ok(v)),
131             Ready(Err(e)) => panic!("error = {:?}", e),
132             Pending => Pending,
133         }
134     }
135 }
136 
137 pub(super) mod pool {
138     use super::*;
139 
len() -> usize140     pub(in super::super) fn len() -> usize {
141         QUEUE.with(|cell| cell.borrow().len())
142     }
143 
run_one()144     pub(in super::super) fn run_one() {
145         let task = QUEUE
146             .with(|cell| cell.borrow_mut().pop_front())
147             .expect("expected task to run, but none ready");
148 
149         task();
150     }
151 }
152