From 9a34f84e9f77fcbb37479457130a3ba667a09ddd Mon Sep 17 00:00:00 2001 From: Timo Tietavainen Date: Thu, 4 Jun 2020 13:03:21 +0300 Subject: [PATCH] Add makefile targets for coverage and rpm/Debian package Log Continuous Integration (ci) tests won't be any more running on a docker but instead directly on the Jenkins minion (virtual machine). For this purpose implement new autotool configure and makefile targets what can be called from Jenkins to build rpm and Debian packages: configure --with-rpm-dir=DIR configure --with-deb-dir=DIR make rpm-pkg make deb-pkg Implement also new configure and makefile target to enable and run code coverage analysis: configure --with-gcov-report-dir=DIR make test_gcov Jenkins can run code coverage analysis and push gcov result files to the Sonarcloud.io. New coverage analysis is replacing the old coverage analysis 'make check-code-coverage'. Signed-off-by: Timo Tietavainen Change-Id: I8b03cc884a29ddf9c38de00575c722b6d4311ea7 --- .gitignore | 24 ++++++++++++++ Makefile.am | 40 ++++++++++++++++++++--- README.md | 41 ++++++++++++++++++++--- configure.ac | 80 ++++++++++++++++++++++++++++++++++++++++++++- docker_test/Dockerfile-Test | 57 ++++++++++++++++++++++++++++++++ docker_test/publish.sh | 40 +++++++++++++++++++++++ package.sh | 59 +++++++++++++++++---------------- 7 files changed, 304 insertions(+), 37 deletions(-) create mode 100644 docker_test/Dockerfile-Test create mode 100755 docker_test/publish.sh diff --git a/.gitignore b/.gitignore index 4ad21a3..e2734b9 100644 --- a/.gitignore +++ b/.gitignore @@ -27,3 +27,27 @@ .tox docs/_build +/build-aux/ +/configure +/libtool +/Makefile +/Makefile.in +/aclocal.m4 +/autom4te.cache/ +/config.* +/m4/* +.deps/ +.libs/ +*.o +*.la +*.lo +*.Plo +.dirstamp +/run-tests.sh +/testrunner +*.gcov +*.gcda +*.gcno +mdclog.pc +rpm/mdclog.spec +debian/changelog diff --git a/Makefile.am b/Makefile.am index b5c723b..37bff63 100644 --- a/Makefile.am +++ b/Makefile.am @@ -20,8 +20,6 @@ ACLOCAL_AMFLAGS = -I m4 -@CODE_COVERAGE_RULES@ - BASE_CFLAGS = -Wall -Werror -Wextra $(PTHREAD_CFLAGS) -I$(top_srcdir)/include -D_GNU_SOURCE BASE_LDFLAGS = $(PTHREAD_CFLAGS) BASE_LIBS = $(PTHREAD_LIBS) @@ -71,6 +69,9 @@ libgmock_la_SOURCES = \ 3rdparty/googlemock/include/gmock/internal/gmock-internal-utils.h \ 3rdparty/googlemock/include/gmock/internal/gmock-port.h \ 3rdparty/googlemock/include/gmock/internal/gmock-pp.h \ + 3rdparty/googlemock/include/gmock/internal/custom/gmock-generated-actions.h \ + 3rdparty/googlemock/include/gmock/internal/custom/gmock-matchers.h \ + 3rdparty/googlemock/include/gmock/internal/custom/gmock-port.h \ 3rdparty/googlemock/src/gmock-cardinalities.cc \ 3rdparty/googlemock/src/gmock-internal-utils.cc \ 3rdparty/googlemock/src/gmock-matchers.cc \ @@ -97,6 +98,9 @@ libgmock_la_SOURCES = \ 3rdparty/googletest/include/gtest/internal/gtest-port.h \ 3rdparty/googletest/include/gtest/internal/gtest-string.h \ 3rdparty/googletest/include/gtest/internal/gtest-type-util.h \ + 3rdparty/googletest/include/gtest/internal/custom/gtest.h \ + 3rdparty/googletest/include/gtest/internal/custom/gtest-port.h \ + 3rdparty/googletest/include/gtest/internal/custom/gtest-printers.h \ 3rdparty/googletest/src/gtest-death-test.cc \ 3rdparty/googletest/src/gtest-filepath.cc \ 3rdparty/googletest/src/gtest-internal-inl.h \ @@ -135,7 +139,6 @@ testrunner_SOURCES = \ testrunner_CFLAGS = \ $(BASE_CFLAGS) \ - $(CODE_COVERAGE_CFLAGS) \ -DUNITTEST testrunner_CXXFLAGS = \ @@ -147,7 +150,7 @@ testrunner_CXXFLAGS = \ $(JSONCPP_CFLAGS) testrunner_LDFLAGS = $(BASE_LDFLAGS) -testrunner_LDADD = -lgmock $(BASE_LIBS) $(JSONCPP_LIBS) $(CODE_COVERAGE_LIBS) +testrunner_LDADD = -lgmock $(BASE_LIBS) $(JSONCPP_LIBS) EXTRA_testrunner_DEPENDENCIES = \ libgmock.la @@ -157,8 +160,37 @@ test: testrunner TESTS = run-tests.sh +if ENABLE_GCOV +testrunner_CFLAGS += -O0 --coverage +testrunner_LDADD += -lgcov + +test_gcov: test + @for p in src/*.o; do \ + gcov -abcfru $$p 1>/dev/null; \ + done + mkdir -p @GCOV_REPORT_DIR@ + mv *.gcov @GCOV_REPORT_DIR@ + ls -la @GCOV_REPORT_DIR@ +endif + +if ENABLE_RPM_BUILD +rpm-pkg: package.sh + ./package.sh rpm --target-dir @RPM_DIR@ +endif + + +if ENABLE_DEB_BUILD +deb-pkg: package.sh + ./package.sh debian --target-dir @DEB_DIR@ --skip-test +endif + EXTRA_DIST = \ $(top_srcdir)/mdclog.pc.in clean-local: rm -f mdclog.pc + +if ENABLE_GCOV + rm -rf @GCOV_REPORT_DIR@ + @find . -name '*.gcno' -o -name '*.gcda'| xargs -r rm +endif diff --git a/README.md b/README.md index 5cea4c5..2c00fd2 100644 --- a/README.md +++ b/README.md @@ -69,6 +69,7 @@ Requires * make * pkg-config * autoconf-archive +* libjsoncpp-dev ### Unit testing requires * gcc-c++ @@ -155,13 +156,31 @@ for continuous integration (CI) purposes such as a Jenkins job. Code coverage report -------------------- -Code coverage report can be generated with commands +Enable unit test gcov code coverage analysis by configuring gcov reporting +directory: ` -./configure --enable-code-coverage -make check-code-coverage +configure --with-gcov-report-dir=DIR ` -The run produces a HTML report file and the path is printed out at the end of the make command. +Directory can be an absolute path or a relative path to an log source root. +Unit test build creates directory if it does not exist. + +Build and run unit tests with code coverage analysis: +` +make test_gcov +` + +After successful unit test run code coverage (.gcov) result files are in +a directory, what was defined by `--with-gcov-report-dir` configure option. + +In addition, graphical gcov front-ends such as lcov can be used for coverage +analysis: +` +lcov --directory tst/ --directory src --capture --output-file coverage.info +genhtml coverage.info --output-directory out +` + +Open the out/index.html using any web browser. Binary package creation ----------------------- @@ -178,3 +197,17 @@ To make RPM packages you need to install and run `./package.sh rpm` +Docker Tests +------------ + +It's also possible to test compilation, run unit tests and test building of +rpm and Debian packages in a Docker: +` +docker build --no-cache -f docker_test/Dockerfile-Test -t logtest:latest . +` + +If needed, ready rpm and Debian packages can be copied from Docker to host. In +below example packages are copied to host's /tmp/logtest-packages directory: +` +docker run -v /tmp/logtest-packages:/export logtest:latest /export +` diff --git a/configure.ac b/configure.ac index 274a32b..cf944d9 100644 --- a/configure.ac +++ b/configure.ac @@ -74,7 +74,6 @@ AC_SUBST([CFLAG_VISIBILITY]) LT_INIT AX_PTHREAD -AX_CODE_COVERAGE PKG_PROG_PKG_CONFIG PKG_CHECK_MODULES([JSONCPP], [jsoncpp], [ @@ -82,6 +81,85 @@ PKG_CHECK_MODULES([JSONCPP], [jsoncpp], AC_DEFINE(HAVE_JSONCPP, 1, [Have jsoncpp]) ], [AC_MSG_WARN([jsoncpp not found])]) +# +# Configuration option --with-rpm-dir=DIR +# If this option is given, rpm packages building is enabled and ready rpms are +# copied to the directory. +# +AC_ARG_WITH([rpm-dir], + AS_HELP_STRING([--with-rpm-dir=DIR], + [Directory for build rpm packages]), + [AC_CHECK_PROG(RPMBUILD, rpmbuild, "yes", "no") + AC_CHECK_PROG(RPM, rpm, "yes", "no") + AS_IF([test "x$RPMBUILD" != xyes], + [AC_MSG_ERROR([rpmbuild needs to be installed])], + [test "x$RPM" != xyes], + [AC_MSG_ERROR([rpm is needs to be installed])])], + [with_rpm_dir=no]) + +AC_MSG_CHECKING([rpm package]) +if test "x$with_rpm_dir" = "xno"; then + AC_MSG_RESULT([no]) + RPM_DIR="/tmp" +else + AC_MSG_RESULT([yes]) + AC_MSG_NOTICE([rpm directory: $with_rpm_dir]) + RPM_DIR="$with_rpm_dir" +fi +AC_SUBST(RPM_DIR) +AM_CONDITIONAL([ENABLE_RPM_BUILD],[test "x$with_rpm_dir" != "xno"]) + + +# +# Configuration option --with-deb-dir=DIR +# If this option is given, Debian packages packages building is enabled and ready +# packages are copied to the directory. +# +AC_ARG_WITH([deb-dir], + AS_HELP_STRING([--with-deb-dir=DIR], + [Directory for build Debian packages]), + [AC_CHECK_PROG(DEBUILD, dpkg-buildpackage, "yes", "no") + AS_IF([test "x$DEBUILD" != xyes], + [AC_MSG_ERROR([dpkg-buildpackage needs to be installed])], + [test "x$with_rpm_dir" != "xno"], + [AC_MSG_ERROR([--with-deb-dir and --with-rpm-dir are mutually exclusive])])], + [with_deb_dir=no]) + +AC_MSG_CHECKING([deb package]) +if test "x$with_deb_dir" = "xno"; then + AC_MSG_RESULT([no]) + DEB_DIR="/tmp" +else + AC_MSG_RESULT([yes]) + AC_MSG_NOTICE([deb directory: $with_deb_dir]) + DEB_DIR="$with_deb_dir" +fi +AC_SUBST(DEB_DIR) +AM_CONDITIONAL([ENABLE_DEB_BUILD],[test "x$with_deb_dir" != "xno"]) + + +# +# Configuration option --with-gcov-report-dir=DIR +# If this option is given, gcov unit test coverage analysis is enabled and +# results are copied to the directory. +# +AC_ARG_WITH([gcov-report-dir], + AS_HELP_STRING([--with-gcov-report-dir=DIR], + [Directory for GCOV report files]), + [], + [with_gcov_report_dir=no]) +AC_MSG_CHECKING([gcov]) +if test "x$with_gcov_report_dir" = "xno"; then + AC_MSG_RESULT([no]) + GCOV_REPORT_DIR="gcov_report" +else + AC_MSG_RESULT([yes]) + AC_MSG_NOTICE([gcov report directory: $with_gcov_report_dir]) + GCOV_REPORT_DIR="$with_gcov_report_dir" +fi +AC_SUBST(GCOV_REPORT_DIR) +AM_CONDITIONAL([ENABLE_GCOV],[test "x$with_gcov_report_dir" != "xno"]) + MDCLOG_LT_VERSION=m4_format("%d:%d:%d", MDCLOG_CURRENT, MDCLOG_REVISION, MDCLOG_AGE) AC_SUBST(MDCLOG_LT_VERSION) AC_OUTPUT diff --git a/docker_test/Dockerfile-Test b/docker_test/Dockerfile-Test new file mode 100644 index 0000000..2f7fa49 --- /dev/null +++ b/docker_test/Dockerfile-Test @@ -0,0 +1,57 @@ +# O-RAN-SC +# +# Copyright (C) 2019 AT&T Intellectual Property and Nokia +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# This source code is part of the near-RT RIC (RAN Intelligent Controller) +# platform project (RICP). +# + + +# Dockerfile to verify, build and publish MDCLOG packages +# Inherits C toolchain from buildpack-deps:stretch +# Adds required build tools + +FROM nexus3.o-ran-sc.org:10004/o-ran-sc/bldr-ubuntu18-c-go:8-u18.04 + +RUN apt-get update && apt-get -q -y install \ + libjsoncpp-dev \ + rpm \ + devscripts \ + debhelper \ + gawk + + +RUN mkdir -p /tmp/build +COPY . /tmp/build +WORKDIR /tmp/build + +# Compile and run unit tests: +RUN ./autogen.sh && \ + ./configure && \ + make all && \ + make test + +# Build packages: +RUN make clean && \ + make distclean && \ + ./configure --with-rpm-dir=/tmp/pkgs && \ + make rpm-pkg && \ + make clean && \ + make distclean && \ + ./configure --with-deb-dir=/tmp/pkgs && \ + make deb-pkg + +RUN cp /tmp/build/docker_test/publish.sh /bin +ENTRYPOINT ["/bin/publish.sh"] diff --git a/docker_test/publish.sh b/docker_test/publish.sh new file mode 100755 index 0000000..2e7a639 --- /dev/null +++ b/docker_test/publish.sh @@ -0,0 +1,40 @@ +#!/bin/bash +# +# Copyright (C) 2019 AT&T Intellectual Property and Nokia +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# This source code is part of the near-RT RIC (RAN Intelligent Controller) +# platform project (RICP). +# + +# This script is used as a docker ENTRYPOINT in 'Dockerfile-Test'. Script +# purpose is to help rpm and Debian packages copying from docker to host. +# For further information please read the chapter 'Docker Tests' of the +# README file. + +echo "$0: start copying packages" + +TARGET=/export +if [ $# -eq 1 ] +then + TARGET=$1 +fi + +if [ ! -d "$TARGET" ] +then + echo "$0: Error: target dir $TARGET does not exist" + exit 1 +fi + +cp -v /tmp/pkgs/*.rpm /tmp/pkgs/*.deb "$TARGET" diff --git a/package.sh b/package.sh index 925735a..2b0c1f0 100755 --- a/package.sh +++ b/package.sh @@ -34,31 +34,30 @@ BUILD_DEB=0 SKIP_TEST=0 TARGET_DIR=/tmp -for i in "$@" -do - case "$i" in - --target-dir) - shift - TARGET_DIR=$i - ;; - --skip-config) - SKIP_CONF=1 - ;; - --skip-test) - SKIP_TEST=1 - ;; - rpm) - BUILD_RPM=1 - shift - ;; - debian) - BUILD_DEB=1 - ;; - *) - echo "Unknown argument $1" - exit 1 - ;; +while [[ "$#" -gt 0 ]]; do + case $1 in + --target-dir) + TARGET_DIR="$2" + shift + ;; + --skip-config) + SKIP_CONF=1 + ;; + --skip-test) + SKIP_TEST=1 + ;; + rpm) + BUILD_RPM=1 + ;; + debian) + BUILD_DEB=1 + ;; + *) + echo "Unknown argument $1"; + exit 1 + ;; esac + shift done if [ $SKIP_CONF -eq 0 ] @@ -73,7 +72,10 @@ then TESTOPT=--nocheck fi rpmbuild --nodeps $TESTOPT -bb rpm/mdclog.spec --define="_sourcedir $PWD" --define="_builddir $PWD" --define="_rpmdir .." - cp ../x86_64/*.rpm "$TARGET_DIR" + mkdir -p "$TARGET_DIR" + if ! [[ ../x86_64 -ef "$TARGET_DIR" ]]; then + cp ../x86_64/*.rpm "$TARGET_DIR" + fi fi if [ $BUILD_DEB -ne 0 ] @@ -83,7 +85,8 @@ then export DEB_BUILD_OPTIONS="nocheck noddebs" fi debuild -b -us -uc - cp ../x86_64/*.rpm "$TARGET_DIR" + mkdir -p "$TARGET_DIR" + if ! [[ ../ -ef "$TARGET_DIR" ]]; then + cp ../*.deb "$TARGET_DIR" + fi fi - - -- 2.16.6