blob: 9895f835e6b65f5479f78e2376d30c0c07509e1d [file] [log] [blame]
#![allow(clippy::unnecessary_operation)]
use std::collections::VecDeque;
use std::fmt;
use std::fs::{Metadata, Permissions};
use std::io;
use std::io::prelude::*;
use std::io::SeekFrom;
use std::path::PathBuf;
use std::sync::{Arc, Mutex};
pub struct File {
shared: Arc<Mutex<Shared>>,
}
pub struct Handle {
shared: Arc<Mutex<Shared>>,
}
struct Shared {
calls: VecDeque<Call>,
}
#[derive(Debug)]
enum Call {
Read(io::Result<Vec<u8>>),
Write(io::Result<Vec<u8>>),
Seek(SeekFrom, io::Result<u64>),
SyncAll(io::Result<()>),
SyncData(io::Result<()>),
SetLen(u64, io::Result<()>),
}
impl Handle {
pub fn read(&self, data: &[u8]) -> &Self {
let mut s = self.shared.lock().unwrap();
s.calls.push_back(Call::Read(Ok(data.to_owned())));
self
}
pub fn read_err(&self) -> &Self {
let mut s = self.shared.lock().unwrap();
s.calls
.push_back(Call::Read(Err(io::ErrorKind::Other.into())));
self
}
pub fn write(&self, data: &[u8]) -> &Self {
let mut s = self.shared.lock().unwrap();
s.calls.push_back(Call::Write(Ok(data.to_owned())));
self
}
pub fn write_err(&self) -> &Self {
let mut s = self.shared.lock().unwrap();
s.calls
.push_back(Call::Write(Err(io::ErrorKind::Other.into())));
self
}
pub fn seek_start_ok(&self, offset: u64) -> &Self {
let mut s = self.shared.lock().unwrap();
s.calls
.push_back(Call::Seek(SeekFrom::Start(offset), Ok(offset)));
self
}
pub fn seek_current_ok(&self, offset: i64, ret: u64) -> &Self {
let mut s = self.shared.lock().unwrap();
s.calls
.push_back(Call::Seek(SeekFrom::Current(offset), Ok(ret)));
self
}
pub fn sync_all(&self) -> &Self {
let mut s = self.shared.lock().unwrap();
s.calls.push_back(Call::SyncAll(Ok(())));
self
}
pub fn sync_all_err(&self) -> &Self {
let mut s = self.shared.lock().unwrap();
s.calls
.push_back(Call::SyncAll(Err(io::ErrorKind::Other.into())));
self
}
pub fn sync_data(&self) -> &Self {
let mut s = self.shared.lock().unwrap();
s.calls.push_back(Call::SyncData(Ok(())));
self
}
pub fn sync_data_err(&self) -> &Self {
let mut s = self.shared.lock().unwrap();
s.calls
.push_back(Call::SyncData(Err(io::ErrorKind::Other.into())));
self
}
pub fn set_len(&self, size: u64) -> &Self {
let mut s = self.shared.lock().unwrap();
s.calls.push_back(Call::SetLen(size, Ok(())));
self
}
pub fn set_len_err(&self, size: u64) -> &Self {
let mut s = self.shared.lock().unwrap();
s.calls
.push_back(Call::SetLen(size, Err(io::ErrorKind::Other.into())));
self
}
pub fn remaining(&self) -> usize {
let s = self.shared.lock().unwrap();
s.calls.len()
}
}
impl Drop for Handle {
fn drop(&mut self) {
if !std::thread::panicking() {
let s = self.shared.lock().unwrap();
assert_eq!(0, s.calls.len());
}
}
}
impl File {
pub fn open(_: PathBuf) -> io::Result<File> {
unimplemented!();
}
pub fn create(_: PathBuf) -> io::Result<File> {
unimplemented!();
}
pub fn mock() -> (Handle, File) {
let shared = Arc::new(Mutex::new(Shared {
calls: VecDeque::new(),
}));
let handle = Handle {
shared: shared.clone(),
};
let file = File { shared };
(handle, file)
}
pub fn sync_all(&self) -> io::Result<()> {
use self::Call::*;
let mut s = self.shared.lock().unwrap();
match s.calls.pop_front() {
Some(SyncAll(ret)) => ret,
Some(op) => panic!("expected next call to be {:?}; was sync_all", op),
None => panic!("did not expect call"),
}
}
pub fn sync_data(&self) -> io::Result<()> {
use self::Call::*;
let mut s = self.shared.lock().unwrap();
match s.calls.pop_front() {
Some(SyncData(ret)) => ret,
Some(op) => panic!("expected next call to be {:?}; was sync_all", op),
None => panic!("did not expect call"),
}
}
pub fn set_len(&self, size: u64) -> io::Result<()> {
use self::Call::*;
let mut s = self.shared.lock().unwrap();
match s.calls.pop_front() {
Some(SetLen(arg, ret)) => {
assert_eq!(arg, size);
ret
}
Some(op) => panic!("expected next call to be {:?}; was sync_all", op),
None => panic!("did not expect call"),
}
}
pub fn metadata(&self) -> io::Result<Metadata> {
unimplemented!();
}
pub fn set_permissions(&self, _perm: Permissions) -> io::Result<()> {
unimplemented!();
}
pub fn try_clone(&self) -> io::Result<Self> {
unimplemented!();
}
}
impl Read for &'_ File {
fn read(&mut self, dst: &mut [u8]) -> io::Result<usize> {
use self::Call::*;
let mut s = self.shared.lock().unwrap();
match s.calls.pop_front() {
Some(Read(Ok(data))) => {
assert!(dst.len() >= data.len());
assert!(dst.len() <= 16 * 1024, "actual = {}", dst.len()); // max buffer
&mut dst[..data.len()].copy_from_slice(&data);
Ok(data.len())
}
Some(Read(Err(e))) => Err(e),
Some(op) => panic!("expected next call to be {:?}; was a read", op),
None => panic!("did not expect call"),
}
}
}
impl Write for &'_ File {
fn write(&mut self, src: &[u8]) -> io::Result<usize> {
use self::Call::*;
let mut s = self.shared.lock().unwrap();
match s.calls.pop_front() {
Some(Write(Ok(data))) => {
assert_eq!(src, &data[..]);
Ok(src.len())
}
Some(Write(Err(e))) => Err(e),
Some(op) => panic!("expected next call to be {:?}; was write", op),
None => panic!("did not expect call"),
}
}
fn flush(&mut self) -> io::Result<()> {
Ok(())
}
}
impl Seek for &'_ File {
fn seek(&mut self, pos: SeekFrom) -> io::Result<u64> {
use self::Call::*;
let mut s = self.shared.lock().unwrap();
match s.calls.pop_front() {
Some(Seek(expect, res)) => {
assert_eq!(expect, pos);
res
}
Some(op) => panic!("expected call {:?}; was `seek`", op),
None => panic!("did not expect call; was `seek`"),
}
}
}
impl fmt::Debug for File {
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt.debug_struct("mock::File").finish()
}
}
#[cfg(unix)]
impl std::os::unix::io::AsRawFd for File {
fn as_raw_fd(&self) -> std::os::unix::io::RawFd {
unimplemented!();
}
}
#[cfg(windows)]
impl std::os::windows::io::AsRawHandle for File {
fn as_raw_handle(&self) -> std::os::windows::io::RawHandle {
unimplemented!();
}
}