use pf8::{
archive::{create_from_dir, extract},
*,
};
use std::fs;
use std::path::Path;
use tempfile::TempDir;
#[test]
fn test_create_and_read_simple_archive() {
let temp_dir = TempDir::new().unwrap();
let input_dir = temp_dir.path().join("input");
let archive_path = temp_dir.path().join("test.pfs");
let output_dir = temp_dir.path().join("output");
fs::create_dir_all(&input_dir).unwrap();
fs::write(input_dir.join("file1.txt"), b"Hello, World!").unwrap();
fs::write(input_dir.join("file2.bin"), b"\x00\x01\x02\x03").unwrap();
let subdir = input_dir.join("subdir");
fs::create_dir_all(&subdir).unwrap();
fs::write(subdir.join("file3.txt"), b"Nested file content").unwrap();
let mut builder = Pf8Builder::new();
builder.add_dir(&input_dir).unwrap();
builder.write_to_file(&archive_path).unwrap();
assert!(archive_path.exists());
let mut archive = Pf8Archive::open(&archive_path).unwrap();
assert_eq!(archive.len(), 3);
assert!(archive.contains("file1.txt"));
assert!(archive.contains("file2.bin"));
assert!(archive.contains("subdir/file3.txt"));
let content1 = archive.read_file("file1.txt").unwrap();
assert_eq!(content1, b"Hello, World!");
let content2 = archive.read_file("file2.bin").unwrap();
assert_eq!(content2, b"\x00\x01\x02\x03");
let content3 = archive.read_file("subdir/file3.txt").unwrap();
assert_eq!(content3, b"Nested file content");
archive.extract_all(&output_dir).unwrap();
assert_eq!(
fs::read(output_dir.join("file1.txt")).unwrap(),
b"Hello, World!"
);
assert_eq!(
fs::read(output_dir.join("file2.bin")).unwrap(),
b"\x00\x01\x02\x03"
);
assert_eq!(
fs::read(output_dir.join("subdir/file3.txt")).unwrap(),
b"Nested file content"
);
}
#[test]
fn test_convenience_functions() {
let temp_dir = TempDir::new().unwrap();
let input_dir = temp_dir.path().join("input");
let archive_path = temp_dir.path().join("test.pfs");
let output_dir = temp_dir.path().join("output");
fs::create_dir_all(&input_dir).unwrap();
fs::write(input_dir.join("test.txt"), b"Test content").unwrap();
create_from_dir(&input_dir, &archive_path).unwrap();
assert!(archive_path.exists());
extract(&archive_path, &output_dir).unwrap();
assert_eq!(
fs::read(output_dir.join("test.txt")).unwrap(),
b"Test content"
);
}
#[test]
fn test_builder_add_file_as() {
let temp_dir = TempDir::new().unwrap();
let input_file = temp_dir.path().join("input.txt");
let archive_path = temp_dir.path().join("test.pfs");
fs::write(&input_file, b"File content").unwrap();
let mut builder = Pf8Builder::new();
builder
.add_file_as(&input_file, "custom/path/file.txt")
.unwrap();
builder.write_to_file(&archive_path).unwrap();
let mut archive = Pf8Archive::open(&archive_path).unwrap();
assert!(archive.contains("custom/path/file.txt"));
let content = archive.read_file("custom/path/file.txt").unwrap();
assert_eq!(content, b"File content");
}
#[test]
fn test_empty_archive() {
let temp_dir = TempDir::new().unwrap();
let archive_path = temp_dir.path().join("empty.pfs");
let builder = Pf8Builder::new();
let result = builder.write_to_file(&archive_path);
assert!(result.is_err());
}
#[test]
fn test_file_not_found_error() {
let temp_dir = TempDir::new().unwrap();
let nonexistent = temp_dir.path().join("nonexistent.txt");
let mut builder = Pf8Builder::new();
let result = builder.add_file(&nonexistent);
assert!(result.is_err());
}
#[test]
fn test_reader_low_level_api() {
let temp_dir = TempDir::new().unwrap();
let input_dir = temp_dir.path().join("input");
let archive_path = temp_dir.path().join("test.pfs");
fs::create_dir_all(&input_dir).unwrap();
fs::write(input_dir.join("test.txt"), b"Test content").unwrap();
create_from_dir(&input_dir, &archive_path).unwrap();
let mut reader = Pf8Reader::open(&archive_path).unwrap();
assert_eq!(reader.len(), 1);
assert!(!reader.is_empty());
let entry = reader.get_entry("test.txt").unwrap();
assert_eq!(entry.size(), 12);
assert_eq!(entry.file_name().unwrap(), "test.txt");
let content = reader.read_file("test.txt").unwrap();
assert_eq!(content, b"Test content");
}
#[test]
fn test_pack_unpack_integrity() {
let temp_dir = TempDir::new().unwrap();
let original_dir = temp_dir.path().join("original");
let archive_path = temp_dir.path().join("test.pfs");
let extracted_dir = temp_dir.path().join("extracted");
fs::create_dir_all(&original_dir).unwrap();
let readme_content = "This is a readme file\nwith multiple lines\nand UTF-8 content: 你好世界";
fs::write(original_dir.join("readme.txt"), readme_content.as_bytes()).unwrap();
fs::write(
original_dir.join("config.ini"),
b"[section]\nkey=value\nother_key=other_value",
)
.unwrap();
fs::write(
original_dir.join("data.bin"),
[0u8, 1, 2, 3, 255, 254, 253, 128, 127],
)
.unwrap();
fs::write(
original_dir.join("image.jpg"),
b"\xFF\xD8\xFF\xE0\x00\x10JFIF\x00\x01",
)
.unwrap();
fs::write(original_dir.join("empty.txt"), b"").unwrap();
let large_content = "Lorem ipsum dolor sit amet, consectetur adipiscing elit. ".repeat(1000);
fs::write(original_dir.join("large.txt"), large_content.as_bytes()).unwrap();
let nested_dir = original_dir.join("nested").join("deep").join("structure");
fs::create_dir_all(&nested_dir).unwrap();
fs::write(nested_dir.join("nested_file.txt"), b"Deep nested content").unwrap();
fs::write(nested_dir.join("binary.dat"), [42u8; 256]).unwrap();
let special_dir = original_dir.join("special");
fs::create_dir_all(&special_dir).unwrap();
fs::write(
special_dir.join("file with spaces.txt"),
b"Content with spaces",
)
.unwrap();
fs::write(
special_dir.join("file-with-dashes.txt"),
b"Content with dashes",
)
.unwrap();
fs::write(
special_dir.join("file_with_underscores.txt"),
b"Content with underscores",
)
.unwrap();
let mut builder = Pf8Builder::new();
builder.add_dir(&original_dir).unwrap();
builder.write_to_file(&archive_path).unwrap();
assert!(archive_path.exists());
let mut archive = Pf8Archive::open(&archive_path).unwrap();
archive.extract_all(&extracted_dir).unwrap();
fn compare_directories(original: &Path, extracted: &Path) -> Result<()> {
use std::collections::HashSet;
let original_entries: HashSet<_> = fs::read_dir(original)?
.map(|entry| entry.unwrap().file_name())
.collect();
let extracted_entries: HashSet<_> = fs::read_dir(extracted)?
.map(|entry| entry.unwrap().file_name())
.collect();
assert_eq!(original_entries, extracted_entries);
for entry in fs::read_dir(original)? {
let entry = entry?;
let original_path = entry.path();
let extracted_path = extracted.join(entry.file_name());
if original_path.is_file() {
let original_content = fs::read(&original_path)?;
let extracted_content = fs::read(&extracted_path)?;
assert_eq!(
original_content,
extracted_content,
"File content mismatch: {:?}",
entry.file_name()
);
let original_metadata = fs::metadata(&original_path)?;
let extracted_metadata = fs::metadata(&extracted_path)?;
assert_eq!(
original_metadata.len(),
extracted_metadata.len(),
"File size mismatch: {:?}",
entry.file_name()
);
} else if original_path.is_dir() {
compare_directories(&original_path, &extracted_path)?;
}
}
Ok(())
}
compare_directories(&original_dir, &extracted_dir).unwrap();
assert_eq!(archive.len(), 11);
let readme_content = archive.read_file("readme.txt").unwrap();
let expected_readme = "This is a readme file\nwith multiple lines\nand UTF-8 content: 你好世界";
assert_eq!(readme_content, expected_readme.as_bytes());
let binary_content = archive.read_file("data.bin").unwrap();
assert_eq!(binary_content, [0u8, 1, 2, 3, 255, 254, 253, 128, 127]);
let empty_content = archive.read_file("empty.txt").unwrap();
assert_eq!(empty_content, b"");
let nested_content = archive
.read_file("nested/deep/structure/nested_file.txt")
.unwrap();
assert_eq!(nested_content, b"Deep nested content");
}