Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fs storage device unit tests #461

Draft
wants to merge 2 commits into
base: master
Choose a base branch
from
Draft
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
186 changes: 182 additions & 4 deletions fs/src/interface/storage.rs
Original file line number Diff line number Diff line change
Expand Up @@ -89,11 +89,10 @@ impl<B> StorageDevice for StorageCachedBlockDevice<B> where B: BlockDevice + Syn
let mut buf = buf;
let mut current_offset = offset;

let buf_addr = buf.as_ptr() as usize;
let block_alignment = core::mem::align_of::<Block>();

// First of all, if buf address is unaligned, we need to do a read for one byte and align it.
if buf_addr % block_alignment != 0 {
if buf.as_ptr() as usize % block_alignment != 0 {
self.read_from_temp_storage(current_offset, &mut buf[..block_alignment - 1])?;

// Align buf to Block.
Expand Down Expand Up @@ -134,7 +133,7 @@ impl<B> StorageDevice for StorageCachedBlockDevice<B> where B: BlockDevice + Syn
if !buf.is_empty() {
let main_blocks = unsafe {
// Safety: Safe because we guarantee that buf_addr follow the layout and alignment of Block.
core::slice::from_raw_parts_mut(buf_addr as *mut Block, buf.len() / Block::LEN)
core::slice::from_raw_parts_mut(buf.as_ptr() as *mut Block, buf.len() / Block::LEN)
};

self.block_device.read(main_blocks, current_block_index)?;
Expand Down Expand Up @@ -314,4 +313,183 @@ impl<B> IStorage for StorageCachedBlockDevice<B> where B: BlockDevice + Sync + S
fn get_size(&mut self) -> LibUserResult<u64> {
self.len().map_err(storage_error_to_libuser_error)
}
}
}

#[cfg(test)]
mod test {
use storage_device::{BlockDevice, Block, BlockIndex, BlockCount, BlockError, CachedBlockDevice, StorageDevice};

/// Block device that when read from returns blocks filled with for every byte
/// their index in the block,
/// and when wrote to checks that for every byte it's its index in the block.
///
/// Used to debug that our reading logic for unaligned buffers is correct.
#[derive(Debug)]
struct DbgBlockDevice;

impl BlockDevice for DbgBlockDevice {
fn read(&mut self, blocks: &mut [Block], _index: BlockIndex) -> Result<(), BlockError> {
assert_eq!(((&blocks[0]) as *const Block as usize) % core::mem::align_of::<Block>(), 0, "DbgBlockDevice got a misaligned block");
for block in blocks.iter_mut() {
for (index, byte) in block.contents.iter_mut().enumerate() {
*byte = index as u8 // overflows once per block
}
}
Ok(())
}

fn write(&mut self, blocks: &[Block], _index: BlockIndex) -> Result<(), BlockError> {
assert_eq!(((&blocks[0]) as *const Block as usize) % core::mem::align_of::<Block>(), 0, "DbgBlockDevice got a misaligned block");
for block in blocks.iter() {
for (index, byte) in block.contents.iter().enumerate() {
if *byte != (index as u8) {
return Err(storage_device::BlockError::WriteError)
}
}
}
Ok(())
}

fn count(&mut self) -> Result<BlockCount, BlockError> {
Ok(BlockCount(8))
}
}

use super::StorageCachedBlockDevice;
use super::IStorage;

/// An aligned buffer.
///
/// To get a misaligned buffer from this, just do `align_buf.buf[1..]`.
#[repr(C, align(8))]
struct AlignedBuf {
buf: [u8; 4096]
}

#[test]
fn check_dbg_block_device_aligned() {
let mut storage_dev = StorageCachedBlockDevice::new(DbgBlockDevice, 16);
let mut aligned = AlignedBuf { buf: [0x55; 4096] };
let aligned_buf = &mut aligned.buf[0..];
assert_eq!((&aligned_buf[0] as *const u8 as usize) % 2, 0, "buf is not actually aligned");

storage_device::StorageDevice::read(&mut storage_dev, 0, aligned_buf)
.expect("reading failed");

for (index, byte) in aligned_buf.iter().enumerate() {
assert_eq!(*byte, index as u8, "failed checking block content. Index: {:02x}, Your buffer:\n{:02x?}", index, &aligned_buf);
}

// writing back should also work
storage_device::StorageDevice::write(&mut storage_dev, 0, aligned_buf)
.expect("writing failed");
storage_dev.flush()
.expect("flushing failed");
}


#[test]
fn check_dbg_block_device_misaligned() {
let mut storage_dev = StorageCachedBlockDevice::new(DbgBlockDevice, 16);
let mut aligned_buf = AlignedBuf { buf: [0x55; 4096] };
let misaligned_buf = &mut aligned_buf.buf[1..];
assert_eq!((&misaligned_buf[0] as *const u8 as usize) % 2, 1, "buf is not actually misaligned");

storage_device::StorageDevice::read(&mut storage_dev, 0, misaligned_buf)
.expect("reading failed");

for (index, byte) in misaligned_buf.iter().enumerate() {
assert_eq!(*byte, index as u8, "failed checking block content. Index: {:02x}, Your buffer:\n{:02x?}", index, &misaligned_buf);
}

// writing back should also work
storage_device::StorageDevice::write(&mut storage_dev, 0, misaligned_buf)
.expect("writing failed");
storage_dev.flush()
.expect("flushing failed");
}

#[test]
fn check_dbg_block_device_aligned_offset_8() {
let mut storage_dev = StorageCachedBlockDevice::new(DbgBlockDevice, 16);
let mut aligned = AlignedBuf { buf: [0x55; 4096] };
let aligned_buf = &mut aligned.buf[0..];
assert_eq!((&aligned_buf[0] as *const u8 as usize) % 2, 0, "buf is not actually saligned");

storage_device::StorageDevice::read(&mut storage_dev, 8, aligned_buf)
.expect("reading failed");

for (index, byte) in aligned_buf.iter().enumerate() {
assert_eq!(*byte, (index + 8) as u8, "failed checking block content. Index: {:02x}, Your buffer:\n{:02x?}", index, &aligned_buf);
}

// writing back should also work
storage_device::StorageDevice::write(&mut storage_dev, 8, aligned_buf)
.expect("writing failed");
storage_dev.flush()
.expect("flushing failed");
}

#[test]
fn check_dbg_block_device_misaligned_offset_8() {
let mut storage_dev = StorageCachedBlockDevice::new(DbgBlockDevice, 16);
let mut aligned_buf = AlignedBuf { buf: [0x55; 4096] };
let misaligned_buf = &mut aligned_buf.buf[1..];
assert_eq!((&misaligned_buf[0] as *const u8 as usize) % 2, 1, "buf is not actually misaligned");

storage_device::StorageDevice::read(&mut storage_dev, 8, misaligned_buf)
.expect("reading failed");

for (index, byte) in misaligned_buf.iter().enumerate() {
assert_eq!(*byte, (index + 8) as u8, "failed checking block content. Index: {:02x}, Your buffer:\n{:02x?}", index, &misaligned_buf);
}

// writing back should also work
storage_device::StorageDevice::write(&mut storage_dev, 8, misaligned_buf)
.expect("writing failed");
storage_dev.flush()
.expect("flushing failed");
}

#[test]
fn check_dbg_block_device_aligned_offset_7() {
let mut storage_dev = StorageCachedBlockDevice::new(DbgBlockDevice, 16);
let mut aligned = AlignedBuf { buf: [0x55; 4096] };
let aligned_buf = &mut aligned.buf[0..];
assert_eq!((&aligned_buf[0] as *const u8 as usize) % 2, 0, "buf is not actually saligned");

storage_device::StorageDevice::read(&mut storage_dev, 7, aligned_buf)
.expect("reading failed");

for (index, byte) in aligned_buf.iter().enumerate() {
assert_eq!(*byte, (index + 7) as u8, "failed checking block content. Index: {:02x}, Your buffer:\n{:02x?}", index, &aligned_buf);
}

// writing back should also work
storage_device::StorageDevice::write(&mut storage_dev, 7, aligned_buf)
.expect("writing failed");
storage_dev.flush()
.expect("flushing failed");
}

#[test]
fn check_dbg_block_device_misaligned_offset_7() {
let mut storage_dev = StorageCachedBlockDevice::new(DbgBlockDevice, 16);
let mut aligned_buf = AlignedBuf { buf: [0x55; 4096] };
let misaligned_buf = &mut aligned_buf.buf[1..];
assert_eq!((&misaligned_buf[0] as *const u8 as usize) % 2, 1, "buf is not actually misaligned");

storage_device::StorageDevice::read(&mut storage_dev, 7, misaligned_buf)
.expect("reading failed");

for (index, byte) in misaligned_buf.iter().enumerate() {
assert_eq!(*byte, (index + 7) as u8, "failed checking block content. Index: {:02x}, Your buffer:\n{:02x?}", index, &misaligned_buf);
}

// writing back should also work
storage_device::StorageDevice::write(&mut storage_dev, 7, misaligned_buf)
.expect("writing failed");
storage_dev.flush()
.expect("flushing failed");
}
}