Skip to content
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
58 changes: 58 additions & 0 deletions spin/cmds/meson.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import contextlib
import copy
import itertools
import json
import os
import re
Expand All @@ -14,6 +15,8 @@
from .util import get_commands, get_config
from .util import run as _run

LCOV_OUTPUT_FILE = Path("build", "meson-logs", "coveragereport")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This will depend on the build path the user specifies, so has to be set inside the build fn.



class GcovReportFormat(str, Enum):
html = "html"
Expand Down Expand Up @@ -231,6 +234,48 @@ def _check_coverage_tool_installation(coverage_type: GcovReportFormat, build_dir
)


def _get_coverage_files():
cwd = Path.cwd()
build_dir = Path(cwd, "build")
return itertools.chain(build_dir.rglob("*.gcda"), build_dir.rglob("*.da"))


def _gcov_reset_counters():
click.secho("Removing previous GCOV .gcda files...", fg="yellow")
for filename in _get_coverage_files():
Path.unlink(filename)


def _generate_lcov_coverage_html():
if next(_get_coverage_files(), None) is None:
raise click.ClickException(
"GCOV files missing... Cannot generate coverage reports. "
"Coverage reports can be generated by `spin test --coverage --gcov`"
)

click.secho(
"Deleting old HTML coverage report...",
fg="yellow",
)
shutil.rmtree(LCOV_OUTPUT_FILE, ignore_errors=True)

click.secho(
"Generating HTML coverage report...",
fg="blue",
)
cmd = ["ninja", "coverage-html", "-C", "build"]
p = _run(
cmd,
echo=True,
output=False,
)
coverage_folder = re.search(r"file://(.*)", p.stdout.decode("utf-8")).group(1)
click.secho(
f"Coverage report generated successfully and written to {coverage_folder}",
fg="green",
)


if sys.platform.startswith("win"):
DEFAULT_PREFIX = "C:/"
else:
Expand Down Expand Up @@ -447,6 +492,13 @@ def _get_configured_command(command_name):
default="html",
help=f"Format of the gcov report. Can be one of {', '.join(e.value for e in GcovReportFormat)}.",
)
@click.option(
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Instead of adding a new flag, what do you think of adding an html-lcov option to --gcov-format?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, it makes sense to club it. It would need a bit of rework I have used the enum to denote the coverage format directly. Let me see how we can make it neater and more generic.

"--generate-lcov-html",
is_flag=True,
help="produce HTML for C code coverage information "
"from a previous run with --gcov. "
"HTML output goes to `build/meson-logs/coveragereport/`",
)
@build_dir_option
@click.pass_context
def test(
Expand All @@ -459,6 +511,7 @@ def test(
coverage=False,
gcov=None,
gcov_format=None,
generate_lcov_html=None,
build_dir=None,
):
"""🔧 Run tests
Expand Down Expand Up @@ -503,6 +556,10 @@ def test(
distname = cfg.get("project.name", None)
pytest_args = pytest_args or ()

if generate_lcov_html:
_generate_lcov_coverage_html()
sys.exit(0)

# User specified tests without -t flag
# Rewrite arguments as though they specified using -t and proceed
if (len(pytest_args) == 1) and (not tests):
Expand Down Expand Up @@ -547,6 +604,7 @@ def test(
"Invoking `build` prior to running tests:", bold=True, fg="bright_green"
)
if gcov is not None:
_gcov_reset_counters()
ctx.invoke(build_cmd, build_dir=build_dir, gcov=bool(gcov))
else:
ctx.invoke(build_cmd, build_dir=build_dir)
Expand Down
Loading