Skip to content

Commit 97cdc62

Browse files
authored
Bring CMAKE unit test infrastructure (FreeRTOS#5)
* Enable and run unit tests from this repo.
1 parent bc7c2da commit 97cdc62

12 files changed

+586
-60
lines changed

.github/workflows/ci.yml

+64
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
name: CI Checks
2+
3+
on:
4+
push:
5+
branches: ["**"]
6+
pull_request:
7+
branches: [master]
8+
workflow_dispatch:
9+
10+
jobs:
11+
unittest:
12+
runs-on: ubuntu-latest
13+
steps:
14+
- name: Clone This Repo
15+
uses: actions/checkout@v2
16+
- name: Build
17+
run: |
18+
sudo apt-get install -y lcov
19+
cmake -S . -B build/ \
20+
-G "Unix Makefiles" \
21+
-DCMAKE_BUILD_TYPE=Debug \
22+
-DCMAKE_C_FLAGS='--coverage -Wall -Wextra -DNDEBUG'
23+
make -C build/ all
24+
- name: Test
25+
run: |
26+
cd build/
27+
ctest -E system --output-on-failure
28+
cd ..
29+
- name: Coverage
30+
run: |
31+
make -C build/ coverage
32+
lcov --rc lcov_branch_coverage=1 --remove build/coverage.info '*test*' --output-file build/coverage.info
33+
lcov --rc lcov_branch_coverage=1 --remove build/coverage.info '*CMakeCCompilerId*' --output-file build/coverage.info
34+
lcov --rc lcov_branch_coverage=1 --remove build/coverage.info '*third_party*' --output-file build/coverage.info
35+
lcov --list build/coverage.info
36+
- name: lcov-cop
37+
uses: ChicagoFlutter/[email protected]
38+
with:
39+
path: "build/coverage.info"
40+
min_coverage: 99
41+
exclude: "**/*test*"
42+
complexity:
43+
runs-on: ubuntu-latest
44+
steps:
45+
- uses: actions/checkout@v2
46+
- name: Setup
47+
run: sudo apt-get install complexity
48+
- name: Complexity
49+
run: |
50+
find source/ -iname '*.c' |\
51+
xargs complexity --scores --threshold=0 --horrid-threshold=8
52+
doxygen:
53+
runs-on: ubuntu-20.04
54+
steps:
55+
- uses: actions/checkout@v2
56+
- name: Install Doxygen
57+
run: |
58+
wget -qO- "http://doxygen.nl/files/doxygen-1.8.20.linux.bin.tar.gz" | sudo tar --strip-components=1 -xz -C /usr/local
59+
sudo apt-get install -y libclang-9-dev
60+
- name: Run Doxygen
61+
run: doxygen docs/doxygen/config.doxyfile | tee doxyoutput.txt
62+
- name: Test that Doxygen Command Output is Empty
63+
# -s checks if the file is non-zero. Inverted to make sure file is empty.
64+
run: bash -c "[ ! -s doxoutput.txt ]"

.gitignore

+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
# Ignore documentation output.
2+
**/docs/**/output/*
3+
4+
# Ignore CMake build directory.
5+
build/
6+
7+
# Ignore build artifacts
8+
*.o
9+
10+
# Ignore code coverage artifacts
11+
*.gcda
12+
*.gcno
13+
*.gcov

CMakeLists.txt

+99-10
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,118 @@
1+
# ============================ Repo configurations =============================
2+
3+
# Project information.
4+
cmake_minimum_required( VERSION 3.13.0 )
5+
project( coreHTTP
6+
VERSION 4.0.2
7+
LANGUAGES C )
8+
9+
# Allow the project to be organized into folders.
10+
set_property( GLOBAL PROPERTY USE_FOLDERS ON )
11+
12+
# Use C90.
13+
set( CMAKE_C_STANDARD 90 )
14+
set( CMAKE_C_STANDARD_REQUIRED ON )
15+
16+
# Do not allow in-source build.
17+
if( ${PROJECT_SOURCE_DIR} STREQUAL ${PROJECT_BINARY_DIR} )
18+
message( FATAL_ERROR "In-source build is not allowed. Please build in a separate directory, such as ${PROJECT_SOURCE_DIR}/build." )
19+
endif()
20+
21+
# Set global path variables.
22+
get_filename_component(__MODULE_ROOT_DIR "${CMAKE_CURRENT_LIST_DIR}" ABSOLUTE)
23+
set(MODULE_ROOT_DIR ${__MODULE_ROOT_DIR} CACHE INTERNAL "HTTP source root.")
24+
25+
# Configure options to always show in CMake GUI.
26+
option( BUILD_CLONE_SUBMODULES
27+
"Set this to ON to automatically clone any required Git submodules. When OFF, submodules must be manually cloned."
28+
ON )
29+
30+
include( CMakeDependentOption )
31+
CMAKE_DEPENDENT_OPTION( BUILD_SHARED_LIBS
32+
"Set this to ON to build HTTP as a shared library. When OFF, HTTP builds as a static library."
33+
ON "${ALLOW_SHARED_LIBRARIES}"
34+
OFF )
35+
36+
# Set output directories.
37+
set( CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin )
38+
set( CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib )
39+
set( CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib )
40+
41+
# ====================== coreHTTP library configurations =======================
42+
143
# Include filepaths for source and include.
244
include(httpFilePaths.cmake)
345

446
# Add http_parser submodule to HTTP client library.
5-
add_subdirectory( third_party )
47+
add_subdirectory( source/third_party )
48+
49+
# Check if the http_parser source directory exists.
50+
if( NOT EXISTS ${CMAKE_CURRENT_LIST_DIR}/source/third_party/http_parser/http_parser.c )
51+
# Attempt to clone http_parser.
52+
if( ${BUILD_CLONE_SUBMODULES} )
53+
clone_http_parser()
54+
else()
55+
message( FATAL_ERROR "The required submodule http_parser does not exist. Either clone it manually, or set BUILD_CLONE_SUBMODULES to 1 to automatically clone it during build." )
56+
endif()
57+
endif()
658

759
# HTTP library target.
860
add_library( http
961
${HTTP_SOURCES} )
1062

1163
# HTTP public include path.
12-
target_include_directories( http PUBLIC ${HTTP_INCLUDE_PUBLIC_DIRS}
13-
${LOGGING_INCLUDE_DIRS} )
64+
target_include_directories( http PUBLIC ${HTTP_INCLUDE_PUBLIC_DIRS} )
1465

15-
# HTTP private include path.
16-
target_include_directories( http PRIVATE ${HTTP_INCLUDE_PRIVATE_DIRS} )
66+
# HTTP private include path. The unit test is default build so we include the test
67+
# configuration for now.
68+
target_include_directories( http PRIVATE ${HTTP_INCLUDE_PRIVATE_DIRS}
69+
${MODULE_ROOT_DIR}/test )
1770

1871
# Link http_parser to http target.
1972
target_link_libraries( http PRIVATE http_parser )
2073

2174
# Organization of HTTP in IDE projects.
2275
set_target_properties( http PROPERTIES FOLDER libraries/standard )
23-
source_group( include FILES include/http_client.h )
24-
source_group( src FILES ${HTTP_SOURCES} )
25-
source_group( src\\private FILES src/private/http_internal.h )
76+
source_group( include FILES source/include/http_client.h source/portable/transport_interface.h )
77+
source_group( source FILES ${HTTP_SOURCES} )
78+
source_group( source\\private FILES source/private/http_internal.h )
79+
80+
# ============================ Test configurations =============================
81+
82+
# Include CMock build configuration.
83+
include( test/cmock_build.cmake )
84+
85+
# Check if the CMock source directory exists, and if not present, clone the submodule
86+
# if BUILD_CLONE_SUBMODULES configuration is enabled.
87+
if( NOT EXISTS ${MODULE_ROOT_DIR}/test/CMock/src )
88+
# Attempt to clone CMock.
89+
if( ${BUILD_CLONE_SUBMODULES} )
90+
clone_cmock()
91+
else()
92+
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." )
93+
endif()
94+
endif()
95+
96+
# Add unit test and coverage configuration only if CMock directory exists.
97+
if( EXISTS ${MODULE_ROOT_DIR}/test/CMock/src )
98+
99+
# Use CTest utility for managing test runs. This has to be added BEFORE
100+
# defining test targets with add_test()
101+
enable_testing()
102+
103+
# Add build targets for CMock and Unit, required for unit testing.
104+
add_cmock_targets()
105+
106+
# Add function to enable CMOck based tests and coverage.
107+
include("${MODULE_ROOT_DIR}/tools/cmock/create_test.cmake")
26108

27-
if(BUILD_TESTS)
28-
add_subdirectory(utest)
109+
# Include build configuration for unit tests.
110+
add_subdirectory( test )
111+
112+
# Add a target for running coverage on tests.
113+
add_custom_target(coverage
114+
COMMAND ${CMAKE_COMMAND} -P ${CMAKE_SOURCE_DIR}/tools/cmock/coverage.cmake
115+
DEPENDS cmock unity http_utest http_send_utest
116+
WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
117+
)
29118
endif()

httpFilePaths.cmake

+7-7
Original file line numberDiff line numberDiff line change
@@ -7,18 +7,18 @@
77

88
# HTTP library source files.
99
set( HTTP_SOURCES
10-
${MODULES_DIR}/standard/http/src/http_client.c )
10+
${MODULE_ROOT_DIR}/source/http_client.c )
1111

1212
# HTTP library Public Include directories.
1313
set( HTTP_INCLUDE_PUBLIC_DIRS
14-
${MODULES_DIR}/standard/http/include
15-
${PLATFORM_DIR}/include )
14+
${MODULE_ROOT_DIR}/source/include
15+
${MODULE_ROOT_DIR}/source/portable )
1616

1717
# HTTP library Private Include directories.
1818
set( HTTP_INCLUDE_PRIVATE_DIRS
19-
${MODULES_DIR}/standard/http/src
20-
${MODULES_DIR}/standard/http/third_party/http_parser )
19+
${MODULE_ROOT_DIR}/source
20+
${MODULE_ROOT_DIR}/source/third_party/http_parser )
2121

2222
# HTTP library Include directories for Tests.
23-
set( HTTP_TEST_INCLUDE_DIRS
24-
${MODULES_DIR}/standard/http/third_party/http_parser )
23+
set( HTTP_INCLUDE_THIRD_PARTY_DIRS
24+
${MODULE_ROOT_DIR}/source/third_party/http_parser )

source/third_party/CMakeLists.txt

+5-11
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,15 @@
1-
# Check if the http_parser source directory exists.
2-
if( NOT EXISTS ${CMAKE_CURRENT_LIST_DIR}/http_parser/http_parser.c )
3-
# Attempt to clone http_parser.
4-
if( ${BUILD_CLONE_SUBMODULES} )
5-
find_package( Git REQUIRED )
61

2+
macro( clone_http_parser )
3+
find_package( Git REQUIRED )
74
message( "Cloning submodule http_parser." )
8-
execute_process( COMMAND ${GIT_EXECUTABLE} submodule update --init --recursive http_parser
9-
WORKING_DIRECTORY ${CMAKE_CURRENT_LIST_DIR}
5+
execute_process( COMMAND ${GIT_EXECUTABLE} submodule update --init --recursive ${MODULE_ROOT_DIR}/source/third_party/http_parser
6+
WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}
107
RESULT_VARIABLE HTTP_PARSER_CLONE_RESULT )
118

129
if( NOT ${HTTP_PARSER_CLONE_RESULT} STREQUAL "0" )
1310
message( FATAL_ERROR "Failed to clone http_parser submodule." )
1411
endif()
15-
else()
16-
message( FATAL_ERROR "The required submodule http_parser does not exist. Either clone it manually, or set BUILD_CLONE_SUBMODULES to 1 to automatically clone it during build." )
17-
endif()
18-
endif()
12+
endmacro()
1913

2014
# http_parser library target.
2115
add_library( http_parser

test/CMakeLists.txt

+5-7
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,11 @@ set(project_name "http")
99

1010
# list the files to mock here
1111
list(APPEND mock_list
12-
${MODULES_DIR}/standard/http/third_party/http_parser/http_parser.h
12+
${MODULE_ROOT_DIR}/source/third_party/http_parser/http_parser.h
1313
)
1414
# list the directories your mocks need
1515
list(APPEND mock_include_list
16-
${MODULES_DIR}/standard/http/third_party/http_parser
16+
${MODULE_ROOT_DIR}/source/third_party/http_parser
1717
)
1818
#list the definitions of your mocks to control what to be included
1919
list(APPEND mock_define_list
@@ -31,7 +31,6 @@ list(APPEND real_include_directories
3131
.
3232
${HTTP_INCLUDE_PUBLIC_DIRS}
3333
${HTTP_INCLUDE_PRIVATE_DIRS}
34-
${LOGGING_INCLUDE_DIRS}
3534
)
3635

3736
# ===================== Create UnitTest Code here (edit) =====================
@@ -41,8 +40,7 @@ list(APPEND test_include_directories
4140
.
4241
${HTTP_INCLUDE_PUBLIC_DIRS}
4342
${HTTP_INCLUDE_PRIVATE_DIRS}
44-
${HTTP_TEST_INCLUDE_DIRS}
45-
${LOGGING_INCLUDE_DIRS}
43+
${HTTP_INCLUDE_THIRD_PARTY_DIRS}
4644
)
4745

4846
# ============================= (end edit) ===================================
@@ -52,7 +50,7 @@ set(real_name "${project_name}_real")
5250

5351
create_mock_list(${mock_name}
5452
"${mock_list}"
55-
"${ROOT_DIR}/tools/cmock/project.yml"
53+
"${MODULE_ROOT_DIR}/tools/cmock/project.yml"
5654
"${mock_include_list}"
5755
"${mock_define_list}"
5856
)
@@ -64,8 +62,8 @@ create_real_library(${real_name}
6462
)
6563

6664
list(APPEND utest_link_list
67-
lib${real_name}.a
6865
-l${mock_name}
66+
lib${real_name}.a
6967
)
7068

7169
list(APPEND utest_dep_list

test/cmock_build.cmake

+58
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
# Macro utility to clone the CMock submodule.
2+
macro( clone_cmock )
3+
find_package( Git REQUIRED )
4+
message( "Cloning submodule CMock." )
5+
execute_process( COMMAND rm -rf ${MODULE_ROOT_DIR}/test/CMock
6+
COMMAND ${GIT_EXECUTABLE} submodule update --init --recursive ${MODULE_ROOT_DIR}/test/CMock
7+
WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}
8+
RESULT_VARIABLE CMOCK_CLONE_RESULT )
9+
10+
if( NOT ${CMOCK_CLONE_RESULT} STREQUAL "0" )
11+
message( FATAL_ERROR "Failed to clone CMock submodule." )
12+
endif()
13+
endmacro()
14+
15+
# Macro utility to add library targets for Unity and CMock to build configuration.
16+
macro( add_cmock_targets )
17+
# Build Configuration for CMock and Unity libraries.
18+
list( APPEND CMOCK_INCLUDE_DIRS
19+
"${MODULE_ROOT_DIR}/test/CMock/vendor/unity/src/"
20+
"${MODULE_ROOT_DIR}/test/CMock/vendor/unity/extras/fixture/src"
21+
"${MODULE_ROOT_DIR}/test/CMock/vendor/unity/extras/memory/src"
22+
"${MODULE_ROOT_DIR}/test/CMock/src"
23+
)
24+
25+
add_library(cmock STATIC
26+
"${MODULE_ROOT_DIR}/test/CMock/src/cmock.c"
27+
)
28+
29+
set_target_properties(cmock PROPERTIES
30+
ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib
31+
POSITION_INDEPENDENT_CODE ON
32+
COMPILE_FLAGS "-Og"
33+
)
34+
35+
target_include_directories(cmock PUBLIC
36+
${MODULE_ROOT_DIR}/test/CMock/src
37+
${MODULE_ROOT_DIR}/test/CMock/vendor/unity/src/
38+
${MODULE_ROOT_DIR}/test/CMock/examples
39+
${CMOCK_INCLUDE_DIRS}
40+
)
41+
42+
add_library(unity STATIC
43+
"${MODULE_ROOT_DIR}/test/CMock/vendor/unity/src/unity.c"
44+
"${MODULE_ROOT_DIR}/test/CMock/vendor/unity/extras/fixture/src/unity_fixture.c"
45+
"${MODULE_ROOT_DIR}/test/CMock/vendor/unity/extras/memory/src/unity_memory.c"
46+
)
47+
48+
set_target_properties(unity PROPERTIES
49+
ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib
50+
POSITION_INDEPENDENT_CODE ON
51+
)
52+
53+
target_include_directories(unity PUBLIC
54+
${CMOCK_INCLUDE_DIRS}
55+
)
56+
57+
target_link_libraries(cmock unity)
58+
endmacro()

0 commit comments

Comments
 (0)