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 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
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