Verified Commit 1985c678 authored by Marek Vavruša's avatar Marek Vavruša Committed by Petr Špaček

build: added `make coverage` to compute C and Lua code coverage

Currently it gathers gcov and luacov code coverage, and merges it
in a single lcov info file. It returns summary at the end which the
CI can parse and interpret. It can build a html report later using
the data.
parent f41676d2
......@@ -9,7 +9,19 @@ clean: contrib-clean lib-clean daemon-clean client-clean modules-clean \
tests-clean doc-clean bench-clean
doc: doc-html
luacheck --codes .
luacheck --codes --formatter TAP .
coverage: $(wildcard */*/luacov.stats.out)
@echo "# C coverage in"
@lcov --no-external --capture --directory . --output-file > /dev/null
@if [ ! -z "$^" ]; then \
echo "# Lua coverage in luacov.stats.out and"; \
cat $^ > luacov.stats.out; \
./scripts/luacov_to_info.lua $^ >; \
lcov --add-tracefile --add-tracefile --output-file; \
else \
lcov --add-tracefile --output-file; \
.PHONY: all install check clean doc info
# Options
......@@ -63,6 +63,7 @@ There are also *optional* packages that enable specific functionality in Knot DN
"`libprotobuf-c`_ 1.0+", "``modules/dnstap``", "C bindings for Protobuf."
"libfstrm_ 0.2+", "``modules/dnstap``", "Frame Streams data transport protocol."
"luacheck_", "``lint``", "Syntax and static analysis checker for Lua."
"luacov_", "``check-config``", "Code coverage analysis for Lua modules."
.. [#] Requires C99, ``__attribute__((cleanup))`` and ``-MMD -MP`` for dependency file generation. GCC, Clang and ICC are supported.
.. [#] You can use variables ``<dependency>_CFLAGS`` and ``<dependency>_LIBS`` to configure dependencies manually (i.e. ``libknot_CFLAGS`` and ``libknot_LIBS``).
......@@ -250,6 +251,12 @@ Building extras
The project can be built with code coverage tracking using the ``COVERAGE=1`` variable.
The `make coverage` target gathers both gcov code coverage for C files, and luacov_ code coverage for Lua files and merges it for analysis. It requires lcov_ to be installed.
.. code-block:: bash
$ make coverage
Running unit and integration tests
......@@ -322,5 +329,7 @@ You can hack on the container by changing the container entrypoint to shell like
.. _libprotobuf-c:
.. _libfstrm:
.. _luacheck:
.. _luacov:
.. _lcov:
#!/usr/bin/env luajit
local luacov = require('luacov')
local ReporterBase = require('luacov.reporter').ReporterBase
local LcovReporter = setmetatable({}, ReporterBase)
LcovReporter.__index = LcovReporter
function LcovReporter:on_new_file(filename)
self.finfo = self.current_files[filename] or {name=filename, coverage={}}
function LcovReporter:on_mis_line(_, lineno, _)
self.finfo.coverage[lineno] = self.finfo.coverage[lineno] or 0
function LcovReporter:on_hit_line(_, lineno, _, hits)
self.finfo.coverage[lineno] = (self.finfo.coverage[lineno] or 0) + hits
function LcovReporter:on_end_file()
self.current_files[] = self.finfo
self.finfo = nil
-- Write out results in lcov format
local function write_lcov_info(files)
for fname, finfo in pairs(files) do
local instrumented, nonzero = 0, 0
print(string.format('SF:%s', fname))
for i, hits in pairs(finfo.coverage) do
print(string.format('DA:%d,%d', i - 1, hits))
instrumented = instrumented + 1
if hits > 0 then
nonzero = nonzero + 1
print(string.format('LH:%d', nonzero))
print(string.format('LF:%d', instrumented))
-- Accumulate total coverage
local all_files = {}
for _, fname in ipairs(arg) do
local conf = luacov.load_config()
conf.statsfile = fname
local reporter = assert(LcovReporter:new(conf))
reporter.current_files = all_files
-- Write results
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment