From a5377c8ce8f2eb86cdef2d98a4ba96c966084c83 Mon Sep 17 00:00:00 2001 From: Archit Aggarwal Date: Wed, 9 Sep 2020 14:23:18 -0700 Subject: [PATCH] Re-add MQTT library target to run coverity and test MQTT_DO_NOT_USE_CUSTOM_CONFIG config (#37) * Add a library target to run Coverity analysis in CI * Use the new library target as a mechanism to build the MQTT library without custom config --- .github/workflows/ci.yml | 2 +- README.md | 12 +-- test/CMakeLists.txt | 91 ++++++++++++++++ test/unit-test/CMakeLists.txt | 153 +++++++++++++++++---------- test/unit-test/unit_test_build.cmake | 114 -------------------- 5 files changed, 196 insertions(+), 176 deletions(-) create mode 100644 test/CMakeLists.txt delete mode 100644 test/unit-test/unit_test_build.cmake diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index cf7d040..26a069e 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -16,7 +16,7 @@ jobs: - name: Build run: | sudo apt-get install -y lcov - cmake -S test/unit-test -B build/ \ + cmake -S test -B build/ \ -G "Unix Makefiles" \ -DCMAKE_BUILD_TYPE=Debug \ -DCMAKE_C_FLAGS='--coverage -Wall -Wextra -Werror -DNDEBUG' diff --git a/README.md b/README.md index a0cc735..d8f5393 100644 --- a/README.md +++ b/README.md @@ -21,21 +21,19 @@ and build the library with default configuration values, provide `MQTT_DO_NOT_US ### Platform Prerequisites -- For building the library, CMake 3.13.0 or later and a C90 compiler. +- For building the library, **CMake 3.13.0 or later** and a **C90 compiler**. - For running unit tests, Ruby 2.0.0 or later is additionally required for the CMock test framework (that we use). - For running the coverage target, gcov is additionally required. -### Steps to build Unit Tests +### Steps to build **Library** and **Unit Tests** 1. Go to the root directory of this repository. -1. Create build directory: `mkdir build && cd build` +1. Run *cmake* while inside build directory: `cmake -S ../test -B build -DBUILD_CLONE_SUBMODULES=ON ` -1. Run *cmake* while inside build directory: `cmake -S ../test/unit-test ` +1. Run this command to build the library and unit tests: `make -C build all` -1. Run this command to build the library and unit tests: `make all` - -1. The generated test executables will be present in `build/bin/tests` folder. +1. The built library will be present in `build/lib` folder, and generated test executables will be present in `build/bin/tests` folder. 1. Run `ctest` to execute all tests and view the test run summary. diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt new file mode 100644 index 0000000..52fa897 --- /dev/null +++ b/test/CMakeLists.txt @@ -0,0 +1,91 @@ +cmake_minimum_required ( VERSION 3.13.0 ) +project ( "CoreMQTT unit test" + VERSION 1.0.0 + LANGUAGES C ) + +# Allow the project to be organized into folders. +set_property( GLOBAL PROPERTY USE_FOLDERS ON ) + +# Use C90. +set( CMAKE_C_STANDARD 90 ) +set( CMAKE_C_STANDARD_REQUIRED ON ) + +# Do not allow in-source build. +if( ${PROJECT_SOURCE_DIR} STREQUAL ${PROJECT_BINARY_DIR} ) + message( FATAL_ERROR "In-source build is not allowed. Please build in a separate directory, such as ${PROJECT_SOURCE_DIR}/build." ) +endif() + +# Set global path variables. +get_filename_component(__MODULE_ROOT_DIR "${CMAKE_CURRENT_LIST_DIR}/.." ABSOLUTE) +set(MODULE_ROOT_DIR ${__MODULE_ROOT_DIR} CACHE INTERNAL "coreMQTT repository root.") + +# Configure options to always show in CMake GUI. +option( BUILD_CLONE_SUBMODULES + "Set this to ON to automatically clone any required Git submodules. When OFF, submodules must be manually cloned." + ON ) + +# Set output directories. +set( CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin ) +set( CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib ) +set( CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib ) + +# ===================================== Coverity Analysis Configuration ================================================= + +# Include filepaths for source and include. +include( ${MODULE_ROOT_DIR}/mqttFilePaths.cmake ) + +# Target for Coverity analysis that builds the library. +add_library( coverity_analysis + ${MQTT_SOURCES} ) + +# Build MQTT library target without custom config dependency. +target_compile_definitions( coverity_analysis PUBLIC MQTT_DO_NOT_USE_CUSTOM_CONFIG=1 ) + +# MQTT public include path. +target_include_directories( coverity_analysis PUBLIC ${MQTT_INCLUDE_PUBLIC_DIRS} ) + +# MQTT private include path. +target_include_directories( coverity_analysis PRIVATE ${MQTT_INCLUDE_PRIVATE_DIRS} ) + +# ==================================== Test Configuration ======================================== + +# Define a CMock resource path. +set( CMOCK_DIR ${MODULE_ROOT_DIR}/test/unit-test/CMock CACHE INTERNAL "CMock library source directory." ) + +# Include CMock build configuration. +include( unit-test/cmock_build.cmake ) + +# Check if the CMock source directory exists, and if not present, clone the submodule +# if BUILD_CLONE_SUBMODULES configuration is enabled. +if( NOT EXISTS ${CMOCK_DIR}/src ) + # Attempt to clone CMock. + if( ${BUILD_CLONE_SUBMODULES} ) + clone_cmock() + else() + message( FATAL_ERROR "The required submodule CMock does not exist. Either clone it manually, or set BUILD_CLONE_SUBMODULES to 1 to automatically clone it during build." ) + endif() +endif() + +# Add unit test and coverage configuration. + +# Use CTest utility for managing test runs. This has to be added BEFORE +# defining test targets with add_test() +enable_testing() + +# Add build targets for CMock and Unit, required for unit testing. +add_cmock_targets() + +# Add function to enable CMock based tests and coverage. +include( ${MODULE_ROOT_DIR}/tools/cmock/create_test.cmake ) + +# Include build configuration for unit tests. +add_subdirectory( unit-test ) + +# ==================================== Coverage Analysis configuration ======================================== + +# Add a target for running coverage on tests. +add_custom_target( coverage + COMMAND ${CMAKE_COMMAND} -P ${MODULE_ROOT_DIR}/tools/cmock/coverage.cmake + DEPENDS cmock unity core_mqtt_utest core_mqtt_serializer_utest core_mqtt_state_utest + WORKING_DIRECTORY ${CMAKE_BINARY_DIR} +) diff --git a/test/unit-test/CMakeLists.txt b/test/unit-test/CMakeLists.txt index 4e48053..241fdb2 100644 --- a/test/unit-test/CMakeLists.txt +++ b/test/unit-test/CMakeLists.txt @@ -1,69 +1,114 @@ -cmake_minimum_required ( VERSION 3.13.0 ) -project ( "CoreMQTT unit test" - VERSION 1.0.0 - LANGUAGES C ) +# Include filepaths for source and include. +include( ${MODULE_ROOT_DIR}/mqttFilePaths.cmake ) -# Allow the project to be organized into folders. -set_property( GLOBAL PROPERTY USE_FOLDERS ON ) +# ==================== Define your project name (edit) ======================== +set(project_name "core_mqtt") -# Use C90. -set( CMAKE_C_STANDARD 90 ) -set( CMAKE_C_STANDARD_REQUIRED ON ) +# ===================== Create your mock here (edit) ======================== -# Do not allow in-source build. -if( ${PROJECT_SOURCE_DIR} STREQUAL ${PROJECT_BINARY_DIR} ) - message( FATAL_ERROR "In-source build is not allowed. Please build in a separate directory, such as ${PROJECT_SOURCE_DIR}/build." ) -endif() +# list the files to mock here +list(APPEND mock_list + "${MODULE_ROOT_DIR}/source/include/core_mqtt_serializer.h" + "${MODULE_ROOT_DIR}/source/include/core_mqtt_state.h" + ) +# list the directories your mocks need +list(APPEND mock_include_list + . + ${MQTT_INCLUDE_PUBLIC_DIRS} + ) +#list the definitions of your mocks to control what to be included +list(APPEND mock_define_list + "" + ) -# Set global path variables. -get_filename_component(__MODULE_ROOT_DIR "${CMAKE_CURRENT_LIST_DIR}/../.." ABSOLUTE) -set(MODULE_ROOT_DIR ${__MODULE_ROOT_DIR} CACHE INTERNAL "coreMQTT repository root.") +# ================= Create the library under test here (edit) ================== -# Configure options to always show in CMake GUI. -option( BUILD_CLONE_SUBMODULES - "Set this to ON to automatically clone any required Git submodules. When OFF, submodules must be manually cloned." - ON ) +# list the files you would like to test here +list(APPEND real_source_files + ${MQTT_SOURCES} + ${MQTT_SERIALIZER_SOURCES} + ) +# list the directories the module under test includes +list(APPEND real_include_directories + . + ${MQTT_INCLUDE_PUBLIC_DIRS} + ${MQTT_INCLUDE_PRIVATE_DIRS} + ) -# Set output directories. -set( CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin ) -set( CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib ) -set( CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib ) +# ===================== Create UnitTest Code here (edit) ===================== -# Define a CMock resource path. -set( CMOCK_DIR ${MODULE_ROOT_DIR}/test/unit-test/CMock CACHE INTERNAL "CMock library source directory." ) +# list the directories your test needs to include +list(APPEND test_include_directories + . + ${MQTT_INCLUDE_PUBLIC_DIRS} + ${MQTT_INCLUDE_PRIVATE_DIRS} + ) -# Include CMock build configuration. -include( cmock_build.cmake ) +# ============================= (end edit) =================================== -# Check if the CMock source directory exists, and if not present, clone the submodule -# if BUILD_CLONE_SUBMODULES configuration is enabled. -if( NOT EXISTS ${CMOCK_DIR}/src ) - # Attempt to clone CMock. - if( ${BUILD_CLONE_SUBMODULES} ) - clone_cmock() - else() - message( FATAL_ERROR "The required submodule CMock does not exist. Either clone it manually, or set BUILD_CLONE_SUBMODULES to 1 to automatically clone it during build." ) - endif() -endif() +set(mock_name "${project_name}_mock") +set(real_name "${project_name}_real") -# Add unit test and coverage configuration. +create_mock_list(${mock_name} + "${mock_list}" + "${MODULE_ROOT_DIR}/tools/cmock/project.yml" + "${mock_include_list}" + "${mock_define_list}" + ) -# Use CTest utility for managing test runs. This has to be added BEFORE -# defining test targets with add_test() -enable_testing() +create_real_library(${real_name} + "${real_source_files}" + "${real_include_directories}" + "${mock_name}" + ) -# Add build targets for CMock and Unit, required for unit testing. -add_cmock_targets() +list(APPEND utest_link_list + -l${mock_name} + lib${real_name}.a + ) -# Add function to enable CMock based tests and coverage. -include( ${MODULE_ROOT_DIR}/tools/cmock/create_test.cmake ) +list(APPEND utest_dep_list + ${real_name} + ) -# Include build configuration for unit tests. -include( unit_test_build.cmake ) +set(utest_name "${project_name}_utest") +set(utest_source "${project_name}_utest.c") +create_test(${utest_name} + ${utest_source} + "${utest_link_list}" + "${utest_dep_list}" + "${test_include_directories}" + ) -# Add a target for running coverage on tests. -add_custom_target( coverage - COMMAND ${CMAKE_COMMAND} -P ${MODULE_ROOT_DIR}/tools/cmock/coverage.cmake - DEPENDS cmock unity core_mqtt_utest core_mqtt_serializer_utest core_mqtt_state_utest - WORKING_DIRECTORY ${CMAKE_BINARY_DIR} -) +# need to redefine because the tests below don't use any mocks +set(utest_link_list "") +list(APPEND utest_link_list + lib${real_name}.a + ) + +# mqtt_state_utest +set(utest_name "${project_name}_state_utest") +set(utest_source "${project_name}_state_utest.c") + +create_test(${utest_name} + ${utest_source} + "${utest_link_list}" + "${utest_dep_list}" + "${test_include_directories}" + ) + +# mqtt_serializer_utest +set(utest_name "${project_name}_serializer_utest") +set(utest_source "${project_name}_serializer_utest.c") + +set(utest_link_list "") +list(APPEND utest_link_list + lib${real_name}.a + ) + +create_test(${utest_name} + ${utest_source} + "${utest_link_list}" + "${utest_dep_list}" + "${test_include_directories}" + ) diff --git a/test/unit-test/unit_test_build.cmake b/test/unit-test/unit_test_build.cmake deleted file mode 100644 index 241fdb2..0000000 --- a/test/unit-test/unit_test_build.cmake +++ /dev/null @@ -1,114 +0,0 @@ -# Include filepaths for source and include. -include( ${MODULE_ROOT_DIR}/mqttFilePaths.cmake ) - -# ==================== Define your project name (edit) ======================== -set(project_name "core_mqtt") - -# ===================== Create your mock here (edit) ======================== - -# list the files to mock here -list(APPEND mock_list - "${MODULE_ROOT_DIR}/source/include/core_mqtt_serializer.h" - "${MODULE_ROOT_DIR}/source/include/core_mqtt_state.h" - ) -# list the directories your mocks need -list(APPEND mock_include_list - . - ${MQTT_INCLUDE_PUBLIC_DIRS} - ) -#list the definitions of your mocks to control what to be included -list(APPEND mock_define_list - "" - ) - -# ================= Create the library under test here (edit) ================== - -# list the files you would like to test here -list(APPEND real_source_files - ${MQTT_SOURCES} - ${MQTT_SERIALIZER_SOURCES} - ) -# list the directories the module under test includes -list(APPEND real_include_directories - . - ${MQTT_INCLUDE_PUBLIC_DIRS} - ${MQTT_INCLUDE_PRIVATE_DIRS} - ) - -# ===================== Create UnitTest Code here (edit) ===================== - -# list the directories your test needs to include -list(APPEND test_include_directories - . - ${MQTT_INCLUDE_PUBLIC_DIRS} - ${MQTT_INCLUDE_PRIVATE_DIRS} - ) - -# ============================= (end edit) =================================== - -set(mock_name "${project_name}_mock") -set(real_name "${project_name}_real") - -create_mock_list(${mock_name} - "${mock_list}" - "${MODULE_ROOT_DIR}/tools/cmock/project.yml" - "${mock_include_list}" - "${mock_define_list}" - ) - -create_real_library(${real_name} - "${real_source_files}" - "${real_include_directories}" - "${mock_name}" - ) - -list(APPEND utest_link_list - -l${mock_name} - lib${real_name}.a - ) - -list(APPEND utest_dep_list - ${real_name} - ) - -set(utest_name "${project_name}_utest") -set(utest_source "${project_name}_utest.c") -create_test(${utest_name} - ${utest_source} - "${utest_link_list}" - "${utest_dep_list}" - "${test_include_directories}" - ) - -# need to redefine because the tests below don't use any mocks -set(utest_link_list "") -list(APPEND utest_link_list - lib${real_name}.a - ) - -# mqtt_state_utest -set(utest_name "${project_name}_state_utest") -set(utest_source "${project_name}_state_utest.c") - -create_test(${utest_name} - ${utest_source} - "${utest_link_list}" - "${utest_dep_list}" - "${test_include_directories}" - ) - -# mqtt_serializer_utest -set(utest_name "${project_name}_serializer_utest") -set(utest_source "${project_name}_serializer_utest.c") - -set(utest_link_list "") -list(APPEND utest_link_list - lib${real_name}.a - ) - -create_test(${utest_name} - ${utest_source} - "${utest_link_list}" - "${utest_dep_list}" - "${test_include_directories}" - )