From: Frank Lichtenheld <[email protected]> Can be used like this ./configure --enable-code-coverage make make check make code-coverage-capture
We heavily patch ax_code_coverage.m4, mostly to achieve better compatibility with non-Linux systems. - Do not depend on autoconf-archive - Do not depend on GNU make - Use more modern --coverage flag to better support different compilers Change-Id: I79b2dc4a550b1c5068a45407976b0dfc2f765b33 Signed-off-by: Frank Lichtenheld <[email protected]> Acked-by: Razvan Cojocaru <[email protected]> Gerrit URL: https://gerrit.openvpn.net/c/openvpn/+/1592 --- This change was reviewed on Gerrit and approved by at least one developer. I request to merge it to master. Gerrit URL: https://gerrit.openvpn.net/c/openvpn/+/1592 This mail reflects revision 6 of this Change. Acked-by according to Gerrit (reflected above): Razvan Cojocaru <[email protected]> diff --git a/.gitignore b/.gitignore index 04523af..2749739 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,9 @@ *.[oa] *.l[oa] +*.gcda +*.gcno +*-coverage/ +*-coverage.info *.dll *.exe *.exe.* @@ -18,6 +22,7 @@ Makefile Makefile.in aclocal.m4 +aminclude_static.am autodefs.h autom4te.cache config.guess diff --git a/Makefile.am b/Makefile.am index 125fe84..d3910ed 100644 --- a/Makefile.am +++ b/Makefile.am @@ -22,6 +22,8 @@ # with this program; if not, see <https://www.gnu.org/licenses/>. # +include $(top_srcdir)/aminclude_static.am + ACLOCAL_AMFLAGS = -I m4 MAINTAINERCLEANFILES = \ @@ -45,7 +47,8 @@ CMakeLists.txt \ CMakePresets.json \ config.h.cmake.in \ - forked-test-driver + forked-test-driver \ + lcovrc .PHONY: config-version.h doxygen @@ -98,3 +101,7 @@ INCLUDE_FLAGS="$(LIBNL_GENL_CFLAGS)" \ CPPCHECK_VERBOSE="$(AM_V_P)" \ "$(top_srcdir)/dev-tools/run-cppcheck.sh" + +CODE_COVERAGE_LCOV_SHOPTS=--config-file $(srcdir)/lcovrc +clean-local: code-coverage-clean +distclean-local: code-coverage-dist-clean diff --git a/configure.ac b/configure.ac index 56109af..7d646c5 100644 --- a/configure.ac +++ b/configure.ac @@ -59,6 +59,8 @@ AC_CANONICAL_HOST AC_USE_SYSTEM_EXTENSIONS +AX_CODE_COVERAGE + AC_ARG_ENABLE( [lzo], [AS_HELP_STRING([--disable-lzo], [disable LZO compression support @<:@default=yes@:>@])], @@ -1236,6 +1238,11 @@ ACL_CHECK_ADD_COMPILE_FLAGS([-Wno-cast-function-type]) fi +# If coverage is enabled remove -O arguments from CFLAGS +if test "$enable_code_coverage" = "yes"; then + [CFLAGS="`echo $CFLAGS | $SED -e 's/-O[a-z0-9]*//g'`"] +fi + if test "${enable_pedantic}" = "yes"; then CFLAGS="${CFLAGS} -pedantic" AC_DEFINE([PEDANTIC], [1], [Enable pedantic mode]) @@ -1355,10 +1362,10 @@ TEST_LDFLAGS="${OPTIONAL_CRYPTO_LIBS} ${OPTIONAL_PKCS11_HELPER_LIBS} ${OPTIONAL_LIBCAPNG_LIBS}" TEST_LDFLAGS="${TEST_LDFLAGS} ${OPTIONAL_LIBNL_GENL_LIBS}" -TEST_LDFLAGS="${TEST_LDFLAGS} ${OPTIONAL_LZO_LIBS} ${CMOCKA_LIBS}" +TEST_LDFLAGS="${TEST_LDFLAGS} ${OPTIONAL_LZO_LIBS} ${CMOCKA_LIBS} ${CODE_COVERAGE_LIBS}" TEST_CFLAGS="${OPTIONAL_CRYPTO_CFLAGS} ${OPTIONAL_PKCS11_HELPER_CFLAGS} ${OPTIONAL_LIBCAPNG_CFLAGS}" TEST_CFLAGS="${TEST_CFLAGS} ${OPTIONAL_LIBNL_GENL_CFLAGS} ${OPTIONAL_LZO_CFLAGS}" -TEST_CFLAGS="${TEST_CFLAGS} -I\$(top_srcdir)/include ${CMOCKA_CFLAGS}" +TEST_CFLAGS="${TEST_CFLAGS} -I\$(top_srcdir)/include ${CMOCKA_CFLAGS} ${CODE_COVERAGE_CFLAGS}" AC_SUBST([TEST_LDFLAGS]) AC_SUBST([TEST_CFLAGS]) diff --git a/lcovrc b/lcovrc new file mode 100644 index 0000000..f8b4138 --- /dev/null +++ b/lcovrc @@ -0,0 +1,2 @@ +geninfo_external = 1 +geninfo_unexecuted_blocks = 1 diff --git a/m4/ax_code_coverage.m4 b/m4/ax_code_coverage.m4 index 216708a4..f156d4d 100644 --- a/m4/ax_code_coverage.m4 +++ b/m4/ax_code_coverage.m4 @@ -42,8 +42,8 @@ # clean-local: code-coverage-clean # distclean-local: code-coverage-dist-clean # -# This results in a "check-code-coverage" rule being added to any -# Makefile.am which do "include $(top_srcdir)/aminclude_static.am" +# This results in a "check-code-coverage" rule being added to the +# Makefile.am which does "include $(top_srcdir)/aminclude_static.am" # (assuming the module has been configured with --enable-code-coverage). # Running `make check-code-coverage` in that directory will run the # module's test suite (`make check`) and build a code coverage report @@ -76,10 +76,51 @@ #serial 37 +dnl Local modifications compared to the autoconf-archive version: +dnl +dnl - AX_ADD_AM_MACRO_STATIC (from autoconf-archive) is replaced by a +dnl minimal local equivalent, OPENVPN_ADD_AM_MACRO_STATIC, so that we do +dnl not depend on autoconf-archive being installed. +dnl - The generated rules no longer require GNU make. The AX_CHECK_GNU_MAKE +dnl check is gone (which also removed the last autoconf-archive +dnl dependency) and the GNU make specific constructs in the rules were +dnl replaced: +dnl * the "ifeq ($(abs_builddir), $(abs_top_builddir))" guard is gone, +dnl aminclude_static.am may only be included by the top level +dnl Makefile.am now (which is the only place it was ever included +dnl from in this project), +dnl * $(addprefix ...) and $(if ...) are replaced by shell code inside +dnl the recipes, +dnl * $(call ...)/$(subst ...) for the lcov test name is replaced by +dnl CODE_COVERAGE_TEST_NAME, computed at configure time, +dnl * "find ... -delete" is replaced by "find ... -exec rm -f {} +". +dnl The only remaining non-POSIX construct is the nested variable +dnl expansion used for the silent rules ($(foo_$(V))), which is the same +dnl idiom automake itself uses for AM_V_at and friends and which is +dnl understood by BSD make as well. + +AC_DEFUN([OPENVPN_PRINT_TO_FILE],[ +m4_esyscmd( +[ +printf "%s" "$2" > "$1" +]) +]) + +AC_DEFUN([OPENVPN_ADD_AM_MACRO_STATIC],[ + OPENVPN_PRINT_TO_FILE([aminclude_static.am],[$1]) +]) + m4_define(_AX_CODE_COVERAGE_RULES,[ -AX_ADD_AM_MACRO_STATIC([ +OPENVPN_ADD_AM_MACRO_STATIC([ +# This file was generated by ax_code_coverage # Code coverage # +# This file must only be included by the top level Makefile.am: the rules +# below always report on the complete build tree. +# +# The rules avoid GNU make specific syntax so that they also work with +# other make implementations, e.g. BSD make. +# # Optional: # - CODE_COVERAGE_DIRECTORY: Top-level directory for code coverage reporting. # Multiple directories may be specified, separated by whitespace. @@ -90,51 +131,51 @@ # - CODE_COVERAGE_OUTPUT_DIRECTORY: Directory for generated code coverage # reports to be created. (Default: # \$(PACKAGE_NAME)-\$(PACKAGE_VERSION)-coverage) +# - CODE_COVERAGE_TEST_NAME: Test name to record in the .info file. It is +# computed by configure (\$(PACKAGE_NAME)-\$(PACKAGE_VERSION), with dashes +# and dots replaced by underscores) and can be overridden by defining it +# in Makefile.am. # - CODE_COVERAGE_BRANCH_COVERAGE: Set to 1 to enforce branch coverage, # set to 0 to disable it and leave empty to stay with the default. -# (Default: empty) +# The corresponding --rc option is passed to lcov and genhtml in +# addition to the options below. (Default: empty) # - CODE_COVERAGE_LCOV_SHOPTS_DEFAULT: Extra options shared between both lcov -# instances. (Default: based on $CODE_COVERAGE_BRANCH_COVERAGE) +# instances. (Default: empty) # - CODE_COVERAGE_LCOV_SHOPTS: Extra options to shared between both lcov -# instances. (Default: $CODE_COVERAGE_LCOV_SHOPTS_DEFAULT) +# instances. (Default: \$CODE_COVERAGE_LCOV_SHOPTS_DEFAULT) # - CODE_COVERAGE_LCOV_OPTIONS_GCOVPATH: --gcov-tool pathtogcov # - CODE_COVERAGE_LCOV_OPTIONS_DEFAULT: Extra options to pass to the -# collecting lcov instance. (Default: $CODE_COVERAGE_LCOV_OPTIONS_GCOVPATH) +# collecting lcov instance. (Default: \$CODE_COVERAGE_LCOV_OPTIONS_GCOVPATH) # - CODE_COVERAGE_LCOV_OPTIONS: Extra options to pass to the collecting lcov -# instance. (Default: $CODE_COVERAGE_LCOV_OPTIONS_DEFAULT) +# instance. (Default: \$CODE_COVERAGE_LCOV_OPTIONS_DEFAULT) # - CODE_COVERAGE_LCOV_RMOPTS_DEFAULT: Extra options to pass to the filtering # lcov instance. (Default: empty) -# - CODE_COVERAGE_LCOV_RMOPTS: Extra options to pass to the filtering lcov -# instance. (Default: $CODE_COVERAGE_LCOV_RMOPTS_DEFAULT) +# - CODE_COVERAGE_LCOV_RMOPTS: Extra options to pass to the filtering +# lcov instance. (Default: \$CODE_COVERAGE_LCOV_RMOPTS_DEFAULT) # - CODE_COVERAGE_GENHTML_OPTIONS_DEFAULT: Extra options to pass to the -# genhtml instance. (Default: based on $CODE_COVERAGE_BRANCH_COVERAGE) +# genhtml instance. (Default: empty) # - CODE_COVERAGE_GENHTML_OPTIONS: Extra options to pass to the genhtml -# instance. (Default: $CODE_COVERAGE_GENHTML_OPTIONS_DEFAULT) +# instance. (Default: \$CODE_COVERAGE_GENHTML_OPTIONS_DEFAULT) # - CODE_COVERAGE_IGNORE_PATTERN: Extra glob pattern of files to ignore # # The generated report will be titled using the \$(PACKAGE_NAME) and # \$(PACKAGE_VERSION). In order to add the current git hash to the title, # use the git-version-gen script, available online. # Optional variables -# run only on top dir if CODE_COVERAGE_ENABLED - ifeq (\$(abs_builddir), \$(abs_top_builddir)) CODE_COVERAGE_DIRECTORY ?= \$(top_builddir) CODE_COVERAGE_OUTPUT_FILE ?= \$(PACKAGE_NAME)-\$(PACKAGE_VERSION)-coverage.info CODE_COVERAGE_OUTPUT_DIRECTORY ?= \$(PACKAGE_NAME)-\$(PACKAGE_VERSION)-coverage CODE_COVERAGE_BRANCH_COVERAGE ?= -CODE_COVERAGE_LCOV_SHOPTS_DEFAULT ?= \$(if \$(CODE_COVERAGE_BRANCH_COVERAGE),\ ---rc lcov_branch_coverage=\$(CODE_COVERAGE_BRANCH_COVERAGE)) +CODE_COVERAGE_LCOV_SHOPTS_DEFAULT ?= CODE_COVERAGE_LCOV_SHOPTS ?= \$(CODE_COVERAGE_LCOV_SHOPTS_DEFAULT) CODE_COVERAGE_LCOV_OPTIONS_GCOVPATH ?= --gcov-tool \"\$(GCOV)\" CODE_COVERAGE_LCOV_OPTIONS_DEFAULT ?= \$(CODE_COVERAGE_LCOV_OPTIONS_GCOVPATH) CODE_COVERAGE_LCOV_OPTIONS ?= \$(CODE_COVERAGE_LCOV_OPTIONS_DEFAULT) CODE_COVERAGE_LCOV_RMOPTS_DEFAULT ?= CODE_COVERAGE_LCOV_RMOPTS ?= \$(CODE_COVERAGE_LCOV_RMOPTS_DEFAULT) -CODE_COVERAGE_GENHTML_OPTIONS_DEFAULT ?=\ -\$(if \$(CODE_COVERAGE_BRANCH_COVERAGE),\ ---rc genhtml_branch_coverage=\$(CODE_COVERAGE_BRANCH_COVERAGE)) +CODE_COVERAGE_GENHTML_OPTIONS_DEFAULT ?= CODE_COVERAGE_GENHTML_OPTIONS ?= \$(CODE_COVERAGE_GENHTML_OPTIONS_DEFAULT) CODE_COVERAGE_IGNORE_PATTERN ?= @@ -152,8 +193,15 @@ code_coverage_quiet_ = \$(code_coverage_quiet_\$(AM_DEFAULT_VERBOSITY)) code_coverage_quiet_0 = --quiet -# sanitizes the test-name: replaces with underscores: dashes and dots -code_coverage_sanitize = \$(subst -,_,\$(subst .,_,\$(1))) +# Shell fragments used by the recipes below. They are portable +# replacements for the GNU make functions \$(addprefix ...) and \$(if ...): +# code_coverage_dirs_opt sets \$cc_dirs to a list of --directory options, +# code_coverage_prefix_opt sets \$cc_prefix to a list of --prefix options and +# code_coverage_*_branch_opt set \$cc_branch to the branch coverage option. +code_coverage_dirs_opt = cc_dirs=; for cc_dir in \$(CODE_COVERAGE_DIRECTORY); do cc_dirs=\"\$\$cc_dirs --directory \$\$cc_dir\"; done +code_coverage_prefix_opt = cc_prefix=; for cc_dir in \$(CODE_COVERAGE_DIRECTORY); do cc_prefix=\"\$\$cc_prefix --prefix \$\$cc_dir\"; done +code_coverage_lcov_branch_opt = cc_branch=; test -z \"\$(CODE_COVERAGE_BRANCH_COVERAGE)\" || cc_branch=\"--rc lcov_branch_coverage=\$(CODE_COVERAGE_BRANCH_COVERAGE)\" +code_coverage_genhtml_branch_opt = cc_branch=; test -z \"\$(CODE_COVERAGE_BRANCH_COVERAGE)\" || cc_branch=\"--rc genhtml_branch_coverage=\$(CODE_COVERAGE_BRANCH_COVERAGE)\" # Use recursive makes in order to ignore errors during check check-code-coverage: @@ -162,29 +210,26 @@ # Capture code coverage data code-coverage-capture: code-coverage-capture-hook - \$(code_coverage_v_lcov_cap)\$(LCOV) \$(code_coverage_quiet) \$(addprefix --directory ,\$(CODE_COVERAGE_DIRECTORY)) --capture --output-file \"\$(CODE_COVERAGE_OUTPUT_FILE).tmp\" --test-name \"\$(call code_coverage_sanitize,\$(PACKAGE_NAME)-\$(PACKAGE_VERSION))\" --no-checksum --compat-libtool \$(CODE_COVERAGE_LCOV_SHOPTS) \$(CODE_COVERAGE_LCOV_OPTIONS) - \$(code_coverage_v_lcov_ign)\$(LCOV) \$(code_coverage_quiet) \$(addprefix --directory ,\$(CODE_COVERAGE_DIRECTORY)) --remove \"\$(CODE_COVERAGE_OUTPUT_FILE).tmp\" \$(CODE_COVERAGE_IGNORE_PATTERN) --output-file \"\$(CODE_COVERAGE_OUTPUT_FILE)\" \$(CODE_COVERAGE_LCOV_SHOPTS) \$(CODE_COVERAGE_LCOV_RMOPTS) + \$(code_coverage_v_lcov_cap)\$(code_coverage_dirs_opt); \\ + \$(code_coverage_lcov_branch_opt); \\ + \$(LCOV) \$(code_coverage_quiet) \$\$cc_dirs --capture --output-file \"\$(CODE_COVERAGE_OUTPUT_FILE).tmp\" --test-name \"\$(CODE_COVERAGE_TEST_NAME)\" --no-checksum --compat-libtool \$\$cc_branch \$(CODE_COVERAGE_LCOV_SHOPTS) \$(CODE_COVERAGE_LCOV_OPTIONS) + \$(code_coverage_v_lcov_ign)\$(code_coverage_dirs_opt); \\ + \$(code_coverage_lcov_branch_opt); \\ + \$(LCOV) \$(code_coverage_quiet) \$\$cc_dirs --remove \"\$(CODE_COVERAGE_OUTPUT_FILE).tmp\" \$(CODE_COVERAGE_IGNORE_PATTERN) --output-file \"\$(CODE_COVERAGE_OUTPUT_FILE)\" \$\$cc_branch \$(CODE_COVERAGE_LCOV_SHOPTS) \$(CODE_COVERAGE_LCOV_RMOPTS) -@rm -f \"\$(CODE_COVERAGE_OUTPUT_FILE).tmp\" - \$(code_coverage_v_genhtml)LANG=C \$(GENHTML) \$(code_coverage_quiet) \$(addprefix --prefix ,\$(CODE_COVERAGE_DIRECTORY)) --output-directory \"\$(CODE_COVERAGE_OUTPUT_DIRECTORY)\" --title \"\$(PACKAGE_NAME)-\$(PACKAGE_VERSION) Code Coverage\" --legend --show-details \"\$(CODE_COVERAGE_OUTPUT_FILE)\" \$(CODE_COVERAGE_GENHTML_OPTIONS) + \$(code_coverage_v_genhtml)\$(code_coverage_prefix_opt); \\ + \$(code_coverage_genhtml_branch_opt); \\ + LANG=C \$(GENHTML) \$(code_coverage_quiet) \$\$cc_prefix --output-directory \"\$(CODE_COVERAGE_OUTPUT_DIRECTORY)\" --title \"\$(PACKAGE_NAME)-\$(PACKAGE_VERSION) Code Coverage\" --legend --show-details \"\$(CODE_COVERAGE_OUTPUT_FILE)\" \$\$cc_branch \$(CODE_COVERAGE_GENHTML_OPTIONS) @echo \"file://\$(abs_builddir)/\$(CODE_COVERAGE_OUTPUT_DIRECTORY)/index.html\" code-coverage-clean: -\$(LCOV) --directory \$(top_builddir) -z -rm -rf \"\$(CODE_COVERAGE_OUTPUT_FILE)\" \"\$(CODE_COVERAGE_OUTPUT_FILE).tmp\" \"\$(CODE_COVERAGE_OUTPUT_DIRECTORY)\" - -find . \\( -name \"*.gcda\" -o -name \"*.gcno\" -o -name \"*.gcov\" \\) -delete + -find . \\( -name \"*.gcda\" -o -name \"*.gcno\" -o -name \"*.gcov\" \\) -exec rm -f '{}' + code-coverage-dist-clean: A][M_DISTCHECK_CONFIGURE_FLAGS := \$(A][M_DISTCHECK_CONFIGURE_FLAGS) --disable-code-coverage - else # ifneq (\$(abs_builddir), \$(abs_top_builddir)) -check-code-coverage: - -code-coverage-capture: code-coverage-capture-hook - -code-coverage-clean: - -code-coverage-dist-clean: - endif # ifeq (\$(abs_builddir), \$(abs_top_builddir)) else #! CODE_COVERAGE_ENABLED # Use recursive makes in order to ignore errors during check check-code-coverage: @@ -206,8 +251,7 @@ ]) AC_DEFUN([_AX_CODE_COVERAGE_ENABLED],[ - AX_CHECK_GNU_MAKE([],[AC_MSG_ERROR([not using GNU make that is needed for coverage])]) - AC_REQUIRE([AX_ADD_AM_MACRO_STATIC]) + AC_REQUIRE([OPENVPN_ADD_AM_MACRO_STATIC]) # check for gcov AC_CHECK_TOOL([GCOV], [$_AX_CODE_COVERAGE_GCOV_PROG_WITH], @@ -232,13 +276,12 @@ AC_MSG_ERROR([Could not find genhtml from the lcov package]) ]) - AC_CHECK_LIB([gcov], [_gcov_init], [CODE_COVERAGE_LIBS="-lgcov"], [CODE_COVERAGE_LIBS=""]) - dnl Build the code coverage flags dnl Define CODE_COVERAGE_LDFLAGS for backwards compatibility CODE_COVERAGE_CPPFLAGS="-DNDEBUG" - CODE_COVERAGE_CFLAGS="-O0 -g -fprofile-arcs -ftest-coverage" - CODE_COVERAGE_CXXFLAGS="-O0 -g -fprofile-arcs -ftest-coverage" + CODE_COVERAGE_CFLAGS="-O0 -g --coverage" + CODE_COVERAGE_CXXFLAGS="-O0 -g --coverage" + CODE_COVERAGE_LIBS="--coverage" AC_SUBST([CODE_COVERAGE_CPPFLAGS]) AC_SUBST([CODE_COVERAGE_CFLAGS]) @@ -265,6 +308,10 @@ AC_SUBST([CODE_COVERAGE_ENABLED], [$enable_code_coverage]) AC_MSG_RESULT($enable_code_coverage) + dnl The lcov test name must not contain dashes or dots + CODE_COVERAGE_TEST_NAME=`echo "$PACKAGE_NAME-$PACKAGE_VERSION" | tr '.-' '__'` + AC_SUBST([CODE_COVERAGE_TEST_NAME]) + AS_IF([ test "x$enable_code_coverage" = xyes ], [ _AX_CODE_COVERAGE_ENABLED ]) diff --git a/src/openvpn/Makefile.am b/src/openvpn/Makefile.am index 7ecddff..9424801 100644 --- a/src/openvpn/Makefile.am +++ b/src/openvpn/Makefile.am @@ -31,9 +31,12 @@ $(OPTIONAL_SYSTEMD_CFLAGS) \ $(OPTIONAL_PKCS11_HELPER_CFLAGS) \ $(OPTIONAL_INOTIFY_CFLAGS) \ + $(CODE_COVERAGE_CFLAGS) \ -DPLUGIN_LIBDIR=\"${plugindir}\" \ -DDEFAULT_DNS_UPDOWN=\"${scriptdir}/dns-updown\" +AM_LDFLAGS = $(CODE_COVERAGE_LIBS) + if WIN32 # we want unicode entry point but not the macro AM_CFLAGS += -municode -UUNICODE _______________________________________________ Openvpn-devel mailing list [email protected] https://lists.sourceforge.net/lists/listinfo/openvpn-devel
