1 #![allow(clippy::unnecessary_operation)]
2 
3 use std::collections::VecDeque;
4 use std::fmt;
5 use std::fs::{Metadata, Permissions};
6 use std::io;
7 use std::io::prelude::*;
8 use std::io::SeekFrom;
9 use std::path::PathBuf;
10 use std::sync::{Arc, Mutex};
11 
12 pub struct File {
13     shared: Arc<Mutex<Shared>>,
14 }
15 
16 pub struct Handle {
17     shared: Arc<Mutex<Shared>>,
18 }
19 
20 struct Shared {
21     calls: VecDeque<Call>,
22 }
23 
24 #[derive(Debug)]
25 enum Call {
26     Read(io::Result<Vec<u8>>),
27     Write(io::Result<Vec<u8>>),
28     Seek(SeekFrom, io::Result<u64>),
29     SyncAll(io::Result<()>),
30     SyncData(io::Result<()>),
31     SetLen(u64, io::Result<()>),
32 }
33 
34 impl Handle {
read(&self, data: &[u8]) -> &Self35     pub fn read(&self, data: &[u8]) -> &Self {
36         let mut s = self.shared.lock().unwrap();
37         s.calls.push_back(Call::Read(Ok(data.to_owned())));
38         self
39     }
40 
read_err(&self) -> &Self41     pub fn read_err(&self) -> &Self {
42         let mut s = self.shared.lock().unwrap();
43         s.calls
44             .push_back(Call::Read(Err(io::ErrorKind::Other.into())));
45         self
46     }
47 
write(&self, data: &[u8]) -> &Self48     pub fn write(&self, data: &[u8]) -> &Self {
49         let mut s = self.shared.lock().unwrap();
50         s.calls.push_back(Call::Write(Ok(data.to_owned())));
51         self
52     }
53 
write_err(&self) -> &Self54     pub fn write_err(&self) -> &Self {
55         let mut s = self.shared.lock().unwrap();
56         s.calls
57             .push_back(Call::Write(Err(io::ErrorKind::Other.into())));
58         self
59     }
60 
seek_start_ok(&self, offset: u64) -> &Self61     pub fn seek_start_ok(&self, offset: u64) -> &Self {
62         let mut s = self.shared.lock().unwrap();
63         s.calls
64             .push_back(Call::Seek(SeekFrom::Start(offset), Ok(offset)));
65         self
66     }
67 
seek_current_ok(&self, offset: i64, ret: u64) -> &Self68     pub fn seek_current_ok(&self, offset: i64, ret: u64) -> &Self {
69         let mut s = self.shared.lock().unwrap();
70         s.calls
71             .push_back(Call::Seek(SeekFrom::Current(offset), Ok(ret)));
72         self
73     }
74 
sync_all(&self) -> &Self75     pub fn sync_all(&self) -> &Self {
76         let mut s = self.shared.lock().unwrap();
77         s.calls.push_back(Call::SyncAll(Ok(())));
78         self
79     }
80 
sync_all_err(&self) -> &Self81     pub fn sync_all_err(&self) -> &Self {
82         let mut s = self.shared.lock().unwrap();
83         s.calls
84             .push_back(Call::SyncAll(Err(io::ErrorKind::Other.into())));
85         self
86     }
87 
sync_data(&self) -> &Self88     pub fn sync_data(&self) -> &Self {
89         let mut s = self.shared.lock().unwrap();
90         s.calls.push_back(Call::SyncData(Ok(())));
91         self
92     }
93 
sync_data_err(&self) -> &Self94     pub fn sync_data_err(&self) -> &Self {
95         let mut s = self.shared.lock().unwrap();
96         s.calls
97             .push_back(Call::SyncData(Err(io::ErrorKind::Other.into())));
98         self
99     }
100 
set_len(&self, size: u64) -> &Self101     pub fn set_len(&self, size: u64) -> &Self {
102         let mut s = self.shared.lock().unwrap();
103         s.calls.push_back(Call::SetLen(size, Ok(())));
104         self
105     }
106 
set_len_err(&self, size: u64) -> &Self107     pub fn set_len_err(&self, size: u64) -> &Self {
108         let mut s = self.shared.lock().unwrap();
109         s.calls
110             .push_back(Call::SetLen(size, Err(io::ErrorKind::Other.into())));
111         self
112     }
113 
remaining(&self) -> usize114     pub fn remaining(&self) -> usize {
115         let s = self.shared.lock().unwrap();
116         s.calls.len()
117     }
118 }
119 
120 impl Drop for Handle {
drop(&mut self)121     fn drop(&mut self) {
122         if !std::thread::panicking() {
123             let s = self.shared.lock().unwrap();
124             assert_eq!(0, s.calls.len());
125         }
126     }
127 }
128 
129 impl File {
open(_: PathBuf) -> io::Result<File>130     pub fn open(_: PathBuf) -> io::Result<File> {
131         unimplemented!();
132     }
133 
create(_: PathBuf) -> io::Result<File>134     pub fn create(_: PathBuf) -> io::Result<File> {
135         unimplemented!();
136     }
137 
mock() -> (Handle, File)138     pub fn mock() -> (Handle, File) {
139         let shared = Arc::new(Mutex::new(Shared {
140             calls: VecDeque::new(),
141         }));
142 
143         let handle = Handle {
144             shared: shared.clone(),
145         };
146         let file = File { shared };
147 
148         (handle, file)
149     }
150 
sync_all(&self) -> io::Result<()>151     pub fn sync_all(&self) -> io::Result<()> {
152         use self::Call::*;
153 
154         let mut s = self.shared.lock().unwrap();
155 
156         match s.calls.pop_front() {
157             Some(SyncAll(ret)) => ret,
158             Some(op) => panic!("expected next call to be {:?}; was sync_all", op),
159             None => panic!("did not expect call"),
160         }
161     }
162 
sync_data(&self) -> io::Result<()>163     pub fn sync_data(&self) -> io::Result<()> {
164         use self::Call::*;
165 
166         let mut s = self.shared.lock().unwrap();
167 
168         match s.calls.pop_front() {
169             Some(SyncData(ret)) => ret,
170             Some(op) => panic!("expected next call to be {:?}; was sync_all", op),
171             None => panic!("did not expect call"),
172         }
173     }
174 
set_len(&self, size: u64) -> io::Result<()>175     pub fn set_len(&self, size: u64) -> io::Result<()> {
176         use self::Call::*;
177 
178         let mut s = self.shared.lock().unwrap();
179 
180         match s.calls.pop_front() {
181             Some(SetLen(arg, ret)) => {
182                 assert_eq!(arg, size);
183                 ret
184             }
185             Some(op) => panic!("expected next call to be {:?}; was sync_all", op),
186             None => panic!("did not expect call"),
187         }
188     }
189 
metadata(&self) -> io::Result<Metadata>190     pub fn metadata(&self) -> io::Result<Metadata> {
191         unimplemented!();
192     }
193 
set_permissions(&self, _perm: Permissions) -> io::Result<()>194     pub fn set_permissions(&self, _perm: Permissions) -> io::Result<()> {
195         unimplemented!();
196     }
197 
try_clone(&self) -> io::Result<Self>198     pub fn try_clone(&self) -> io::Result<Self> {
199         unimplemented!();
200     }
201 }
202 
203 impl Read for &'_ File {
read(&mut self, dst: &mut [u8]) -> io::Result<usize>204     fn read(&mut self, dst: &mut [u8]) -> io::Result<usize> {
205         use self::Call::*;
206 
207         let mut s = self.shared.lock().unwrap();
208 
209         match s.calls.pop_front() {
210             Some(Read(Ok(data))) => {
211                 assert!(dst.len() >= data.len());
212                 assert!(dst.len() <= 16 * 1024, "actual = {}", dst.len()); // max buffer
213 
214                 &mut dst[..data.len()].copy_from_slice(&data);
215                 Ok(data.len())
216             }
217             Some(Read(Err(e))) => Err(e),
218             Some(op) => panic!("expected next call to be {:?}; was a read", op),
219             None => panic!("did not expect call"),
220         }
221     }
222 }
223 
224 impl Write for &'_ File {
write(&mut self, src: &[u8]) -> io::Result<usize>225     fn write(&mut self, src: &[u8]) -> io::Result<usize> {
226         use self::Call::*;
227 
228         let mut s = self.shared.lock().unwrap();
229 
230         match s.calls.pop_front() {
231             Some(Write(Ok(data))) => {
232                 assert_eq!(src, &data[..]);
233                 Ok(src.len())
234             }
235             Some(Write(Err(e))) => Err(e),
236             Some(op) => panic!("expected next call to be {:?}; was write", op),
237             None => panic!("did not expect call"),
238         }
239     }
240 
flush(&mut self) -> io::Result<()>241     fn flush(&mut self) -> io::Result<()> {
242         Ok(())
243     }
244 }
245 
246 impl Seek for &'_ File {
seek(&mut self, pos: SeekFrom) -> io::Result<u64>247     fn seek(&mut self, pos: SeekFrom) -> io::Result<u64> {
248         use self::Call::*;
249 
250         let mut s = self.shared.lock().unwrap();
251 
252         match s.calls.pop_front() {
253             Some(Seek(expect, res)) => {
254                 assert_eq!(expect, pos);
255                 res
256             }
257             Some(op) => panic!("expected call {:?}; was `seek`", op),
258             None => panic!("did not expect call; was `seek`"),
259         }
260     }
261 }
262 
263 impl fmt::Debug for File {
fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result264     fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
265         fmt.debug_struct("mock::File").finish()
266     }
267 }
268 
269 #[cfg(unix)]
270 impl std::os::unix::io::AsRawFd for File {
as_raw_fd(&self) -> std::os::unix::io::RawFd271     fn as_raw_fd(&self) -> std::os::unix::io::RawFd {
272         unimplemented!();
273     }
274 }
275 
276 #[cfg(windows)]
277 impl std::os::windows::io::AsRawHandle for File {
as_raw_handle(&self) -> std::os::windows::io::RawHandle278     fn as_raw_handle(&self) -> std::os::windows::io::RawHandle {
279         unimplemented!();
280     }
281 }
282