Add test for loading and storing symlink nodes and fix multiple logic errors

This commit is contained in:
Nathan Fisher 2023-12-15 00:25:08 -05:00
parent e226f1982d
commit 455a2d36f9
2 changed files with 78 additions and 10 deletions

View File

@ -4,7 +4,7 @@ use {
};
#[repr(u8)]
#[derive(Clone, Copy)]
#[derive(Clone, Copy, Debug, PartialEq)]
pub(crate) enum Flag {
Normal = 0,
HardLink = 1,
@ -52,7 +52,15 @@ impl From<&FileType> for Flag {
impl Flag {
pub(crate) fn append_mode(&self, mode: u16) -> u16 {
let mask: u16 = u16::from(*self as u8) << 13;
mode & mask
mode | mask
}
pub(crate) fn extract_from_raw(raw: u16) -> Result<(Self, u16), Error> {
let mask: u16 = 0b111 << 13;
let mode = raw & 0o777;
let flag: u8 = ((raw & mask) >> 13).try_into()?;
let flag: Self = flag.try_into()?;
Ok((flag, mode))
}
}
@ -90,7 +98,7 @@ impl FileType {
let len = u16::from_le_bytes(len);
let mut buf = Vec::with_capacity(len.into());
let mut handle = reader.take(len.into());
handle.read_exact(&mut buf)?;
handle.read_to_end(&mut buf)?;
let s = String::from_utf8(buf)?;
Ok(Self::HardLink(s))
}
@ -100,7 +108,7 @@ impl FileType {
let len = u16::from_le_bytes(len);
let mut buf = Vec::with_capacity(len.into());
let mut handle = reader.take(len.into());
handle.read_exact(&mut buf)?;
handle.read_to_end(&mut buf)?;
let s = String::from_utf8(buf)?;
Ok(Self::SoftLink(s))
}
@ -122,7 +130,7 @@ impl FileType {
match self {
Self::Normal(f) => f.write(writer)?,
Self::HardLink(s) | Self::SoftLink(s) => {
let len = s.len() as u64;
let len = s.len() as u16;
writer.write_all(&len.to_le_bytes())?;
writer.write_all(s.as_bytes())?;
}
@ -132,3 +140,28 @@ impl FileType {
Ok(())
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn manipulate_mode_softlink() {
let mode: u16 = 0o644;
let flag = Flag::SoftLink;
let raw = flag.append_mode(mode);
let (f, m) = Flag::extract_from_raw(raw).unwrap();
assert_eq!(m, mode);
assert_eq!(f, flag);
}
#[test]
fn manipulate_mode_normal() {
let mode: u16 = 0o755;
let flag = Flag::Normal;
let raw = flag.append_mode(mode);
let (f, m) = Flag::extract_from_raw(raw).unwrap();
assert_eq!(m, mode);
assert_eq!(f, flag);
}
}

View File

@ -85,10 +85,7 @@ impl Node {
let mtime: [u8; 8] = buf[8..16].try_into()?;
let raw_mode: [u8; 2] = buf[16..18].try_into()?;
let raw_mode = u16::from_le_bytes(raw_mode);
let mask: u16 = 0b111 << 13;
let mode = raw_mode & mask;
let flag: u8 = ((raw_mode & !mask) >> 13).try_into()?;
let flag: Flag = flag.try_into()?;
let (flag, mode) = Flag::extract_from_raw(raw_mode)?;
let filetype = FileType::read(reader, flag)?;
Ok(Self {
name: String::from_utf8(name)?,
@ -203,12 +200,13 @@ impl Node {
}
}
};
let mode = Flag::from(&filetype).append_mode(u16::try_from(mode & 0o7777)?);
Ok(Self {
name,
uid,
gid,
mtime,
mode: (mode & !(0o111 << 13)).try_into()?,
mode,
filetype,
})
}
@ -405,12 +403,22 @@ mod tests {
let mut writer = std::io::BufWriter::new(fd);
let links = Mutex::new(HashMap::new());
let node = Node::from_path("test/li.txt", Algorithm::Sha1, &links).unwrap();
let FileType::Normal(_) = node.filetype else {
eprintln!("Created wrong filetype: {:?}", node.filetype);
panic!();
};
node.write(&mut writer).unwrap();
}
let meta = fs::metadata("test/li.txt").unwrap();
let fd = std::fs::File::open("test/li.node").unwrap();
let mut reader = BufReader::new(fd);
let node = Node::read(&mut reader).unwrap();
assert_eq!(meta.mode() & 0o777, node.mode as u32);
assert_eq!(meta.uid(), node.uid);
assert_eq!(meta.gid(), node.gid);
assert_eq!(meta.mtime(), node.mtime as i64);
let FileType::Normal(f) = node.filetype else {
eprintln!("Read incorrect filetype: {:?}", node.filetype);
panic!()
};
let Checksum::Sha1(sum) = f.checksum else {
@ -424,6 +432,33 @@ mod tests {
assert_eq!(LI, f.data);
}
#[test]
fn load_store_symlink() {
{
let _res = remove_file("test/lilnk.txt");
symlink("li.txt", "test/lilnk.txt").unwrap();
let _res = remove_file("test/lilnk.node");
let fd = std::fs::File::create("test/lilnk.node").unwrap();
let mut writer = std::io::BufWriter::new(fd);
let links = Mutex::new(HashMap::new());
let node = Node::from_path("test/lilnk.txt", Algorithm::Sha1, &links).unwrap();
let FileType::SoftLink(ref tgt) = node.filetype else {
eprintln!("Created wrong filetype: {:?}", node.filetype);
panic!();
};
assert_eq!(tgt, "li.txt");
node.write(&mut writer).unwrap();
}
let fd = std::fs::File::open("test/lilnk.node").unwrap();
let mut reader = BufReader::new(fd);
let node = Node::read(&mut reader).unwrap();
let FileType::SoftLink(ref tgt) = node.filetype else {
eprintln!("Read incorrect filetype: {:?}", node.filetype);
panic!();
};
assert_eq!(tgt, "li.txt");
}
#[test]
fn extract_file() {
let links = Mutex::new(HashMap::new());