Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Single html report #916

Merged
merged 16 commits into from
Jun 4, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
1 change: 1 addition & 0 deletions CHANGELOG.rst
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ New features and notable changes:

- In Azure pipelines or GitHub actions errors and warnings are printed in an additional format captured by the CI. (:issue:`904`)
- Detect suspicious counter values in ``gcov`` output. (:issue:`903`)
- Add :option:`--html-single-page` to create a single page report (static or with Javascript). (:issue:`916`)

Bug fixes and small improvements:

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,10 @@
</head>

<body>

<header>
<h1>GCC Code Coverage Report</h1>

<hr/>

<div class="summary">
<div>
<table class="legend">
Expand Down Expand Up @@ -60,10 +59,8 @@ <h1>GCC Code Coverage Report</h1>
</table>
</div>
</div>

<hr/>
</header>

<nav>
<details>
<summary>List of functions</summary>
Expand All @@ -79,7 +76,6 @@ <h1>GCC Code Coverage Report</h1>
</details>

</nav>

<main>
<div class="file-source">
<table>
Expand Down Expand Up @@ -254,7 +250,6 @@ <h1>GCC Code Coverage Report</h1>
</div>
<hr/>
</main>

<footer>
Generated by: <a href="http://gcovr.com/en/main">GCOVR (Version 7.2+main)</a>
</footer>
Expand Down
7 changes: 1 addition & 6 deletions doc/examples/example_html.details.functions.html
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,10 @@
</head>

<body>

<header>
<h1>GCC Code Coverage Report</h1>

<hr/>

<div class="summary">
<div>
<table class="legend">
Expand Down Expand Up @@ -57,13 +56,10 @@ <h1>GCC Code Coverage Report</h1>
</table>
</div>
</div>

<hr/>
</header>

<nav>
</nav>

<main>
<table class="listOfFunctions">
<tr>
Expand All @@ -77,7 +73,6 @@ <h1>GCC Code Coverage Report</h1>

<hr/>
</main>

<footer>
Generated by: <a href="http://gcovr.com/en/main">GCOVR (Version 7.2+main)</a>
</footer>
Expand Down
7 changes: 1 addition & 6 deletions doc/examples/example_html.details.html
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,10 @@
</head>

<body>

<header>
<h1>GCC Code Coverage Report</h1>

<hr/>

<div class="summary">
<div>
<table class="legend">
Expand Down Expand Up @@ -65,14 +64,11 @@ <h1>GCC Code Coverage Report</h1>
</table>
</div>
</div>

<hr/>
</header>

<nav>
<a href="example_html.details.functions.html">List of functions</a>
</nav>

<main>
<table class="file-list">
<col/>
Expand Down Expand Up @@ -106,7 +102,6 @@ <h1>GCC Code Coverage Report</h1>
</table>
<hr/>
</main>

<footer>
Generated by: <a href="http://gcovr.com/en/main">GCOVR (Version 7.2+main)</a>
</footer>
Expand Down
7 changes: 1 addition & 6 deletions doc/examples/example_html.html
Original file line number Diff line number Diff line change
Expand Up @@ -612,11 +612,10 @@
</head>

<body>

<header>
<h1>GCC Code Coverage Report</h1>

<hr/>

<div class="summary">
<div>
<table class="legend">
Expand Down Expand Up @@ -668,14 +667,11 @@ <h1>GCC Code Coverage Report</h1>
</table>
</div>
</div>

<hr/>
</header>

<nav>

</nav>

<main>
<table class="file-list">
<col/>
Expand Down Expand Up @@ -709,7 +705,6 @@ <h1>GCC Code Coverage Report</h1>
</table>
<hr/>
</main>

<footer>
Generated by: <a href="http://gcovr.com/en/main">GCOVR (Version 7.2+main)</a>
</footer>
Expand Down
42 changes: 4 additions & 38 deletions gcovr/__main__.py
Original file line number Diff line number Diff line change
Expand Up @@ -275,46 +275,12 @@ def main(args=None):
)
sys.exit(EXIT_CMDLINE_ERROR)

if options.html_tab_size < 1:
LOGGER.error("value of --html-tab-size= should be greater 0.")
sys.exit(EXIT_CMDLINE_ERROR)

if options.html_details and options.html_nested:
LOGGER.error("--html-details and --html-nested can not be used together.")
sys.exit(EXIT_CMDLINE_ERROR)

potential_html_output = (
(options.html and options.html.value)
or (options.html_details and options.html_details.value)
or (options.html_nested and options.html_nested.value)
or (options.output and options.output.value)
)
if options.html_details and not potential_html_output:
LOGGER.error(
"a named output must be given, if the option --html-details\n" "is used."
)
sys.exit(EXIT_CMDLINE_ERROR)

if options.html_nested and not potential_html_output:
LOGGER.error(
"a named output must be given, if the option --html-nested\n" "is used."
)
sys.exit(EXIT_CMDLINE_ERROR)

if options.html_self_contained is False and not potential_html_output:
LOGGER.error(
"can only disable --html-self-contained when a named output is given."
)
try:
gcovr_formats.validate_options(options)
except RuntimeError as exc:
LOGGER.error(str(exc))
sys.exit(EXIT_CMDLINE_ERROR)

if options.gcov_objdir is not None:
if not os.path.exists(options.gcov_objdir):
LOGGER.error(
"Bad --gcov-object-directory option.\n"
"\tThe specified directory does not exist."
)
sys.exit(EXIT_CMDLINE_ERROR)

options.starting_dir = os.path.abspath(os.getcwd())
options.root_dir = os.path.abspath(options.root)

Expand Down
17 changes: 17 additions & 0 deletions gcovr/formats/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,23 @@ def get_options() -> List[GcovrConfigOption]:
]


def validate_options(options) -> CovData:
for handler in [
GcovHandler,
CloverHandler,
CoberturaHandler,
CoverallsHandler,
CsvHandler,
HtmlHandler,
JaCoCoHandler,
JsonHandler,
LcovHandler,
SonarqubeHandler,
TxtHandler,
]:
handler(options).validate_options()


def read_reports(options) -> CovData:
if options.json_add_tracefile or options.cobertura_add_tracefile:
covdata: CovData = JsonHandler(options).read_report() or {}
Expand Down
8 changes: 8 additions & 0 deletions gcovr/formats/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ def get_options() -> List[GcovrConfigOption]:

def __init__(self, options: Options):
global_options = [
"output",
"timestamp",
"root",
"root_dir",
Expand All @@ -49,11 +50,18 @@ def __init__(self, options: Options):
option_dict[name] = options.get(name)
self.options = Options(**option_dict)

def validate_options(self) -> None:
"""Validation of command line options"""
pass

def read_report(self) -> CovData:
"""Read a report in the format of the handler"""
raise RuntimeError("Function 'read_report' not implemented.")

def write_report(self, covdata: CovData, output_file: str) -> None:
"""Write a report in the format of the handler"""
raise RuntimeError("Function 'write_report' not implemented.")

def write_summary_report(self, covdata: CovData, output_file: str) -> None:
"""Write a summary report in the format of the handler"""
raise RuntimeError("Function 'write_summary_report' not implemented.")
9 changes: 9 additions & 0 deletions gcovr/formats/gcov/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -198,6 +198,15 @@ def get_options() -> List[GcovrConfigOption]:
),
]

def validate_options(self) -> None:
if self.options.gcov_objdir is not None and not os.path.exists(
self.options.gcov_objdir
):
raise RuntimeError(
"Bad --gcov-object-directory option.\n"
"\tThe specified directory does not exist."
)

def read_report(self) -> CovData:
from .read import read_report

Expand Down
75 changes: 74 additions & 1 deletion gcovr/formats/html/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -256,15 +256,88 @@ def get_options() -> List[GcovrConfigOption]:
"Control whether the HTML report bundles resources like CSS styles. "
"Self-contained reports can be sent via email, "
"but conflict with the Content Security Policy of some web servers. "
"Defaults to self-contained reports unless --html-details is used."
"Defaults to self-contained reports unless --html-details or "
"--html-nested is used without --html-single-page."
),
action="store_const",
default=None,
const=True,
const_negate=False,
),
GcovrConfigOption(
"html_single_page",
["--html-single-page"],
group="output_options",
choices=["static", "js-enabled"],
nargs="?",
const="js-enabled",
default=None,
help=(
"Use one single html output file containing all data in the "
"specified mode. If mode is 'js-enabled' (default) and javascript "
"is possible the page is interactive like the normal report. "
"If mode is 'static' all files are shown at once."
),
),
]

def validate_options(self) -> None:
if self.options.html_tab_size < 1:
raise RuntimeError("value of --html-tab-size= should be greater 0.")

if self.options.html_details and self.options.html_nested:
raise RuntimeError(
"--html-details and --html-nested can not be used together."
)

html_output = None
if self.options.html and self.options.html.value:
html_output = self.options.html.value
elif self.options.html_details and self.options.html_details.value:
html_output = self.options.html_details.value
elif self.options.html_nested and self.options.html_nested.value:
html_output = self.options.html_nested.value
elif self.options.output and self.options.output.value:
html_output = self.options.output.value

if self.options.html_details and not html_output:
raise RuntimeError(
"a named output must be given, if the option --html-details is used."
)

if self.options.html_nested and not html_output:
raise RuntimeError(
"a named output must be given, if the option --html-nested is used."
)

if (
html_output == "-"
and not self.options.html_single_page
and (self.options.html_details or self.options.html_nested)
):
raise RuntimeError(
"detailed reports can only be printed to STDOUT as --html-single-page."
)

if self.options.html_single_page and not (
self.options.html_details or self.options.html_nested
):
raise RuntimeError(
"option --html-details or --html-nested is needed, if the option --html-single-page is used."
)

if self.options.html_self_contained is False and not html_output:
raise RuntimeError(
"can only disable --html-self-contained when a named output is given."
)

if (
self.options.html_self_contained is False
and html_output == "-"
and not self.options.html_single_page
):
raise RuntimeError("only self contained reports can be printed to STDOUT")

def write_report(self, covdata: CovData, output_file: str) -> None:
from .write import write_report

Expand Down