use proptest::prelude::*;
use ricecoder_execution::{TestFailure, TestFramework, TestResults};
use tempfile::TempDir;
#[test]
fn prop_test_failures_prevent_completion() {
proptest!(|(
passed in 0usize..100,
failed in 1usize..100, // At least 1 failure
skipped in 0usize..50,
)| {
let results = TestResults {
passed,
failed,
skipped,
failures: (0..failed)
.map(|i| TestFailure {
name: format!("test_{}", i),
message: "Test failed".to_string(),
location: None,
})
.collect(),
framework: TestFramework::Rust,
};
prop_assert!(results.failed > 0, "Failed count must be positive");
prop_assert_eq!(
results.failures.len(),
results.failed,
"Failure details must match failed count"
);
for failure in &results.failures {
prop_assert!(!failure.name.is_empty(), "Failure name must not be empty");
}
for failure in &results.failures {
prop_assert!(!failure.message.is_empty(), "Failure message must not be empty");
}
});
}
#[test]
fn prop_test_results_consistency() {
proptest!(|(
passed in 0usize..1000,
failed in 0usize..1000,
skipped in 0usize..1000,
)| {
let results = TestResults {
passed,
failed,
skipped,
failures: (0..failed)
.map(|i| TestFailure {
name: format!("test_{}", i),
message: "Test failed".to_string(),
location: None,
})
.collect(),
framework: TestFramework::Rust,
};
let _ = results.passed;
let _ = results.failed;
let _ = results.skipped;
prop_assert_eq!(results.framework, TestFramework::Rust, "Framework must be set");
prop_assert_eq!(
results.failures.len(),
results.failed,
"Failures list length must match failed count"
);
});
}
#[test]
fn prop_test_framework_detection_deterministic() {
proptest!(|(framework_type in 0u8..3)| {
let temp_dir = TempDir::new().unwrap();
match framework_type {
0 => {
std::fs::write(temp_dir.path().join("Cargo.toml"), "").unwrap();
}
1 => {
std::fs::write(temp_dir.path().join("package.json"), "").unwrap();
}
2 => {
std::fs::write(temp_dir.path().join("pytest.ini"), "").unwrap();
}
_ => unreachable!(),
}
let runner = ricecoder_execution::TestRunner::new(temp_dir.path());
let result1 = runner.detect_framework();
let result2 = runner.detect_framework();
match (result1, result2) {
(Ok(f1), Ok(f2)) => {
prop_assert_eq!(f1, f2, "Framework detection must be deterministic");
}
(Err(_), Err(_)) => {
}
_ => {
prop_assert!(false, "Framework detection must be consistent");
}
}
});
}
#[test]
fn prop_test_command_building_deterministic() {
proptest!(|(
framework_type in 0u8..3,
pattern_opt in prop::option::of("[a-z_]{1,20}"),
)| {
let temp_dir = TempDir::new().unwrap();
let runner = ricecoder_execution::TestRunner::new(temp_dir.path());
let framework = match framework_type {
0 => TestFramework::Rust,
1 => TestFramework::TypeScript,
2 => TestFramework::Python,
_ => unreachable!(),
};
let result1 = runner.build_test_command(&framework, pattern_opt.as_deref());
let result2 = runner.build_test_command(&framework, pattern_opt.as_deref());
match (result1, result2) {
(Ok((cmd1, args1)), Ok((cmd2, args2))) => {
prop_assert_eq!(cmd1, cmd2, "Command must be deterministic");
prop_assert_eq!(args1, args2, "Arguments must be deterministic");
}
(Err(_), Err(_)) => {
}
_ => {
prop_assert!(false, "Command building must be consistent");
}
}
});
}
#[test]
fn prop_test_failure_details_preserved() {
proptest!(|(
name in "[a-z_]{1,50}",
message in "[a-zA-Z0-9 ]{1,100}",
)| {
let failure = TestFailure {
name: name.clone(),
message: message.clone(),
location: None,
};
prop_assert_eq!(failure.name, name, "Failure name must be preserved");
prop_assert_eq!(failure.message, message, "Failure message must be preserved");
prop_assert_eq!(failure.location, None, "Location should be None");
});
}
#[test]
fn prop_test_multiple_framework_detection() {
proptest!(|(frameworks in prop::collection::vec(0u8..3, 1..10))| {
for framework_type in frameworks {
let temp_dir = TempDir::new().unwrap();
match framework_type {
0 => {
std::fs::write(temp_dir.path().join("Cargo.toml"), "").unwrap();
}
1 => {
std::fs::write(temp_dir.path().join("package.json"), "").unwrap();
}
2 => {
std::fs::write(temp_dir.path().join("pytest.ini"), "").unwrap();
}
_ => unreachable!(),
}
let runner = ricecoder_execution::TestRunner::new(temp_dir.path());
let result = runner.detect_framework();
prop_assert!(result.is_ok(), "Framework detection must succeed for valid projects");
if let Ok(detected) = result {
let expected = match framework_type {
0 => TestFramework::Rust,
1 => TestFramework::TypeScript,
2 => TestFramework::Python,
_ => unreachable!(),
};
prop_assert_eq!(detected, expected, "Detected framework must match marker file");
}
}
});
}