From 9dad6b93e4e735d061db6b4349227d8f23b65116 Mon Sep 17 00:00:00 2001 From: 魏曹先生 <1992414357@qq.com> Date: Wed, 12 Aug 2026 16:47:49 +0800 Subject: fix(cov-test): recolor coverage summary with project thresholds Apply project-specific color coding (0-50% red, 51-80% yellow, 81-100% green) to the per-file coverage summary in the generated HTML report, overriding llvm-cov's default thresholds. --- .run/src/bin/cov-test.rs | 79 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 79 insertions(+) diff --git a/.run/src/bin/cov-test.rs b/.run/src/bin/cov-test.rs index dd431ba..1599ff1 100644 --- a/.run/src/bin/cov-test.rs +++ b/.run/src/bin/cov-test.rs @@ -226,6 +226,19 @@ fn main() { println_cargo_style!("Files moved successfully."); } + // 6. Recolor the per-file coverage summary with project-specific + // thresholds: 0-50% red, 51-80% yellow, 81-100% green. llvm-cov's + // built-in thresholds differ, and the color is assigned when the HTML + // is generated, so the summary table is rewritten here. + let index_path = output_path.join("index.html"); + if let Err(e) = recolor_report_index(&index_path) { + eprintln_cargo_style!( + "Warning: failed to recolor {}: {}", + index_path.display(), + e + ); + } + println_cargo_style!( "Done: coverage report generated at {}/index.html", OUTPUT_DIR @@ -405,6 +418,48 @@ fn get_binary_name(example_name: &str) -> String { } } +/// Rewrite the per-file coverage colors in `index.html` with project-specific +/// thresholds: 0-50% red, 51-80% yellow, 81-100% green. +fn recolor_report_index(index_path: &Path) -> std::io::Result<()> { + let content = fs::read_to_string(index_path)?; + fs::write(index_path, recolor_coverage_table(&content)) +} + +/// Recolor every `
XX% ...
` cell +/// in the coverage summary table according to the new thresholds. Cells with +/// no data (e.g. branch coverage `- (0/0)`, class `gray`) are left as-is. +fn recolor_coverage_table(input: &str) -> String { + const TD: &str = "
") else {
+            out.push_str(rest);
+            return out;
+        };
+        let color = &rest[..pre_end];
+        let tail = &rest[pre_end + "'>
".len()..];
+        let pct: String = tail
+            .trim_start()
+            .chars()
+            .take_while(|c| c.is_ascii_digit() || *c == '.')
+            .collect();
+        let new_color = match pct.parse::() {
+            Ok(v) if v <= 50.0 => "red",
+            Ok(v) if v <= 80.0 => "yellow",
+            Ok(_) => "green",
+            Err(_) => color, // no data (e.g. gray branch column)
+        };
+        out.push_str(new_color);
+        out.push_str("'>
");
+        rest = tail;
+    }
+    out.push_str(rest);
+    out
+}
+
 /// True if the file is executable: mode bits on Unix, `.exe` on Windows.
 fn is_executable(path: &Path) -> bool {
     #[cfg(unix)]
@@ -460,3 +515,27 @@ fn find_git_repo() -> Option {
 
     None
 }
+
+#[cfg(test)]
+mod tests {
+    use super::recolor_coverage_table;
+
+    #[test]
+    fn recolor_thresholds() {
+        let input = concat!(
+            "
  50.00% (2/4)
", + "
  51.23% (32/52)
", + "
  80.00% (48/89)
", + "
  81.00% (1/1)
", + "
  90.00% (6/7)
", + "
- (0/0)
", + ); + let out = recolor_coverage_table(input); + assert!(out.contains("class='column-entry-red'>
  50.00%"));
+        assert!(out.contains("class='column-entry-yellow'>
  51.23%"));
+        assert!(out.contains("class='column-entry-yellow'>
  80.00%"));
+        assert!(out.contains("class='column-entry-green'>
  81.00%"));
+        assert!(out.contains("class='column-entry-green'>
  90.00%"));
+        assert!(out.contains("class='column-entry-gray'>
- (0/0)"));
+    }
+}
-- 
cgit