CI: Add ability to generate patch coverage reports
This commit is contained in:
parent
f09c30df35
commit
540e042221
36
Makefile.in
36
Makefile.in
|
|
@ -603,9 +603,16 @@ COVERAGE_DIR := obj_coverage
|
|||
|
||||
ifeq ($(CFG_WITH_DEV_GCOV),yes)
|
||||
|
||||
FASTCOV := nodist/fastcov.py
|
||||
# Figure out base and head refs for coverage report
|
||||
COVERAGE_REF_BASE := $(if $(COVERAGE_BASE),$(shell git rev-parse --short $(COVERAGE_BASE)))
|
||||
COVERAGE_REF_HEAD := $(shell git rev-parse --short HEAD)
|
||||
override undefine COVERAGE_BASE # Use the above variabels instead
|
||||
COVERAGE_PATCH_FILE := $(COVERAGE_DIR)/$(if $(COVERAGE_REF_BASE),$(COVERAGE_REF_BASE).patch,.none.pach)
|
||||
|
||||
# 'fastcov' setup
|
||||
FASTCOV := nodist/fastcov.py
|
||||
FASTCOV_OPT := -j $(shell nproc)
|
||||
FASTCOV_OPT += --lcov
|
||||
FASTCOV_OPT += --process-gcno
|
||||
FASTCOV_OPT += --branch-coverage
|
||||
FASTCOV_OPT += --dump-statistic
|
||||
|
|
@ -642,7 +649,9 @@ FASTCOV_OPT += BROKEN_BASE_RTN
|
|||
FASTCOV_OPT += SELF_CHECK
|
||||
FASTCOV_OPT += 'if (VL_UNCOVERABLE'
|
||||
FASTCOV_OPT += '} else if (VL_UNCOVERABLE'
|
||||
FASTCOV_OPT += $(if $(COVERAGE_REF_BASE),--diff-filter $(COVERAGE_PATCH_FILE))
|
||||
|
||||
# 'genhtml' setup
|
||||
GENHTML := genhtml
|
||||
GENHTML_OPT := -j $(shell nproc)
|
||||
GENHTML_OPT += --branch-coverage
|
||||
|
|
@ -650,26 +659,43 @@ GENHTML_OPT += --demangle-cpp
|
|||
GENHTML_OPT += --rc branch_coverage=1
|
||||
GENHTML_OPT += --rc genhtml_hi_limit=100
|
||||
GENHTML_OPT += --ignore-errors negative
|
||||
GENHTML_OPT += --header-title "Verilator code coverage report"
|
||||
ifeq ($(COVERAGE_REF_BASE),)
|
||||
GENHTML_OPT += --header-title "Code coverage for Verilator $(shell git describe --dirty)"
|
||||
else
|
||||
GENHTML_OPT += --header-title "Patch coverage for Verilator $(COVERAGE_REF_BASE)..$(COVERAGE_REF_HEAD)$(if $(git status --porcelain),,-dirty)"
|
||||
endif
|
||||
GENHTML_OPT += --flat
|
||||
GENHTML_OPT += --precision 2
|
||||
GENHTML_OPT += --legend
|
||||
GENHTML_OPT += --show-proportion
|
||||
GENHTML_OPT += --filter brace,blank,range
|
||||
|
||||
# There are loads (~20k combined), but using this seems fine on modern hardware
|
||||
GCNO_FILES = $(shell find . -name '*.gcno')
|
||||
GCDA_FILES = $(shell find . -name '*.gcda')
|
||||
|
||||
# Patch file to filter coverage with - unused if doing full coverage
|
||||
$(COVERAGE_PATCH_FILE):
|
||||
@mkdir -p $(COVERAGE_DIR)
|
||||
@touch $@
|
||||
$(if $(COVERAGE_REF_BASE), git diff $(COVERAGE_REF_BASE) > $(COVERAGE_PATCH_FILE))
|
||||
|
||||
# Combine all .gcda coverage date files into lcov .info file
|
||||
$(COVERAGE_DIR)/verilator.info: $(GCNO_FILES) $(GCDA_FILES)
|
||||
$(COVERAGE_DIR)/verilator.info: $(COVERAGE_PATCH_FILE) $(GCNO_FILES) $(GCDA_FILES)
|
||||
@echo "####################################################################"
|
||||
@echo "# fastcov: combining all .gcda files into lcov .info"
|
||||
@echo "####################################################################"
|
||||
mkdir -p $(COVERAGE_DIR)
|
||||
/usr/bin/time -f "That took %E" \
|
||||
$(FASTCOV) $(FASTCOV_OPT) --lcov --output $@
|
||||
$(FASTCOV) $(FASTCOV_OPT) --output $@
|
||||
@# Uncommitted changes not tracked, force rebuild on next run if patch coverage
|
||||
@$(if $(COVERAGE_REF_BASE),rm $(COVERAGE_PATCH_FILE))
|
||||
|
||||
# Build coverage report
|
||||
$(COVERAGE_DIR)/report/index.html: $(COVERAGE_DIR)/verilator.info
|
||||
@echo "####################################################################"
|
||||
@echo "# genhtml: Generating coverage report"
|
||||
@echo "####################################################################"
|
||||
@rm -rf $(COVERAGE_DIR)/reprot
|
||||
/usr/bin/time -f "That took %E" \
|
||||
$(GENHTML) $(GENHTML_OPT) --output-directory $(COVERAGE_DIR)/report $^
|
||||
|
||||
|
|
|
|||
|
|
@ -1695,6 +1695,15 @@ Be aware if changing a test, if that test no longer covers some item, the
|
|||
report will still contain the old coverage. Use ``make coverage-zero`` and
|
||||
rerun all tests if this is a concern.
|
||||
|
||||
It is also possible to generate a 'patch coverage' report, which will only
|
||||
contain information about lines modified compared to a Git ref specified by the
|
||||
``COVERAGE_BASE`` Make variable (including uncommitted changes). For example,
|
||||
to see coverage of changes compared to upstream, use:
|
||||
|
||||
.. code:: shell
|
||||
|
||||
make coverage-view COVERAGE_BASE=origin/master
|
||||
|
||||
Fuzzing
|
||||
-------
|
||||
|
||||
|
|
|
|||
|
|
@ -509,6 +509,13 @@ def containsMarker(markers, strBody):
|
|||
def exclProcessSource(fastcov_sources, source, exclude_branches_sw, include_branches_sw, exclude_line_marker, fallback_encodings, gcov_prefix, gcov_prefix_strip):
|
||||
source_to_open = processPrefix(source, gcov_prefix, gcov_prefix_strip)
|
||||
|
||||
# Before doing any work, check if this file even needs to be processed
|
||||
if not exclude_branches_sw and not include_branches_sw:
|
||||
# Ignore unencodable characters
|
||||
with open(source_to_open, errors="ignore") as f:
|
||||
if not containsMarker(exclude_line_marker + ["LCOV_EXCL"], f.read()):
|
||||
return False
|
||||
|
||||
# If we've made it this far we have to check every line
|
||||
|
||||
start_line = 0
|
||||
|
|
@ -526,10 +533,8 @@ def exclProcessSource(fastcov_sources, source, exclude_branches_sw, include_bran
|
|||
if del_exclude_br or del_include_br:
|
||||
del fastcov_data["branches"][i]
|
||||
|
||||
lineIsClosingBrace = line.strip() == "}"
|
||||
|
||||
# Skip to next line as soon as possible
|
||||
if not containsMarker(exclude_line_marker + ["LCOV_EXCL"], line) and not lineIsClosingBrace:
|
||||
if not containsMarker(exclude_line_marker + ["LCOV_EXCL"], line):
|
||||
continue
|
||||
|
||||
# Build line to function dict so can quickly delete by line number
|
||||
|
|
@ -540,7 +545,7 @@ def exclProcessSource(fastcov_sources, source, exclude_branches_sw, include_bran
|
|||
line_to_func[l] = set()
|
||||
line_to_func[l].add(f)
|
||||
|
||||
if lineIsClosingBrace or any(marker in line for marker in exclude_line_marker):
|
||||
if any(marker in line for marker in exclude_line_marker):
|
||||
for key in ["lines", "branches"]:
|
||||
if i in fastcov_data[key]:
|
||||
del fastcov_data[key][i]
|
||||
|
|
|
|||
Loading…
Reference in New Issue