Skip to content

Commit

Permalink
feat(tests): Add support for coverage report
Browse files Browse the repository at this point in the history
This patch enables support for coverage report on the
unit tests by using the gcovr tool.

The coverage report is stored in ${RMM_BUILD_DIR}/$<CONFIG>/coverage

Signed-off-by: Javier Almansa Sobrino <javier.almansasobrino@arm.com>
Change-Id: I5b6a2f3ebf13cbc036c0d64f422ea18f337dd8f5
  • Loading branch information
javieralso-arm authored and soby-mathew committed Dec 14, 2022
1 parent 35f487b commit 576071e
Show file tree
Hide file tree
Showing 5 changed files with 198 additions and 4 deletions.
6 changes: 6 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -61,11 +61,17 @@ set(CMAKE_C_EXTENSIONS TRUE)
if(RMM_STATIC_ANALYSIS_CPPCHECK)
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
endif()

#
# Include the platform makefile
#
include("cmake/Platforms.cmake")

#
# Include Coverage report framework
#
include("cmake/CoverageReport.cmake")

#
# Include the Unit Test Framework
#
Expand Down
151 changes: 151 additions & 0 deletions cmake/CoverageReport.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,151 @@
#
# SPDX-License-Identifier: BSD-3-Clause
# SPDX-FileCopyrightText: Copyright TF-RMM Contributors.
#

arm_config_option(
NAME RMM_COVERAGE
HELP "Enable coverage tests"
TYPE BOOL
DEFAULT "OFF")

arm_config_option(
NAME RMM_HTML_COV_REPORT
HELP "Enable html coverage report"
TYPE BOOL
DEPENDS RMM_COVERAGE
DEFAULT "ON")

arm_config_option(
NAME COVERAGE_REPORT_NAME
HELP "Canonical name for the coverage report"
TYPE STRING
DEPENDS RMM_COVERAGE
DEFAULT "tf-rmm-coverage"
ADVANCED)

macro(check_and_prepare_c_coverage_flags)
# Store a copy of CMAKE_C_FLAGS
set(CMAKE_C_FLAGS_BACKUP "${CMAKE_C_FLAGS}")

foreach(flag ${ARGN})
string(REPLACE "-" "_" flag_no_hyphen ${flag})
check_c_compiler_flag("-${flag}" COVERAGE_C_FLAG_${flag_no_hyphen})
if (COVERAGE_C_FLAG_${flag_no_hyphen})
# Some of the coverage flags depend on the previous ones being
# enabled, so add them to the C Flags now for the next check.
string(APPEND CMAKE_C_FLAGS " -${flag}")
string(APPEND COVERAGE_C_FLAGS " -${flag}")
else()
set(COVERAGE_SUPPORTED "FALSE")
endif()
endforeach()

# Restore CMAKE_C_FLAGS
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS_BACKUP}")
endmacro(check_and_prepare_c_coverage_flags)

macro(check_and_prepare_cxx_coverage_flags)
# Store a copy of CMAKE_CXX_FLAGS
set(CMAKE_CXX_FLAGS_BACKUP "${CMAKE_CXX_FLAGS}")

foreach(flag ${ARGN})
string(REPLACE "-" "_" flag_no_hyphen ${flag})
check_cxx_compiler_flag("-${flag}" COVERAGE_CXX_FLAG_${flag_no_hyphen})
if (COVERAGE_CXX_FLAG_${flag_no_hyphen})
# Some of the coverage flags depend on the previous ones being
# enabled, so add them to the CXX Flags now for the next check.
string(APPEND CMAKE_CXX_FLAGS " -${flag}")
string(APPEND COVERAGE_CXX_FLAGS " -${flag}")
endif()
endforeach()

# Restore CMAKE_CXX_FLAGS
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS_BACKUP}")
endmacro(check_and_prepare_cxx_coverage_flags)

if(RMM_COVERAGE)

find_program(GCOVR_EXECUTABLE "gcovr" DOC "Path to gcovr")

if(${GCOVR_EXECUTABLE} STREQUAL "GCOVR_EXECUTABLE-NOTFOUND")
message (WARNING "gcovr executable not found. Coverage tests disabled")
return()
endif()

include(CheckCCompilerFlag)
include(CheckCXXCompilerFlag)

if(CMAKE_C_COMPILER_ID STREQUAL "Clang")
# Using LLVM. Select the coverage flags to test
set(COVERAGE_FLAGS
ftest-coverage
fprofile-instr-generate
fprofile-arcs
fcoverage-mapping)

# Setup the right coverage tool if using llvm
set(GCOVR_EXE_OPTION --gcov-executable "llvm-cov gcov"
CACHE INTERNAL "GCOV_EXECUTABLE")

elseif(CMAKE_C_COMPILER_ID STREQUAL "GNU")
# Using GNU. Select the coverage flags to test
set(COVERAGE_FLAGS
-coverage)

# Flags needed to enable coverage testing
string(APPEND CMAKE_EXE_LINKER_FLAGS " -coverage -lgcov ")
else()
message(WARNING "Toolchain ${CMAKE_C_COMPILER_ID} does not support coverage")
return()
endif()

set(COVERAGE_SUPPORTED "TRUE")
check_and_prepare_c_coverage_flags(${COVERAGE_FLAGS})
check_and_prepare_cxx_coverage_flags(${COVERAGE_FLAGS})

# If coverage is not supported by the C compiler, or the C and C++
# compilers do not support the same set of coverage flags (which can
# lead to link problems), abort.
if ((COVERAGE_SUPPORTED STREQUAL "FALSE") OR
(NOT (COVERAGE_C_FLAGS STREQUAL COVERAGE_CXX_FLAGS)))
message (WARNING "Toolchain ${CMAKE_C_COMPILER_ID} does not support coverage")
return()
endif()

# Setup flags for coverage
foreach(language in ITEMS C CXX)
string(APPEND CMAKE_${language}_FLAGS
" ${COVERAGE_${language}_FLAGS} ")
endforeach()

# Directory where to store the results
set(COVERAGE_DIRECTORY
"${CMAKE_BINARY_DIR}/$<CONFIG>/coverage")

set(COVERAGE_OUTPUT "${COVERAGE_DIRECTORY}/${COVERAGE_REPORT_NAME}")

if(RMM_HTML_COV_REPORT)
set(HTML_REPORT --html-details ${COVERAGE_OUTPUT}.html)
endif()

#
# Rules for coverage report generation
#
add_custom_target(run-coverage
COMMAND ${CMAKE_COMMAND} -E make_directory "${COVERAGE_DIRECTORY}"
COMMAND ${GCOVR_EXECUTABLE}
${GCOVR_EXE_OPTION}
--exclude "'((.+)ext(.+))|((.+)CMakeFiles(.+)\..)|((.+)\.cpp)|((.+)test(.+))'"
-r ${CMAKE_SOURCE_DIR}
-x ${COVERAGE_OUTPUT}.xml
${HTML_REPORT}
${CMAKE_BINARY_DIR})
#
# Add dependency on unit test target if being invoked in a
# multi-target build command line.
#
if(RMM_UNITTESTS)
add_dependencies(run-coverage run-unittests)
endif()
endif() # RMM_COVERAGE
19 changes: 15 additions & 4 deletions docs/getting_started/build-options.rst
Original file line number Diff line number Diff line change
Expand Up @@ -162,7 +162,7 @@ Run checkincludes on entire codebase:
cmake -DRMM_CONFIG=fvp_defcfg -S ${RMM_SOURCE_DIR} -B ${RMM_BUILD_DIR}
cmake --build ${RMM_BUILD_DIR} -- checkincludes-codebase
14. Perform unit tests on development host:
14. Perform unit tests on development host:

Build and run unit tests on host platform. It is recommended to do the Debug
build of RMM.
Expand All @@ -172,6 +172,17 @@ build of RMM.
cmake -DRMM_CONFIG=host_defcfg -DHOST_VARIANT=host_test -DCMAKE_BUILD_TYPE=Debug -S ${RMM_SOURCE_DIR} -B ${RMM_BUILD_DIR}
cmake --build ${RMM_BUILD_DIR} -- run-unittests
Run coverage analysis on unit tests.

.. code-block:: bash
cmake -DRMM_CONFIG=host_defcfg -DHOST_VARIANT=host_test -DRMM_COVERAGE=ON -DCMAKE_BUILD_TYPE=Debug -S ${RMM_SOURCE_DIR} -B ${RMM_BUILD_DIR}
cmake --build ${RMM_BUILD_DIR} -- run-coverage
The above commands will automatically generate the HTML coverage report in folder
`build/Debug/coverage` within build directory. The HTML generation can be
disabled by setting `RMM_HTML_COV_REPORT=OFF`.

.. _build_options_table:

###################
Expand Down Expand Up @@ -208,9 +219,9 @@ The |RMM| build system supports the following CMake build options.
MBEDTLS_ECP_MAX_OPS ,248 - ,1000 ,"Number of max operations per ECC signing iteration"
RMM_FPU_USE_AT_REL2 ,ON | OFF ,OFF(fake_host) ON(aarch64),"Enable FPU/SIMD usage in RMM."
RMM_MAX_GRANULES , ,0 ,"Maximum number of memory granules available to the system"
HOST_VARIANT ,host_build | host_test ,host_build , "Variant to build for the host platform. Only available when RMM_PLATFORM=host"


HOST_VARIANT ,host_build | host_test ,host_build ,"Variant to build for the host platform. Only available when RMM_PLATFORM=host"
RMM_COVERAGE ,ON | OFF ,OFF ,"Enable coverage analysis"
RMM_HTML_COV_REPORT ,ON | OFF ,ON ,"Enable HTML output report for coverage analysis"

.. _llvm_build:

Expand Down
25 changes: 25 additions & 0 deletions docs/getting_started/getting-started.rst
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ The following tools are required to obtain and build |RMM|:
"Git",, "Firmware, Documentation"
"Graphviz dot",">v2.38.0","Documentation"
"docutils",">v2.38.0","Documentation"
"gcovr",">=v4.2","Tools(Coverage analysis)"

.. _getting_started_toolchain:

Expand Down Expand Up @@ -143,6 +144,30 @@ Install them with ``pip3``:
cd <rmm source folder>
pip3 install -r docs/requirements.txt
############################################
Install coverage tools analysis dependencies
############################################

.. note::

This is an optional step only needed if you intend to run coverage
analysis on the source code.

On Ubuntu, ``gcovr`` tool can be installed in two different ways:

Using the pagckage manager:

.. code-block:: bash
sudo apt-get install gcovr
The second (and recommended) way is install it with ``pip3``:

.. code-block:: bash
pip3 install --upgrade pip
pip3 install gcovr
.. _getting_started_get_source:

#########################
Expand Down
1 change: 1 addition & 0 deletions plat/host/host_test/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ add_library(rmm-plat-host_test)
arm_config_option(
NAME RMM_UNITTESTS
HELP "Enable Unitests for the build"
TYPE BOOL
DEFAULT "ON"
TYPE INTERNAL)

Expand Down

0 comments on commit 576071e

Please sign in to comment.