#![cfg(test)]
use super::{hash_file, hash_stream, hash_stream_common, GeneratorOrIOError};
use std::error::Error;
use std::fs::File;
use std::io::Read;
use crate::generate::{Generator, GeneratorError};
#[test]
fn hash_file_usage() {
let hash = hash_file("data/examples/hello.txt");
assert!(hash.is_ok());
assert_eq!(hash.unwrap().to_string(), "3:aaX8v:aV");
}
#[test]
fn hash_file_not_exist() {
let err = hash_file("data/examples/nonexistent.bin");
if let Err(GeneratorOrIOError::IOError(err)) = err {
let str_display_bare = format!("{}", err);
let str_debug_bare = format!("{:?}", err);
assert_eq!(err.kind(), std::io::ErrorKind::NotFound);
let orig_error = GeneratorOrIOError::IOError(err);
assert_eq!(format!("{}", orig_error), str_display_bare);
assert_eq!(
format!("{:?}", orig_error),
format!("IOError({})", str_debug_bare)
);
assert_eq!(
format!(
"{}",
orig_error
.source()
.unwrap()
.downcast_ref::<std::io::Error>()
.unwrap()
),
str_display_bare
);
assert_eq!(
format!(
"{:?}",
orig_error
.source()
.unwrap()
.downcast_ref::<std::io::Error>()
.unwrap()
),
str_debug_bare
);
} else {
panic!("the error must be an IOError");
}
}
#[cfg(unix)]
#[test]
fn hash_file_too_large() {
fn test_body_ignore_os_errors() -> Result<(), std::io::Error> {
use std::io::{Seek, SeekFrom, Write};
use std::os::fd::AsRawFd;
let tmpfile = tempfile::NamedTempFile::new()?;
let mut file = std::fs::OpenOptions::new()
.read(true)
.write(true)
.open(tmpfile.path())?;
const SPARSE_INITIAL_SIZE: u64 = 1024 * 1024;
file.seek(SeekFrom::Start(SPARSE_INITIAL_SIZE - 1))?;
file.write_all(&[1])?;
file.seek(SeekFrom::Start(0))?;
unsafe {
let fd = file.as_raw_fd();
let ret = libc::lseek(fd, 0, libc::SEEK_HOLE);
if ret == -1 {
return Ok(());
}
if ret == SPARSE_INITIAL_SIZE as i64 {
return Ok(());
}
let ret = libc::lseek(fd, 0, libc::SEEK_SET);
if ret != 0 {
return Ok(());
}
}
file.seek(SeekFrom::Start(Generator::MAX_INPUT_SIZE))?;
file.write_all(&[1])?;
drop(file);
assert!(matches!(
hash_file(tmpfile.path()),
Err(GeneratorOrIOError::GeneratorError(
GeneratorError::FixedSizeTooLarge
))
));
Ok(())
}
let _ = test_body_ignore_os_errors();
}
#[test]
fn hash_stream_common_usage() {
let mut file = File::open("data/examples/hello.txt").unwrap();
let hash = hash_stream(&mut file);
assert!(hash.is_ok());
assert_eq!(hash.unwrap().to_string(), "3:aaX8v:aV");
}
#[test]
fn hash_stream_common_size_inconsistency() {
let mut file = File::open("data/examples/hello.txt").unwrap();
let mut generator = Generator::new();
generator.set_fixed_input_size(0).unwrap();
let err = hash_stream_common(&mut generator, &mut file);
if let Err(GeneratorOrIOError::GeneratorError(err)) = err {
let str_display_bare = format!("{}", err);
let str_debug_bare = format!("{:?}", err);
assert_eq!(err, GeneratorError::FixedSizeMismatch);
let orig_error = GeneratorOrIOError::GeneratorError(err);
assert_eq!(format!("{}", orig_error), str_display_bare);
assert_eq!(
format!("{:?}", orig_error),
format!("GeneratorError({})", str_debug_bare)
);
assert_eq!(
format!(
"{}",
orig_error
.source()
.unwrap()
.downcast_ref::<GeneratorError>()
.unwrap()
),
str_display_bare
);
assert_eq!(
format!(
"{:?}",
orig_error
.source()
.unwrap()
.downcast_ref::<GeneratorError>()
.unwrap()
),
str_debug_bare
);
} else {
panic!("the error must be a GeneratorError");
}
}
#[test]
fn hash_stream_common_io_fail() {
struct IOFail;
impl Read for IOFail {
fn read(&mut self, _buf: &mut [u8]) -> std::io::Result<usize> {
Err(std::io::Error::from(std::io::ErrorKind::Other))
}
}
let mut generator = Generator::new();
let err = hash_stream_common(&mut generator, &mut IOFail);
if let Err(GeneratorOrIOError::IOError(err)) = err {
let str_display_bare = format!("{}", err);
let str_debug_bare = format!("{:?}", err);
assert_eq!(err.kind(), std::io::ErrorKind::Other);
let orig_error = GeneratorOrIOError::IOError(err);
assert_eq!(format!("{}", orig_error), str_display_bare);
assert_eq!(
format!("{:?}", orig_error),
format!("IOError({})", str_debug_bare)
);
assert_eq!(
format!(
"{}",
orig_error
.source()
.unwrap()
.downcast_ref::<std::io::Error>()
.unwrap()
),
str_display_bare
);
assert_eq!(
format!(
"{:?}",
orig_error
.source()
.unwrap()
.downcast_ref::<std::io::Error>()
.unwrap()
),
str_debug_bare
);
} else {
panic!("the error must be an IOError");
}
}