#![cfg_attr(coverage_nightly, coverage(off))]
use super::cache::{read_cached_metric, read_deny_cache_fallback};
use crate::cli::handlers::work_contract::{EvidenceType, FalsificationResult};
use anyhow::Result;
use std::path::{Path, PathBuf};
use std::process::Command;
#[provable_contracts_macros::contract("pmat-core.yaml", equation = "check_compliance")]
pub(crate) async fn test_supply_chain_integrity(
project_path: &Path,
) -> Result<FalsificationResult> {
print!("Reading deny cache... ");
if let Some(cache) = read_cached_metric(project_path, "deny-status.json")
.or_else(|| read_deny_cache_fallback(project_path))
{
if cache.is_stale_block {
return Ok(FalsificationResult::failed(
format!(
"Deny cache too old ({} min). Run 'cargo deny check' first.",
cache.age_minutes
),
EvidenceType::BooleanCheck(false),
));
}
let passed = match cache.value.get("passed").and_then(|v| v.as_bool()) {
Some(p) => p,
None => {
return Ok(FalsificationResult::failed(
"Invalid deny cache (missing 'passed' field). Re-run 'cargo deny check'."
.to_string(),
EvidenceType::BooleanCheck(false),
));
}
};
let stale_note = format!(" (cached {} min ago)", cache.age_minutes);
if passed {
return Ok(FalsificationResult::passed(format!(
"No vulnerabilities{}",
stale_note
)));
} else {
let count = cache
.value
.get("vulnerability_count")
.and_then(|v| v.as_u64())
.unwrap_or(0);
return Ok(FalsificationResult::failed(
format!("{} vulnerabilities{}", count, stale_note),
EvidenceType::NumericComparison {
actual: count as f64,
threshold: 0.0,
},
));
}
}
Ok(FalsificationResult::failed(
"No deny cache. Run 'cargo deny check' first (O(1) requirement)".to_string(),
EvidenceType::BooleanCheck(false),
))
}
#[provable_contracts_macros::contract("pmat-core.yaml", equation = "check_compliance")]
pub(crate) async fn test_examples_compile(project_path: &Path) -> Result<FalsificationResult> {
print!("Reading examples cache... ");
if let Some(cache) = read_cached_metric(project_path, "examples-status.json") {
if cache.is_stale_block {
return Ok(FalsificationResult::failed(
format!(
"Examples cache too old ({} min). Run 'cargo build --examples' first.",
cache.age_minutes
),
EvidenceType::BooleanCheck(false),
));
}
let passed = match cache.value.get("passed").and_then(|v| v.as_bool()) {
Some(p) => p,
None => {
return Ok(FalsificationResult::failed(
"Invalid examples cache (missing 'passed' field). Re-run 'cargo build --examples'.".to_string(),
EvidenceType::BooleanCheck(false),
));
}
};
let count = cache
.value
.get("count")
.and_then(|v| v.as_u64())
.unwrap_or(0);
let stale_note = format!(" (cached {} min ago)", cache.age_minutes);
if passed {
return Ok(FalsificationResult::passed(format!(
"{} examples OK{}",
count, stale_note
)));
} else {
let failed = cache
.value
.get("failed")
.and_then(|v| v.as_array())
.map(|a| {
a.iter()
.filter_map(|v| v.as_str())
.collect::<Vec<_>>()
.join(", ")
})
.unwrap_or_default();
return Ok(FalsificationResult::failed(
format!("Examples failed{}: {}", stale_note, failed),
EvidenceType::CounterExample { details: failed },
));
}
}
let examples_dir = project_path.join("examples");
if !examples_dir.exists() {
return Ok(FalsificationResult::passed(
"No examples directory found (skipping)".to_string(),
));
}
Ok(FalsificationResult::passed(
"No examples cache (run 'cargo build --examples' to populate)".to_string(),
))
}
fn try_make_validate_book(project_path: &Path) -> Option<FalsificationResult> {
let output = Command::new("make")
.args(["validate-book"])
.current_dir(project_path)
.output()
.ok()?;
if output.status.success() {
Some(FalsificationResult::passed(
"pmat-book validation passed".to_string(),
))
} else {
let stderr = String::from_utf8_lossy(&output.stderr);
Some(FalsificationResult::failed(
"pmat-book validation failed".to_string(),
EvidenceType::CounterExample {
details: stderr.chars().take(500).collect(),
},
))
}
}
fn try_book_chapter_tests(book_path: &Path) -> Option<FalsificationResult> {
let test_script = book_path.join("tests/ch13/test_language_examples.sh");
if !test_script.exists() {
return None;
}
let output = Command::new("bash")
.arg(&test_script)
.current_dir(book_path)
.output()
.ok()?;
if output.status.success() {
Some(FalsificationResult::passed(
"pmat-book chapter tests passed".to_string(),
))
} else {
let stderr = String::from_utf8_lossy(&output.stderr);
Some(FalsificationResult::failed(
"pmat-book chapter tests failed".to_string(),
EvidenceType::CounterExample {
details: stderr.chars().take(500).collect(),
},
))
}
}
#[provable_contracts_macros::contract("pmat-core.yaml", equation = "check_compliance")]
pub(crate) async fn test_book_validation(project_path: &Path) -> Result<FalsificationResult> {
print!("Validating pmat-book... ");
let book_path = match project_path.parent().map(|p| p.join("pmat-book")) {
Some(p) if p.exists() => p,
_ => {
return Ok(FalsificationResult::passed(
"pmat-book not found (skipping validation)".to_string(),
));
}
};
if let Some(result) = try_make_validate_book(project_path) {
return Ok(result);
}
if let Some(result) = try_book_chapter_tests(&book_path) {
return Ok(result);
}
Ok(FalsificationResult::passed(
"pmat-book not found (skipping validation)".to_string(),
))
}
#[provable_contracts_macros::contract("pmat-core.yaml", equation = "check_compliance")]
pub(crate) async fn test_cross_crate_parity(project_path: &Path) -> Result<FalsificationResult> {
print!("Checking cross-crate config... ");
let config_path = project_path.join(".pmat-work/cross-crate.json");
if !config_path.exists() {
return Ok(FalsificationResult::passed(
"No cross-crate config (create .pmat-work/cross-crate.json to enable)".to_string(),
));
}
let content = std::fs::read_to_string(&config_path)?;
let config: serde_json::Value = serde_json::from_str(&content)?;
let Some(projects) = config.get("projects").and_then(|p| p.as_array()) else {
return Ok(FalsificationResult::passed(
"No projects in cross-crate config".to_string(),
));
};
let mut failures = Vec::new();
let mut passed_count = 0;
for project in projects {
let Some(path) = project.get("path").and_then(|p| p.as_str()) else {
continue;
};
let test_cmd = project
.get("test_command")
.and_then(|c| c.as_str())
.unwrap_or("cargo test --lib");
let full_path = project_path.join(path);
if !full_path.exists() {
continue;
}
let parts: Vec<&str> = test_cmd.split_whitespace().collect();
let (program, args) = parts.split_first().unwrap_or((&"cargo", &[]));
let output = Command::new(program)
.args(args)
.current_dir(&full_path)
.output();
match output {
Ok(out) if out.status.success() => passed_count += 1,
Ok(_) => failures.push(path.to_string()),
Err(_) => failures.push(format!("{} (command failed)", path)),
}
}
if failures.is_empty() {
Ok(FalsificationResult::passed(format!(
"{} sibling project(s) pass",
passed_count
)))
} else {
let paths: Vec<PathBuf> = failures.iter().map(PathBuf::from).collect();
Ok(FalsificationResult::failed(
format!(
"{} sibling project(s) failed: {}",
failures.len(),
failures.join(", ")
),
EvidenceType::FileList(paths),
))
}
}
#[provable_contracts_macros::contract("pmat-core.yaml", equation = "check_compliance")]
pub(crate) async fn test_regression_gate(project_path: &Path) -> Result<FalsificationResult> {
print!("Reading benchmark cache... ");
if let Some(cache) = read_cached_metric(project_path, "benchmark-status.json") {
if cache.is_stale_block {
return Ok(FalsificationResult::passed(format!(
"Benchmark cache old ({} min), skipping",
cache.age_minutes
)));
}
let passed = cache
.value
.get("passed")
.and_then(|v| v.as_bool())
.unwrap_or(true);
let stale_note = format!(" (cached {} min ago)", cache.age_minutes);
if passed {
let benchmarks = cache
.value
.get("count")
.and_then(|v| v.as_u64())
.unwrap_or(0);
return Ok(FalsificationResult::passed(format!(
"{} benchmark(s) OK{}",
benchmarks, stale_note
)));
} else {
let regressions = cache
.value
.get("regressions")
.and_then(|v| v.as_array())
.map(|a| {
a.iter()
.filter_map(|v| v.as_str())
.collect::<Vec<_>>()
.join(", ")
})
.unwrap_or_default();
return Ok(FalsificationResult::failed(
format!("Performance regression{}: {}", stale_note, regressions),
EvidenceType::CounterExample {
details: regressions,
},
));
}
}
Ok(FalsificationResult::passed(
"No benchmark cache (run benchmarks to populate .pmat-metrics/benchmark-status.json)"
.to_string(),
))
}
#[provable_contracts_macros::contract("pmat-core.yaml", equation = "check_compliance")]
pub(crate) fn test_meta_falsification(project_path: &Path) -> Result<FalsificationResult> {
print!("Injecting dummy failure... ");
let detector_working = crate::services::gaming_detector::run_meta_falsification(project_path)?;
if detector_working {
Ok(FalsificationResult::passed(
"Detected dummy gaming pattern correctly".to_string(),
))
} else {
Ok(FalsificationResult::failed(
"Falsifier FAILED to detect known gaming pattern (SYSTEM BROKEN)".to_string(),
EvidenceType::CounterExample {
details: "Dummy #[cfg(not(coverage))] was ignored by detector".into(),
},
))
}
}