Add migration testing utils

This commit is contained in:
Sosthène Guédon
2024-03-07 14:37:34 +01:00
parent c9519175e0
commit 97e5557bbf
3 changed files with 135 additions and 0 deletions
+1
View File
@@ -29,6 +29,7 @@ wrap-key-to-file = ["chacha20poly1305"]
chunked = []
encrypted-chunked = ["chunked", "chacha20poly1305/stream"]
manage = []
migration-tests = ["manage"]
virt = ["std", "trussed/virt"]
std = []
+3
View File
@@ -15,6 +15,9 @@ use trussed::{
Error,
};
#[cfg(feature = "migration-tests")]
pub mod test_utils;
#[derive(Debug)]
pub struct Migrator {
/// The function performing the migration
+131
View File
@@ -0,0 +1,131 @@
// Copyright (C) Nitrokey GmbH
// SPDX-License-Identifier: Apache-2.0 or MIT
use littlefs2::{
fs::Filesystem, io::Error, object_safe::DynFilesystem, path, path::Path, ram_storage,
};
/// Represent a directory of data
pub enum FsValues {
Dir(&'static [(&'static Path, FsValues)]),
File(usize),
}
type Result<T, E = Error> = core::result::Result<T, E>;
/// Prepare the filesystem for a given tests values
pub fn prepare_fs(fs: &dyn DynFilesystem, value: &FsValues, path: &Path) {
match value {
FsValues::File(f_data_len) => {
fs.create_file_and_then(path, &mut |f| {
f.set_len(*f_data_len).unwrap();
Ok(())
})
.unwrap();
}
FsValues::Dir(d) => {
if path != path!("/") {
fs.create_dir(path).unwrap();
}
for (p, v) in *d {
prepare_fs(fs, v, &path.join(p));
}
}
}
}
/// Test equality between the filesystem and the expected values
pub fn test_fs_equality(fs: &dyn DynFilesystem, value: &FsValues, path: &Path) {
match value {
FsValues::Dir(d) => {
let mut expected_iter = d.iter();
fs.read_dir_and_then(path, &mut |dir| {
// skip . and ..
dir.next().unwrap().unwrap();
dir.next().unwrap().unwrap();
for (expected_path, expected_values) in expected_iter.by_ref() {
let entry = dir.next().unwrap().unwrap();
assert_eq!(entry.file_name(), *expected_path);
test_fs_equality(fs, expected_values, &path.join(expected_path));
}
assert!(dir.next().is_none());
Ok(())
})
.unwrap();
}
FsValues::File(f_data_len) => {
fs.open_file_and_then(path, &mut |f| {
let mut buf = [0; 512];
let data = f.read(&mut buf).unwrap();
assert_eq!(data, *f_data_len);
Ok(())
})
.unwrap();
}
}
}
ram_storage!(
name=NoBackendStorage,
backend=RamDirect,
trait=littlefs2::driver::Storage,
erase_value=0xff,
read_size=16,
write_size=16,
cache_size_ty=littlefs2::consts::U512,
block_size=512,
block_count=128,
lookahead_size_ty=littlefs2::consts::U8,
filename_max_plus_one_ty=littlefs2::consts::U256,
path_max_plus_one_ty=littlefs2::consts::U256,
result=Result,
);
pub fn test_migration_one(
before: &FsValues,
after: &FsValues,
migrate: impl Fn(&dyn DynFilesystem) -> Result<(), Error>,
) {
test_migration(
before,
after,
&FsValues::Dir(&[]),
&FsValues::Dir(&[]),
|ifs, _efs| migrate(ifs),
);
}
pub fn test_migration(
before_ifs: &FsValues,
after_ifs: &FsValues,
before_efs: &FsValues,
after_efs: &FsValues,
migrate: impl Fn(&dyn DynFilesystem, &dyn DynFilesystem) -> Result<(), Error>,
) {
let mut storage_ifs = RamDirect::default();
let mut storage_efs = RamDirect::default();
let backend_efs = &mut NoBackendStorage::new(&mut storage_efs);
let backend_ifs = &mut NoBackendStorage::new(&mut storage_ifs);
Filesystem::format(backend_ifs).unwrap();
Filesystem::format(backend_efs).unwrap();
Filesystem::mount_and_then(backend_ifs, |ifs| {
Filesystem::mount_and_then(backend_efs, |efs| {
prepare_fs(ifs, before_ifs, path!("/"));
prepare_fs(efs, before_efs, path!("/"));
test_fs_equality(ifs, before_ifs, path!("/"));
test_fs_equality(efs, before_efs, path!("/"));
migrate(ifs, efs).unwrap();
test_fs_equality(efs, after_efs, path!("/"));
test_fs_equality(ifs, after_ifs, path!("/"));
Ok(())
})
.unwrap();
Ok(())
})
.unwrap();
}