use anyhow::Result;
use std::collections::HashMap;
use std::time::{Duration, Instant};
#[derive(Debug)]
struct TestResult {
name: String,
success: bool,
duration: Duration,
error: Option<String>,
}
pub struct ProtocolTestSuite {
results: Vec<TestResult>,
}
impl ProtocolTestSuite {
pub fn new() -> Self {
Self {
results: Vec::new(),
}
}
pub fn run_test<F>(&mut self, name: &str, test_fn: F)
where
F: FnOnce() -> Result<()>,
{
println!("Running test: {}", name);
let start = Instant::now();
let result = test_fn();
let duration = start.elapsed();
let success = result.is_ok();
let error = result.err().map(|e| format!("{:#}", e));
let test_result = TestResult {
name: name.to_string(),
success,
duration,
error,
};
self.results.push(test_result);
if success {
println!(" SUCCESS ({:.2?})", duration);
} else {
println!(" FAILED ({:.2?})", duration);
if let Some(err) = &self.results.last().unwrap().error {
println!(" Error: {}", err);
}
}
}
pub fn print_summary(&self) {
let total = self.results.len();
let passed = self.results.iter().filter(|r| r.success).count();
let failed = total - passed;
println!("\n{}", "=".repeat(50));
println!("Test Summary:");
println!(" Total: {}", total);
println!(" Passed: {}", passed);
if failed > 0 {
println!(" Failed: {}", failed);
println!("\nFailed tests:");
for result in &self.results {
if !result.success {
println!(" - {} ({:.2?})", result.name, result.duration);
if let Some(err) = &result.error {
println!(" Error: {}", err);
}
}
}
} else {
println!(" Failed: {}", "0");
}
println!("{}", "=".repeat(50));
}
pub fn is_success(&self) -> bool {
self.results.iter().all(|r| r.success)
}
pub fn results_map(&self) -> HashMap<String, bool> {
self.results
.iter()
.map(|r| (r.name.clone(), r.success))
.collect()
}
pub fn total_tests(&self) -> usize {
self.results.len()
}
pub fn successful_tests(&self) -> usize {
self.results.iter().filter(|r| r.success).count()
}
}
pub fn run_all_tests() -> Result<HashMap<String, bool>> {
let mut suite = ProtocolTestSuite::new();
use super::bip341_compliance_simple::*;
suite.run_test("BIP-341: Key Path Spending (Simple)", || {
test_taproot_key_path_spending_simple()
});
suite.print_summary();
Ok(suite.results_map())
}
pub fn main() -> Result<()> {
println!("{}", "Running Bitcoin Protocol Tests");
println!("{}", "=".repeat(50));
let results = run_all_tests()?;
let all_passed = results.values().all(|&success| success);
if all_passed {
println!("\n{}", "All tests passed!");
} else {
println!("\n{}", "Some tests failed!");
std::process::exit(1);
}
Ok(())
}