From a87e2558cfaa30b22fd24fa0d69def54a147822f Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Thu, 5 Jan 2017 15:21:24 +1000 Subject: [PATCH] Hook up gcov for coverage reports ./configure --enable-gcov adds the required flags to link everything ready for gcov. A new make gcov target runs the test suite, then pulls all the gcov bits together into ./test/gcov-reports/ including a summary file. The script to pull everything out is used in libevdev too, we just have an extra condition here to ignore the selftest gcov bits (it overwrites the useful litest.c coverage output). Signed-off-by: Peter Hutterer --- Makefile.am | 3 +++ configure.ac | 21 ++++++++++++++++++ src/Makefile.am | 13 ++++++----- test/Makefile.am | 13 ++++++++++- test/generate-gcov-report.sh | 42 ++++++++++++++++++++++++++++++++++++ 5 files changed, 86 insertions(+), 6 deletions(-) create mode 100755 test/generate-gcov-report.sh diff --git a/Makefile.am b/Makefile.am index c2001b3c..dd98722e 100644 --- a/Makefile.am +++ b/Makefile.am @@ -6,3 +6,6 @@ valgrind: (cd test; $(MAKE) valgrind) AM_DISTCHECK_CONFIGURE_FLAGS = --disable-test-run + +gcov: + (cd test; $(MAKE) gcov) diff --git a/configure.ac b/configure.ac index 195862a7..1d6b7203 100644 --- a/configure.ac +++ b/configure.ac @@ -262,6 +262,26 @@ AM_CONDITIONAL(BUILD_DOCS, [test "x$build_documentation" = "xyes"]) AM_CONDITIONAL(HAVE_LIBUNWIND, [test "x$HAVE_LIBUNWIND" = xyes]) AM_CONDITIONAL(BUILD_EVENTGUI, [test "x$build_eventgui" = "xyes"]) +####################### +# enable/disable gcov # +####################### + +AC_ARG_ENABLE([gcov], + [AS_HELP_STRING([--enable-gcov], + [Enable to enable coverage testing (default:disabled)])], + [enable_gcov="$enableval"], + [enable_gcov=no]) +if test "x$enable_gcov" != "xno"; then + GCOV_CFLAGS="-fprofile-arcs -ftest-coverage" + GCOV_LDFLAGS="-fprofile-arcs -ftest-coverage" + enable_gcov=yes +fi + +AM_CONDITIONAL([GCOV_ENABLED], [test "x$enable_gcov" != "xno"]) +AC_SUBST([GCOV_CFLAGS]) +AC_SUBST([GCOV_LDFLAGS]) + + AC_CONFIG_FILES([Makefile doc/Makefile doc/libinput.doxygen @@ -288,4 +308,5 @@ AC_MSG_RESULT([ Tests use valgrind ${VALGRIND} Tests use libunwind ${HAVE_LIBUNWIND} Build GUI event tool ${build_eventgui} + Enable gcov profiling ${enable_gcov} ]) diff --git a/src/Makefile.am b/src/Makefile.am index a2bc94c3..a7ce4720 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -39,13 +39,17 @@ libinput_la_LIBADD = $(MTDEV_LIBS) \ $(LIBEVDEV_LIBS) \ $(LIBWACOM_LIBS) \ libinput-util.la +libinput_la_LDFLAGS = $(GCOV_LDFLAGS) \ + -version-info $(LIBINPUT_LT_VERSION) -shared \ + -Wl,--version-script=$(srcdir)/libinput.sym libinput_la_CFLAGS = -I$(top_srcdir)/include \ $(MTDEV_CFLAGS) \ $(LIBUDEV_CFLAGS) \ $(LIBEVDEV_CFLAGS) \ $(LIBWACOM_CFLAGS) \ - $(GCC_CFLAGS) + $(GCC_CFLAGS) \ + $(GCOV_CFLAGS) EXTRA_libinput_la_DEPENDENCIES = $(srcdir)/libinput.sym libinput_util_la_SOURCES = \ @@ -53,9 +57,11 @@ libinput_util_la_SOURCES = \ libinput-util.h libinput_util_la_LIBADD = +libinput_util_la_LDFLAGS = $(GCOV_LDFLAGS) libinput_util_la_CFLAGS = -I$(top_srcdir)/include \ $(LIBUDEV_CFLAGS) \ - $(GCC_CFLAGS) + $(GCC_CFLAGS) \ + $(GCOV_CFLAGS) libfilter_la_SOURCES = \ filter.c \ @@ -64,9 +70,6 @@ libfilter_la_SOURCES = \ libfilter_la_LIBADD = libfilter_la_CFLAGS = -libinput_la_LDFLAGS = -version-info $(LIBINPUT_LT_VERSION) -shared \ - -Wl,--version-script=$(srcdir)/libinput.sym - pkgconfigdir = $(libdir)/pkgconfig pkgconfig_DATA = libinput.pc diff --git a/test/Makefile.am b/test/Makefile.am index ba05729e..5980dba0 100644 --- a/test/Makefile.am +++ b/test/Makefile.am @@ -6,7 +6,7 @@ AM_CPPFLAGS = -I$(top_srcdir)/include \ $(LIBUDEV_CFLAGS) \ -I$(top_builddir)/src # for libinput-version.h -AM_CFLAGS = $(GCC_CFLAGS) +AM_CFLAGS = $(GCC_CFLAGS) $(GCOV_CFLAGS) AM_CXXFLAGS = $(GCC_CXXFLAGS) TEST_LIBS = liblitest.la $(CHECK_LIBS) $(LIBUDEV_LIBS) $(LIBEVDEV_LIBS) $(top_builddir)/src/libinput.la @@ -163,3 +163,14 @@ DISTCLEANFILES=test-suite-valgrind.log endif endif EXTRA_DIST=valgrind.suppressions + +if GCOV_ENABLED + +CLEANFILES = gcov-reports/*.gcov gcov-reports/summary.txt *.gcno *.gcda + +gcov: generate-gcov-report.sh check-TESTS + $(AM_V_GEN)$(srcdir)/generate-gcov-report.sh gcov-reports $(top_builddir)/src $(builddir) +else +gcov: + @echo "Run ./configure --enable-gcov to produce gcov reports" && false +endif diff --git a/test/generate-gcov-report.sh b/test/generate-gcov-report.sh new file mode 100755 index 00000000..2d913710 --- /dev/null +++ b/test/generate-gcov-report.sh @@ -0,0 +1,42 @@ +#!/bin/bash -e + +if [[ $# -lt 2 ]]; then + echo "Usage: ./generate-gcov-report.sh [ ... ]" + exit 1 +fi + +target_dir=$1 +shift +source_dirs=$* + +if [[ "${target_dir:0:1}" != '/' ]]; then + target_dir="$PWD/$target_dir" +fi +summary_file="$target_dir/summary.txt" + +mkdir -p "$target_dir" +rm -f "$target_dir"/*.gcov + +for dir in $source_dirs; do + pushd "$dir" > /dev/null + for file in *.c; do + find ./ -name "*${file/\.c/.gcda}" \ + \! -path "*selftest*" \ + -exec gcov {} \; > /dev/null + done + find ./ -name "*.gcov" \ + \! -path "*/`basename "$target_dir"`/*" \ + -exec mv {} "$target_dir" \; + popd > /dev/null +done + +echo "========== coverage report ========" > "$summary_file" +for file in "$target_dir"/*.gcov; do + total=`grep -v " -:" "$file" | wc -l` + missing=`grep "#####" "$file" | wc -l` + hit=$((total - missing)); + percent=$((($hit * 100)/$total)) + fname=`basename "$file"` + printf "%-50s total lines: %4s not tested: %4s (%3s%%)\n" "$fname" "$total" "$missing" "$percent">> "$summary_file" +done +echo "========== =============== ========" >> "$summary_file"