pub mod lcov;
pub mod policy;
pub use lcov::{
CoverageReport, FileCoverage, LcovError, new_code_coverage, parse_lcov, parse_lcov_file,
};
pub use policy::{CoverageFileConfig, CoveragePolicy, CoverageVerdictContrib, evaluate_coverage};
use crate::{
models::Verdict,
pipeline::letter_grade::{Grade, clamp_grade_to_verdict},
};
pub fn apply_coverage_floor(
verdict: Verdict,
grade: Grade,
contrib: &CoverageVerdictContrib,
) -> (Verdict, Grade) {
let Some(floor) = contrib.floor.as_ref() else {
return (verdict, grade);
};
let new_verdict = match (&verdict, floor) {
(Verdict::Block, _) => Verdict::Block,
(Verdict::Approve | Verdict::ApproveWithReservations, Verdict::RequestChanges) => {
Verdict::RequestChanges
}
_ => verdict,
};
let new_grade = if let Some(ceiling) = contrib.grade_ceiling {
if grade > ceiling { ceiling } else { grade }
} else {
clamp_grade_to_verdict(grade, &new_verdict)
};
(new_verdict, new_grade)
}
#[cfg(test)]
mod tests {
use super::*;
use crate::coverage::policy::CoverageVerdictContrib;
fn pass_contrib() -> CoverageVerdictContrib {
CoverageVerdictContrib {
floor: None,
grade_ceiling: None,
summary: "pass".to_string(),
}
}
fn fail_contrib() -> CoverageVerdictContrib {
CoverageVerdictContrib {
floor: Some(Verdict::RequestChanges),
grade_ceiling: Some(Grade::DPlus),
summary: "fail".to_string(),
}
}
#[test]
fn apply_coverage_floor_noop_when_no_floor() {
let (v, g) = apply_coverage_floor(Verdict::Approve, Grade::A, &pass_contrib());
assert_eq!(v, Verdict::Approve);
assert_eq!(g, Grade::A);
}
#[test]
fn apply_coverage_floor_tightens_approve() {
let (v, g) = apply_coverage_floor(Verdict::Approve, Grade::A, &fail_contrib());
assert_eq!(v, Verdict::RequestChanges);
assert_eq!(g, Grade::DPlus, "grade must be clamped to D+");
}
#[test]
fn apply_coverage_floor_tightens_approve_star() {
let (v, g) =
apply_coverage_floor(Verdict::ApproveWithReservations, Grade::C, &fail_contrib());
assert_eq!(v, Verdict::RequestChanges);
assert_eq!(g, Grade::DPlus);
}
#[test]
fn apply_coverage_floor_does_not_weaken_block() {
let (v, g) = apply_coverage_floor(Verdict::Block, Grade::F, &fail_contrib());
assert_eq!(v, Verdict::Block, "BLOCK must not be softened by coverage");
assert_eq!(g, Grade::F);
}
#[test]
fn apply_coverage_floor_idempotent_on_request_changes() {
let (v, g) = apply_coverage_floor(Verdict::RequestChanges, Grade::D, &fail_contrib());
assert_eq!(v, Verdict::RequestChanges);
assert_eq!(g, Grade::D, "D does not exceed D+ ceiling so stays D");
}
}