use libarchive2::{ArchiveFormat, ReadArchive, WriteArchive};
use std::fs;
use std::path::PathBuf;
use tempfile::TempDir;
#[test]
fn test_open_filenames_empty_list() {
let paths: Vec<PathBuf> = vec![];
let result = ReadArchive::open_filenames(&paths);
assert!(result.is_err());
if let Err(e) = result {
assert!(e.to_string().contains("At least one file path"));
}
}
#[test]
fn test_open_filenames_nonexistent_files() {
let paths = vec!["nonexistent1.rar", "nonexistent2.rar"];
let result = ReadArchive::open_filenames(&paths);
assert!(result.is_err());
}
#[test]
fn test_open_filenames_single_file() {
let temp_dir = TempDir::new().unwrap();
let file_path = temp_dir.path().join("single.txt");
fs::write(&file_path, b"test content").unwrap();
let paths = vec![file_path];
let result = ReadArchive::open_filenames(&paths);
assert!(result.is_err());
}
#[test]
fn test_open_filenames_path_with_nul_byte() {
let paths = vec!["test\0.rar"];
let result = ReadArchive::open_filenames(&paths);
assert!(result.is_err());
if let Err(e) = result {
assert!(e.to_string().contains("null byte"));
}
}
#[test]
fn test_open_filenames_api_accepts_valid_paths() {
let temp_dir = TempDir::new().unwrap();
let file1 = temp_dir.path().join("archive.part1");
let file2 = temp_dir.path().join("archive.part2");
fs::write(&file1, b"dummy").unwrap();
fs::write(&file2, b"dummy").unwrap();
let paths = vec![file1, file2];
let result = ReadArchive::open_filenames(&paths);
assert!(result.is_err());
}
#[test]
fn test_open_filenames_with_string_slices() {
let temp_dir = TempDir::new().unwrap();
let file1 = temp_dir.path().join("test1.dat");
let file2 = temp_dir.path().join("test2.dat");
fs::write(&file1, b"dummy").unwrap();
fs::write(&file2, b"dummy").unwrap();
let paths = vec![file1.to_str().unwrap(), file2.to_str().unwrap()];
let result = ReadArchive::open_filenames(&paths);
assert!(result.is_err());
}
#[test]
fn test_open_filenames_ordering() {
let temp_dir = TempDir::new().unwrap();
let paths: Vec<_> = (1..=3)
.map(|i| {
let path = temp_dir.path().join(format!("part{}.dat", i));
fs::write(&path, format!("data{}", i).as_bytes()).unwrap();
path
})
.collect();
let result = ReadArchive::open_filenames(&paths);
assert!(result.is_err());
let mut reversed_paths = paths.clone();
reversed_paths.reverse();
let result2 = ReadArchive::open_filenames(&reversed_paths);
assert!(result2.is_err());
}
#[test]
fn test_open_filenames_mixed_path_types() {
use std::path::Path;
let temp_dir = TempDir::new().unwrap();
let file1 = temp_dir.path().join("file1.dat");
let file2 = temp_dir.path().join("file2.dat");
fs::write(&file1, b"test1").unwrap();
fs::write(&file2, b"test2").unwrap();
let path_ref: &Path = file1.as_path();
let pathbuf = file2.clone();
let paths = vec![path_ref, pathbuf.as_path()];
let result = ReadArchive::open_filenames(&paths);
assert!(result.is_err()); }
#[test]
fn test_open_filenames_unicode_paths() {
let temp_dir = TempDir::new().unwrap();
let file = temp_dir.path().join("αρχείο.dat");
fs::write(&file, b"test").unwrap();
let paths = vec![file];
let result = ReadArchive::open_filenames(&paths);
assert!(result.is_err()); }
#[test]
fn test_open_filenames_relative_paths() {
let paths = vec!["./file1.rar", "./file2.rar"];
let result = ReadArchive::open_filenames(&paths);
assert!(result.is_err());
}
#[test]
fn test_open_filenames_absolute_paths() {
let temp_dir = TempDir::new().unwrap();
let file1 = temp_dir.path().join("abs1.dat");
let file2 = temp_dir.path().join("abs2.dat");
fs::write(&file1, b"data1").unwrap();
fs::write(&file2, b"data2").unwrap();
let paths = vec![file1.canonicalize().unwrap(), file2.canonicalize().unwrap()];
let result = ReadArchive::open_filenames(&paths);
assert!(result.is_err()); }
#[test]
fn test_simulated_multivolume_with_separate_archives() {
let temp_dir = TempDir::new().unwrap();
let files = vec![
("archive1.tar", "file1.txt", b"Content of file 1"),
("archive2.tar", "file2.txt", b"Content of file 2"),
("archive3.tar", "file3.txt", b"Content of file 3"),
];
let mut archive_paths = Vec::new();
for (archive_name, file_name, content) in &files {
let archive_path = temp_dir.path().join(archive_name);
let mut archive = WriteArchive::new()
.format(ArchiveFormat::TarPax)
.open_file(&archive_path)
.unwrap();
archive.add_file(file_name, *content).unwrap();
archive.finish().unwrap();
archive_paths.push(archive_path);
}
let result = ReadArchive::open(&archive_paths[0]);
assert!(result.is_ok());
let mut archive = result.unwrap();
if let Some(entry) = archive.next_entry().unwrap() {
assert_eq!(entry.pathname().unwrap(), "file1.txt");
let data = archive.read_data_to_vec().unwrap();
assert_eq!(&data, b"Content of file 1");
}
let result = ReadArchive::open_filenames(&archive_paths);
match result {
Ok(mut archive) => {
if let Some(entry) = archive.next_entry().unwrap() {
let pathname = entry.pathname().unwrap_or_default().to_string();
assert!(!pathname.is_empty());
}
}
Err(_) => {
}
}
}
#[test]
fn test_multivolume_api_with_concatenated_archives() {
let temp_dir = TempDir::new().unwrap();
let part1_path = temp_dir.path().join("concat.part1");
let mut archive1 = WriteArchive::new()
.format(ArchiveFormat::TarPax)
.open_file(&part1_path)
.unwrap();
archive1
.add_file("part1_file.txt", b"Data from part 1")
.unwrap();
archive1.finish().unwrap();
let part2_path = temp_dir.path().join("concat.part2");
let mut archive2 = WriteArchive::new()
.format(ArchiveFormat::TarPax)
.open_file(&part2_path)
.unwrap();
archive2
.add_file("part2_file.txt", b"Data from part 2")
.unwrap();
archive2.finish().unwrap();
let paths = vec![&part1_path, &part2_path];
let result = ReadArchive::open_filenames(&paths);
match result {
Ok(mut archive) => {
let mut entry_count = 0;
while let Some(_entry) = archive.next_entry().unwrap() {
entry_count += 1;
let _data = archive.read_data_to_vec().unwrap();
}
assert!(
entry_count >= 1,
"Should read at least one entry from multi-volume API"
);
}
Err(e) => {
let error_msg = e.to_string();
assert!(!error_msg.is_empty(), "Error message should not be empty");
}
}
}
#[test]
fn test_multivolume_path_validation_with_real_files() {
let temp_dir = TempDir::new().unwrap();
let part1 = temp_dir.path().join("test.part1.tar");
let part2 = temp_dir.path().join("test.part2.tar");
let part3 = temp_dir.path().join("test.part3.tar");
for path in [&part1, &part2, &part3] {
let mut archive = WriteArchive::new()
.format(ArchiveFormat::TarPax)
.open_file(path)
.unwrap();
let filename = format!("file_in_{}", path.file_name().unwrap().to_str().unwrap());
archive.add_file(&filename, b"test data").unwrap();
archive.finish().unwrap();
}
assert!(part1.exists());
assert!(part2.exists());
assert!(part3.exists());
let paths_correct = vec![&part1, &part2, &part3];
let result = ReadArchive::open_filenames(&paths_correct);
match result {
Ok(mut archive) => {
if let Some(entry) = archive.next_entry().unwrap() {
let pathname = entry.pathname().unwrap_or_default();
assert!(!pathname.is_empty());
}
}
Err(_) => {
}
}
let paths_wrong = vec![&part3, &part1, &part2];
let result2 = ReadArchive::open_filenames(&paths_wrong);
let _ = result2;
let paths_dup = vec![&part1, &part1, &part2];
let result3 = ReadArchive::open_filenames(&paths_dup);
let _ = result3;
}
#[test]
fn test_open_filenames_with_passphrase_empty_list() {
let paths: Vec<PathBuf> = vec![];
let result = ReadArchive::open_filenames_with_passphrase(&paths, "password");
assert!(result.is_err());
if let Err(e) = result {
assert!(e.to_string().contains("At least one file path"));
}
}
#[test]
fn test_open_filenames_with_passphrase_nonexistent_files() {
let paths = vec!["nonexistent1.rar", "nonexistent2.rar"];
let result = ReadArchive::open_filenames_with_passphrase(&paths, "password");
assert!(result.is_err());
}
#[test]
fn test_open_filenames_with_passphrase_null_in_password() {
let temp_dir = TempDir::new().unwrap();
let file1 = temp_dir.path().join("test1.dat");
let file2 = temp_dir.path().join("test2.dat");
fs::write(&file1, b"dummy").unwrap();
fs::write(&file2, b"dummy").unwrap();
let paths = vec![&file1, &file2];
let result = ReadArchive::open_filenames_with_passphrase(&paths, "pass\0word");
assert!(result.is_err());
if let Err(e) = result {
assert!(e.to_string().contains("null byte"));
}
}
#[test]
fn test_open_filenames_with_passphrase_api() {
let temp_dir = TempDir::new().unwrap();
let file1 = temp_dir.path().join("encrypted.part1");
let file2 = temp_dir.path().join("encrypted.part2");
fs::write(&file1, b"dummy").unwrap();
fs::write(&file2, b"dummy").unwrap();
let paths = vec![&file1, &file2];
let result = ReadArchive::open_filenames_with_passphrase(&paths, "my_password");
assert!(result.is_err());
let paths_str = vec![file1.to_str().unwrap(), file2.to_str().unwrap()];
let result2 = ReadArchive::open_filenames_with_passphrase(&paths_str, "my_password");
assert!(result2.is_err());
let paths_owned = vec![file1.clone(), file2.clone()];
let result3 = ReadArchive::open_filenames_with_passphrase(&paths_owned, "my_password");
assert!(result3.is_err()); }