use anyhow::Result;
use std::fs::{self, File};
use std::io::Write;
use std::path::Path;
use tempfile::TempDir;
use workspace::{cli::Args, run_refac};
#[test]
fn test_invalid_utf8_encoding_handling() -> Result<()> {
let temp_dir = TempDir::new()?;
let invalid_utf8_file = temp_dir.path().join("oldname_invalid_utf8.txt");
let mut file = File::create(&invalid_utf8_file)?;
file.write_all(b"This is valid text with oldname pattern\n")?;
file.write_all(&[0xFF, 0xFE, 0xFD, 0xFC])?; file.write_all(b"\nMore text after invalid bytes")?;
let args = create_test_args(temp_dir.path(), "oldname", "newname");
let result = run_refac(args);
match result {
Ok(_) => {
let output_file = temp_dir.path().join("newname_invalid_utf8.txt");
assert!(output_file.exists(), "File should have been renamed successfully");
println!("Successfully processed file with mixed encoding using automatic detection");
},
Err(e) => {
let error_msg = e.to_string();
if error_msg.contains("binary") {
println!("File correctly identified as binary and skipped: {}", error_msg);
} else {
panic!("Unexpected error (encoding detection should handle this): {}", error_msg);
}
}
}
Ok(())
}
#[test]
fn test_binary_file_mixed_with_text_validation() -> Result<()> {
let temp_dir = TempDir::new()?;
let mixed_file = temp_dir.path().join("oldname_mixed.txt");
let mut file = File::create(&mixed_file)?;
file.write_all(b"Start with oldname text\n")?;
file.write_all(&[0x00, 0x01, 0x02, 0x03])?;
file.write_all(b"More text with oldname")?;
let args = create_test_args(temp_dir.path(), "oldname", "newname");
let result = run_refac(args);
match result {
Ok(_) => {
println!("Binary detection correctly skipped mixed file");
},
Err(e) => {
let error_msg = e.to_string();
assert!(error_msg.contains("validation") || error_msg.contains("binary") || error_msg.contains("encoding"),
"Expected encoding/binary error, got: {}", error_msg);
}
}
Ok(())
}
#[test]
fn test_different_line_endings_handling() -> Result<()> {
let temp_dir = TempDir::new()?;
let unix_file = temp_dir.path().join("oldname_unix.txt");
let mut file = File::create(&unix_file)?;
file.write_all(b"Unix line endings with oldname\nSecond line with oldname\n")?;
let windows_file = temp_dir.path().join("oldname_windows.txt");
let mut file = File::create(&windows_file)?;
file.write_all(b"Windows line endings with oldname\r\nSecond line with oldname\r\n")?;
let mac_file = temp_dir.path().join("oldname_mac.txt");
let mut file = File::create(&mac_file)?;
file.write_all(b"Mac line endings with oldname\rSecond line with oldname\r")?;
let args = create_test_args(temp_dir.path(), "oldname", "newname");
let result = run_refac(args);
match result {
Ok(_) => {
assert!(temp_dir.path().join("newname_unix.txt").exists());
assert!(temp_dir.path().join("newname_windows.txt").exists());
assert!(temp_dir.path().join("newname_mac.txt").exists());
let unix_content = fs::read_to_string(temp_dir.path().join("newname_unix.txt"))?;
assert!(unix_content.contains("newname"));
assert!(!unix_content.contains("oldname"));
},
Err(e) => {
panic!("Line ending variations should be handled correctly, but got error: {}", e);
}
}
Ok(())
}
#[test]
fn test_large_file_with_mixed_encoding() -> Result<()> {
let temp_dir = TempDir::new()?;
let large_file = temp_dir.path().join("oldname_large_mixed.txt");
let mut file = File::create(&large_file)?;
for i in 0..1000 {
writeln!(file, "Line {} with oldname pattern that should be replaced", i)?;
}
file.write_all(&[0xC0, 0x80])?;
for i in 1000..2000 {
writeln!(file, "Line {} with oldname pattern continued", i)?;
}
let args = create_test_args(temp_dir.path(), "oldname", "newname");
let result = run_refac(args);
match result {
Ok(_) => {
let output_file = temp_dir.path().join("newname_large_mixed.txt");
assert!(output_file.exists(), "Large file should have been renamed successfully");
println!("Successfully processed large file with mixed encoding using automatic detection");
},
Err(e) => {
let error_msg = e.to_string();
if error_msg.contains("binary") {
println!("Large file correctly identified as binary and skipped: {}", error_msg);
} else {
panic!("Unexpected error (encoding detection should handle large files): {}", error_msg);
}
}
}
Ok(())
}
#[test]
fn test_utf8_bom_handling() -> Result<()> {
let temp_dir = TempDir::new()?;
let bom_file = temp_dir.path().join("oldname_bom.txt");
let mut file = File::create(&bom_file)?;
file.write_all(&[0xEF, 0xBB, 0xBF])?;
file.write_all(b"File with BOM and oldname content")?;
let args = create_test_args(temp_dir.path(), "oldname", "newname");
let result = run_refac(args);
match result {
Ok(_) => {
assert!(temp_dir.path().join("newname_bom.txt").exists());
let content = fs::read_to_string(temp_dir.path().join("newname_bom.txt"))?;
assert!(content.contains("newname"));
assert!(!content.contains("oldname"));
},
Err(e) => {
panic!("UTF-8 BOM files should be handled correctly, but got error: {}", e);
}
}
Ok(())
}
#[test]
fn test_empty_and_whitespace_only_files() -> Result<()> {
let temp_dir = TempDir::new()?;
let empty_file = temp_dir.path().join("oldname_empty.txt");
File::create(&empty_file)?;
let whitespace_file = temp_dir.path().join("oldname_whitespace.txt");
let mut file = File::create(&whitespace_file)?;
file.write_all(b" \n\t\r\n \n")?;
let args = create_test_args(temp_dir.path(), "oldname", "newname");
let result = run_refac(args);
match result {
Ok(_) => {
assert!(temp_dir.path().join("newname_empty.txt").exists());
assert!(temp_dir.path().join("newname_whitespace.txt").exists());
},
Err(e) => {
panic!("Empty and whitespace files should be handled correctly, but got error: {}", e);
}
}
Ok(())
}
#[test]
fn test_very_long_lines_handling() -> Result<()> {
let temp_dir = TempDir::new()?;
let long_lines_file = temp_dir.path().join("oldname_long_lines.txt");
let mut file = File::create(&long_lines_file)?;
let long_content = "a".repeat(50000) + "oldname" + &"b".repeat(50000);
writeln!(file, "{}", long_content)?;
writeln!(file, "Normal line with oldname")?;
let args = create_test_args(temp_dir.path(), "oldname", "newname");
let result = run_refac(args);
match result {
Ok(_) => {
assert!(temp_dir.path().join("newname_long_lines.txt").exists());
let content = fs::read_to_string(temp_dir.path().join("newname_long_lines.txt"))?;
assert!(content.contains("newname"));
assert!(!content.contains("oldname"));
},
Err(e) => {
panic!("Very long lines should be handled correctly, but got error: {}", e);
}
}
Ok(())
}
fn create_test_args(root_dir: &Path, pattern: &str, substitute: &str) -> Args {
Args {
root_dir: root_dir.to_path_buf(),
pattern: pattern.to_string(),
substitute: substitute.to_string(),
assume_yes: true,
verbose: true, follow_symlinks: false,
backup: false,
files_only: false,
dirs_only: false,
names_only: false,
content_only: false,
max_depth: 0,
exclude_patterns: vec![],
include_patterns: vec![],
format: workspace::cli::OutputFormat::Plain,
threads: 1,
progress: workspace::cli::ProgressMode::Never,
ignore_case: false,
use_regex: false,
include_hidden: false,
binary_names: false,
}
}