use crate::utils::ExtractedTarget;
use std::fs;
use std::path::Path;
use tempfile::tempdir;
use crate::utils::{CmprssInput, CmprssOutput, CompressionLevelValidator, Compressor, Result};
pub fn test_compressor_interface<T: Compressor>(
compressor: &T,
expected_name: &str,
expected_extension: Option<&str>,
) {
let ext = expected_extension.unwrap_or(expected_name);
assert_eq!(compressor.name(), expected_name);
assert_eq!(compressor.extension(), ext);
let temp_dir = tempdir().expect("Failed to create temp dir");
let archive_path = temp_dir.path().join(format!("test.{}", ext));
fs::File::create(&archive_path).expect("Failed to create test file");
assert!(compressor.is_archive(&archive_path));
let non_archive_path = temp_dir.path().join("test.txt");
fs::File::create(&non_archive_path).expect("Failed to create test file");
assert!(!compressor.is_archive(&non_archive_path));
let test_path = Path::new("test.txt");
let expected = format!("test.txt.{}", ext);
assert_eq!(compressor.default_compressed_filename(test_path), expected);
let formatted_name = format!("test.{}", ext);
let archive_path = Path::new(&formatted_name);
match compressor.default_extracted_target() {
ExtractedTarget::FILE => {
assert_eq!(compressor.default_extracted_filename(archive_path), "test");
}
ExtractedTarget::DIRECTORY => {
assert_eq!(compressor.default_extracted_filename(archive_path), ".");
}
}
let non_archive_path = Path::new("test.txt");
match compressor.default_extracted_target() {
ExtractedTarget::FILE => {
assert_eq!(
compressor.default_extracted_filename(non_archive_path),
"archive"
);
}
ExtractedTarget::DIRECTORY => {
assert_eq!(compressor.default_extracted_filename(non_archive_path), ".");
}
}
}
pub fn test_compressor_roundtrip<T: Compressor>(compressor: &T, test_data: &str) -> Result {
let temp_dir = tempdir().expect("Failed to create temp dir");
let input_path = temp_dir.path().join("input.txt");
fs::write(&input_path, test_data)?;
let archive_path = temp_dir
.path()
.join(format!("archive.{}", compressor.extension()));
compressor.compress(
CmprssInput::Path(vec![input_path.clone()]),
CmprssOutput::Path(archive_path.clone()),
)?;
let output_path = match compressor.default_extracted_target() {
ExtractedTarget::FILE => temp_dir.path().join("output.txt"),
ExtractedTarget::DIRECTORY => temp_dir.path().join("output"),
};
compressor.extract(
CmprssInput::Path(vec![archive_path]),
CmprssOutput::Path(output_path.clone()),
)?;
let input_filename = "input.txt";
let output_data = match compressor.default_extracted_target() {
ExtractedTarget::FILE => fs::read_to_string(output_path)?,
ExtractedTarget::DIRECTORY => fs::read_to_string(output_path.join(input_filename))?,
};
assert_eq!(output_data, test_data);
Ok(())
}
pub fn test_compression<T: Compressor>(compressor: &T) -> Result {
test_compressor_roundtrip(compressor, "")?;
test_compressor_roundtrip(compressor, "Small test content")?;
let medium_content = "0123456789".repeat(1024);
test_compressor_roundtrip(compressor, &medium_content)?;
Ok(())
}
pub fn run_compressor_tests<T: Compressor>(
compressor: &T,
expected_name: &str,
expected_extension: Option<&str>,
) -> Result {
test_compressor_interface(compressor, expected_name, expected_extension);
test_compression(compressor)?;
Ok(())
}
pub fn test_compression_validator_helper<V: CompressionLevelValidator>(
validator: &V,
min_level: i32,
max_level: i32,
default_level: i32,
fast_name_level: Option<i32>,
best_name_level: Option<i32>,
none_name_level: Option<i32>,
) {
assert_eq!(validator.min_level(), min_level);
assert_eq!(validator.max_level(), max_level);
assert_eq!(validator.default_level(), default_level);
assert!(validator.is_valid_level(min_level));
assert!(validator.is_valid_level(max_level));
assert!(!validator.is_valid_level(min_level - 1));
assert!(!validator.is_valid_level(max_level + 1));
if max_level - min_level >= 2 {
let mid_level = (min_level + max_level) / 2;
assert!(validator.is_valid_level(mid_level));
}
assert_eq!(validator.validate_and_clamp_level(min_level - 1), min_level);
assert_eq!(validator.validate_and_clamp_level(min_level), min_level);
assert_eq!(validator.validate_and_clamp_level(max_level), max_level);
assert_eq!(validator.validate_and_clamp_level(max_level + 1), max_level);
if let Some(level) = fast_name_level {
assert_eq!(validator.name_to_level("fast"), Some(level));
} else {
assert_eq!(validator.name_to_level("fast"), None);
}
if let Some(level) = best_name_level {
assert_eq!(validator.name_to_level("best"), Some(level));
} else {
assert_eq!(validator.name_to_level("best"), None);
}
if let Some(level) = none_name_level {
assert_eq!(validator.name_to_level("none"), Some(level));
} else {
assert_eq!(validator.name_to_level("none"), None);
}
assert_eq!(validator.name_to_level("invalid"), None);
}