Add code coverage for unit tests

Enable code coverage to run during CI testing.

Signed-off-by: Matt Spinler <spinler@us.ibm.com>
Change-Id: I9d928122c9c629f1e74e8660f716f148afa2988a
diff --git a/.gitignore b/.gitignore
index ac5d13b..10293c4 100644
--- a/.gitignore
+++ b/.gitignore
@@ -4,6 +4,7 @@
 ar-lib
 *-libtool
 autom4te.cache*
+aminclude_static.am
 compile
 config.*
 depcomp
@@ -15,7 +16,7 @@
 missing
 test-driver
 test/.deps*
-test/.dirstamp
+*.dirstamp
 test/Makefile
 test/Makefile.in
 .deps*
@@ -30,7 +31,6 @@
 libtool
 callout-test
 callouts-gen.hpp
-callouts/.dirstamp
 elog-lookup.cpp
 elog-process-metadata.cpp
 phosphor-log-manager
@@ -40,6 +40,10 @@
 test/*_test_*.log
 test/*_test_*.trs
 test/test-suite.log
+*.gcda
+*.gcno
+*.trs
+*-coverage*
 test/remote_logging_test_address
 test/remote_logging_test_config
 test/remote_logging_test_port
diff --git a/.lcovrc b/.lcovrc
new file mode 100644
index 0000000..360a8b4
--- /dev/null
+++ b/.lcovrc
@@ -0,0 +1,3 @@
+geninfo_gcov_all_blocks = 1
+lcov_function_coverage = 1
+lcov_branch_coverage = 0
diff --git a/Makefile.am b/Makefile.am
index dfa0eb3..2c6aedc 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -1,3 +1,19 @@
+if AUTOCONF_CODE_COVERAGE_2019_01_06
+include $(top_srcdir)/Makefile.am.include
+include $(top_srcdir)/aminclude_static.am
+clean-local: code-coverage-clean
+distclean-local: code-coverage-dist-clean
+else
+@CODE_COVERAGE_RULES@
+endif
+
+AM_LIBS = $(CODE_COVERAGE_LIBS)
+AM_CPPFLAGS = $(CODE_COVERAGE_CPPFLAGS) -UNDEBUG $(GTEST_CPPFLAGS)
+AM_CFLAGS = $(CODE_COVERAGE_CFLAGS)
+AM_CXXFLAGS = $(CODE_COVERAGE_CXXFLAGS)
+AM_LDFLAGS = $(GMOCK_LIBS) -lgmock_main \
+	$(GTEST_LIBS) $(OESDK_TESTCASE_FLAGS) $(PTHREAD_LIBS) $(SDBUSPLUS_LIBS)
+
 if !INSTALL_SCRIPTS
 # export these headers
 nobase_include_HEADERS = \
@@ -132,3 +148,7 @@
 nobase_elog_DATA =  \
 	tools/elog-gen.py \
 	tools/phosphor-logging/templates/elog-gen-template.mako.hpp
+
+# check_PROGRAMS =
+# XFAIL_TESTS =
+# TESTS = $(check_PROGRAMS)
diff --git a/Makefile.am.include b/Makefile.am.include
new file mode 100644
index 0000000..7037738
--- /dev/null
+++ b/Makefile.am.include
@@ -0,0 +1,25 @@
+# Ignore system headers
+CODE_COVERAGE_IGNORE_PATTERN = '/include/*' '/usr/include/*' '$(includedir)/*'
+export CODE_COVERAGE_IGNORE_PATTERN
+
+CODE_COVERAGE_LCOV_SHOPTS = $(CODE_COVERAGE_LCOV_SHOPTS_DEFAULT)
+# Use our configuration file for lcov
+CODE_COVERAGE_LCOV_SHOPTS += --config-file $(abs_srcdir)/.lcovrc
+export CODE_COVERAGE_LCOV_SHOPTS
+#
+CODE_COVERAGE_LCOV_OPTIONS = $(CODE_COVERAGE_LCOV_OPTIONS_DEFAULT)
+# Use our configuration file for lcov
+CODE_COVERAGE_LCOV_OPTIONS += --config-file $(abs_srcdir)/.lcovrc
+export CODE_COVERAGE_LCOV_OPTIONS
+
+CODE_COVERAGE_LCOV_RMOPTS = $(CODE_COVERAGE_LCOV_RMOPTS_DEFAULT)
+# Use our configuration file for lcov
+CODE_COVERAGE_LCOV_RMOPTS += --config-file $(abs_srcdir)/.lcovrc
+export CODE_COVERAGE_LCOV_RMOPTS
+
+CODE_COVERAGE_GENHTML_OPTIONS = $(CODE_COVERAGE_GENHTML_OPTIONS_DEFAULT)
+# Use our configuration file for genhtml
+CODE_COVERAGE_GENHTML_OPTIONS += --config-file $(abs_srcdir)/.lcovrc
+# Don't generate the absolute path for each file in the HTML output
+CODE_COVERAGE_GENHTML_OPTIONS += --prefix $(abs_srcdir) --prefix $(abs_builddir)
+export CODE_COVERAGE_GENHTML_OPTIONS
diff --git a/configure.ac b/configure.ac
index 80be721..c275b1d 100644
--- a/configure.ac
+++ b/configure.ac
@@ -2,9 +2,22 @@
 AC_PREREQ([2.69])
 AC_INIT([phosphor-logging], [1.0], [https://github.com/openbmc/phosphor-logging/issues])
 AC_LANG([C++])
-AM_INIT_AUTOMAKE([subdir-objects -Wall -Werror foreign dist-xz])
+AM_INIT_AUTOMAKE([subdir-objects -Wall -Werror -Wno-portability foreign dist-xz])
 AM_SILENT_RULES([yes])
 
+# Make sure the default CFLAGS of `-O2 -g` don't override CODE_COVERAGE_CFLAGS
+# It is important that this comes before AC_PROG_C{C,XX}, as we are attempting
+# to stop them from populating default CFLAGS and CXXFLAGS.
+AS_IF([test "x$enable_tests" = "xno"], [enable_code_coverage=no])
+AS_IF([test "x$enable_code_coverage" != "xno"], [
+    AS_IF([test "x${CXXFLAGS+set}" != "xset"], [
+        AC_SUBST(CXXFLAGS, [""])
+    ])
+    AS_IF([test "x${CFLAGS+set}" != "xset"], [
+        AC_SUBST(CFLAGS, [""])
+    ])
+])
+
 # Checks for programs
 AC_PROG_CXX
 AM_PROG_AR
@@ -75,6 +88,27 @@
     AS_HELP_STRING([--enable-tests], [Specifies running in the CI environment])
 )
 
+
+# Check for valgrind
+AS_IF([test "x$enable_tests" = "xno"], [enable_valgrind=no])
+m4_foreach([vgtool], [valgrind_tool_list],
+    [AX_VALGRIND_DFLT(vgtool, [off])])
+AX_VALGRIND_DFLT([memcheck], [on])
+AX_VALGRIND_CHECK
+AM_EXTRA_RECURSIVE_TARGETS([check-valgrind])
+m4_foreach([vgtool], [valgrind_tool_list],
+    [AM_EXTRA_RECURSIVE_TARGETS([check-valgrind-]vgtool)])
+
+# Code coverage
+AX_CODE_COVERAGE
+AS_IF([test "x$CODE_COVERAGE_ENABLED" = "xyes"], [
+    AX_APPEND_COMPILE_FLAGS([-DHAVE_GCOV], [CODE_COVERAGE_CPPFLAGS])
+])
+m4_ifdef([_AX_CODE_COVERAGE_RULES],
+    [AM_CONDITIONAL(AUTOCONF_CODE_COVERAGE_2019_01_06, [true])],
+    [AM_CONDITIONAL(AUTOCONF_CODE_COVERAGE_2019_01_06, [false])])
+AX_ADD_AM_MACRO_STATIC([])
+
 AC_DEFINE(BUSNAME_LOGGING, "xyz.openbmc_project.Logging", [The log manager DBus busname to own.])
 AC_DEFINE(OBJ_LOGGING, "/xyz/openbmc_project/logging", [The log manager DBus object path.])
 AC_DEFINE(OBJ_INTERNAL, "/xyz/openbmc_project/logging/internal/manager", [The private log manager DBus object path.])
diff --git a/test/Makefile.am b/test/Makefile.am
index 6d249e2..ab1378a 100644
--- a/test/Makefile.am
+++ b/test/Makefile.am
@@ -1,4 +1,11 @@
-AM_CPPFLAGS = -I${top_srcdir}
+AM_CPPFLAGS = -I${top_srcdir} \
+	$(CODE_COVERAGE_CPPFLAGS)
+AM_CFLAGS = \
+	$(CODE_COVERAGE_CFLAGS)
+AM_CXXFLAGS = \
+	$(CODE_COVERAGE_CXXFLAGS)
+AM_LDFLAGS = \
+	$(CODE_COVERAGE_LIBS)
 
 TESTS = $(check_PROGRAMS)
 
@@ -20,10 +27,12 @@
 	$(AM_CPPFLAGS) \
 	$(PHOSPHOR_DBUS_INTERFACES_CFLAGS) \
 	$(SDBUSPLUS_CFLAGS) \
-	$(SYSTEMD_CFLAGS)
+	$(SYSTEMD_CFLAGS) \
+	$(CODE_COVERAGE_CPPFLAGS)
 
 test_cxxflags = \
-	$(PTHREAD_CFLAGS)
+	$(PTHREAD_CFLAGS) \
+	$(CODE_COVERAGE_CXXFLAGS)
 
 test_ldflags = \
 	-lgtest_main -lgtest \
@@ -32,7 +41,8 @@
 	$(OESDK_TESTCASE_FLAGS) \
 	$(PHOSPHOR_DBUS_INTERFACES_LIBS) \
 	$(SDBUSPLUS_LIBS) \
-	$(SYSTEMD_LIBS)
+	$(SYSTEMD_LIBS) \
+	$(CODE_COVERAGE_LIBS)
 
 test_ldadd = \
 	$(top_builddir)/elog_serialize.o \
@@ -43,18 +53,20 @@
 	$(top_builddir)/elog-lookup.o \
 	$(top_builddir)/elog-process-metadata.o \
 	$(top_builddir)/sdjournal.o \
-	$(top_builddir)/extensions.o
+	$(top_builddir)/extensions.o \
+	$(CODE_COVERAGE_LIBS)
 
 remote_logging_test_ldadd = \
 	$(top_builddir)/phosphor-rsyslog-config/server-conf.o \
-	$(top_builddir)/sdjournal.o
+	$(top_builddir)/sdjournal.o \
+	$(CODE_COVERAGE_LIBS)
 
 elog_errorwrap_test_CPPFLAGS = $(test_cppflags)
 elog_errorwrap_test_CXXFLAGS = $(test_cxxflags)
 elog_errorwrap_test_SOURCES = elog_errorwrap_test.cpp
 elog_errorwrap_test_LDADD = $(test_ldadd)
 elog_errorwrap_test_LDFLAGS = \
-        $(test_ldflags)
+	$(test_ldflags)
 
 serialization_test_path_CPPFLAGS = $(test_cppflags)
 serialization_test_path_CXXFLAGS = $(test_cxxflags)
@@ -94,7 +106,8 @@
 sdjournal_mock_test_CPPFLAGS = $(test_cppflags)
 sdjournal_mock_test_CXXFLAGS = $(test_cxxflags)
 sdjournal_mock_test_SOURCES = sdtest.cpp
-sdjournal_mock_test_LDADD = $(top_builddir)/sdjournal.o
+sdjournal_mock_test_LDADD = $(top_builddir)/sdjournal.o \
+	$(CODE_COVERAGE_LIBS)
 sdjournal_mock_test_LDFLAGS = $(test_ldflags)
 
 extensions_test_CPPFLAGS = $(test_cppflags)