use embedded_sdmmc::{Mode, VolumeIdx};
use relative_path::RelativePathBuf;
use crate::{FileSystem, device::Device};
#[test]
fn device_can_open() {
let cases = vec![Device::MIN_SIZE, 4 * 1024 * 1024, Device::MAX_SIZE];
for c in cases {
let dev = Device::new(c).unwrap();
let mut mgr = dev.clone().open();
let mut vol = mgr.open_volume(VolumeIdx(0)).unwrap();
let mut root = vol.open_root_dir().unwrap();
root.make_dir_in_dir("var").unwrap();
let mut var = root.open_dir("var").unwrap();
var.make_dir_in_dir("lib").unwrap();
let mut lib = var.open_dir("lib").unwrap();
let mut foo = lib
.open_file_in_dir("foo.txt", Mode::ReadWriteCreateOrAppend)
.unwrap();
foo.write(b"bar").unwrap();
foo.close().unwrap();
lib.close().unwrap();
var.close().unwrap();
root.close().unwrap();
let bytes = dev.try_to_bytes().unwrap();
let dev = Device::try_from_bytes(&bytes).unwrap();
let mut mgr = dev.open();
let mut vol = mgr.open_volume(VolumeIdx(0)).unwrap();
let mut root = vol.open_root_dir().unwrap();
let mut var = root.open_dir("var").unwrap();
let mut lib = var.open_dir("lib").unwrap();
let mut foo = lib.open_file_in_dir("foo.txt", Mode::ReadOnly).unwrap();
let mut len = foo.length() as usize;
assert_eq!(len, 3);
let mut buffer = vec![0u8; len];
let mut read = 0;
while len > 0 {
let n = foo.read(&mut buffer[read..]).unwrap();
read += n;
len -= n;
}
assert_eq!(&buffer, b"bar");
}
}
fn create_test_fs(contents: &[(Option<&[&str]>, &str, Option<&[u8]>)]) -> FileSystem {
let c = 4 * 1024 * 1024;
let dev = Device::new(c).unwrap();
let mut mgr = dev.clone().open();
let mut vol = mgr.open_volume(VolumeIdx(0)).unwrap();
for (path, name, contents) in contents {
let mut root = vol.open_root_dir().unwrap();
if let Some(p) = path {
for n in *p {
root.change_dir(*n).unwrap();
}
}
match contents {
Some(c) => root
.open_file_in_dir(*name, Mode::ReadWriteCreateOrAppend)
.unwrap()
.write(c)
.unwrap(),
None => root.make_dir_in_dir(*name).unwrap(),
}
root.close().unwrap();
}
FileSystem::from(dev)
}
#[test]
fn cd_works() -> anyhow::Result<()> {
let mut fs = create_test_fs(&[
(None, "var", None),
(Some(&["var"]), "lib", None),
(Some(&["var", "lib"]), "foo.bar", Some(b"baz")),
]);
let cases = vec![
("/", "/"),
(".", "/"),
("..", "/"),
("/var", "/VAR"),
("..", "/"),
("/var/lib", "/VAR/LIB"),
("..", "/VAR"),
("..", "/"),
("/var/lib", "/VAR/LIB"),
("../..", "/"),
("/var/lib", "/VAR/LIB"),
("./../..", "/"),
("/var/lib", "/VAR/LIB"),
("../../", "/"),
("/var/lib", "/VAR/LIB"),
("./../../", "/"),
("/var", "/VAR"),
("./", "/VAR"),
("./lib", "/VAR/LIB"),
("/", "/"),
("/var/lib", "/VAR/LIB"),
];
for (cd, p) in cases {
fs.cd(cd)?;
assert_eq!(fs.cwd(), RelativePathBuf::from(p));
}
assert!(fs.cd("foo.bar").is_err());
Ok(())
}
#[test]
fn ls_works() -> anyhow::Result<()> {
let fs = create_test_fs(&[
(None, "var", None),
(Some(&["var"]), "lib", None),
(Some(&["var"]), "share", None),
(Some(&["var", "lib"]), "x", None),
(Some(&["var", "lib"]), "foo.bin", Some(b"contents")),
(Some(&["var", "lib"]), "bar.bin", Some(b"contents")),
]);
let cases: Vec<(&str, &[&str])> = vec![
("/", &["VAR"]),
("/var", &["LIB"]),
("/var/lib", &["X", "BAR.BIN", "FOO.BIN"]),
("/var/lib/x", &[]),
];
for (l, d) in cases {
let c = fs.ls(l)?;
for i in 0..d.len() {
assert_eq!(c[i].path().as_str(), d[i]);
}
}
Ok(())
}
#[test]
fn rm_works() -> anyhow::Result<()> {
let mut fs = create_test_fs(&[
(None, "var", None),
(Some(&["var"]), "lib", None),
(Some(&["var"]), "share", None),
(Some(&["var", "lib"]), "x", None),
(Some(&["var", "lib"]), "foo.bin", Some(b"contents")),
(Some(&["var", "lib"]), "bar.bin", Some(b"contents")),
]);
let cases = vec![
("/", "/", false),
("/var/lib", "foo.bin", true),
("/var/lib", "foo.bin", false),
(".", "../lib/bar.bin", true),
(".", "../lib/bar.bin", false),
];
for (cd, p, ok) in cases {
fs.cd(cd)?;
let ret = fs.rm(p);
assert_eq!(ret.is_ok(), ok, "unexpected result: {ret:?}");
}
Ok(())
}
#[test]
fn open_save_works() -> anyhow::Result<()> {
let mut fs = create_test_fs(&[]);
let data = b"foo";
fs.mkdir("/var/share/baz")?;
fs.open("/var/share/data.bin")?
.update(|b| b.extend(data))
.save(&mut fs)?;
fs.open("/var/share/bar.bin")?
.update(|b| b.extend(data))
.save(&mut fs)?;
assert_eq!(fs.open("/var/share/data.bin")?.contents, data);
let contents = fs.ls("/var/share")?;
assert_eq!(contents.len(), 3);
assert_eq!(contents[0].path(), RelativePathBuf::from("BAZ"));
assert_eq!(contents[1].path(), RelativePathBuf::from("BAR.BIN"));
assert_eq!(contents[2].path(), RelativePathBuf::from("DATA.BIN"));
fs.cd("/var")?;
let contents = fs.ls("share")?;
assert_eq!(contents.len(), 3);
assert_eq!(contents[0].path(), RelativePathBuf::from("BAZ"));
assert_eq!(contents[1].path(), RelativePathBuf::from("BAR.BIN"));
assert_eq!(contents[2].path(), RelativePathBuf::from("DATA.BIN"));
fs.cd("share")?;
let contents = fs.ls(".")?;
assert_eq!(contents.len(), 3);
assert_eq!(contents[0].path(), RelativePathBuf::from("BAZ"));
assert_eq!(contents[1].path(), RelativePathBuf::from("BAR.BIN"));
assert_eq!(contents[2].path(), RelativePathBuf::from("DATA.BIN"));
Ok(())
}