use rustar::{oct2bin, extract_file, TarIter};
#[cfg(test)]
#[cfg(test)]
mod tests {
use super::*;
fn make_tar(filename: &str, contents: &[u8]) -> Vec<u8> {
let mut header = [0u8; 512];
let name_bytes = filename.as_bytes();
header[..name_bytes.len()].copy_from_slice(name_bytes);
let size_str = format!("{:o}", contents.len());
let size_bytes = size_str.as_bytes();
header[0x7c..0x7c + size_bytes.len()].copy_from_slice(size_bytes);
header[257..257 + 5].copy_from_slice(b"ustar");
for i in 148..156 {
header[i] = b' ';
}
let chksum: u32 = header.iter().map(|&b| b as u32).sum();
let chksum_str = format!("{:06o}\0 ", chksum);
header[148..148 + chksum_str.len()].copy_from_slice(chksum_str.as_bytes());
let mut archive = Vec::new();
archive.extend_from_slice(&header);
archive.extend_from_slice(contents);
let padding = (512 - (contents.len() % 512)) % 512;
archive.extend(core::iter::repeat(0).take(padding));
archive.extend([0u8; 1024]);
archive
}
#[test]
fn test_oct2bin() {
assert_eq!(oct2bin(b"10"), 8);
assert_eq!(oct2bin(b"7"), 7);
assert_eq!(oct2bin(b"00010"), 8); assert_eq!(oct2bin(b""), 0); }
#[test]
fn test_extract_file_from_sample() {
let archive: &[u8] = include_bytes!("./sample.tar");
let file = extract_file(archive, "hello.txt")
.expect("file not found");
assert_eq!(file, b"Hello World!\n");
}
#[test]
fn test_extract_file_from_generated() {
let tar = make_tar("liz.txt", b"hello owo\n");
let file = extract_file(&tar, "liz.txt")
.expect("file not found in generated tar");
assert_eq!(file, b"hello owo\n");
}
#[test]
fn test_extract_missing_file() {
let tar = make_tar("only.txt", b"data");
assert!(extract_file(&tar, "missing.txt\0").is_none());
}
#[test]
fn test_extract_empty_file() {
let tar = make_tar("in the grim darkness of the future.txt", b"");
let file = extract_file(&tar, "in the grim darkness of the future.txt")
.expect("empty file not found");
assert!(file.is_empty());
}
#[test]
fn test_iter_multiple_files() {
let mut tar1 = make_tar("puppyboy.txt", b"OwO\n");
let mut tar2 = make_tar("puppygirl.txt", b"^W^\n");
tar1.truncate(tar1.len() - 1024);
tar1.append(&mut tar2);
let files: Vec<_> = TarIter::new(&tar1)
.map(|hdr| {
let raw: &[u8] = hdr.name.as_bytes(); let trimmed = raw.split(|&b| b == 0) .next()
.unwrap();
String::from_utf8_lossy(trimmed).to_string()
})
.collect();
assert!(files.contains(&"puppyboy.txt".to_string()));
assert!(files.contains(&"puppygirl.txt".to_string()));
}
}