mirror of
https://github.com/lvgl/lvgl.git
synced 2026-05-10 04:37:55 +08:00
feat(scripts/check_gcov_coverage): add analysis of specified file paths (#9264)
Arduino Lint / lint (push) Has been cancelled
Build Examples with C++ Compiler / build-examples (push) Has been cancelled
MicroPython CI / Build esp32 port (push) Has been cancelled
MicroPython CI / Build rp2 port (push) Has been cancelled
MicroPython CI / Build stm32 port (push) Has been cancelled
MicroPython CI / Build unix port (push) Has been cancelled
C/C++ CI / Build OPTIONS_16BIT - Ubuntu (push) Has been cancelled
C/C++ CI / Build OPTIONS_24BIT - Ubuntu (push) Has been cancelled
C/C++ CI / Build OPTIONS_FULL_32BIT - Ubuntu (push) Has been cancelled
C/C++ CI / Build OPTIONS_NORMAL_8BIT - Ubuntu (push) Has been cancelled
C/C++ CI / Build OPTIONS_SDL - Ubuntu (push) Has been cancelled
C/C++ CI / Build OPTIONS_16BIT - cl - Windows (push) Has been cancelled
C/C++ CI / Build OPTIONS_16BIT - gcc - Windows (push) Has been cancelled
C/C++ CI / Build OPTIONS_24BIT - cl - Windows (push) Has been cancelled
C/C++ CI / Build OPTIONS_24BIT - gcc - Windows (push) Has been cancelled
C/C++ CI / Build OPTIONS_FULL_32BIT - cl - Windows (push) Has been cancelled
C/C++ CI / Build OPTIONS_FULL_32BIT - gcc - Windows (push) Has been cancelled
C/C++ CI / Build ESP IDF ESP32S3 (push) Has been cancelled
C/C++ CI / Run tests with 32bit build (push) Has been cancelled
C/C++ CI / Run tests with 64bit build (push) Has been cancelled
BOM Check / bom-check (push) Has been cancelled
Verify that lv_conf_internal.h matches repository state / verify-conf-internal (push) Has been cancelled
Verify the widget property name / verify-property-name (push) Has been cancelled
Verify code formatting / verify-formatting (push) Has been cancelled
Compare file templates with file names / template-check (push) Has been cancelled
Build docs / build-and-deploy (push) Has been cancelled
Test API JSON generator / Test API JSON (push) Has been cancelled
Install LVGL using CMake / build-examples (push) Has been cancelled
Check Makefile / Build using Makefile (push) Has been cancelled
Check Makefile for UEFI / Build using Makefile for UEFI (push) Has been cancelled
Emulated Performance Test / ARM Emulated Benchmark - Script Check (scripts/perf/tests/benchmark_results_comment/test.sh) (push) Has been cancelled
Emulated Performance Test / ARM Emulated Benchmark - Script Check (scripts/perf/tests/filter_docker_logs/test.sh) (push) Has been cancelled
Emulated Performance Test / ARM Emulated Benchmark - Script Check (scripts/perf/tests/serialize_results/test.sh) (push) Has been cancelled
Emulated Performance Test / ARM Emulated Benchmark 32b - lv_conf_perf32b (push) Has been cancelled
Emulated Performance Test / ARM Emulated Benchmark 64b - lv_conf_perf64b (push) Has been cancelled
Emulated Performance Test / ARM Emulated Benchmark - Save PR Number (push) Has been cancelled
Hardware Performance Test / Hardware Performance Benchmark (push) Has been cancelled
Hardware Performance Test / HW Benchmark - Save PR Number (push) Has been cancelled
Performance Tests CI / Perf Tests OPTIONS_TEST_PERF_32B - Ubuntu (push) Has been cancelled
Performance Tests CI / Perf Tests OPTIONS_TEST_PERF_64B - Ubuntu (push) Has been cancelled
Port repo release update / run-release-branch-updater (push) Has been cancelled
Verify Font License / verify-font-license (push) Has been cancelled
Verify Kconfig / verify-kconfig (push) Has been cancelled
Close stale issues and PRs / stale (push) Has been cancelled
Arduino Lint / lint (push) Has been cancelled
Build Examples with C++ Compiler / build-examples (push) Has been cancelled
MicroPython CI / Build esp32 port (push) Has been cancelled
MicroPython CI / Build rp2 port (push) Has been cancelled
MicroPython CI / Build stm32 port (push) Has been cancelled
MicroPython CI / Build unix port (push) Has been cancelled
C/C++ CI / Build OPTIONS_16BIT - Ubuntu (push) Has been cancelled
C/C++ CI / Build OPTIONS_24BIT - Ubuntu (push) Has been cancelled
C/C++ CI / Build OPTIONS_FULL_32BIT - Ubuntu (push) Has been cancelled
C/C++ CI / Build OPTIONS_NORMAL_8BIT - Ubuntu (push) Has been cancelled
C/C++ CI / Build OPTIONS_SDL - Ubuntu (push) Has been cancelled
C/C++ CI / Build OPTIONS_16BIT - cl - Windows (push) Has been cancelled
C/C++ CI / Build OPTIONS_16BIT - gcc - Windows (push) Has been cancelled
C/C++ CI / Build OPTIONS_24BIT - cl - Windows (push) Has been cancelled
C/C++ CI / Build OPTIONS_24BIT - gcc - Windows (push) Has been cancelled
C/C++ CI / Build OPTIONS_FULL_32BIT - cl - Windows (push) Has been cancelled
C/C++ CI / Build OPTIONS_FULL_32BIT - gcc - Windows (push) Has been cancelled
C/C++ CI / Build ESP IDF ESP32S3 (push) Has been cancelled
C/C++ CI / Run tests with 32bit build (push) Has been cancelled
C/C++ CI / Run tests with 64bit build (push) Has been cancelled
BOM Check / bom-check (push) Has been cancelled
Verify that lv_conf_internal.h matches repository state / verify-conf-internal (push) Has been cancelled
Verify the widget property name / verify-property-name (push) Has been cancelled
Verify code formatting / verify-formatting (push) Has been cancelled
Compare file templates with file names / template-check (push) Has been cancelled
Build docs / build-and-deploy (push) Has been cancelled
Test API JSON generator / Test API JSON (push) Has been cancelled
Install LVGL using CMake / build-examples (push) Has been cancelled
Check Makefile / Build using Makefile (push) Has been cancelled
Check Makefile for UEFI / Build using Makefile for UEFI (push) Has been cancelled
Emulated Performance Test / ARM Emulated Benchmark - Script Check (scripts/perf/tests/benchmark_results_comment/test.sh) (push) Has been cancelled
Emulated Performance Test / ARM Emulated Benchmark - Script Check (scripts/perf/tests/filter_docker_logs/test.sh) (push) Has been cancelled
Emulated Performance Test / ARM Emulated Benchmark - Script Check (scripts/perf/tests/serialize_results/test.sh) (push) Has been cancelled
Emulated Performance Test / ARM Emulated Benchmark 32b - lv_conf_perf32b (push) Has been cancelled
Emulated Performance Test / ARM Emulated Benchmark 64b - lv_conf_perf64b (push) Has been cancelled
Emulated Performance Test / ARM Emulated Benchmark - Save PR Number (push) Has been cancelled
Hardware Performance Test / Hardware Performance Benchmark (push) Has been cancelled
Hardware Performance Test / HW Benchmark - Save PR Number (push) Has been cancelled
Performance Tests CI / Perf Tests OPTIONS_TEST_PERF_32B - Ubuntu (push) Has been cancelled
Performance Tests CI / Perf Tests OPTIONS_TEST_PERF_64B - Ubuntu (push) Has been cancelled
Port repo release update / run-release-branch-updater (push) Has been cancelled
Verify Font License / verify-font-license (push) Has been cancelled
Verify Kconfig / verify-kconfig (push) Has been cancelled
Close stale issues and PRs / stale (push) Has been cancelled
Signed-off-by: pengyiqiang <pengyiqiang@xiaomi.com> Co-authored-by: pengyiqiang <pengyiqiang@xiaomi.com>
This commit is contained in:
+154
-34
@@ -8,7 +8,7 @@ import json
|
||||
import re
|
||||
import sys
|
||||
import os
|
||||
from typing import Dict, Set, Tuple, List
|
||||
from typing import Dict, Set, Tuple, List, Optional
|
||||
|
||||
|
||||
def create_argument_parser() -> argparse.ArgumentParser:
|
||||
@@ -24,6 +24,15 @@ def create_argument_parser() -> argparse.ArgumentParser:
|
||||
default="HEAD",
|
||||
)
|
||||
|
||||
parser.add_argument(
|
||||
"--path",
|
||||
metavar="PATH",
|
||||
help=(
|
||||
"Analyze coverage for a single file or a directory (relative or absolute path). "
|
||||
"When specified, --commit is ignored."
|
||||
),
|
||||
)
|
||||
|
||||
parser.add_argument(
|
||||
"--fail-under",
|
||||
type=float,
|
||||
@@ -212,6 +221,126 @@ def check_commit_coverage(
|
||||
return covered_lines, total_new_lines, uncovered_lines, skipped_noncoverable
|
||||
|
||||
|
||||
def check_path_coverage(path: str, root: str) -> Tuple[int, int, List[Tuple[str, int]]]:
|
||||
"""
|
||||
Compute coverage for a specific file or directory.
|
||||
Returns: (covered_lines, total_coverable_lines, uncovered_lines)
|
||||
Notes:
|
||||
- Only lines reported by gcovr as coverable are counted toward totals.
|
||||
- If PATH is a directory, coverage is aggregated over all coverable files within it.
|
||||
- If PATH is a file, coverage is computed only for that file.
|
||||
"""
|
||||
# Normalize input path
|
||||
abs_path = os.path.abspath(path)
|
||||
if not os.path.exists(abs_path):
|
||||
print(f"Error: The specified path does not exist: {abs_path}", file=sys.stderr)
|
||||
sys.exit(1)
|
||||
|
||||
# Ensure we operate from repo root to construct relative POSIX paths
|
||||
root = os.path.abspath(root)
|
||||
|
||||
# Build relative POSIX target(s)
|
||||
rel = os.path.relpath(abs_path, root)
|
||||
rel_posix = rel.replace(os.path.sep, "/")
|
||||
|
||||
print("Getting coverage data...")
|
||||
coverage_data = get_coverage_data(root)
|
||||
|
||||
covered = 0
|
||||
total = 0
|
||||
uncovered: List[Tuple[str, int]] = []
|
||||
|
||||
if os.path.isdir(abs_path):
|
||||
# Directory scope: include all files under this directory
|
||||
scoped_files = {}
|
||||
for f, lines in coverage_data.items():
|
||||
# Convert both to absolute paths for comparison
|
||||
f_abs = os.path.abspath(os.path.join(root, f.replace("/", os.path.sep)))
|
||||
# If the common path of abs_path and f_abs is abs_path, f is under abs_path
|
||||
if os.path.commonpath([abs_path, f_abs]) == abs_path:
|
||||
scoped_files[f] = lines
|
||||
|
||||
print(f"Found {len(scoped_files)} coverable file(s) under: {rel_posix}")
|
||||
for filename, line_map in sorted(scoped_files.items()):
|
||||
for lineno, count in line_map.items():
|
||||
total += 1
|
||||
if count > 0:
|
||||
covered += 1
|
||||
else:
|
||||
uncovered.append((filename, lineno))
|
||||
else:
|
||||
# File scope
|
||||
if rel_posix in coverage_data:
|
||||
line_map = coverage_data[rel_posix]
|
||||
print(f"Found coverable file: {rel_posix}")
|
||||
for lineno, count in line_map.items():
|
||||
total += 1
|
||||
if count > 0:
|
||||
covered += 1
|
||||
else:
|
||||
uncovered.append((rel_posix, lineno))
|
||||
else:
|
||||
print(
|
||||
f"Warning: No coverable lines found for '{rel_posix}' in gcovr output."
|
||||
)
|
||||
|
||||
return covered, total, uncovered
|
||||
|
||||
|
||||
def report_coverage(
|
||||
header: str,
|
||||
total: int,
|
||||
covered: int,
|
||||
uncovered: List[Tuple[str, int]],
|
||||
fail_under: float,
|
||||
*,
|
||||
total_label: str,
|
||||
skipped_noncoverable: Optional[int] = None,
|
||||
) -> int:
|
||||
"""
|
||||
Print a standardized coverage report and return exit code (0/1).
|
||||
|
||||
- header: text to show in the report title (e.g., "commit <hash>", "'<path>'")
|
||||
- total_label: label to use for the total line count (e.g.,
|
||||
"New coverable lines (per gcovr)" for commit mode, or
|
||||
"Coverable lines (per gcovr)" for path mode)
|
||||
- skipped_noncoverable: when provided, prints the skipped non-coverable count
|
||||
"""
|
||||
|
||||
title = f" Coverage analysis results for {header} "
|
||||
separator = "=" * len(title)
|
||||
print(f"\n{separator}\n{title}\n{separator}")
|
||||
print(f"{total_label}: {total}")
|
||||
print(f"Covered lines: {covered}")
|
||||
print(f"Uncovered lines: {len(uncovered)}")
|
||||
if skipped_noncoverable is not None:
|
||||
print(f"Skipped non-coverable changed lines: {skipped_noncoverable}")
|
||||
|
||||
retval = 0
|
||||
if total > 0:
|
||||
coverage_percent = (covered / total) * 100
|
||||
print(f"Coverage: {coverage_percent:.2f}%")
|
||||
if coverage_percent < fail_under:
|
||||
print(
|
||||
f"\n✗ Coverage {coverage_percent:.2f}% is below required {fail_under}%"
|
||||
)
|
||||
retval = 1
|
||||
|
||||
if uncovered:
|
||||
print(
|
||||
"\nUncovered lines (explicitly reported by gcovr as coverable with 0 hits):"
|
||||
)
|
||||
for filename, lineno in sorted(uncovered):
|
||||
print(f" {filename}:{lineno}")
|
||||
else:
|
||||
if total == 0:
|
||||
print("\nNo coverable lines found.")
|
||||
else:
|
||||
print(f"\n✓ Code coverage check passed!")
|
||||
|
||||
return retval
|
||||
|
||||
|
||||
def main() -> int:
|
||||
"""Main entry point"""
|
||||
parser = create_argument_parser()
|
||||
@@ -223,42 +352,33 @@ def main() -> int:
|
||||
os.chdir(root)
|
||||
print(f"Current working directory: {root}")
|
||||
|
||||
covered, total, uncovered, skipped_noncoverable = check_commit_coverage(
|
||||
args.commit, root
|
||||
)
|
||||
if args.path:
|
||||
# Path mode: ignore commit, compute coverage for file/dir
|
||||
covered, total, uncovered = check_path_coverage(args.path, root)
|
||||
|
||||
# Print results with better formatting
|
||||
title = f" Coverage analysis results for commit {args.commit} "
|
||||
separator = "=" * len(title)
|
||||
print(f"\n{separator}\n{title}\n{separator}")
|
||||
print(f"New coverable lines (per gcovr): {total}")
|
||||
print(f"Covered lines: {covered}")
|
||||
print(f"Uncovered lines: {len(uncovered)}")
|
||||
print(f"Skipped non-coverable changed lines: {skipped_noncoverable}")
|
||||
retval = 0
|
||||
|
||||
if total > 0:
|
||||
coverage_percent = (covered / total) * 100
|
||||
print(f"Coverage: {coverage_percent:.2f}%")
|
||||
|
||||
# Check if coverage meets minimum requirement
|
||||
if coverage_percent < args.fail_under:
|
||||
print(
|
||||
f"\n✗ Coverage {coverage_percent:.2f}% is below required {args.fail_under}%"
|
||||
)
|
||||
retval = 1
|
||||
|
||||
if uncovered:
|
||||
print(
|
||||
"\nUncovered lines (explicitly reported by gcovr as coverable with 0 hits):"
|
||||
return report_coverage(
|
||||
header=f"'{args.path}'",
|
||||
total=total,
|
||||
covered=covered,
|
||||
uncovered=uncovered,
|
||||
fail_under=args.fail_under,
|
||||
total_label="Coverable lines (per gcovr)",
|
||||
)
|
||||
else:
|
||||
# Commit mode: default behavior
|
||||
covered, total, uncovered, skipped_noncoverable = check_commit_coverage(
|
||||
args.commit, root
|
||||
)
|
||||
for filename, lineno in sorted(uncovered):
|
||||
print(f" {filename}:{lineno}")
|
||||
|
||||
return retval
|
||||
|
||||
print("\n✓ All new coverable code is covered!")
|
||||
return retval
|
||||
return report_coverage(
|
||||
header=f"commit {args.commit}",
|
||||
total=total,
|
||||
covered=covered,
|
||||
uncovered=uncovered,
|
||||
fail_under=args.fail_under,
|
||||
total_label="New coverable lines (per gcovr)",
|
||||
skipped_noncoverable=skipped_noncoverable,
|
||||
)
|
||||
|
||||
except subprocess.CalledProcessError as e:
|
||||
print(f"Error: Command failed - {e}", file=sys.stderr)
|
||||
|
||||
Reference in New Issue
Block a user