anya-core 1.2.0

Enterprise-grade Bitcoin Infrastructure Platform
Documentation
// Sectional Testing Utilities
// This module provides helpers for the sectional testing approach

use std::collections::HashMap;
use std::env;
use std::fs::{self, File};
use std::io::Write;
use std::path::Path;
use std::time::{Duration, Instant};

/// Utility module for sectional testing
pub mod sectional {
    use super::*;

    /// Sections available for testing
    #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
    pub enum Section {
        CoreIssuance,
        Distribution,
        DexIntegration,
        Governance,
        Security,
        MemoryOptimization,
    }

    impl Section {
        pub fn as_str(&self) -> &'static str {
            match self {
                Section::CoreIssuance => "core-issuance",
                Section::Distribution => "distribution",
                Section::DexIntegration => "dex-integration",
                Section::Governance => "governance",
                Section::Security => "security",
                Section::MemoryOptimization => "memory-optimization",
            }
        }

        pub fn from_str(s: &str) -> Option<Self> {
            match s {
                "core-issuance" => Some(Section::CoreIssuance),
                "distribution" => Some(Section::Distribution),
                "dex-integration" => Some(Section::DexIntegration),
                "governance" => Some(Section::Governance),
                "security" => Some(Section::Security),
                "memory-optimization" => Some(Section::MemoryOptimization),
                _ => None,
            }
        }
    }

    /// Test result information
    #[derive(Debug, Clone)]
    pub struct TestResult {
        pub section: Section,
        pub passed: bool,
        pub duration: Duration,
        pub memory_usage: Option<usize>,
        pub details: HashMap<String, String>,
    }

    impl TestResult {
        pub fn new(section: Section) -> Self {
            Self {
                section,
                passed: false,
                duration: Duration::from_secs(0),
                memory_usage: None,
                details: HashMap::new(),
            }
        }

        pub fn mark_passed(&mut self) {
            self.passed = true;
        }

        pub fn set_duration(&mut self, duration: Duration) {
            self.duration = duration;
        }

        pub fn set_memory_usage(&mut self, bytes: usize) {
            self.memory_usage = Some(bytes);
        }

        pub fn add_detail(&mut self, key: &str, value: String) {
            self.details.insert(key.to_string(), value);
        }
    }

    /// Run a sectional test and record the results
    pub fn run_test<F>(section: Section, test_fn: F) -> TestResult
    where
        F: FnOnce() -> bool,
    {
        let mut result = TestResult::new(section);
        let start = Instant::now();

        let passed = test_fn();

        result.set_duration(start.elapsed());
        if passed {
            result.mark_passed();
        }

        // Report test result
        report_test_result(&result);

        result
    }

    /// Report test result to file for the CI pipeline
    pub fn report_test_result(result: &TestResult) {
        // Create reports directory if it doesn't exist
        let reports_dir = Path::new("reports");
        if !reports_dir.exists() {
            let _ = fs::create_dir_all(reports_dir);
        }

        // Write result to file
        let file_path = reports_dir.join(format!("{}_result.txt", result.section.as_str()));
        let mut file = match File::create(&file_path) {
            Ok(f) => f,
            Err(_) => return, // Skip reporting if we can't create the file
        };

        // Write basic info
        let _ = writeln!(file, "Section: {}", result.section.as_str());
        let _ = writeln!(file, "Passed: {}", result.passed);
        let _ = writeln!(file, "Duration: {:?}", result.duration);

        if let Some(memory) = result.memory_usage {
            let _ = writeln!(file, "Memory usage: {memory} bytes");
        }

        // Write details
        if !result.details.is_empty() {
            let _ = writeln!(file, "\nDetails:");
            for (key, value) in &result.details {
                let _ = writeln!(file, "  {key}: {value}");
            }
        }
    }

    /// Check if a specific section should be tested
    pub fn should_test_section(section: Section) -> bool {
        // Check environment variable for filtered sections
        if let Ok(filter) = env::var("TEST_SECTION") {
            if filter == "all" {
                return true;
            }
            return filter.split(',').any(|s| s.trim() == section.as_str());
        }

        // By default, test all sections
        true
    }

    /// Measure memory usage during a function execution
    ///
    /// Note: This is a basic approximation and should be used with caution
    #[cfg(feature = "memory_tracking")]
    pub fn measure_memory_usage<F, T>(f: F) -> (T, usize)
    where
        F: FnOnce() -> T,
    {
        use std::alloc::{GlobalAlloc, System};
        use std::mem;

        // Force a garbage collection if possible (fixed unsafe call)
        unsafe {
            let layout = std::alloc::Layout::new::<u8>();
            let _ = System.alloc(layout);
        }

        // Run the function and measure the result
        let result = f();

        // This is a very rough approximation
        // For better results, use a proper memory profiler
        let estimate = mem::size_of_val(&result);

        (result, estimate)
    }

    #[cfg(not(feature = "memory_tracking"))]
    pub fn measure_memory_usage<F, T>(f: F) -> (T, usize)
    where
        F: FnOnce() -> T,
    {
        let result = f();
        (result, 0)
    }
}

// Macros to simplify sectional testing usage
#[macro_export]
macro_rules! sectional_test {
    ($section:expr, $test_name:ident, $body:block) => {
        #[test]
        fn $test_name() {
            if $crate::sectional_test_utils::sectional::should_test_section($section) {
                $crate::sectional_test_utils::sectional::run_test($section, || $body);
            }
        }
    };
}

// Example usage:
/*
#[cfg(test)]
mod tests {
    use super::*;
    use crate::sectional_test_utils::sectional::Section;

    #[test]
    fn test_core_issuance() {
        if sectional::should_test_section(Section::CoreIssuance) {
            let result = sectional::run_test(Section::CoreIssuance, || {
                // Test core issuance
                true // Test passed
            });
            assert!(result.passed);
        }
    }
}
*/