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 { |
57 | fn read(&mut self, dst: &mut [u8]) -> io::Result<usize> { |
58 | self.inner_read(dst) |
59 | } |
60 | } |
61 | |
62 | impl Read for &'_ MockFile { |
63 | fn read(&mut self, dst: &mut [u8]) -> io::Result<usize> { |
64 | self.inner_read(dst) |
65 | } |
66 | } |
67 | |
68 | impl Seek for &'_ MockFile { |
69 | fn seek(&mut self, pos: SeekFrom) -> io::Result<u64> { |
70 | self.inner_seek(pos) |
71 | } |
72 | } |
73 | |
74 | impl Write for &'_ MockFile { |
75 | fn write(&mut self, src: &[u8]) -> io::Result<usize> { |
76 | self.inner_write(src) |
77 | } |
78 | |
79 | fn flush(&mut self) -> io::Result<()> { |
80 | self.inner_flush() |
81 | } |
82 | } |
83 | |
84 | tokio_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 | |
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 | |
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 | |
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 | Poll::Ready(Ok(v)) => Poll::Ready(Ok(v)), |
131 | Poll::Ready(Err(e)) => panic!("error = {:?}" , e), |
132 | Poll::Pending => Poll::Pending, |
133 | } |
134 | } |
135 | } |
136 | |
137 | pub(super) mod pool { |
138 | use super::*; |
139 | |
140 | pub(in super::super) fn len() -> usize { |
141 | QUEUE.with(|cell| cell.borrow().len()) |
142 | } |
143 | |
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 | |