Added unit tests and related bugfix.

Closes #17
This commit is contained in:
Paul Masurel
2016-08-20 00:11:09 +09:00
parent f1d2f6b34a
commit d244a198e2
3 changed files with 92 additions and 41 deletions
+26 -16
View File
@@ -18,6 +18,9 @@ use std::fs::OpenOptions;
use directory::error::{OpenWriteError, FileError, OpenDirectoryError};
use std::result;
use common::make_io_err;
use std::fs;
use directory::shared_vec_slice::SharedVecSlice;
/// Directory storing data in files, read via MMap.
///
@@ -127,8 +130,11 @@ impl Seek for SafeFileWriter {
impl Directory for MmapDirectory {
fn open_read(&self, path: &Path) -> result::Result<ReadOnlySource, FileError> {
let full_path = self.resolve_path(path);
let mut mmap_cache = try!(
self.mmap_cache
.write()
@@ -136,14 +142,14 @@ impl Directory for MmapDirectory {
make_io_err(format!("Failed to acquired write lock on mmap cache while reading {:?}", path))
})
);
let mmap = match mmap_cache.entry(full_path.clone()) {
HashMapEntry::Occupied(e) => {
e.get().clone()
}
HashMapEntry::Vacant(vacant_entry) => {
let new_mmap = try!(
MmapReadOnly::open_path(full_path.clone())
.map_err(|err| {
let file = try!(
File::open(&full_path).map_err(|err| {
if err.kind() == io::ErrorKind::NotFound {
FileError::FileDoesNotExist(full_path.clone())
}
@@ -152,10 +158,17 @@ impl Directory for MmapDirectory {
}
})
);
if try!(file.metadata()).len() == 0 {
// if the file size is 0, it will not be possible
// to mmap the file, so we return an anonymous mmap_cache
// instead.
return Ok(ReadOnlySource::Anonymous(SharedVecSlice::empty()))
}
let new_mmap = try!(MmapReadOnly::open(&file));
vacant_entry.insert(new_mmap.clone());
new_mmap
}
};
};
Ok(ReadOnlySource::Mmap(mmap))
}
@@ -166,7 +179,7 @@ impl Directory for MmapDirectory {
.write(true)
.create_new(true)
.open(full_path);
let mut file = try!(
open_res.map_err(|err| {
if err.kind() == io::ErrorKind::AlreadyExists {
@@ -177,7 +190,7 @@ impl Directory for MmapDirectory {
}
})
);
// making sure the file is created.
try!(file.flush());
@@ -197,16 +210,13 @@ impl Directory for MmapDirectory {
make_io_err(format!("Failed to acquired write lock on mmap cache while deleting {:?}", path))
})
);
match mmap_cache.remove(&full_path) {
Some(_) => {
// it will be munmapped on drop,
// when the last reference is gone.
Ok(())
}
None => {
Err(FileError::FileDoesNotExist(PathBuf::from(path)))
}
}
// Removing the entry in the MMap cache.
// The munmap will appear on Drop,
// when the last reference is gone.
mmap_cache.remove(&full_path);
try!(fs::remove_file(&full_path));
try!(self.sync_directory());
Ok(())
}
fn atomic_write(&mut self, path: &Path, data: &[u8]) -> io::Result<()> {
+65 -24
View File
@@ -28,6 +28,10 @@ mod tests {
use std::path::Path;
use std::io::SeekFrom;
lazy_static! {
static ref TEST_PATH: &'static Path = Path::new("some_path_for_test");
}
#[test]
fn test_ram_directory() {
let mut ram_directory = RAMDirectory::create();
@@ -40,48 +44,85 @@ mod tests {
test_directory(&mut mmap_directory);
}
fn test_directory_simple(directory: &mut Directory) {
#[test]
#[should_panic]
fn ram_directory_panics_if_flush_forgotten() {
let mut ram_directory = RAMDirectory::create();
let mut write_file = ram_directory.open_write(*TEST_PATH).unwrap();
assert!(write_file.write_all(&[4]).is_ok());
}
fn test_simple(directory: &mut Directory) {
{
let mut write_file = directory.open_write(Path::new("toto")).unwrap();
let mut write_file = directory.open_write(*TEST_PATH).unwrap();
write_file.write_all(&[4]).unwrap();
write_file.write_all(&[3]).unwrap();
write_file.write_all(&[7,3,5]).unwrap();
write_file.flush().unwrap();
}
let read_file = directory.open_read(Path::new("toto")).unwrap();
let read_file = directory.open_read(*TEST_PATH).unwrap();
let data: &[u8] = &*read_file;
assert_eq!(data.len(), 5);
assert_eq!(data[0], 4);
assert_eq!(data[1], 3);
assert_eq!(data[2], 7);
assert_eq!(data[3], 3);
assert_eq!(data[4], 5);
assert_eq!(data, &[4u8, 3u8, 7u8, 3u8, 5u8]);
assert!(directory.delete(*TEST_PATH).is_ok());
}
fn test_directory_seek(directory: &mut Directory) {
fn test_seek(directory: &mut Directory) {
{
let mut write_file = directory.open_write(Path::new("toto_seek")).unwrap();
write_file.write_all(&[4]).unwrap();
write_file.write_all(&[3]).unwrap();
write_file.write_all(&[7,3,5]).unwrap();
let mut write_file = directory.open_write(*TEST_PATH).unwrap();
write_file.write_all(&[4, 3, 7,3,5]).unwrap();
write_file.seek(SeekFrom::Start(0)).unwrap();
write_file.write_all(&[3,1]).unwrap();
write_file.flush().unwrap();
}
let read_file = directory.open_read(Path::new("toto_seek")).unwrap();
let read_file = directory.open_read(*TEST_PATH).unwrap();
let data: &[u8] = &*read_file;
assert_eq!(data.len(), 5);
assert_eq!(data[0], 3);
assert_eq!(data[1], 1);
assert_eq!(data[2], 7);
assert_eq!(data[3], 3);
assert_eq!(data[4], 5);
assert_eq!(data, &[3u8, 1u8, 7u8, 3u8, 5u8]);
assert!(directory.delete(*TEST_PATH).is_ok());
}
fn test_rewrite_forbidden(directory: &mut Directory) {
{
directory.open_write(*TEST_PATH).unwrap();
}
{
assert!(directory.open_write(*TEST_PATH).is_err());
}
assert!(directory.delete(*TEST_PATH).is_ok());
}
fn test_write_create_the_file(directory: &mut Directory) {
{
assert!(directory.open_read(*TEST_PATH).is_err());
let _w = directory.open_write(*TEST_PATH).unwrap();
if let Err(e) = directory.open_read(*TEST_PATH) {
println!("{:?}", e);
}
assert!(directory.open_read(*TEST_PATH).is_ok());
assert!(directory.delete(*TEST_PATH).is_ok());
}
}
fn test_delete(directory: &mut Directory) {
assert!(directory.open_read(*TEST_PATH).is_err());
let mut write_file = directory.open_write(*TEST_PATH).unwrap();
write_file.write_all(&[1, 2, 3, 4]).unwrap();
write_file.flush().unwrap();
let read_handle = directory.open_read(*TEST_PATH).unwrap();
{
assert_eq!(&*read_handle, &[1u8, 2u8, 3u8, 4u8]);
assert!(directory.delete(*TEST_PATH).is_ok());
assert!(directory.delete(Path::new("SomeOtherPath")).is_err());
assert_eq!(&*read_handle, &[1u8, 2u8, 3u8, 4u8]);
}
assert!(directory.open_read(*TEST_PATH).is_err());
}
fn test_directory(directory: &mut Directory) {
test_directory_simple(directory);
test_directory_seek(directory);
test_simple(directory);
test_seek(directory);
test_rewrite_forbidden(directory);
test_write_create_the_file(directory);
test_delete(directory);
}
}
+1 -1
View File
@@ -34,7 +34,7 @@ impl VecWriter {
path: path_buf,
data: Cursor::new(Vec::new()),
shared_directory: shared_directory,
is_flushed: false,
is_flushed: true,
}
}
}