testlint_sdk/runtime_coverage/
mod.rs

1pub mod cpp;
2pub mod csharp;
3pub mod go;
4pub mod java;
5pub mod javascript;
6pub mod php;
7pub mod python;
8pub mod ruby;
9pub mod rust;
10
11use crate::common::Language;
12use std::fmt;
13
14#[derive(Debug)]
15pub struct RuntimeCoverageResult {
16    pub language: String,
17    pub pid: u32,
18    pub duration_secs: u64,
19    pub coverage_file: String,
20    pub summary: CoverageSummary,
21}
22
23#[derive(Debug)]
24pub struct CoverageSummary {
25    pub total_lines: usize,
26    pub covered_lines: usize,
27    pub coverage_percentage: f64,
28    pub total_branches: Option<usize>,
29    pub covered_branches: Option<usize>,
30    pub branch_percentage: Option<f64>,
31}
32
33impl fmt::Display for RuntimeCoverageResult {
34    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
35        writeln!(f, "=== Runtime Coverage Results for {} ===", self.language)?;
36        writeln!(f, "PID: {}", self.pid)?;
37        writeln!(f, "Duration: {} seconds", self.duration_secs)?;
38        writeln!(f, "Coverage file: {}", self.coverage_file)?;
39        writeln!(f)?;
40        writeln!(f, "Coverage Summary:")?;
41        writeln!(
42            f,
43            "  Lines: {}/{} ({:.2}%)",
44            self.summary.covered_lines, self.summary.total_lines, self.summary.coverage_percentage
45        )?;
46
47        if let (Some(covered), Some(total), Some(pct)) = (
48            self.summary.covered_branches,
49            self.summary.total_branches,
50            self.summary.branch_percentage,
51        ) {
52            writeln!(f, "  Branches: {}/{} ({:.2}%)", covered, total, pct)?;
53        }
54
55        Ok(())
56    }
57}
58
59pub struct RuntimeCoverageCollector {
60    language: Language,
61}
62
63impl RuntimeCoverageCollector {
64    pub fn new(language: Language) -> Self {
65        RuntimeCoverageCollector { language }
66    }
67
68    /// Attach to a running process and collect coverage continuously
69    /// Runs until interrupted (Ctrl+C)
70    pub fn attach_and_collect(&self, pid: u32) -> Result<RuntimeCoverageResult, String> {
71        match self.language {
72            Language::Python => {
73                let collector = python::PythonRuntimeCoverage::new();
74                collector.attach_and_collect(pid)
75            }
76            Language::Java => {
77                let collector = java::JavaRuntimeCoverage::new();
78                collector.attach_and_collect(pid)
79            }
80            Language::CSharp => {
81                let collector = csharp::CSharpRuntimeCoverage::new();
82                collector.attach_and_collect(pid)
83            }
84            Language::Ruby => {
85                let collector = ruby::RubyRuntimeCoverage::new();
86                collector.attach_and_collect(pid)
87            }
88            Language::JavaScript | Language::TypeScript => {
89                let collector = javascript::JavaScriptRuntimeCoverage::new();
90                collector.attach_and_collect(pid)
91            }
92            Language::Go => {
93                let collector = go::GoRuntimeCoverage::new();
94                collector.attach_and_collect(pid)
95            }
96            Language::Rust => {
97                let collector = rust::RustRuntimeCoverage::new();
98                collector.attach_and_collect(pid)
99            }
100            Language::Php => {
101                let collector = php::PhpRuntimeCoverage::new();
102                collector.attach_and_collect(pid)
103            }
104            Language::Cpp => {
105                let collector = cpp::CppRuntimeCoverage::new();
106                collector.attach_and_collect(pid)
107            }
108        }
109    }
110}