Skip to content

Commit 5880d5e

Browse files
committed
ENH: Add generate-lcov-html flag
1 parent 794cabf commit 5880d5e

File tree

1 file changed

+58
-0
lines changed

1 file changed

+58
-0
lines changed

spin/cmds/meson.py

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import contextlib
22
import copy
3+
import itertools
34
import json
45
import os
56
import re
@@ -14,6 +15,8 @@
1415
from .util import get_commands, get_config
1516
from .util import run as _run
1617

18+
LCOV_OUTPUT_FILE = Path("build", "meson-logs", "coveragereport")
19+
1720

1821
class GcovReportFormat(str, Enum):
1922
html = "html"
@@ -231,6 +234,48 @@ def _check_coverage_tool_installation(coverage_type: GcovReportFormat, build_dir
231234
)
232235

233236

237+
def _get_coverage_files():
238+
cwd = Path.cwd()
239+
build_dir = Path(cwd, "build")
240+
return itertools.chain(build_dir.rglob("*.gcda"), build_dir.rglob("*.da"))
241+
242+
243+
def _gcov_reset_counters():
244+
click.secho("Removing previous GCOV .gcda files...", fg="yellow")
245+
for filename in _get_coverage_files():
246+
Path.unlink(filename)
247+
248+
249+
def _generate_lcov_coverage_html():
250+
if next(_get_coverage_files(), None) is None:
251+
raise click.ClickException(
252+
"GCOV files missing... Cannot generate coverage reports. "
253+
"Coverage reports can be generated by `spin test --coverage --gcov`"
254+
)
255+
256+
click.secho(
257+
"Deleting old HTML coverage report...",
258+
fg="yellow",
259+
)
260+
shutil.rmtree(LCOV_OUTPUT_FILE, ignore_errors=True)
261+
262+
click.secho(
263+
"Generating HTML coverage report...",
264+
fg="blue",
265+
)
266+
cmd = ["ninja", "coverage-html", "-C", "build"]
267+
p = _run(
268+
cmd,
269+
echo=True,
270+
output=False,
271+
)
272+
coverage_folder = re.search(r"file://(.*)", p.stdout.decode("utf-8")).group(1)
273+
click.secho(
274+
f"Coverage report generated successfully and written to {coverage_folder}",
275+
fg="green",
276+
)
277+
278+
234279
if sys.platform.startswith("win"):
235280
DEFAULT_PREFIX = "C:/"
236281
else:
@@ -447,6 +492,13 @@ def _get_configured_command(command_name):
447492
default="html",
448493
help=f"Format of the gcov report. Can be one of {', '.join(e.value for e in GcovReportFormat)}.",
449494
)
495+
@click.option(
496+
"--generate-lcov-html",
497+
is_flag=True,
498+
help="produce HTML for C code coverage information "
499+
"from a previous run with --gcov. "
500+
"HTML output goes to `build/meson-logs/coveragereport/`",
501+
)
450502
@build_dir_option
451503
@click.pass_context
452504
def test(
@@ -459,6 +511,7 @@ def test(
459511
coverage=False,
460512
gcov=None,
461513
gcov_format=None,
514+
generate_lcov_html=None,
462515
build_dir=None,
463516
):
464517
"""🔧 Run tests
@@ -503,6 +556,10 @@ def test(
503556
distname = cfg.get("project.name", None)
504557
pytest_args = pytest_args or ()
505558

559+
if generate_lcov_html:
560+
_generate_lcov_coverage_html()
561+
sys.exit(0)
562+
506563
# User specified tests without -t flag
507564
# Rewrite arguments as though they specified using -t and proceed
508565
if (len(pytest_args) == 1) and (not tests):
@@ -547,6 +604,7 @@ def test(
547604
"Invoking `build` prior to running tests:", bold=True, fg="bright_green"
548605
)
549606
if gcov is not None:
607+
_gcov_reset_counters()
550608
ctx.invoke(build_cmd, build_dir=build_dir, gcov=bool(gcov))
551609
else:
552610
ctx.invoke(build_cmd, build_dir=build_dir)

0 commit comments

Comments
 (0)