From 776729718bf0be3e060a6853acd6bcf513575a87 Mon Sep 17 00:00:00 2001 From: TizenOpenSource Date: Tue, 27 Dec 2022 12:03:14 +0900 Subject: [PATCH] Imported Upstream version 1.1.5 --- .gitlab-ci.yml | 111 ++++++++++++++++++++++++++++-- 5.patch | 34 ++++++++++ CMakeLists.txt | 16 +++-- ChangeLog | 10 +++ CompilerChecks.cmake | 6 +- ConfigureChecks.cmake | 2 +- DefineOptions.cmake | 1 + cmake/Modules/DefineCMakeDefaults.cmake | 7 ++ cmake/Modules/DefineCompilerFlags.cmake | 12 ++++ cmake/Toolchain-Debian-mips.cmake | 21 ++++++ coverity/coverity_assert_model.c | 95 ++++++++++++++++++++++---- doc/CMakeLists.txt | 2 +- doc/mainpage.dox | 4 +- example/mock/uptime/test_uptime.c | 3 + example/simple_test.c | 1 + include/cmocka.h | 100 +++++++++++++++++++++++++-- src/CMakeLists.txt | 2 + src/cmocka.c | 117 ++++++++++++++++++++++++++++---- src/cmocka.def | 3 + tests/CMakeLists.txt | 5 +- tests/test_float_macros.c | 40 +++++++++++ tests/test_skip_filter.c | 57 ++++++++++++++++ 22 files changed, 602 insertions(+), 47 deletions(-) create mode 100644 5.patch create mode 100644 cmake/Toolchain-Debian-mips.cmake create mode 100644 tests/test_float_macros.c create mode 100644 tests/test_skip_filter.c diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 75f3859..7238240 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -60,6 +60,24 @@ fedora/address-sanitizer: paths: - obj/ +fedora/memory-sanitizer: + image: $CI_REGISTRY/$BUILD_IMAGES_PROJECT:$FEDORA_BUILD + script: + - mkdir -p obj && cd obj && cmake + -DCMAKE_BUILD_TYPE=MemorySanitizer + -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++ + -DUNIT_TESTING=ON .. + && make -j$(nproc) && ctest --output-on-failure + tags: + - shared + except: + - tags + artifacts: + expire_in: 1 week + when: on_failure + paths: + - obj/ + fedora/undefined-sanitizer: image: $CI_REGISTRY/$BUILD_IMAGES_PROJECT:$FEDORA_BUILD script: @@ -77,6 +95,37 @@ fedora/undefined-sanitizer: paths: - obj/ +fedora/csbuild: + image: $CI_REGISTRY/$BUILD_IMAGES_PROJECT:$FEDORA_BUILD + script: + - | + if [[ -z "$CI_COMMIT_BEFORE_SHA" ]]; then + export CI_COMMIT_BEFORE_SHA=$(git rev-parse "${CI_COMMIT_SHA}~20") + fi + + # Check if the commit exists in this branch + # This is not the case for a force push + git branch --contains $CI_COMMIT_BEFORE_SHA 2>/dev/null || export CI_COMMIT_BEFORE_SHA=$(git rev-parse "${CI_COMMIT_SHA}~20") + + export CI_COMMIT_RANGE="$CI_COMMIT_BEFORE_SHA..$CI_COMMIT_SHA" + + - csbuild + --build-dir=obj-csbuild + --prep-cmd="cmake -DCMAKE_BUILD_TYPE=Debug -DPICKY_DEVELOPER=ON -DUNIT_TESTING=ON @SRCDIR@" + --build-cmd "make clean && make -j$(nproc)" + --git-commit-range $CI_COMMIT_RANGE + --color + --print-current --print-fixed + tags: + - shared + except: + - tags + artifacts: + expire_in: 1 week + when: on_failure + paths: + - obj-csbuild/ + freebsd/x86_64: image: script: @@ -148,11 +197,11 @@ fedora/mingw32: - build=$(dpkg-architecture -qDEB_HOST_GNU_TYPE) - host="${CI_JOB_NAME#*.cross.}" - mkdir -p obj && cd obj && cmake - -DCMAKE_C_COMPILER="$(which $host-gcc)" - -DCMAKE_CXX_COMPILER="$(which $host-g++)" + -DCMAKE_TOOLCHAIN_FILE=../cmake/Toolchain-Debian-mips.cmake -DCMAKE_BUILD_TYPE=RelWithDebInfo - -DUNIT_TESTING=ON .. && make -j$(nproc) - - ctest --output-on-failure -j$(nproc) + -DUNIT_TESTING=ON .. && + make -j$(nproc) && + ctest --output-on-failure -j$(nproc) tags: - shared except: @@ -295,3 +344,57 @@ tumbleweed/static-analysis: when: on_failure paths: - obj/scan + +visualstudio/x86_64: + script: + - $env:VCPKG_DEFAULT_TRIPLET="x64-windows" + - mkdir obj + - cd obj + - cmake + -A x64 + -DCMAKE_TOOLCHAIN_FILE="$env:VCPKG_TOOLCHAIN_FILE" + -DPICKY_DEVELOPER=ON + -DUNIT_TESTING=ON .. + - cmake --build . + - ctest --output-on-failure + tags: + - vs2017 + - windows + except: + - tags + only: + - branches@cmocka/cmocka + - branches@ansasaki/cmocka + - branches@cryptomilk/cmocka + artifacts: + expire_in: 1 week + when: on_failure + paths: + - obj/ + +visualstudio/x86: + script: + - $env:VCPKG_DEFAULT_TRIPLET="x86-windows" + - mkdir obj + - cd obj + - cmake + -DCMAKE_TOOLCHAIN_FILE="$env:VCPKG_TOOLCHAIN_FILE" + -DPICKY_DEVELOPER=ON + -DWITH_SFTP=ON -DWITH_SERVER=ON -DWITH_ZLIB=ON -DWITH_PCAP=ON + -DUNIT_TESTING=ON .. + - cmake --build . + - ctest --output-on-failure + tags: + - vs2017 + - windows + except: + - tags + only: + - branches@cmocka/cmocka + - branches@ansasaki/cmocka + - branches@cryptomilk/cmocka + artifacts: + expire_in: 1 week + when: on_failure + paths: + - obj/ diff --git a/5.patch b/5.patch new file mode 100644 index 0000000..32c845a --- /dev/null +++ b/5.patch @@ -0,0 +1,34 @@ +From addb1927eb979310a01abc65f29a5408a970da11 Mon Sep 17 00:00:00 2001 +From: Richard Bayerle +Date: Sun, 24 Feb 2019 16:38:05 +0000 +Subject: [PATCH] XML output is JUnit XML, not xUnit XML. + +--- + doc/mainpage.dox | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/doc/mainpage.dox b/doc/mainpage.dox +index 4c26d96..c378bb1 100644 +--- a/doc/mainpage.dox ++++ b/doc/mainpage.dox +@@ -33,7 +33,7 @@ The CMocka library provides: + - Very well tested + - Testing of memory leaks, buffer overflows and underflows. + - A set of assert macros. +- - Several supported output formats (stdout, TAP, xUnit XML, Subunit) ++ - Several supported output formats (stdout, TAP, JUnit XML, Subunit) + - License: Apache License 2.0 + + @section main-test A cmocka test +@@ -119,7 +119,7 @@ supported values are: + - STDOUT for the default standard output printer + - SUBUNIT for subunit output + - TAP for Test Anything Protocol (TAP) output +- - XML for xUnit XML format ++ - XML for JUnit XML format + The case doesn't matter. + + The XML output goes to stderr by default. If the environment variable +-- +2.18.1 + diff --git a/CMakeLists.txt b/CMakeLists.txt index 88408a9..da3aa68 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -15,7 +15,7 @@ include(DefineCMakeDefaults) include(DefineCompilerFlags) include(DefinePlatformDefaults) -project(cmocka VERSION 1.1.3 LANGUAGES C) +project(cmocka VERSION 1.1.5 LANGUAGES C) # global needed variables set(APPLICATION_NAME ${PROJECT_NAME}) @@ -27,7 +27,7 @@ set(APPLICATION_NAME ${PROJECT_NAME}) # Increment AGE. Set REVISION to 0 # If the source code was changed, but there were no interface changes: # Increment REVISION. -set(LIBRARY_VERSION "0.5.1") +set(LIBRARY_VERSION "0.7.0") set(LIBRARY_SOVERSION "0") # include cmake files @@ -51,16 +51,18 @@ if (MINGW) endif (MINGW) # check subdirectories -add_subdirectory(doc) add_subdirectory(include) add_subdirectory(src) +add_subdirectory(doc) include(AddCMockaTest) if (UNIT_TESTING) add_subdirectory(tests) endif (UNIT_TESTING) -add_subdirectory(example) +if (WITH_EXAMPLES) + add_subdirectory(example) +endif () # pkg-config file configure_file(cmocka.pc.cmake ${CMAKE_CURRENT_BINARY_DIR}/cmocka.pc) @@ -74,7 +76,11 @@ install( ) # cmake config files -set(CMOCKA_LIBRARY_NAME ${CMAKE_SHARED_LIBRARY_PREFIX}${PROJECT_NAME}${CMAKE_SHARED_LIBRARY_SUFFIX}) +if (WIN32) + set(CMOCKA_LIBRARY_NAME ${CMAKE_SHARED_LIBRARY_PREFIX}${PROJECT_NAME}${CMAKE_IMPORT_LIBRARY_SUFFIX}) +else() + set(CMOCKA_LIBRARY_NAME ${CMAKE_SHARED_LIBRARY_PREFIX}${PROJECT_NAME}${CMAKE_SHARED_LIBRARY_SUFFIX}) +endif() set(INCLUDE_INSTALL_DIR ${CMAKE_INSTALL_INCLUDEDIR} CACHE INTERNAL "") set(LIB_INSTALL_DIR ${CMAKE_INSTALL_LIBDIR} CACHE INTERNAL "") diff --git a/ChangeLog b/ChangeLog index 2ad544d..b0c0524 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,13 @@ +Thu Mar 28 2019 Andreas Schneider + * cmocka version 1.1.5 + * Added cmocka_set_skip_filter() + +Thu Mar 28 2019 Andreas Schneider + * cmocka version 1.1.4 + * Added assert_float(_not)_equal() + * Added expect_any_always() + * Small bug fixes + Wed Sep 26 2018 Andreas Schneider * cmocka version 1.1.3 * Fixed subunit output on failures diff --git a/CompilerChecks.cmake b/CompilerChecks.cmake index f07929c..b326807 100644 --- a/CompilerChecks.cmake +++ b/CompilerChecks.cmake @@ -41,6 +41,7 @@ if (UNIX) add_c_compiler_flag("-Werror=strict-overflow" SUPPORTED_COMPILER_FLAGS) add_c_compiler_flag("-Wstrict-overflow=2" SUPPORTED_COMPILER_FLAGS) add_c_compiler_flag("-Wno-format-zero-length" SUPPORTED_COMPILER_FLAGS) + add_c_compiler_flag("-Wmissing-field-initializers" SUPPORTED_COMPILER_FLAGS) check_c_compiler_flag("-Wformat" REQUIRED_FLAGS_WFORMAT) if (REQUIRED_FLAGS_WFORMAT) @@ -51,7 +52,10 @@ if (UNIX) add_c_compiler_flag("-Werror=format-security" SUPPORTED_COMPILER_FLAGS) # Allow zero for a variadic macro argument - add_c_compiler_flag("-Wno-gnu-zero-variadic-macro-arguments" SUPPORTED_COMPILER_FLAGS) + string(TOLOWER "${CMAKE_C_COMPILER_ID}" _C_COMPILER_ID) + if ("${_C_COMPILER_ID}" STREQUAL "clang") + add_c_compiler_flag("-Wno-gnu-zero-variadic-macro-arguments" SUPPORTED_COMPILER_FLAGS) + endif() add_c_compiler_flag("-fno-common" SUPPORTED_COMPILER_FLAGS) diff --git a/ConfigureChecks.cmake b/ConfigureChecks.cmake index 0e063de..fe8da35 100644 --- a/ConfigureChecks.cmake +++ b/ConfigureChecks.cmake @@ -100,7 +100,7 @@ else (WIN32) endif (WIN32) find_library(RT_LIBRARY rt) -if (RT_LIBRARY AND NOT LINUX) +if (RT_LIBRARY AND NOT LINUX AND NOT ANDROID) set(CMOCKA_REQUIRED_LIBRARIES ${RT_LIBRARY} CACHE INTERNAL "cmocka required system libraries") endif () diff --git a/DefineOptions.cmake b/DefineOptions.cmake index 5bc1ef3..911ff1d 100644 --- a/DefineOptions.cmake +++ b/DefineOptions.cmake @@ -1,5 +1,6 @@ option(WITH_STATIC_LIB "Build with a static library" OFF) option(WITH_CMOCKERY_SUPPORT "Install a cmockery header" OFF) +option(WITH_EXAMPLES "Build examples" ON) option(UNIT_TESTING "Build with unit testing" OFF) option(PICKY_DEVELOPER "Build with picky developer flags" OFF) diff --git a/cmake/Modules/DefineCMakeDefaults.cmake b/cmake/Modules/DefineCMakeDefaults.cmake index ab0538b..9fb034f 100644 --- a/cmake/Modules/DefineCMakeDefaults.cmake +++ b/cmake/Modules/DefineCMakeDefaults.cmake @@ -16,3 +16,10 @@ set(CMAKE_COLOR_MAKEFILE ON) # Create the compile command database for clang by default set(CMAKE_EXPORT_COMPILE_COMMANDS ON) + +# Always build with -fPIC +set(CMAKE_POSITION_INDEPENDENT_CODE ON) + +# Avoid source tree pollution +set(CMAKE_DISABLE_SOURCE_CHANGES ON) +set(CMAKE_DISABLE_IN_SOURCE_BUILD ON) diff --git a/cmake/Modules/DefineCompilerFlags.cmake b/cmake/Modules/DefineCompilerFlags.cmake index 3277b99..c9aea58 100644 --- a/cmake/Modules/DefineCompilerFlags.cmake +++ b/cmake/Modules/DefineCompilerFlags.cmake @@ -23,6 +23,18 @@ if (UNIX AND NOT WIN32) set(CMAKE_EXEC_LINKER_FLAGS_ADDRESSSANITIZER "-fsanitize=address" CACHE STRING "Flags used by the linker during ADDRESSSANITIZER builds.") + # Activate with: -DCMAKE_BUILD_TYPE=MemorySanitizer + set(CMAKE_C_FLAGS_MEMORYSANITIZER "-g -O2 -fsanitize=memory -fsanitize-memory-track-origins=2 -fno-omit-frame-pointer" + CACHE STRING "Flags used by the C compiler during MEMORYSANITIZER builds.") + set(CMAKE_CXX_FLAGS_MEMORYSANITIZER "-g -O2 -fsanitize=memory -fsanitize-memory-track-origins=2 -fno-omit-frame-pointer" + CACHE STRING "Flags used by the CXX compiler during MEMORYSANITIZER builds.") + set(CMAKE_SHARED_LINKER_FLAGS_MEMORYSANITIZER "-fsanitize=memory" + CACHE STRING "Flags used by the linker during the creation of shared libraries during MEMORYSANITIZER builds.") + set(CMAKE_MODULE_LINKER_FLAGS_MEMORYSANITIZER "-fsanitize=memory" + CACHE STRING "Flags used by the linker during the creation of shared libraries during MEMORYSANITIZER builds.") + set(CMAKE_EXEC_LINKER_FLAGS_MEMORYSANITIZER "-fsanitize=memory" + CACHE STRING "Flags used by the linker during MEMORYSANITIZER builds.") + # Activate with: -DCMAKE_BUILD_TYPE=UndefinedSanitizer set(CMAKE_C_FLAGS_UNDEFINEDSANITIZER "-g -O1 -fsanitize=undefined -fsanitize=null -fsanitize=alignment -fno-sanitize-recover" CACHE STRING "Flags used by the C compiler during UNDEFINEDSANITIZER builds.") diff --git a/cmake/Toolchain-Debian-mips.cmake b/cmake/Toolchain-Debian-mips.cmake new file mode 100644 index 0000000..d9c9d9f --- /dev/null +++ b/cmake/Toolchain-Debian-mips.cmake @@ -0,0 +1,21 @@ +include(CMakeForceCompiler) + +set(TOOLCHAIN_PREFIX mips-linux-gnu) + +set(CMAKE_SYSTEM_NAME Linux) +set(CMAKE_SYSTEM_VERSION 1) +set(CMAKE_SYSTEM_PROCESSOR mips) + +# This is the location of the mips toolchain +set(CMAKE_C_COMPILER ${TOOLCHAIN_PREFIX}-gcc) +set(CMAKE_CXX_COMPILER ${TOOLCHAIN_PREFIX}-g++) + +# This is the file system root of the target +set(CMAKE_FIND_ROOT_PATH /usr/${TOOLCHAIN_PREFIX}) + +# Search for programs in the build host directories +set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) + +# For libraries and headers in the target directories +set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) +set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) diff --git a/coverity/coverity_assert_model.c b/coverity/coverity_assert_model.c index 9bbb9f7..7ff64d8 100644 --- a/coverity/coverity_assert_model.c +++ b/coverity/coverity_assert_model.c @@ -1,24 +1,31 @@ #define LargestIntegralType unsigned long long + void _assert_true(const LargestIntegralType result, const char* const expression, const char * const file, const int line) { - __coverity_panic__(); + if (!result) { + __coverity_panic__(); + } } void _assert_int_equal( const LargestIntegralType a, const LargestIntegralType b, const char * const file, const int line) { - __coverity_panic__(); + if (a != b) { + __coverity_panic__(); + } } void _assert_int_not_equal( const LargestIntegralType a, const LargestIntegralType b, const char * const file, const int line) { - __coverity_panic__(); + if (a == b) { + __coverity_panic__(); + } } void _assert_return_code(const LargestIntegralType result, @@ -28,60 +35,122 @@ void _assert_return_code(const LargestIntegralType result, const char * const file, const int line) { - __coverity_panic__(); + if (result != 0) { + __coverity_panic__(); + } } void _assert_string_equal(const char * const a, const char * const b, const char * const file, const int line) { - __coverity_panic__(); + char ch; + int cmp; + + __coverity_weak_guard_sink__(a, b); + __coverity_weak_guard_sink__(b, a); + + ch = *((char *)a); + ch = *((char *)b); + + if (cmp != 0) { + __coverity_panic__(); + } } void _assert_string_not_equal(const char * const a, const char * const b, const char *file, const int line) { - __coverity_panic__(); + char ch; + int cmp; + + __coverity_weak_guard_sink__(a, b); + __coverity_weak_guard_sink__(b, a); + + ch = *((char *)a); + ch = *((char *)b); + + if (cmp == 0) { + __coverity_panic__(); + } } void _assert_memory_equal(const void * const a, const void * const b, const size_t size, const char* const file, const int line) { - __coverity_panic__(); + unsigned char ch; + int cmp; + + __coverity_weak_guard_sink__(a, b); + __coverity_weak_guard_sink__(b, a); + + ch = *((unsigned char *)a); + ch = *((unsigned char *)b); + + if (cmp != 0) { + __coverity_panic__(); + } } void _assert_memory_not_equal(const void * const a, const void * const b, const size_t size, const char* const file, const int line) { - __coverity_panic__(); + unsigned char ch; + int cmp; + + __coverity_weak_guard_sink__(a, b); + __coverity_weak_guard_sink__(b, a); + + ch = *((unsigned char *)a); + ch = *((unsigned char *)b); + + if (cmp == 0) { + __coverity_panic__(); + } } void _assert_in_range( const LargestIntegralType value, const LargestIntegralType minimum, const LargestIntegralType maximum, const char* const file, const int line) { - __coverity_panic__(); + if (value < minimum || value > maximum) { + __coverity_panic__(); + } } void _assert_not_in_range( const LargestIntegralType value, const LargestIntegralType minimum, const LargestIntegralType maximum, const char* const file, const int line) { - __coverity_panic__(); + if (value > minimum && value < maximum) { + __coverity_panic__(); + } } void _assert_in_set( const LargestIntegralType value, const LargestIntegralType values[], const size_t number_of_values, const char* const file, const int line) { - __coverity_panic__(); + size_t i; + + for (i = 0; i < number_of_values; i++) { + if (value == values[i]) { + return; + } + } + __coverity_panic__(); } void _assert_not_in_set( const LargestIntegralType value, const LargestIntegralType values[], const size_t number_of_values, const char* const file, const int line) { - __coverity_panic__(); -} + size_t i; + for (i = 0; i < number_of_values; i++) { + if (value == values[i]) { + __coverity_panic__(); + } + } +} diff --git a/doc/CMakeLists.txt b/doc/CMakeLists.txt index a7bc65e..6ac7494 100644 --- a/doc/CMakeLists.txt +++ b/doc/CMakeLists.txt @@ -38,7 +38,7 @@ if (DOXYGEN_FOUND) doxygen_add_docs(docs ${cmocka-library_SOURCE_DIR} - ${cmocka-headers_SOURCE_DIR} + ${cmocka-header_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}) endif(DOXYGEN_FOUND) diff --git a/doc/mainpage.dox b/doc/mainpage.dox index 4c26d96..c378bb1 100644 --- a/doc/mainpage.dox +++ b/doc/mainpage.dox @@ -33,7 +33,7 @@ The CMocka library provides: - Very well tested - Testing of memory leaks, buffer overflows and underflows. - A set of assert macros. - - Several supported output formats (stdout, TAP, xUnit XML, Subunit) + - Several supported output formats (stdout, TAP, JUnit XML, Subunit) - License: Apache License 2.0 @section main-test A cmocka test @@ -119,7 +119,7 @@ supported values are: - STDOUT for the default standard output printer - SUBUNIT for subunit output - TAP for Test Anything Protocol (TAP) output - - XML for xUnit XML format + - XML for JUnit XML format The case doesn't matter. The XML output goes to stderr by default. If the environment variable diff --git a/example/mock/uptime/test_uptime.c b/example/mock/uptime/test_uptime.c index badfac9..c724f95 100644 --- a/example/mock/uptime/test_uptime.c +++ b/example/mock/uptime/test_uptime.c @@ -16,6 +16,7 @@ #include #include +#include #include #include @@ -166,6 +167,8 @@ static void test_calc_uptime_null(void **state) uptime_str = calc_uptime(); assert_null(uptime_str); + + free(uptime_str); } int main(void) diff --git a/example/simple_test.c b/example/simple_test.c index c6eee9c..cfb446c 100644 --- a/example/simple_test.c +++ b/example/simple_test.c @@ -1,6 +1,7 @@ #include #include #include +#include #include /* A test case that does nothing and succeeds. */ diff --git a/include/cmocka.h b/include/cmocka.h index e6861c8..9b47ceb 100644 --- a/include/cmocka.h +++ b/include/cmocka.h @@ -41,12 +41,13 @@ int __stdcall IsDebuggerPresent(); /** * @defgroup cmocka The CMocka API * - * These headers or their equivalents should be included prior to including + * These headers or their equivalents MUST be included prior to including * this header file. * @code * #include * #include * #include + * #include * @endcode * * This allows test applications to use custom definitions of C standard @@ -106,6 +107,10 @@ typedef uintmax_t LargestIntegralType; # endif /* _WIN32 */ #endif /* LargestIntegralTypePrintfFormat */ +#ifndef FloatPrintfFormat +# define FloatPrintfFormat "%f" +#endif /* FloatPrintfFormat */ + /* Perform an unsigned cast to LargestIntegralType. */ #define cast_to_largest_integral_type(value) \ ((LargestIntegralType)(value)) @@ -116,7 +121,7 @@ typedef uintmax_t LargestIntegralType; /* WIN32 is an ILP32 platform */ typedef unsigned int uintptr_t; # elif defined(_WIN64) - typedef unsigned long int uintptr_t + typedef unsigned long int uintptr_t; # else /* _WIN32 */ /* ILP32 and LP64 platforms */ @@ -208,8 +213,8 @@ cast_to_largest_integral_type(cast_to_pointer_integral_type(value)) * } * @endcode * - * For a complete example please at a look - * here. + * For a complete example please take a look + * here. * * @{ */ @@ -425,8 +430,8 @@ void will_return_maybe(#function, LargestIntegralType value); * } * @endcode * - * For a complete example please at a look at - * here + * For a complete example please take a look + * here * * @{ */ @@ -966,6 +971,24 @@ void expect_any(#function, #parameter); #ifdef DOXYGEN /** + * @brief Add an event to always check if a parameter (of any value) has been passed. + * + * The event is triggered by calling check_expected() in the mocked function. + * + * @param[in] #function The function to add the check for. + * + * @param[in] #parameter The name of the parameter passed to the function. + * + * @see check_expected(). + */ +void expect_any_always(#function, #parameter); +#else +#define expect_any_always(function, parameter) \ + expect_any_count(function, parameter, WILL_RETURN_ALWAYS) +#endif + +#ifdef DOXYGEN +/** * @brief Add an event to repeatedly check if a parameter (of any value) has * been passed. * @@ -1217,6 +1240,51 @@ void assert_int_not_equal(int a, int b); #ifdef DOXYGEN /** + * @brief Assert that the two given float are equal given an epsilon. + * + * The function prints an error message to standard error and terminates the + * test by calling fail() if the float are not equal (given an epsilon). + * + * @param[in] a The first float to compare. + * + * @param[in] b The float to compare against the first one. + * + * @param[in] epsilon The epsilon used as margin for float comparison. + */ +void assert_float_equal(float a, float b, float epsilon); +#else +#define assert_float_equal(a, b, epsilon) \ + _assert_float_equal((float)a, \ + (float)b, \ + (float)epsilon, \ + __FILE__, __LINE__) +#endif + +#ifdef DOXYGEN +/** + * @brief Assert that the two given float are not equal given an epsilon. + * + * The function prints an error message to standard error and terminates the + * test by calling fail() if the float are not equal (given an epsilon). + * + * @param[in] a The first float to compare. + * + * @param[in] b The float to compare against the first one. + * + * @param[in] epsilon The epsilon used as margin for float comparison. + */ +void assert_float_not_equal(float a, float b, float epsilon); +#else +#define assert_float_not_equal(a, b, epsilon) \ + _assert_float_not_equal((float)a, \ + (float)b, \ + (float)epsilon, \ + __FILE__, __LINE__) +#endif + + +#ifdef DOXYGEN +/** * @brief Assert that the two given strings are equal. * * The function prints an error message to standard error and terminates the @@ -2199,6 +2267,12 @@ void _assert_return_code(const LargestIntegralType result, const char * const expression, const char * const file, const int line); +void _assert_float_equal(const float a, const float n, + const float epsilon, const char* const file, + const int line); +void _assert_float_not_equal(const float a, const float n, + const float epsilon, const char* const file, + const int line); void _assert_int_equal( const LargestIntegralType a, const LargestIntegralType b, const char * const file, const int line); @@ -2284,7 +2358,7 @@ void cmocka_set_message_output(enum cm_message_output output); /** * @brief Set a pattern to only run the test matching the pattern. * - * This allows to filter tests and only run the ones matching the pattern. Thep + * This allows to filter tests and only run the ones matching the pattern. The * pattern can include two wildards. The first is '*', a wildcard that matches * zero or more characters, or ‘?’, a wildcard that matches exactly one * character. @@ -2293,6 +2367,18 @@ void cmocka_set_message_output(enum cm_message_output output); */ void cmocka_set_test_filter(const char *pattern); +/** + * @brief Set a pattern to skip tests matching the pattern. + * + * This allows to filter tests and skip the ones matching the pattern. The + * pattern can include two wildards. The first is '*', a wildcard that matches + * zero or more characters, or ‘?’, a wildcard that matches exactly one + * character. + * + * @param[in] pattern The pattern to match, e.g. "test_wurst*" + */ +void cmocka_set_skip_filter(const char *pattern); + /** @} */ #endif /* CMOCKA_H_ */ diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index e44ef40..5684685 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -78,6 +78,8 @@ install(TARGETS ${CMAKE_INSTALL_LIBDIR} LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} + RUNTIME DESTINATION + ${CMAKE_INSTALL_BINDIR} COMPONENT ${PROJECT_NAME}) diff --git a/src/cmocka.c b/src/cmocka.c index b21fe15..6233155 100644 --- a/src/cmocka.c +++ b/src/cmocka.c @@ -43,6 +43,7 @@ #include #include #include +#include /* * This allows to add a platform specific header file. Some embedded platforms @@ -312,6 +313,8 @@ static enum cm_message_output global_msg_output = CM_OUTPUT_STDOUT; static const char *global_test_filter_pattern; +static const char *global_skip_filter_pattern; + #ifndef _WIN32 /* Signals caught by exception_handler(). */ static const int exception_signals[] = { @@ -567,7 +570,7 @@ static void fail_if_leftover_values(const char *test_name) { remove_always_return_values_from_list(&global_call_ordering_head); if (check_for_leftover_values_list(&global_call_ordering_head, - "%s function was expected to be called but was not not.\n")) { + "%s function was expected to be called but was not.\n")) { error_occurred = 1; } if (error_occurred) { @@ -898,7 +901,7 @@ static size_t check_for_leftover_values_list(const ListNode * head, child_node = child_node->next, ++leftover_count) { const FuncOrderingValue *const o = (const FuncOrderingValue*) child_node->value; - cm_print_error(error_message, o->function); + cm_print_error(error_message, "%s", o->function); cm_print_error(SOURCE_LOCATION_FORMAT ": note: remaining item was declared here\n", o->location.file, o->location.line); @@ -930,7 +933,7 @@ static size_t check_for_leftover_values( if (!list_empty(child_list)) { if (number_of_symbol_names == 1) { const ListNode *child_node; - cm_print_error(error_message, value->symbol_name); + cm_print_error(error_message, "%s", value->symbol_name); for (child_node = child_list->next; child_node != child_list; child_node = child_node->next) { @@ -1122,6 +1125,62 @@ void _expect_function_call( list_add_value(&global_call_ordering_head, ordering, count); } +/* Returns 1 if the specified float values are equal, else returns 0. */ +static int float_compare(const float left, + const float right, + const float epsilon) { + float absLeft; + float absRight; + float largest; + float relDiff; + + float diff = left - right; + diff = (diff >= 0.f) ? diff : -diff; + + // Check if the numbers are really close -- needed + // when comparing numbers near zero. + if (diff <= epsilon) { + return 1; + } + + absLeft = (left >= 0.f) ? left : -left; + absRight = (right >= 0.f) ? right : -right; + + largest = (absRight > absLeft) ? absRight : absLeft; + relDiff = largest * FLT_EPSILON; + + if (diff > relDiff) { + return 0; + } + return 1; +} + +/* Returns 1 if the specified float values are equal. If the values are not equal + * an error is displayed and 0 is returned. */ +static int float_values_equal_display_error(const float left, + const float right, + const float epsilon) { + const int equal = float_compare(left, right, epsilon); + if (!equal) { + cm_print_error(FloatPrintfFormat " != " + FloatPrintfFormat "\n", left, right); + } + return equal; +} + +/* Returns 1 if the specified float values are different. If the values are equal + * an error is displayed and 0 is returned. */ +static int float_values_not_equal_display_error(const float left, + const float right, + const float epsilon) { + const int not_equal = (float_compare(left, right, epsilon) == 0); + if (!not_equal) { + cm_print_error(FloatPrintfFormat " == " + FloatPrintfFormat "\n", left, right); + } + return not_equal; +} + /* Returns 1 if the specified values are equal. If the values are not equal * an error is displayed and 0 is returned. */ static int values_equal_display_error(const LargestIntegralType left, @@ -1714,6 +1773,26 @@ void _assert_return_code(const LargestIntegralType result, } } +void _assert_float_equal(const float a, + const float b, + const float epsilon, + const char * const file, + const int line) { + if (!float_values_equal_display_error(a, b, epsilon)) { + _fail(file, line); + } +} + +void _assert_float_not_equal(const float a, + const float b, + const float epsilon, + const char * const file, + const int line) { + if (!float_values_not_equal_display_error(a, b, epsilon)) { + _fail(file, line); + } +} + void _assert_int_equal( const LargestIntegralType a, const LargestIntegralType b, const char * const file, const int line) { @@ -1820,11 +1899,11 @@ static ListNode* get_allocated_blocks_list(void) { return &global_allocated_blocks; } -static void *libc_malloc(size_t size) +static void *libc_calloc(size_t nmemb, size_t size) { -#undef malloc - return malloc(size); -#define malloc test_malloc +#undef calloc + return calloc(nmemb, size); +#define calloc test_calloc } static void libc_free(void *ptr) @@ -1864,7 +1943,7 @@ static void vcm_print_error(const char* const format, va_list args) if (cm_error_message == NULL) { /* CREATE MESSAGE */ - cm_error_message = libc_malloc(len + 1); + cm_error_message = libc_calloc(1, len + 1); if (cm_error_message == NULL) { /* TODO */ goto end; @@ -1944,6 +2023,7 @@ void* _test_calloc(const size_t number_of_elements, const size_t size, } return ptr; } +#define calloc test_calloc /* Use the real free in this function. */ @@ -2615,6 +2695,11 @@ void cmocka_set_test_filter(const char *pattern) global_test_filter_pattern = pattern; } +void cmocka_set_skip_filter(const char *pattern) +{ + global_skip_filter_pattern = pattern; +} + /**************************************************************************** * TIME CALCULATIONS ****************************************************************************/ @@ -2889,7 +2974,7 @@ int _cmocka_run_group_tests(const char *group_name, /* Make sure LargestIntegralType is at least the size of a pointer. */ assert_true(sizeof(LargestIntegralType) >= sizeof(void*)); - cm_tests = (struct CMUnitTestState *)libc_malloc(sizeof(struct CMUnitTestState) * num_tests); + cm_tests = libc_calloc(1, sizeof(struct CMUnitTestState) * num_tests); if (cm_tests == NULL) { return -1; } @@ -2901,10 +2986,18 @@ int _cmocka_run_group_tests(const char *group_name, || tests[i].setup_func != NULL || tests[i].teardown_func != NULL)) { if (global_test_filter_pattern != NULL) { - int ok; + int match; + + match = c_strmatch(tests[i].name, global_test_filter_pattern); + if (!match) { + continue; + } + } + if (global_skip_filter_pattern != NULL) { + int match; - ok = c_strmatch(tests[i].name, global_test_filter_pattern); - if (!ok) { + match = c_strmatch(tests[i].name, global_skip_filter_pattern); + if (match) { continue; } } diff --git a/src/cmocka.def b/src/cmocka.def index 393c6da..3633dc1 100644 --- a/src/cmocka.def +++ b/src/cmocka.def @@ -1,5 +1,7 @@ LIBRARY cmocka EXPORTS + _assert_float_equal + _assert_float_not_equal _assert_in_range _assert_in_set _assert_int_equal @@ -41,6 +43,7 @@ EXPORTS cm_print_error cmocka_set_message_output cmocka_set_test_filter + cmocka_set_skip_filter global_expect_assert_env global_expecting_assert global_last_failed_assert diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index f7ea00b..8d53f51 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -15,6 +15,7 @@ set(CMOCKA_TESTS test_fixtures test_group_fixtures test_groups + test_float_macros test_assert_macros test_assert_macros_fail test_basics @@ -25,7 +26,9 @@ set(CMOCKA_TESTS test_ordering_fail test_returns test_returns_fail - test_wildcard) + test_wildcard + test_skip_filter + ) if (TEST_EXCEPTION_HANDLER) list(APPEND CMOCKA_TESTS test_exception_handler) diff --git a/tests/test_float_macros.c b/tests/test_float_macros.c new file mode 100644 index 0000000..a9c7251 --- /dev/null +++ b/tests/test_float_macros.c @@ -0,0 +1,40 @@ +/* + * Copyright 2019 Arnaud Gelas + * + * 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. + */ + +/* Use the unit test allocators */ +#define UNIT_TESTING 1 + +#include +#include +#include +#include + +/* A test case that does check if float is equal. */ +static void float_test_success(void **state) +{ + (void)state; /* unused */ + + assert_float_equal(0.5f, 1.f / 2.f, 0.000001f); + assert_float_not_equal(0.5, 0.499f, 0.000001f); +} + +int main(void) { + const struct CMUnitTest tests[] = { + cmocka_unit_test(float_test_success), + }; + + return cmocka_run_group_tests(tests, NULL, NULL); +} diff --git a/tests/test_skip_filter.c b/tests/test_skip_filter.c new file mode 100644 index 0000000..e40209e --- /dev/null +++ b/tests/test_skip_filter.c @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2019 by Red Hat, Inc. + * + * Author: Anderson Toshiyuki Sasaki + * + * 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. + */ + +#include +#include +#include +#include + +static void test_skip1(void **state) +{ + (void)state; + + assert_true(1); +} + +static void test_skip2(void **state) +{ + (void)state; + + assert_false(1); +} + +static void test_fail(void **state) +{ + (void)state; + + assert_false(1); +} + +int main(void) { + const struct CMUnitTest tests[] = { + cmocka_unit_test(test_skip1), + cmocka_unit_test(test_skip2), + cmocka_unit_test(test_fail), + }; + + cmocka_set_test_filter("test_skip*"); + + cmocka_set_skip_filter("test_skip2"); + + return cmocka_run_group_tests(tests, NULL, NULL); +} -- 2.7.4