use rust_tree::rust_tree::fromfile::{parse_file_listing, read_file_listing};
use std::io::Write;
use tempfile::NamedTempFile;
fn create_temp_file(content: &str) -> NamedTempFile {
let mut temp_file = NamedTempFile::new().unwrap();
temp_file.write_all(content.as_bytes()).unwrap();
temp_file.flush().unwrap();
temp_file
}
#[test]
fn test_tar_format_detection_and_parsing() {
let tar_content = r#"drwxr-xr-x user/group 0 2023-01-01 12:00 src
-rw-r--r-- user/group 123 2023-01-01 12:00 src/main.rs"#;
let lines: Vec<String> = tar_content.lines().map(|s| s.to_string()).collect();
let entries = parse_file_listing(lines);
if entries.is_empty() {
let simple_lines = vec!["src/main.rs".to_string()];
let simple_entries = parse_file_listing(simple_lines);
assert!(!simple_entries.is_empty());
} else {
let has_main_file = entries.iter().any(|e| e.path == "src/main.rs");
assert!(has_main_file);
}
}
#[test]
fn test_tar_simple_format() {
let tar_content = r#"src/
src/main.rs
README.md
tests/
tests/test.rs"#;
let lines: Vec<String> = tar_content.lines().map(|s| s.to_string()).collect();
let entries = parse_file_listing(lines);
assert!(!entries.is_empty());
let has_src = entries.iter().any(|e| e.path.starts_with("src"));
let has_tests = entries.iter().any(|e| e.path.starts_with("tests"));
assert!(has_src);
assert!(has_tests);
}
#[test]
fn test_zip_format_detection_and_parsing() {
let zip_content = r#"Archive: test.zip
src/main.rs
README.md"#;
let lines: Vec<String> = zip_content.lines().map(|s| s.to_string()).collect();
let entries = parse_file_listing(lines);
if entries.is_empty() {
let simple_lines = vec!["src/main.rs".to_string(), "README.md".to_string()];
let simple_entries = parse_file_listing(simple_lines);
assert!(!simple_entries.is_empty());
} else {
let has_entries = entries
.iter()
.any(|e| e.path.contains("main.rs") || e.path.contains("README"));
assert!(has_entries);
}
}
#[test]
fn test_7zip_format_detection_and_parsing() {
let sevenz_content = r#"7-Zip [64] 16.02 : Copyright (c) 1999-2016 Igor Pavlov : 2016-05-21
Listing archive: test.7z
Date Time Attr Size Compressed Name
------------------- ----- ------------ ------------ ------------------------
2023-01-01 12:00:00 D.... 0 0 src
2023-01-01 12:00:00 ....A 123 65 src\main.rs
2023-01-01 12:00:00 ....A 4567 2345 README.md
2023-01-01 12:00:00 D.... 0 0 tests
2023-01-01 12:00:00 ....A 890 456 tests\test.rs
------------------- ----- ------------ ------------ ------------------------
5580 2866 5 files, 2 folders"#;
let lines: Vec<String> = sevenz_content.lines().map(|s| s.to_string()).collect();
let entries = parse_file_listing(lines);
assert!(!entries.is_empty());
let has_normalized_main = entries.iter().any(|e| e.path == "src/main.rs");
let has_normalized_test = entries.iter().any(|e| e.path == "tests/test.rs");
assert!(has_normalized_main);
assert!(has_normalized_test);
}
#[test]
fn test_rar_format_detection_and_parsing() {
let rar_content = r#"RAR 5.40 Copyright (c) 1993-2016 Alexander Roshal 11 Aug 2016
Archive test.rar
Attributes Size Date Time Name
----------- --------- -------- ------ ----
drwxr-xr-x 0 01-01-23 12:00 src
-rw-r--r-- 123 01-01-23 12:00 src\main.rs
-rw-r--r-- 4567 01-01-23 12:00 README.md
drwxr-xr-x 0 01-01-23 12:00 tests
-rw-r--r-- 890 01-01-23 12:00 tests\test.rs
----------- --------- -------- ------ ----
5580 5"#;
let lines: Vec<String> = rar_content.lines().map(|s| s.to_string()).collect();
let entries = parse_file_listing(lines);
assert!(!entries.is_empty());
let has_src_dir = entries.iter().any(|e| e.path == "src" && e.is_dir);
let has_normalized_main = entries.iter().any(|e| e.path == "src/main.rs");
assert!(has_src_dir);
assert!(has_normalized_main);
}
#[test]
fn test_simple_format_fallback() {
let simple_content = r#"src/main.rs
src/lib.rs
tests/test.rs
README.md
Cargo.toml"#;
let lines: Vec<String> = simple_content.lines().map(|s| s.to_string()).collect();
let entries = parse_file_listing(lines);
assert!(!entries.is_empty());
let has_src = entries.iter().any(|e| e.path == "src" && e.is_dir);
let has_tests = entries.iter().any(|e| e.path == "tests" && e.is_dir);
let has_main = entries.iter().any(|e| e.path == "src/main.rs" && !e.is_dir);
assert!(has_src);
assert!(has_tests);
assert!(has_main);
}
#[test]
fn test_path_normalization_windows_to_unix() {
let windows_paths = vec![
"src\\main.rs".to_string(),
"tests\\integration\\test.rs".to_string(),
"C:\\Users\\test\\file.txt".to_string(),
"D:\\project\\src\\lib.rs".to_string(),
];
let entries = parse_file_listing(windows_paths);
for entry in &entries {
assert!(!entry.path.contains('\\'));
if entry.path.len() >= 2 && entry.path.chars().nth(1) == Some(':') {
assert!(
!entry.path.contains(':')
|| entry.path.starts_with("C/")
|| entry.path.starts_with("D/")
);
}
}
let has_normalized_main = entries.iter().any(|e| e.path == "src/main.rs");
let has_normalized_integration = entries
.iter()
.any(|e| e.path == "tests/integration/test.rs");
assert!(has_normalized_main);
assert!(has_normalized_integration);
}
#[test]
fn test_empty_input_handling() {
let empty_lines: Vec<String> = vec![];
let entries = parse_file_listing(empty_lines);
assert!(entries.is_empty());
let whitespace_lines = vec![" ".to_string(), "\t".to_string(), "".to_string()];
let entries = parse_file_listing(whitespace_lines);
assert!(entries.len() < 10); }
#[test]
fn test_malformed_input_handling() {
let malformed_tar = vec![
"drwx".to_string(), "not-a-permission-line".to_string(),
"drwxr-xr-x user/group".to_string(), ];
let entries = parse_file_listing(malformed_tar);
assert!(entries.len() <= 10); }
#[test]
fn test_mixed_format_detection() {
let mixed_content = vec![
"Archive: test.zip".to_string(), "drwxr-xr-x user/group 0 2023-01-01 src/".to_string(), "src/main.rs".to_string(), ];
let entries = parse_file_listing(mixed_content);
assert!(!entries.is_empty());
}
#[test]
fn test_large_file_sizes() {
let large_size_content = vec![
"drwxr-xr-x user/group 0 2023-01-01 12:00 src/".to_string(),
"drwxr-xr-x user/group 1234567890 2023-01-01 12:00 src/large.bin".to_string(),
"drwxr-xr-x user/group 9876543210123 2023-01-01 12:00 src/huge.dat".to_string(),
];
let entries = parse_file_listing(large_size_content);
let large_file = entries.iter().find(|e| e.path == "src/large.bin");
let huge_file = entries.iter().find(|e| e.path == "src/huge.dat");
if let Some(large) = large_file {
assert!(large.size.is_some());
}
if let Some(huge) = huge_file {
assert!(huge.size.is_some());
}
}
#[test]
fn test_special_characters_in_paths() {
let special_paths = vec![
"src/file with spaces.rs".to_string(),
"tests/file-with-dashes.rs".to_string(),
"data/file_with_underscores.txt".to_string(),
"config/file.with.dots.conf".to_string(),
"unicode/файл.txt".to_string(),
];
let entries = parse_file_listing(special_paths);
assert!(!entries.is_empty());
assert!(entries.iter().any(|e| e.path.contains(" ")));
assert!(entries.iter().any(|e| e.path.contains("-")));
assert!(entries.iter().any(|e| e.path.contains("_")));
assert!(entries.iter().any(|e| e.path.contains(".")));
}
#[test]
fn test_read_file_listing_from_temp_file() {
let content = "src/main.rs\ntests/test.rs\nREADME.md";
let temp_file = create_temp_file(content);
let lines = read_file_listing(temp_file.path()).unwrap();
assert_eq!(lines.len(), 3);
assert!(lines.contains(&"src/main.rs".to_string()));
assert!(lines.contains(&"tests/test.rs".to_string()));
assert!(lines.contains(&"README.md".to_string()));
}
#[test]
fn test_read_file_listing_empty_lines() {
let content = "src/main.rs\n\n \ntests/test.rs\n\t\nREADME.md\n";
let temp_file = create_temp_file(content);
let lines = read_file_listing(temp_file.path()).unwrap();
assert_eq!(lines.len(), 3);
assert!(lines.iter().all(|line| !line.trim().is_empty()));
}
#[test]
fn test_file_entry_directory_inference() {
let paths = vec![
"src/nested/deep/file.rs".to_string(),
"tests/integration/http/client.rs".to_string(),
];
let entries = parse_file_listing(paths);
let has_src = entries.iter().any(|e| e.path == "src" && e.is_dir);
let has_nested = entries.iter().any(|e| e.path == "src/nested" && e.is_dir);
let has_deep = entries
.iter()
.any(|e| e.path == "src/nested/deep" && e.is_dir);
let has_integration = entries
.iter()
.any(|e| e.path == "tests/integration" && e.is_dir);
let has_http = entries
.iter()
.any(|e| e.path == "tests/integration/http" && e.is_dir);
assert!(has_src);
assert!(has_nested);
assert!(has_deep);
assert!(has_integration);
assert!(has_http);
}
#[test]
fn test_windows_paths_with_spaces_not_detected_as_zip() {
let windows_paths = vec![
r"C:\Windows\Temp\dir dir dir\directory directory".to_string(),
r"D:\Program Files\My App\data files\config.txt".to_string(),
r"E:\Users\John Doe\Documents\My Documents\file.txt".to_string(),
];
let entries = parse_file_listing(windows_paths);
assert!(!entries.is_empty());
assert!(entries.iter().any(|e| e.path.contains("dir dir dir")));
assert!(entries.iter().any(|e| e.path.contains("Program Files")));
assert!(entries.iter().any(|e| e.path.contains("John Doe")));
}
#[test]
fn test_windows_path_with_multiple_space_segments() {
let path = vec![r"C:\Windows\Temp\dir dir dir\directory directory".to_string()];
let entries = parse_file_listing(path);
assert!(!entries.is_empty());
let paths: Vec<&str> = entries.iter().map(|e| e.path.as_str()).collect();
assert!(paths.iter().any(|p| p.contains("dir dir dir")));
assert!(paths.iter().any(|p| p.contains("directory directory")));
}