use proptest::prelude::*;
use ricecoder_execution::FileOperations;
use tempfile::TempDir;
fn valid_path_strategy() -> impl Strategy<Value = String> {
r"[a-zA-Z0-9_\-]+".prop_map(|s| format!("test_{}.txt", s))
}
fn invalid_path_strategy() -> impl Strategy<Value = String> {
prop_oneof![
Just("".to_string()), Just("path\0with\0nulls".to_string()), ]
}
proptest! {
#[test]
fn prop_path_resolution_consistency(path in valid_path_strategy()) {
let temp_dir = TempDir::new().unwrap();
let file_path = temp_dir.path().join(&path);
let path_str = file_path.to_string_lossy().to_string();
std::fs::write(&file_path, "test content").unwrap();
let exists_1 = FileOperations::file_exists(&path_str);
let exists_2 = FileOperations::file_exists(&path_str);
let exists_3 = FileOperations::file_exists(&path_str);
prop_assert_eq!(&exists_1, &exists_2);
prop_assert_eq!(&exists_2, &exists_3);
prop_assert!(exists_1.is_ok());
prop_assert!(exists_1.unwrap());
}
#[test]
fn prop_invalid_path_rejection(path in invalid_path_strategy()) {
let result_1 = FileOperations::file_exists(&path);
let result_2 = FileOperations::file_exists(&path);
prop_assert!(result_1.is_err());
prop_assert!(result_2.is_err());
}
#[test]
fn prop_file_operations_path_consistency(
path in valid_path_strategy(),
content in ".*"
) {
let temp_dir = TempDir::new().unwrap();
let file_path = temp_dir.path().join(&path);
let path_str = file_path.to_string_lossy().to_string();
let create_result = FileOperations::create_file(&path_str, &content);
prop_assert!(create_result.is_ok());
let read_result = FileOperations::read_file(&path_str);
prop_assert!(read_result.is_ok());
prop_assert_eq!(read_result.unwrap(), content);
}
#[test]
fn prop_backup_restore_path_consistency(path in valid_path_strategy()) {
let temp_dir = TempDir::new().unwrap();
let file_path = temp_dir.path().join(&path);
let path_str = file_path.to_string_lossy().to_string();
std::fs::write(&file_path, "original content").unwrap();
let backup_result = FileOperations::backup_file(&path_str);
prop_assert!(backup_result.is_ok());
let backup_path = backup_result.unwrap();
let backup_str = backup_path.to_string_lossy().to_string();
std::fs::write(&file_path, "modified content").unwrap();
let restore_result = FileOperations::restore_from_backup(&path_str, &backup_str);
prop_assert!(restore_result.is_ok());
let restored_content = std::fs::read_to_string(&file_path).unwrap();
prop_assert_eq!(restored_content, "original content");
}
#[test]
fn prop_path_validation_deterministic(path in valid_path_strategy()) {
let temp_dir = TempDir::new().unwrap();
let file_path = temp_dir.path().join(&path);
let path_str = file_path.to_string_lossy().to_string();
std::fs::write(&file_path, "content").unwrap();
let mut results = Vec::new();
for _ in 0..10 {
let result = FileOperations::file_exists(&path_str);
results.push(result);
}
for result in &results[1..] {
prop_assert_eq!(result, &results[0]);
}
}
#[test]
fn prop_delete_recreate_path_consistency(path in valid_path_strategy()) {
let temp_dir = TempDir::new().unwrap();
let file_path = temp_dir.path().join(&path);
let path_str = file_path.to_string_lossy().to_string();
let create_result = FileOperations::create_file(&path_str, "content 1");
prop_assert!(create_result.is_ok());
let delete_result = FileOperations::delete_file(&path_str);
prop_assert!(delete_result.is_ok());
let exists_result = FileOperations::file_exists(&path_str);
prop_assert!(exists_result.is_ok());
prop_assert!(!exists_result.unwrap());
let recreate_result = FileOperations::create_file(&path_str, "content 2");
prop_assert!(recreate_result.is_ok());
let exists_result = FileOperations::file_exists(&path_str);
prop_assert!(exists_result.is_ok());
prop_assert!(exists_result.unwrap());
let read_result = FileOperations::read_file(&path_str);
prop_assert!(read_result.is_ok());
prop_assert_eq!(read_result.unwrap(), "content 2");
}
}
#[cfg(test)]
mod unit_tests {
use super::*;
#[test]
fn test_path_resolution_with_home_expansion() {
let home_path = "~/test_file.txt";
let result = FileOperations::file_exists(home_path);
assert!(result.is_ok());
}
#[test]
fn test_path_resolution_with_relative_path() {
let temp_dir = TempDir::new().unwrap();
let file_path = temp_dir.path().join("test.txt");
std::fs::write(&file_path, "content").unwrap();
let path_str = file_path.to_string_lossy().to_string();
let result = FileOperations::file_exists(&path_str);
assert!(result.is_ok());
assert!(result.unwrap());
}
#[test]
fn test_path_resolution_with_absolute_path() {
let temp_dir = TempDir::new().unwrap();
let file_path = temp_dir.path().join("test.txt");
std::fs::write(&file_path, "content").unwrap();
let path_str = file_path.to_string_lossy().to_string();
let result = FileOperations::file_exists(&path_str);
assert!(result.is_ok());
assert!(result.unwrap());
}
#[test]
fn test_empty_path_validation() {
let result = FileOperations::file_exists("");
assert!(result.is_err());
}
#[test]
fn test_null_byte_path_validation() {
let result = FileOperations::file_exists("path\0with\0nulls");
assert!(result.is_err());
}
}