aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.clang-format33
-rw-r--r--.editorconfig13
-rw-r--r--.gitignore1
-rw-r--r--.gitlab-ci.yml494
-rw-r--r--CMakeLists.txt36
-rw-r--r--CONTRIBUTING.md399
-rw-r--r--CPackConfig.cmake6
-rw-r--r--CompilerChecks.cmake23
-rw-r--r--ConfigureChecks.cmake4
-rw-r--r--DefineOptions.cmake1
-rw-r--r--INSTALL.md43
-rw-r--r--README.md3
-rw-r--r--cmake/Modules/AddCMockaTest.cmake7
-rw-r--r--cmocka-config.cmake.in17
-rw-r--r--cmocka.pc.cmake14
-rw-r--r--coverity/Makefile9
-rw-r--r--coverity/coverity-builtins.h50
-rw-r--r--coverity/coverity_assert_model.c171
-rw-r--r--doc/index.html706
-rw-r--r--doc/mainpage.dox6
-rw-r--r--example/CMakeLists.txt7
-rw-r--r--example/allocate_module_test.c2
-rw-r--r--example/assert_macro_test.c2
-rw-r--r--example/assert_module_test.c2
-rw-r--r--example/calculator_test.c2
-rw-r--r--example/mock/chef_wrap/chef.c2
-rw-r--r--example/mock/chef_wrap/waiter_test_wrap.c6
-rw-r--r--example/mock/uptime/CMakeLists.txt8
-rw-r--r--example/mock/uptime/test_uptime.c1
-rw-r--r--example/mock/uptime/uptime.c2
-rw-r--r--example/simple_test.c1
-rw-r--r--include/CMakeLists.txt15
-rw-r--r--include/cmocka.h1452
-rw-r--r--include/cmocka_private.h9
-rw-r--r--include/cmocka_version.h.cmake37
-rw-r--r--include/cmockery/cmockery.h1
-rw-r--r--include/cmockery/pbc.h1
-rw-r--r--meson.build64
-rw-r--r--src/CMakeLists.txt64
-rw-r--r--src/cmocka.c2194
-rw-r--r--src/cmocka.def56
-rw-r--r--tests/CMakeLists.txt160
-rw-r--r--tests/cmocka_test.cmake1
-rw-r--r--tests/ctest-default.cmake2
-rw-r--r--tests/meson.build15
-rw-r--r--tests/test_alloc.c22
-rw-r--r--tests/test_assert_false.c27
-rw-r--r--tests/test_assert_false_fail.c27
-rw-r--r--tests/test_assert_macros.c4
-rw-r--r--tests/test_assert_macros_fail.c2
-rw-r--r--tests/test_assert_memory.c49
-rw-r--r--tests/test_assert_memory_fail.c49
-rw-r--r--tests/test_assert_ptr.c48
-rw-r--r--tests/test_assert_ptr_fail.c49
-rw-r--r--tests/test_assert_range.c54
-rw-r--r--tests/test_assert_range_fail.c58
-rw-r--r--tests/test_assert_set.c120
-rw-r--r--tests/test_assert_set_fail.c66
-rw-r--r--tests/test_assert_true.c27
-rw-r--r--tests/test_assert_true_fail.c27
-rw-r--r--tests/test_assert_u_int.c53
-rw-r--r--tests/test_assert_u_int_fail.c55
-rw-r--r--tests/test_basics.c2
-rw-r--r--tests/test_buffer.c49
-rw-r--r--tests/test_double_macros.c2
-rw-r--r--tests/test_exception_handler.c20
-rw-r--r--tests/test_expect_check.c139
-rw-r--r--tests/test_expect_check_fail.c50
-rw-r--r--tests/test_expect_u_int_in_set.c50
-rw-r--r--tests/test_fixtures.c8
-rw-r--r--tests/test_float_macros.c2
-rw-r--r--tests/test_group_fixtures.c2
-rw-r--r--tests/test_group_setup_assert.c2
-rw-r--r--tests/test_group_setup_fail.c2
-rw-r--r--tests/test_groups.c4
-rw-r--r--tests/test_ordering.c2
-rw-r--r--tests/test_ordering_fail.c11
-rw-r--r--tests/test_returns.c99
-rw-r--r--tests/test_returns_fail.c54
-rw-r--r--tests/test_setup_fail.c2
-rw-r--r--tests/test_skip.c2
-rw-r--r--tests/test_skip_filter.c2
-rw-r--r--tests/test_stop.c51
-rw-r--r--tests/test_stop_fail.c95
-rw-r--r--tests/test_string.c (renamed from tests/test_cmockery.c)27
-rw-r--r--tests/test_strmatch.c2
-rw-r--r--tests/test_strreplace.c129
-rw-r--r--tests/test_wildcard.c2
88 files changed, 5252 insertions, 2437 deletions
diff --git a/.clang-format b/.clang-format
new file mode 100644
index 0000000..63d61e6
--- /dev/null
+++ b/.clang-format
@@ -0,0 +1,33 @@
+# https://clang.llvm.org/docs/ClangFormatStyleOptions.html
+#
+AlignAfterOpenBracket: Align
+AlignEscapedNewlines: Left
+AllowAllArgumentsOnNextLine: true
+AllowAllParametersOfDeclarationOnNextLine: false
+AllowShortFunctionsOnASingleLine: Empty
+AllowShortIfStatementsOnASingleLine: false
+AlwaysBreakAfterReturnType: None
+BasedOnStyle: LLVM
+BinPackArguments: false
+BinPackParameters: false
+BraceWrapping:
+ AfterEnum: false
+ AfterFunction: true
+ AfterStruct: false
+ AfterUnion: false
+ AfterExternBlock: true
+ BeforeElse: false
+ BeforeWhile: false
+ AfterControlStatement: MultiLine
+BreakBeforeBinaryOperators: None
+BreakBeforeBraces: Custom
+ColumnLimit: 80
+ContinuationIndentWidth: 4
+IndentCaseLabels: false
+IndentGotoLabels: false
+IndentWidth: 4
+PenaltyBreakAssignment: 200
+PenaltyBreakBeforeFirstCallParameter: 100
+PenaltyReturnTypeOnItsOwnLine: 1000
+SortIncludes: false
+UseTab: Never
diff --git a/.editorconfig b/.editorconfig
new file mode 100644
index 0000000..7cd1362
--- /dev/null
+++ b/.editorconfig
@@ -0,0 +1,13 @@
+# EditorConfig is awesome: https://EditorConfig.org
+
+# top-most EditorConfig file
+root = true
+
+[*]
+charset = utf-8
+max_line_length = 80
+indent_style = space
+indent_size = 4
+tab_width = 4
+insert_final_newline = true
+trim_trailing_whitespace = true
diff --git a/.gitignore b/.gitignore
index e6731b4..fe8ff50 100644
--- a/.gitignore
+++ b/.gitignore
@@ -5,5 +5,6 @@ cscope.*
.ycm_extra_conf.pyc
compile_commands.json
/.clangd
+/.cache
/build
/obj*
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 9e45438..9c9dd8a 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -1,40 +1,90 @@
+---
variables:
BUILD_IMAGES_PROJECT: cmocka/gitlab-build-images
FEDORA_BUILD: buildenv-fedora
CENTOS7_BUILD: buildenv-centos7
TUMBLEWEED_BUILD: buildenv-tumbleweed
MINGW_BUILD: buildenv-mingw
+ UBUNTU_BUILD: buildenv-ubuntu
+
+stages:
+ - build
+ - test
+ - analysis
centos7/x86_64:
+ stage: test
image: $CI_REGISTRY/$BUILD_IMAGES_PROJECT:$CENTOS7_BUILD
script:
- - mkdir -p obj && cd obj && cmake3
- -DCMAKE_BUILD_TYPE=RelWithDebInfo
- -DPICKY_DEVELOPER=ON
- -DUNIT_TESTING=ON .. &&
- make -j$(nproc) && ctest --output-on-failure
+ - mkdir -p obj && cd obj && cmake3
+ -DCMAKE_BUILD_TYPE=RelWithDebInfo
+ -DPICKY_DEVELOPER=ON
+ -DUNIT_TESTING=ON .. &&
+ make -j$(nproc) && ctest --output-on-failure
tags:
- - shared
+ - shared
except:
- - tags
+ - tags
artifacts:
expire_in: 1 week
when: on_failure
paths:
- obj/
-fedora/x86_64:
+fedora/gcc/x86_64:
+ stage: test
image: $CI_REGISTRY/$BUILD_IMAGES_PROJECT:$FEDORA_BUILD
script:
- - mkdir -p obj && cd obj && cmake
- -DCMAKE_BUILD_TYPE=RelWithDebInfo
- -DPICKY_DEVELOPER=ON
- -DUNIT_TESTING=ON .. &&
- make -j$(nproc) && ctest --output-on-failure
+ - mkdir -p obj && cd obj && cmake
+ -DCMAKE_BUILD_TYPE=RelWithDebInfo
+ -DPICKY_DEVELOPER=ON
+ -DUNIT_TESTING=ON .. &&
+ make -j$(nproc) && ctest --output-on-failure
tags:
- - shared
+ - shared
except:
- - tags
+ - tags
+ artifacts:
+ expire_in: 1 week
+ when: on_failure
+ paths:
+ - obj/
+
+fedora/clang/x86_64:
+ stage: test
+ image: $CI_REGISTRY/$BUILD_IMAGES_PROJECT:$FEDORA_BUILD
+ script:
+ - mkdir -p obj && cd obj && cmake
+ -DCMAKE_C_COMPILER=clang
+ -DCMAKE_BUILD_TYPE=RelWithDebInfo
+ -DPICKY_DEVELOPER=ON
+ -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/build:
+ stage: build
+ image: $CI_REGISTRY/$BUILD_IMAGES_PROJECT:$FEDORA_BUILD
+ script:
+ - pushd coverity && make && popd
+ - mkdir -p obj && cd obj && cmake
+ -DCMAKE_BUILD_TYPE=Release
+ -DCMAKE_INSTALL_PREFIX=/tmp/cmocka
+ -DPICKY_DEVELOPER=ON
+ .. &&
+ make -j$(nproc) && make install
+ tags:
+ - shared
+ except:
+ - tags
artifacts:
expire_in: 1 week
when: on_failure
@@ -42,14 +92,15 @@ fedora/x86_64:
- obj/
fedora/meson:
+ stage: build
image: $CI_REGISTRY/$BUILD_IMAGES_PROJECT:$FEDORA_BUILD
script:
- - meson build -Dunit_testing=true &&
- meson test -C build --print-errorlogs
+ - meson build -Dunit_testing=true &&
+ meson test -C build --print-errorlogs
tags:
- - shared
+ - shared
except:
- - tags
+ - tags
artifacts:
expire_in: 1 week
when: on_failure
@@ -57,17 +108,18 @@ fedora/meson:
- build/
fedora/address-sanitizer:
+ stage: build
image: $CI_REGISTRY/$BUILD_IMAGES_PROJECT:$FEDORA_BUILD
script:
- - mkdir -p obj && cd obj && cmake
- -DCMAKE_BUILD_TYPE=AddressSanitizer
- -DPICKY_DEVELOPER=ON
- -DUNIT_TESTING=ON .. &&
- make -j$(nproc) && ctest --output-on-failure
+ - mkdir -p obj && cd obj && cmake
+ -DCMAKE_BUILD_TYPE=AddressSanitizer
+ -DPICKY_DEVELOPER=ON
+ -DUNIT_TESTING=ON .. &&
+ make -j$(nproc) && ctest --output-on-failure
tags:
- - shared
+ - shared
except:
- - tags
+ - tags
artifacts:
expire_in: 1 week
when: on_failure
@@ -75,17 +127,18 @@ fedora/address-sanitizer:
- obj/
fedora/memory-sanitizer:
+ stage: analysis
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
+ - 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
+ - shared
except:
- - tags
+ - tags
artifacts:
expire_in: 1 week
when: on_failure
@@ -93,16 +146,17 @@ fedora/memory-sanitizer:
- obj/
fedora/undefined-sanitizer:
+ stage: analysis
image: $CI_REGISTRY/$BUILD_IMAGES_PROJECT:$FEDORA_BUILD
script:
- - mkdir -p obj && cd obj && cmake
- -DCMAKE_BUILD_TYPE=UndefinedSanitizer
- -DUNIT_TESTING=ON ..
- && make -j$(nproc) && ctest --output-on-failure
+ - mkdir -p obj && cd obj && cmake
+ -DCMAKE_BUILD_TYPE=UndefinedSanitizer
+ -DUNIT_TESTING=ON ..
+ && make -j$(nproc) && ctest --output-on-failure
tags:
- - shared
+ - shared
except:
- - tags
+ - tags
artifacts:
expire_in: 1 week
when: on_failure
@@ -110,51 +164,78 @@ fedora/undefined-sanitizer:
- obj/
fedora/csbuild:
+ stage: analysis
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
+ - |
+ 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")
+ # 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"
+ 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
+ - 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
+ - shared
except:
- - tags
+ - tags
artifacts:
expire_in: 1 week
when: on_failure
paths:
- obj-csbuild/
+fedora/coverage:
+ stage: analysis
+ image: $CI_REGISTRY/$BUILD_IMAGES_PROJECT:$FEDORA_BUILD
+ script:
+ - mkdir -p obj && cd obj && cmake
+ -DCMAKE_BUILD_TYPE=Profiling
+ -DCMAKE_INSTALL_PREFIX=/tmp/cmocka
+ -DPICKY_DEVELOPER=ON
+ -DUNIT_TESTING=ON
+ .. &&
+ make -j$(nproc) &&
+ make ExperimentalTest &&
+ make ExperimentalCoverage
+ coverage: '/Percentage Coverage: \d+.\d+%/'
+ tags:
+ - shared
+ except:
+ - tags
+ artifacts:
+ expire_in: 1 week
+ when: on_failure
+ paths:
+ - obj/
+
freebsd/x86_64:
+ stage: test
image:
script:
- - mkdir -p obj && cd obj && cmake
- -DCMAKE_BUILD_TYPE=RelWithDebInfo
- -DPICKY_DEVELOPER=ON
- -DUNIT_TESTING=ON .. &&
- make && ctest --output-on-failure
+ - mkdir -p obj && cd obj && cmake
+ -DCMAKE_BUILD_TYPE=RelWithDebInfo
+ -DPICKY_DEVELOPER=ON
+ -DUNIT_TESTING=ON .. &&
+ make && ctest --output-on-failure
tags:
- - freebsd
+ - freebsd
except:
- - tags
+ - tags
only:
- - branches@cmocka/cmocka
- - branches@cryptomilk/cmocka
+ - branches@cmocka/cmocka
+ - branches@cryptomilk/cmocka
artifacts:
expire_in: 1 week
when: on_failure
@@ -162,20 +243,21 @@ freebsd/x86_64:
- obj/
fedora/mingw64:
+ stage: test
image: $CI_REGISTRY/$BUILD_IMAGES_PROJECT:$MINGW_BUILD
script:
- - export WINEPATH=/usr/x86_64-w64-mingw32/sys-root/mingw/bin
- - export WINEDEBUG=-all
- - mkdir -p obj && cd obj && mingw64-cmake
- -DCMAKE_BUILD_TYPE=RelWithDebInfo
- -DPICKY_DEVELOPER=ON
- -DUNIT_TESTING=ON .. &&
- make -j$(nproc) &&
- ctest --output-on-failure
+ - export WINEPATH=/usr/x86_64-w64-mingw32/sys-root/mingw/bin
+ - export WINEDEBUG=-all
+ - mkdir -p obj && cd obj && mingw64-cmake
+ -DCMAKE_BUILD_TYPE=RelWithDebInfo
+ -DPICKY_DEVELOPER=ON
+ -DUNIT_TESTING=ON .. &&
+ make -j$(nproc) &&
+ ctest --output-on-failure
tags:
- - shared
+ - shared
except:
- - tags
+ - tags
artifacts:
expire_in: 1 week
when: on_failure
@@ -183,21 +265,22 @@ fedora/mingw64:
- obj/
fedora/mingw32:
+ stage: test
image: $CI_REGISTRY/$BUILD_IMAGES_PROJECT:$MINGW_BUILD
script:
- - export WINEPATH=/usr/i686-w64-mingw32/sys-root/mingw/bin
- - export WINEDEBUG=-all
- - mkdir -p obj && cd obj && mingw32-cmake
- -DCMAKE_BUILD_TYPE=RelWithDebInfo
- -DPICKY_DEVELOPER=ON
- -DWITH_SFTP=ON -DWITH_SERVER=ON -DWITH_ZLIB=ON --DWITH_PCAP=ON
- -DUNIT_TESTING=ON .. &&
- make -j$(nproc) &&
- ctest --output-on-failure
+ - export WINEPATH=/usr/i686-w64-mingw32/sys-root/mingw/bin
+ - export WINEDEBUG=-all
+ - mkdir -p obj && cd obj && mingw32-cmake
+ -DCMAKE_BUILD_TYPE=RelWithDebInfo
+ -DPICKY_DEVELOPER=ON
+ -DWITH_SFTP=ON -DWITH_SERVER=ON -DWITH_ZLIB=ON -DWITH_PCAP=ON
+ -DUNIT_TESTING=ON .. &&
+ make -j$(nproc) &&
+ ctest --output-on-failure
tags:
- - shared
+ - shared
except:
- - tags
+ - tags
artifacts:
expire_in: 1 week
when: on_failure
@@ -205,17 +288,18 @@ fedora/mingw32:
- obj/
tumbleweed/x86_64/gcc:
+ stage: test
image: $CI_REGISTRY/$BUILD_IMAGES_PROJECT:$TUMBLEWEED_BUILD
script:
- - mkdir -p obj && cd obj && cmake
- -DCMAKE_BUILD_TYPE=RelWithDebInfo
- -DPICKY_DEVELOPER=ON
- -DUNIT_TESTING=ON .. &&
- make -j$(nproc) && ctest --output-on-failure
+ - mkdir -p obj && cd obj && cmake
+ -DCMAKE_BUILD_TYPE=RelWithDebInfo
+ -DPICKY_DEVELOPER=ON
+ -DUNIT_TESTING=ON .. &&
+ make -j$(nproc) && ctest --output-on-failure
tags:
- - shared
+ - shared
except:
- - tags
+ - tags
artifacts:
expire_in: 1 week
when: on_failure
@@ -223,18 +307,19 @@ tumbleweed/x86_64/gcc:
- obj/
tumbleweed/x86/gcc:
+ stage: test
image: $CI_REGISTRY/$BUILD_IMAGES_PROJECT:$TUMBLEWEED_BUILD
script:
- - mkdir -p obj && cd obj && cmake
- -DCMAKE_TOOLCHAIN_FILE=../cmake/Toolchain-cross-m32.cmake
- -DCMAKE_BUILD_TYPE=RelWithDebInfo
- -DPICKY_DEVELOPER=ON
- -DUNIT_TESTING=ON .. &&
- make -j$(nproc) && ctest --output-on-failure
+ - mkdir -p obj && cd obj && cmake
+ -DCMAKE_TOOLCHAIN_FILE=../cmake/Toolchain-cross-m32.cmake
+ -DCMAKE_BUILD_TYPE=RelWithDebInfo
+ -DPICKY_DEVELOPER=ON
+ -DUNIT_TESTING=ON .. &&
+ make -j$(nproc) && ctest --output-on-failure
tags:
- - shared
+ - shared
except:
- - tags
+ - tags
artifacts:
expire_in: 1 week
when: on_failure
@@ -242,18 +327,19 @@ tumbleweed/x86/gcc:
- obj/
tumbleweed/x86_64/gcc7:
+ stage: test
image: $CI_REGISTRY/$BUILD_IMAGES_PROJECT:$TUMBLEWEED_BUILD
script:
- - mkdir -p obj && cd obj && cmake
- -DCMAKE_C_COMPILER=gcc-7 -DCMAKE_CXX_COMPILER=g++-7
- -DCMAKE_BUILD_TYPE=RelWithDebInfo
- -DPICKY_DEVELOPER=ON
- -DUNIT_TESTING=ON .. &&
- make -j$(nproc) && ctest --output-on-failure
+ - mkdir -p obj && cd obj && cmake
+ -DCMAKE_C_COMPILER=gcc-7 -DCMAKE_CXX_COMPILER=g++-7
+ -DCMAKE_BUILD_TYPE=RelWithDebInfo
+ -DPICKY_DEVELOPER=ON
+ -DUNIT_TESTING=ON .. &&
+ make -j$(nproc) && ctest --output-on-failure
tags:
- - shared
+ - shared
except:
- - tags
+ - tags
artifacts:
expire_in: 1 week
when: on_failure
@@ -261,19 +347,20 @@ tumbleweed/x86_64/gcc7:
- obj/
tumbleweed/x86/gcc7:
+ stage: test
image: $CI_REGISTRY/$BUILD_IMAGES_PROJECT:$TUMBLEWEED_BUILD
script:
- - mkdir -p obj && cd obj && cmake
- -DCMAKE_TOOLCHAIN_FILE=../cmake/Toolchain-cross-m32.cmake
- -DCMAKE_C_COMPILER=gcc-7 -DCMAKE_CXX_COMPILER=g++-7
- -DCMAKE_BUILD_TYPE=RelWithDebInfo
- -DPICKY_DEVELOPER=ON
- -DUNIT_TESTING=ON .. &&
- make -j$(nproc) && ctest --output-on-failure
+ - mkdir -p obj && cd obj && cmake
+ -DCMAKE_TOOLCHAIN_FILE=../cmake/Toolchain-cross-m32.cmake
+ -DCMAKE_C_COMPILER=gcc-7 -DCMAKE_CXX_COMPILER=g++-7
+ -DCMAKE_BUILD_TYPE=RelWithDebInfo
+ -DPICKY_DEVELOPER=ON
+ -DUNIT_TESTING=ON .. &&
+ make -j$(nproc) && ctest --output-on-failure
tags:
- - shared
+ - shared
except:
- - tags
+ - tags
artifacts:
expire_in: 1 week
when: on_failure
@@ -281,18 +368,19 @@ tumbleweed/x86/gcc7:
- obj/
tumbleweed/x86_64/clang:
+ stage: test
image: $CI_REGISTRY/$BUILD_IMAGES_PROJECT:$TUMBLEWEED_BUILD
script:
- - mkdir -p obj && cd obj && cmake
- -DCMAKE_BUILD_TYPE=RelWithDebInfo
- -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++
- -DPICKY_DEVELOPER=ON
- -DUNIT_TESTING=ON .. &&
- make -j$(nproc) && ctest --output-on-failure
+ - mkdir -p obj && cd obj && cmake
+ -DCMAKE_BUILD_TYPE=RelWithDebInfo
+ -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++
+ -DPICKY_DEVELOPER=ON
+ -DUNIT_TESTING=ON .. &&
+ make -j$(nproc) && ctest --output-on-failure
tags:
- - shared
+ - shared
except:
- - tags
+ - tags
artifacts:
expire_in: 1 week
when: on_failure
@@ -300,13 +388,14 @@ tumbleweed/x86_64/clang:
- obj/
tumbleweed/docs:
+ stage: build
image: $CI_REGISTRY/$BUILD_IMAGES_PROJECT:$TUMBLEWEED_BUILD
script:
- - mkdir -p obj && cd obj && cmake .. && make docs
+ - mkdir -p obj && cd obj && cmake .. && make docs
tags:
- - shared
+ - shared
except:
- - tags
+ - tags
artifacts:
expire_in: 1 week
when: on_failure
@@ -314,77 +403,130 @@ tumbleweed/docs:
- obj/
tumbleweed/static-analysis:
+ stage: analysis
image: $CI_REGISTRY/$BUILD_IMAGES_PROJECT:$TUMBLEWEED_BUILD
script:
- - export CCC_CC=clang
- - export CCC_CXX=clang++
- - mkdir -p obj && cd obj && scan-build cmake
- -DCMAKE_BUILD_TYPE=Debug
- -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++
- -DPICKY_DEVELOPER=ON
- -DUNIT_TESTING=ON .. &&
- scan-build --status-bugs -o scan make -j$(nproc)
+ - export CCC_CC=clang
+ - export CCC_CXX=clang++
+ - mkdir -p obj && cd obj && scan-build cmake
+ -DCMAKE_BUILD_TYPE=Debug
+ -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++
+ -DPICKY_DEVELOPER=ON
+ -DUNIT_TESTING=ON .. &&
+ scan-build --status-bugs -o scan make -j$(nproc)
tags:
- - shared
+ - shared
except:
- - tags
+ - tags
artifacts:
expire_in: 1 week
when: on_failure
paths:
- obj/scan
-visualstudio/x86_64:
+ubuntu/x86_64:
+ stage: test
+ image: $CI_REGISTRY/$BUILD_IMAGES_PROJECT:$UBUNTU_BUILD
script:
- - $env:VCPKG_DEFAULT_TRIPLET="x64-windows"
- - mkdir obj
- - cd obj
- - cmake
- -A x64
- -DCMAKE_TOOLCHAIN_FILE="$env:VCPKG_TOOLCHAIN_FILE"
- -DCMAKE_BUILD_TYPE=Debug
- -DPICKY_DEVELOPER=ON
- -DUNIT_TESTING=ON ..
- - cmake --build .
- - ctest --output-on-failure
+ - mkdir -p obj && cd obj && cmake
+ -DCMAKE_BUILD_TYPE=RelWithDebInfo
+ -DPICKY_DEVELOPER=ON
+ -DUNIT_TESTING=ON .. &&
+ make -j$(nproc) && ctest --output-on-failure
tags:
- - vs2017
- - windows
+ - shared
except:
- - tags
- only:
- - branches@cmocka/cmocka
- - branches@ansasaki/cmocka
- - branches@cryptomilk/cmocka
+ - tags
artifacts:
expire_in: 1 week
when: on_failure
paths:
- obj/
+###############################################################################
+# Visual Studio builds #
+###############################################################################
+.vs:
+ stage: test
+ cache:
+ key: vcpkg.${CI_JOB_NAME}
+ paths:
+ - .vcpkg
+ variables:
+ ErrorActionPreference: STOP
+ tags:
+ - windows
+ - shared-windows
+ except:
+ - tags
+ artifacts:
+ expire_in: 1 week
+ when: on_failure
+ paths:
+ - obj/
+ before_script:
+ - If (!(test-path .vcpkg\archives)) { mkdir -p .vcpkg\archives }
+ - mkdir -p obj; if ($?) {cd obj}; if (! $?) {exit 1}
+ - cmake
+ -A $PLATFORM
+ -DCMAKE_BUILD_TYPE=Debug
+ -DCMAKE_TOOLCHAIN_FILE=C:/vcpkg/scripts/buildsystems/vcpkg.cmake
+ -DPICKY_DEVELOPER=ON
+ -DUNIT_TESTING=ON ..
+ script:
+ - cmake --build .
+ - ctest --output-on-failure
+
+visualstudio/x86_64:
+ extends: .vs
+ variables:
+ PLATFORM: "x64"
+ TRIPLET: "x64"
+
visualstudio/x86:
+ extends: .vs
+ variables:
+ PLATFORM: "win32"
+ TRIPLET: "x86"
+
+###############################################################################
+# Coverity #
+###############################################################################
+#
+# git push -o ci.variable="COVERITY_SCAN_TOKEN=XXXXXX" \
+# -o ci.variable="COVERITY_SCAN_PROJECT_NAME=XXXXXX" \
+# -o ci.variable="COVERITY_SCAN_EMAIL=XXXXXX" \
+# -f gitlab
+
+coverity:
+ stage: analysis
+ image: $CI_REGISTRY/$BUILD_IMAGES_PROJECT:$FEDORA_BUILD
script:
- - $env:VCPKG_DEFAULT_TRIPLET="x86-windows"
- - mkdir obj
- - cd obj
- - cmake
- -DCMAKE_TOOLCHAIN_FILE="$env:VCPKG_TOOLCHAIN_FILE"
- -DCMAKE_BUILD_TYPE=Debug
- -DPICKY_DEVELOPER=ON
- -DUNIT_TESTING=ON ..
- - cmake --build .
- - ctest --output-on-failure
+ - mkdir obj && cd obj
+ - wget https://scan.coverity.com/download/linux64 --post-data "token=$COVERITY_SCAN_TOKEN&project=$COVERITY_SCAN_PROJECT_NAME" -O /tmp/coverity_tool.tgz
+ - tar xf /tmp/coverity_tool.tgz
+ - cmake -DCMAKE_BUILD_TYPE=Debug -DPICKY_DEVELOPER=ON -DUNIT_TESTING=ON ..
+ - cov-analysis-linux64-*/bin/cov-build --dir cov-int make -j$(nproc)
+ - tar czf cov-int.tar.gz cov-int
+ - curl
+ --form token=$COVERITY_SCAN_TOKEN
+ --form email=$COVERITY_SCAN_EMAIL
+ --form file=@cov-int.tar.gz
+ --form version="`git describe --tags`"
+ --form description="CI build"
+ https://scan.coverity.com/builds?project=$COVERITY_SCAN_PROJECT_NAME
tags:
- - vs2017
- - windows
- except:
- - tags
+ - shared
only:
- - branches@cmocka/cmocka
- - branches@ansasaki/cmocka
- - branches@cryptomilk/cmocka
+ refs:
+ - master
+ - schedules
+ variables:
+ - $COVERITY_SCAN_TOKEN != null
+ - $COVERITY_SCAN_PROJECT_NAME != null
+ - $COVERITY_SCAN_EMAIL != null
artifacts:
expire_in: 1 week
when: on_failure
paths:
- - obj/
+ - obj/cov-int/*.txt
diff --git a/CMakeLists.txt b/CMakeLists.txt
index ababa8e..19eb8d9 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -2,7 +2,7 @@
cmake_minimum_required(VERSION 3.5.0)
cmake_policy(SET CMP0048 NEW)
-# Specify search path for CMake modules to be loaded by include()
+# Specify search path for CMake modules to be loaded by include()
# and find_package()
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake/Modules")
@@ -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.7.0")
+set(LIBRARY_VERSION "1.0.0")
set(LIBRARY_SOVERSION "0")
# include cmake files
@@ -55,17 +55,19 @@ add_subdirectory(include)
add_subdirectory(src)
add_subdirectory(doc)
-include(AddCMockaTest)
-if (UNIT_TESTING)
- add_subdirectory(tests)
-endif (UNIT_TESTING)
+if (CMAKE_PROJECT_NAME STREQUAL PROJECT_NAME)
+ include(AddCMockaTest)
+ if (UNIT_TESTING)
+ add_subdirectory(tests)
+ endif (UNIT_TESTING)
-if (WITH_EXAMPLES)
- add_subdirectory(example)
-endif ()
+ if (WITH_EXAMPLES)
+ add_subdirectory(example)
+ endif ()
+endif()
# pkg-config file
-configure_file(cmocka.pc.cmake ${CMAKE_CURRENT_BINARY_DIR}/cmocka.pc)
+configure_file(cmocka.pc.cmake ${CMAKE_CURRENT_BINARY_DIR}/cmocka.pc @ONLY)
install(
FILES
${CMAKE_CURRENT_BINARY_DIR}/cmocka.pc
@@ -75,11 +77,19 @@ install(
pkgconfig
)
+configure_package_config_file(cmocka-config.cmake.in
+ "${CMAKE_CURRENT_BINARY_DIR}/cmocka-config.cmake"
+ INSTALL_DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/cmocka"
+ NO_SET_AND_CHECK_MACRO
+ NO_CHECK_REQUIRED_COMPONENTS_MACRO
+)
+
write_basic_package_version_file(${PROJECT_NAME}-config-version.cmake
COMPATIBILITY
AnyNewerVersion)
-install(FILES ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}-config-version.cmake
+install(FILES "${CMAKE_CURRENT_BINARY_DIR}/cmocka-config.cmake"
+ "${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}-config-version.cmake"
DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}
COMPONENT devel)
@@ -89,5 +99,5 @@ add_custom_target(dist
# Link combile database for clangd
execute_process(COMMAND cmake -E create_symlink
- "${CMAKE_BINARY_DIR}/compile_commands.json"
- "${CMAKE_SOURCE_DIR}/compile_commands.json")
+ "${cmocka_BINARY_DIR}/compile_commands.json"
+ "${cmocka_SOURCE_DIR}/compile_commands.json")
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
new file mode 100644
index 0000000..6bef7cf
--- /dev/null
+++ b/CONTRIBUTING.md
@@ -0,0 +1,399 @@
+CONTRIBUTING TO CMOCKA
+======================
+
+## Merge requests
+
+cmocka uses gitlab for contributing code and code reviews. You can find the
+gitlab repository [here](https://gitlab.com/cmocka/cmocka).
+
+## Coding conventions
+
+### Quick Start
+
+Coding style guidelines are about reducing the number of unnecessary
+reformatting patches and making things easier for developers to work together.
+
+You don't have to like them or even agree with them, but once put in place we
+all have to abide by them (or vote to change them). However, coding style should
+never outweigh coding itself and so the guidelines described here should be good
+enough to follow as they are common and supported by tools and editors.
+
+The basic style for C code is the Linux Kernel coding style (See
+Documentation/CodingStyle in the Kernel source tree). This closely matches what
+cmocka developers use already anyways, with a few exceptions as mentioned below.
+
+To save you the trouble of reading the Linux kernel style guide, here are the
+highlights.
+
+* Maximum Line Width is 80 Characters
+ The reason is not about people with low-res screens but rather sticking to 80
+ columns prevents you from nesting more than one level of if statements or
+ other code blocks.
+
+* Use 4 spaces to indent
+
+* No trailing spaces
+ Clean up your files before committing.
+
+* Follow the K&R guidelines. We won't go through all of them here. You have a
+ copy of "The C Programming Language" anyways right?
+
+
+### Editor Hints
+
+The projects provides a configuration file for [editorconf](https://editorconfig.org/).
+
+Most modern code editor provide support for editorconfig either natively or via
+a plugin. You should make use of it!
+
+### FAQ & Statement Reference
+
+#### Comments
+
+Comments should always use the standard C syntax. C++ style comments are not
+encouraged.
+
+The lines before a comment should be empty. If the comment directly belongs to
+the following code, there should be no empty line after the comment, except if
+the comment contains a summary of multiple following code blocks.
+
+This is good:
+
+```c
+ ...
+ int i;
+
+ /*
+ * This is a multi line comment,
+ * which explains the logical steps we have to do:
+ *
+ * 1. We need to set i=5, because...
+ * 2. We need to call complex_fn1
+ */
+
+ /* This is a one line comment about i = 5. */
+ i = 5;
+
+ /*
+ * This is a multi line comment,
+ * explaining the call to complex_fn1()
+ */
+ ret = complex_fn1();
+ if (ret != 0) {
+ ...
+
+ /**
+ * @brief This is a doxygen comment.
+ *
+ * This is a more detailed explanation of
+ * this simple function.
+ *
+ * @param[in] param1 The parameter value of the function.
+ *
+ * @param[out] result1 The result value of the function.
+ *
+ * @return 0 on success and -1 on error.
+ */
+ int example(int param1, int *result1);
+```
+
+This is bad:
+
+```c
+ ...
+ int i;
+ /*
+ * This is a multi line comment,
+ * which explains the logical steps we have to do:
+ *
+ * 1. We need to set i=5, because...
+ * 2. We need to call complex_fn1
+ */
+ /* This is a one line comment about i = 5. */
+ i = 5;
+ /*
+ * This is a multi line comment,
+ * explaining the call to complex_fn1()
+ */
+ ret = complex_fn1();
+ if (ret != 0) {
+ ...
+
+ /*This is a one line comment.*/
+
+ /* This is a multi line comment,
+ with some more words...*/
+
+ /*
+ * This is a multi line comment,
+ * with some more words...*/
+```
+
+### Indentation, spaces and 80 columns
+
+To avoid confusion, indentations have to be 4 spaces. Do not use tabs!
+
+When wrapping parameters for function calls, align the parameter list with the
+first parameter on the previous line. For example:
+
+```c
+ var1 = foo(long_long_long_long_long_long_long_arg_name1,
+ long_long_long_long_long_long_long_arg_name2,
+ long_long_long_long_long_long_long_arg_name3);
+```
+
+The previous example is intended to illustrate alignment of function parameters
+across lines and not as encourage for gratuitous line splitting. Never split a
+line before columns 70 - 79 unless you have a really good reason. Be smart
+about formatting.
+
+
+### If, switch and code blocks
+
+Always follow an `if` keyword with a space but don't include additional
+spaces following or preceding the parentheses in the conditional.
+
+Examples:
+
+```c
+ // This is good
+ if (x == 1)
+
+ // This is bad
+ if ( x == 1 )
+
+ // This is also bad
+ if (x==1)
+```
+
+Yes we have a lot of code that uses the second and third form and we are trying
+to clean it up without being overly intrusive.
+
+Note that this is a rule about parentheses following keywords and not functions.
+Don't insert a space between the name and left parentheses when invoking
+functions.
+
+Braces for code blocks used by `for`, `if`, `switch`, `while`, `do..while`, etc should
+begin on the same line as the statement keyword and end on a line of their own.
+You should always include braces, even if the block only contains one statement.
+
+**NOTE**: Functions are different and the beginning left brace should be located
+in the first column on the next line.
+
+If the beginning statement has to be broken across lines due to length, the
+beginning brace should be on a line of its own.
+
+The exception to the ending rule is when the closing brace is followed by
+another language keyword such as else or the closing while in a `do..while` loop.
+
+Good examples:
+
+```c
+ if (x == 1) {
+ printf("good\n");
+ }
+
+ for (x = 1; x < 10; x++) {
+ print("%d\n", x);
+ }
+
+ for (really_really_really_really_long_var_name = 0;
+ really_really_really_really_long_var_name < 10;
+ really_really_really_really_long_var_name++)
+ {
+ print("%d\n", really_really_really_really_long_var_name);
+ }
+
+ do {
+ printf("also good\n");
+ } while (1);
+```
+
+Bad examples:
+
+```c
+ while (1)
+ {
+ print("I'm in a loop!\n"); }
+
+ for (x=1;
+ x<10;
+ x++)
+ {
+ print("no good\n");
+ }
+
+ if (i < 10)
+ print("I should be in braces.\n");
+```
+
+### Goto
+
+While many people have been academically taught that goto's are fundamentally
+evil, they can greatly enhance readability and reduce memory leaks when used as
+the single exit point from a function. But in no world what so ever is a goto
+outside of a function or block of code a good idea.
+
+Good Examples:
+
+```c
+ int function foo(int y)
+ {
+ int *z = NULL;
+ int rc = 0;
+
+ if (y < 10) {
+ z = malloc(sizeof(int)*y);
+ if (z == NULL) {
+ rc = 1;
+ goto done;
+ }
+ }
+
+ print("Allocated %d elements.\n", y);
+
+ done:
+ if (z != NULL) {
+ free(z);
+ }
+
+ return rc;
+ }
+```
+
+### Initialize pointers
+
+All pointer variables **MUST** be initialized to `NULL`. History has
+demonstrated that uninitialized pointer variables have lead to various bugs and
+security issues.
+
+Pointers **MUST** be initialized even if the assignment directly follows the
+declaration, like pointer2 in the example below, because the instructions
+sequence may change over time.
+
+Good Example:
+
+```c
+ char *pointer1 = NULL;
+ char *pointer2 = NULL;
+
+ pointer2 = some_func2();
+
+ ...
+
+ pointer1 = some_func1();
+```
+
+### Typedefs
+
+cmocka tries to avoid `typedef struct { .. } x_t;` so we do always try to use
+`struct x { .. };`. We know there are still such typedefs in the code, but for
+new code, please don't do that anymore.
+
+### Make use of helper variables (aka debugging UX)
+
+Please try to avoid passing function calls as function parameters in new code.
+This makes the code much easier to read and it's also easier to use the "step"
+command within gdb.
+
+Good Example:
+
+```c
+ char *name = NULL;
+
+ name = get_some_name();
+ if (name == NULL) {
+ ...
+ }
+
+ rc = some_function_my_name(name);
+ ...
+```
+
+
+Bad Example:
+
+```c
+ rc = some_function_my_name(get_some_name());
+ ...
+```
+
+Please try to avoid passing function return values to if- or while-conditions.
+The reason for this is better handling of code under a debugger.
+
+Good example:
+
+```c
+ x = malloc(sizeof(short) * 10);
+ if (x == NULL) {
+ fprintf(stderr, "Unable to alloc memory!\n");
+ }
+```
+
+Bad example:
+
+```c
+ if ((x = malloc(sizeof(short)*10)) == NULL ) {
+ fprintf(stderr, "Unable to alloc memory!\n");
+ }
+```
+
+There are exceptions to this rule. One example is walking a data structure in
+an iterator style:
+
+```c
+ while ((opt = poptGetNextOpt(pc)) != -1) {
+ ... do something with opt ...
+ }
+```
+
+In general, please try to avoid this pattern.
+
+### Control-Flow changing macros
+
+Macros like `STATUS_NOT_OK_RETURN` that change control flow (return/goto/etc)
+from within the macro are considered bad, because they look like function calls
+that never change control flow. Please do not introduce them.
+
+### Switch/case indentation
+
+The `case` should not be indented to avoid wasting too much horizontal space.
+When the case block contains local variables that need to be wrapped in braces,
+they should not be indented again either.
+
+Good example:
+
+```c
+ switch (x) {
+ case 0:
+ do_stuff();
+ break;
+ case 1: {
+ int y;
+ do_stuff();
+ break;
+ }
+ default:
+ do_other_stuff();
+ break;
+ }
+```
+
+Bad example:
+
+```c
+ switch (x) {
+ case 0:
+ do_stuff();
+ break;
+ case 1:
+ {
+ int y;
+ do_stuff();
+ break;
+ }
+ default:
+ do_other_stuff();
+ break;
+ }
+```
diff --git a/CPackConfig.cmake b/CPackConfig.cmake
index 1af76c6..da730fd 100644
--- a/CPackConfig.cmake
+++ b/CPackConfig.cmake
@@ -16,7 +16,11 @@ set(CPACK_PACKAGE_VERSION ${PROJECT_VERSION})
### source generator
set(CPACK_SOURCE_GENERATOR "TXZ")
-set(CPACK_SOURCE_IGNORE_FILES "~$;[.]swp$;/[.]svn/;/[.]git/;.gitignore;/obj*;tags;cscope.*;.ycm_extra_conf.pyc")
+set(CPACK_SOURCE_IGNORE_FILES "~$;[.]swp$;/[.]git;/[.]gitignore")
+string(APPEND CPACK_SOURCE_IGNORE_FILES ";/build*;/obj*")
+string(APPEND CPACK_SOURCE_IGNORE_FILES ";/tags;/cscope\.*")
+string(APPEND CPACK_SOURCE_IGNORE_FILES ";/[.]ycm_extra_conf.pyc;")
+string(APPEND CPACK_SOURCE_IGNORE_FILES ";/[.]clangd;/[.]cache;/compile_commands.json")
set(CPACK_SOURCE_PACKAGE_FILE_NAME "${CPACK_PACKAGE_NAME}-${CPACK_PACKAGE_VERSION}")
if (WIN32)
diff --git a/CompilerChecks.cmake b/CompilerChecks.cmake
index b326807..62a9094 100644
--- a/CompilerChecks.cmake
+++ b/CompilerChecks.cmake
@@ -16,7 +16,7 @@ if (UNIX)
endif()
endif()
- add_c_compiler_flag("-std=gnu99" SUPPORTED_COMPILER_FLAGS)
+ add_c_compiler_flag("-std=c99" SUPPORTED_COMPILER_FLAGS)
add_c_compiler_flag("-Wpedantic" SUPPORTED_COMPILER_FLAGS)
add_c_compiler_flag("-Wall" SUPPORTED_COMPILER_FLAGS)
add_c_compiler_flag("-Wshadow" SUPPORTED_COMPILER_FLAGS)
@@ -28,11 +28,10 @@ if (UNIX)
add_c_compiler_flag("-Werror=strict-prototypes" SUPPORTED_COMPILER_FLAGS)
add_c_compiler_flag("-Wwrite-strings" SUPPORTED_COMPILER_FLAGS)
add_c_compiler_flag("-Werror=write-strings" SUPPORTED_COMPILER_FLAGS)
+ add_c_compiler_flag("-Wimplicit-function-declaration" SUPPORTED_COMPILER_FLAGS)
add_c_compiler_flag("-Werror-implicit-function-declaration" SUPPORTED_COMPILER_FLAGS)
add_c_compiler_flag("-Wpointer-arith" SUPPORTED_COMPILER_FLAGS)
add_c_compiler_flag("-Werror=pointer-arith" SUPPORTED_COMPILER_FLAGS)
- add_c_compiler_flag("-Wdeclaration-after-statement" SUPPORTED_COMPILER_FLAGS)
- add_c_compiler_flag("-Werror=declaration-after-statement" SUPPORTED_COMPILER_FLAGS)
add_c_compiler_flag("-Wreturn-type" SUPPORTED_COMPILER_FLAGS)
add_c_compiler_flag("-Werror=return-type" SUPPORTED_COMPILER_FLAGS)
add_c_compiler_flag("-Wuninitialized" SUPPORTED_COMPILER_FLAGS)
@@ -42,6 +41,12 @@ if (UNIX)
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)
+ add_c_compiler_flag("-Wold-style-definition" SUPPORTED_COMPILER_FLAGS)
+ add_c_compiler_flag("-Werror=old-style-definition" SUPPORTED_COMPILER_FLAGS)
+ add_c_compiler_flag("-Wimplicit-int" SUPPORTED_COMPILER_FLAGS)
+ add_c_compiler_flag("-Werror=implicit-int" SUPPORTED_COMPILER_FLAGS)
+ add_c_compiler_flag("-Wint-conversion" SUPPORTED_COMPILER_FLAGS)
+ add_c_compiler_flag("-Werror=int-conversion" SUPPORTED_COMPILER_FLAGS)
check_c_compiler_flag("-Wformat" REQUIRED_FLAGS_WFORMAT)
if (REQUIRED_FLAGS_WFORMAT)
@@ -69,18 +74,14 @@ if (UNIX)
check_c_compiler_flag_ssp("-fstack-protector-strong" WITH_STACK_PROTECTOR_STRONG)
if (WITH_STACK_PROTECTOR_STRONG)
list(APPEND SUPPORTED_COMPILER_FLAGS "-fstack-protector-strong")
- # This is needed as Solaris has a seperate libssp
- if (SOLARIS)
- list(APPEND SUPPORTED_LINKER_FLAGS "-fstack-protector-strong")
- endif()
+ # This is needed as Solaris and others have a seperate libssp
+ list(APPEND SUPPORTED_LINKER_FLAGS "-fstack-protector-strong")
else (WITH_STACK_PROTECTOR_STRONG)
check_c_compiler_flag_ssp("-fstack-protector" WITH_STACK_PROTECTOR)
if (WITH_STACK_PROTECTOR)
list(APPEND SUPPORTED_COMPILER_FLAGS "-fstack-protector")
- # This is needed as Solaris has a seperate libssp
- if (SOLARIS)
- list(APPEND SUPPORTED_LINKER_FLAGS "-fstack-protector")
- endif()
+ # This is needed as Solaris and others have a seperate libssp
+ list(APPEND SUPPORTED_LINKER_FLAGS "-fstack-protector")
endif()
endif (WITH_STACK_PROTECTOR_STRONG)
diff --git a/ConfigureChecks.cmake b/ConfigureChecks.cmake
index 028774f..68cd3be 100644
--- a/ConfigureChecks.cmake
+++ b/ConfigureChecks.cmake
@@ -1,5 +1,6 @@
include(CheckIncludeFile)
include(CheckSymbolExists)
+include(CheckCSourceCompiles)
include(CheckFunctionExists)
include(CheckLibraryExists)
include(CheckTypeSize)
@@ -55,6 +56,7 @@ check_include_file(memory.h HAVE_MEMORY_H)
check_include_file(setjmp.h HAVE_SETJMP_H)
check_include_file(signal.h HAVE_SIGNAL_H)
check_include_file(stdarg.h HAVE_STDARG_H)
+check_include_file(stdbool.h HAVE_STDBOOL_H)
check_include_file(stddef.h HAVE_STDDEF_H)
check_include_file(stdint.h HAVE_STDINT_H)
check_include_file(stdio.h HAVE_STDIO_H)
@@ -89,6 +91,8 @@ check_function_exists(signal HAVE_SIGNAL)
check_function_exists(strsignal HAVE_STRSIGNAL)
check_function_exists(strcmp HAVE_STRCMP)
check_function_exists(clock_gettime HAVE_CLOCK_GETTIME)
+# Supported by Clang v10+
+check_c_source_compiles("int main(void) { int a = 1; return __builtin_align_down(&a, 8);}" HAVE_BUILTIN_ALIGN_DOWN)
if (WIN32)
check_function_exists(_vsnprintf_s HAVE__VSNPRINTF_S)
diff --git a/DefineOptions.cmake b/DefineOptions.cmake
index 986fe47..e6b876f 100644
--- a/DefineOptions.cmake
+++ b/DefineOptions.cmake
@@ -1,5 +1,4 @@
option(BUILD_SHARED_LIBS "Build shared libraries" ON)
-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/INSTALL.md b/INSTALL.md
index d20a357..8c2138b 100644
--- a/INSTALL.md
+++ b/INSTALL.md
@@ -1,8 +1,23 @@
-# How to build from source
+# Installing cmocka
-## Requirements
+## Use a package manger (also on Windows)
-### Common requirements
+If you're using a BSD or Linux distribution, cmocka is already packaged and
+you should find it in your package manager.
+
+ <your package manager> install cmocka-devel
+ or
+ <your package manager> install libcmocka-devel
+
+For Windows it is recommended to use: https://vcpkg.io/
+
+ vcpkg install cmocka
+
+## Building from source
+
+### Requirements
+
+#### Common requirements
In order to build cmocka, you need to install several components:
@@ -12,7 +27,7 @@ In order to build cmocka, you need to install several components:
Note that these version numbers are version we know works correctly. If you
build and run cmocka successfully with an older version, please let us know.
-## Building
+### Building
First, you need to configure the compilation, using CMake. Go inside the
`build` dir. Create it if it doesn't exist.
@@ -23,13 +38,13 @@ GNU/Linux, MacOS X, MSYS/MinGW:
On Windows you should choose a makefile gernerator with -G, for example:
- cmake -G "Visual Studio 12 2013" -DCMAKE_BUILD_TYPE=Debug /path/to/source
+ cmake -G "Visual Studio 15 2017" -DCMAKE_BUILD_TYPE=Debug /path/to/source
You can also use the CMake GUI which is shipped with CMake. It will list all
-available generators for MSVC on Windows. We only support Visual Studio 2013
+available generators for MSVC on Windows. We only support Visual Studio 2017
or newer which supports C99.
-### CMake standard options
+#### CMake standard options
Here is a list of the most interesting options provided out of the box by
CMake.
@@ -40,7 +55,7 @@ CMake.
- CMAKE_C_COMPILER: The path to the C compiler
- CMAKE_CXX_COMPILER: The path to the C++ compiler
-### CMake options defined for cmocka
+#### CMake options defined for cmocka
Options are defined in the following files:
@@ -50,29 +65,31 @@ They can be changed with the -D option:
`cmake -DCMAKE_INSTALL_PREFIX=/usr -DCMAKE_BUILD_TYPE=Debug -DUNIT_TESTING=ON ..`
-### Browsing/editing CMake options
+#### Browsing/editing CMake options
In addition to passing options on the command line, you can browse and edit
-CMake options using `cmakesetup` (Windows), `cmake-gui` or `ccmake` (GNU/Linux
+CMake options using `cmake-gui.exe` (Windows) or `ccmake` (GNU/Linux
and MacOS X).
- Go to the build dir
- On Windows: run `cmakesetup`
- On GNU/Linux and MacOS X: run `ccmake ..`
-## Installing
+More at https://cmake.org/runningcmake/
+
+### Installing
If you want to install cmocka after compilation run:
make install
-## Running
+### Running
The cmocka library can be found in the `build/src` directory.
You can run the binaries in `build/examples/*` which is a
are example tests.
-## Testing
+### Testing
As mention above you can turn on the unit tests and make it possible to easily
execute them:
diff --git a/README.md b/README.md
index 62d99cb..7558b13 100644
--- a/README.md
+++ b/README.md
@@ -13,7 +13,8 @@ Compiling
To compile the cmocka library and example applications run, create a build dir,
and in the build dir call 'cmake /path/to/cmocka' followed by 'make'. On
-Windows you can use the cmake gui. More details can be found in the INSTALL file.
+Windows you can use the cmake gui. More details can be found in the INSTALL.md
+file.
Website
-------
diff --git a/cmake/Modules/AddCMockaTest.cmake b/cmake/Modules/AddCMockaTest.cmake
index 498ced8..916088b 100644
--- a/cmake/Modules/AddCMockaTest.cmake
+++ b/cmake/Modules/AddCMockaTest.cmake
@@ -38,7 +38,10 @@
# executable.
#
# ``LINK_OPTIONS``:
-# Optional, expects one or more options to be passed to the linker
+# Optional, expects one or more ``LINK_FLAGS`` to be passed to the linker.
+# For CMake <3.13 compatibility, this is **not** set as the ``LINK_OPTIONS``
+# property. Instead, these values are set the ``LINK_FLAGS`` property.
+# See https://cmake.org/cmake/help/latest/prop_tgt/LINK_FLAGS.html
#
#
# Example:
@@ -126,7 +129,7 @@ function(ADD_CMOCKA_TEST_ENVIRONMENT _TARGET_NAME)
if (TARGET_SYSTEM_EMULATOR)
set(DLL_PATH_ENV "WINEPATH=${CMOCKA_DLL_PATH};$ENV{WINEPATH}")
else()
- set(DLL_PATH_ENV "PATH=${CMOCKA_DLL_PATH};$ENV{PATH}")
+ set(DLL_PATH_ENV "PATH=${CMOCKA_DLL_PATH}\\${CMAKE_BUILD_TYPE};$ENV{PATH}")
endif()
#
# IMPORTANT NOTE: The set_tests_properties(), below, internally
diff --git a/cmocka-config.cmake.in b/cmocka-config.cmake.in
index a3af5d7..d39bcb2 100644
--- a/cmocka-config.cmake.in
+++ b/cmocka-config.cmake.in
@@ -1,15 +1,10 @@
@PACKAGE_INIT@
-get_filename_component(CMOCKA_CMAKE_DIR "${CMAKE_CURRENT_LIST_FILE}" PATH)
-
-if (EXISTS "${CMOCKA_CMAKE_DIR}/CMakeCache.txt")
- # In build tree
- include(${CMOCKA_CMAKE_DIR}/cmocka-build-tree-settings.cmake)
-else()
- set_and_check(CMOCKA_INCLUDE_DIR @PACKAGE_INCLUDE_INSTALL_DIR@)
-
- set_and_check(CMOCKA_LIBRARY @PACKAGE_LIB_INSTALL_DIR@/@CMOCKA_LIBRARY_NAME@)
- set_and_check(CMOCKA_LIBRARIES @PACKAGE_LIB_INSTALL_DIR@/@CMOCKA_LIBRARY_NAME@)
+get_filename_component(cmocka_CMAKE_DIR "${CMAKE_CURRENT_LIST_FILE}" PATH)
+if(NOT TARGET cmocka::cmocka)
+ include("${cmocka_CMAKE_DIR}/cmocka-targets.cmake")
endif()
-mark_as_advanced(CMOCKA_LIBRARY CMOCKA_INCLUDE_DIR)
+# for backwards compatibility
+set(CMOCKA_LIBRARY cmocka::cmocka)
+set(CMOCKA_LIBRARIES cmocka::cmocka)
diff --git a/cmocka.pc.cmake b/cmocka.pc.cmake
index f54d0a7..ee189c6 100644
--- a/cmocka.pc.cmake
+++ b/cmocka.pc.cmake
@@ -1,5 +1,11 @@
-Name: ${PROJECT_NAME}
+# cmocka pkg-config source file
+
+prefix=@CMAKE_INSTALL_PREFIX@
+libdir=@CMAKE_INSTALL_FULL_LIBDIR@
+includedir=@CMAKE_INSTALL_FULL_INCLUDEDIR@
+
+Name: @PROJECT_NAME@
Description: The cmocka unit testing library
-Version: ${PROJECT_VERSION}
-Libs: -L${CMAKE_INSTALL_FULL_LIBDIR} -lcmocka
-Cflags: -I${CMAKE_INSTALL_FULL_INCLUDEDIR}
+Version: @PROJECT_VERSION@
+Libs: -L${libdir} -lcmocka
+Cflags: -I${includedir}
diff --git a/coverity/Makefile b/coverity/Makefile
new file mode 100644
index 0000000..e1cd8a3
--- /dev/null
+++ b/coverity/Makefile
@@ -0,0 +1,9 @@
+.PHONY: check-gcc
+
+# Part of csdiff package on Fedora
+CSGREP ?= csgrep
+
+CFLAGS ?= -Wall -Wno-uninitialized -Wno-unused-variable -Wno-unused-but-set-variable -Werror
+
+check-gcc:
+ gcc -o /dev/null -fPIC -shared -include ./coverity-builtins.h $(CFLAGS) *.c 2> >($(CSGREP))
diff --git a/coverity/coverity-builtins.h b/coverity/coverity-builtins.h
new file mode 100644
index 0000000..8dbf47f
--- /dev/null
+++ b/coverity/coverity-builtins.h
@@ -0,0 +1,50 @@
+#define ALLOCATION 1
+#define ENVIRONMENT 1
+#define FILESYSTEM 1
+#define FORMAT_STRING 1
+#define GENERIC 1
+#define OS_CMD_ARGUMENTS 1
+#define OS_CMD_FILENAME 1
+#define OS_CMD_ONE_STRING 1
+#define OVERRUN 1
+#define PATH 1
+#define TAINT_TYPE_CONSOLE 1
+#define TAINT_TYPE_ENVIRONMENT 1
+#define TAINT_TYPE_FILESYSTEM 1
+#define TAINT_TYPE_NETWORK 1
+
+struct va_list_str;
+
+typedef unsigned long size_t;
+
+void*__coverity_alloc__(size_t);
+void*__coverity_alloc_nosize__();
+void __coverity_close__(int);
+void __coverity_escape__();
+void __coverity_free__(void *);
+void __coverity_mark_as_uninitialized_buffer__(void *);
+void __coverity_mark_as_afm_allocated__(const void *, const char *);
+void __coverity_mark_as_afm_freed__(const void *, const char *);
+void __coverity_mark_pointee_as_sanitized__(const void *, int);
+void __coverity_mark_pointee_as_tainted__(const void *, int);
+void __coverity_negative_sink__(long);
+int __coverity_open__(void);
+void __coverity_panic__() __attribute__((__noreturn__));
+void __coverity_printf_function_varargs__(int, const char *);
+void __coverity_printf_function_valist__(int, const char *, struct va_list_str *);
+void __coverity_read_buffer_bytes__(const void *, size_t);
+void __coverity_string_size_sink__(const void *);
+void __coverity_string_size_sink_vararg__(int);
+void __coverity_string_null_argument__(void *, size_t);
+void __coverity_string_null_sink__(const void *);
+void __coverity_string_null_sink_vararg__(int);
+void __coverity_taint_sink__(const void *, int);
+void __coverity_tainted_data_sanitize__(const void *);
+void __coverity_tainted_data_sink__(const void *);
+void __coverity_tainted_data_transitive__(void *, const void *);
+void __coverity_tainted_string_sanitize_content__(const char *);
+void __coverity_use_handle__(int);
+void __coverity_weak_guard_sink__(const void *a, const void *b);
+void __coverity_write_buffer_bytes__(char *, size_t);
+void __coverity_writeall__(void *);
+void __coverity_writeall0__(void *);
diff --git a/coverity/coverity_assert_model.c b/coverity/coverity_assert_model.c
index 7ff64d8..d3061c0 100644
--- a/coverity/coverity_assert_model.c
+++ b/coverity/coverity_assert_model.c
@@ -1,7 +1,29 @@
-#define LargestIntegralType unsigned long long
+/*
+ * Modelling file for Coverity Scan
+ *
+ * This is a modeling file for Coverity Scan. Modeling helps to avoid false
+ * positives.
+ *
+ * - A model file can't import any header files.
+ * - Therefore only some built-in primitives like int, char and void are
+ * available but not NULL etc.
+ * - Modeling doesn't need full structs and typedefs. Rudimentary structs
+ * and similar types are sufficient.
+ * - An uninitialized local pointer is not an error. It signifies that the
+ * variable could be either NULL or have some data.
+ *
+ * Coverity Scan doesn't pick up modifications automatically. The model file
+ * must be uploaded by an admin.
+ *
+ * See also https://scan.coverity.com/models
+ */
+typedef int int32_t;
+typedef long long intmax_t;
+typedef unsigned long long uintmax_t;
+/* size_t is already defined by Coverity */
-void _assert_true(const LargestIntegralType result,
+void _assert_true(const uintmax_t result,
const char* const expression,
const char * const file, const int line)
{
@@ -11,7 +33,7 @@ void _assert_true(const LargestIntegralType result,
}
void _assert_int_equal(
- const LargestIntegralType a, const LargestIntegralType b,
+ const intmax_t a, const intmax_t b,
const char * const file, const int line)
{
if (a != b) {
@@ -19,8 +41,18 @@ void _assert_int_equal(
}
}
+void _assert_uint_equal(const uintmax_t a,
+ const uintmax_t b,
+ const char *const file,
+ const int line)
+{
+ if (a != b) {
+ __coverity_panic__();
+ }
+}
+
void _assert_int_not_equal(
- const LargestIntegralType a, const LargestIntegralType b,
+ const intmax_t a, const intmax_t b,
const char * const file, const int line)
{
if (a == b) {
@@ -28,14 +60,67 @@ void _assert_int_not_equal(
}
}
-void _assert_return_code(const LargestIntegralType result,
- size_t rlen,
- const LargestIntegralType error,
+void _assert_uint_not_equal(const uintmax_t a,
+ const uintmax_t b,
+ const char *const file,
+ const int line)
+{
+ if (a == b) {
+ __coverity_panic__();
+ }
+}
+
+void _assert_return_code(const intmax_t result,
+ const int32_t error,
const char * const expression,
const char * const file,
const int line)
{
- if (result != 0) {
+ if (result < 0) {
+ __coverity_panic__();
+ }
+}
+
+void _assert_float_equal(const float a,
+ const float b,
+ const float epsilon,
+ const char * const file,
+ const int line)
+{
+ if (a != b) {
+ __coverity_panic__();
+ }
+}
+
+void _assert_float_not_equal(const float a,
+ const float b,
+ const float epsilon,
+ const char * const file,
+ const int line)
+{
+ if (a == b) {
+ __coverity_panic__();
+ }
+}
+
+void _assert_double_equal(const double a,
+ const double b,
+ const double epsilon,
+ const char * const file,
+ const int line)
+{
+ if (a != b) {
+ __coverity_panic__();
+ }
+}
+
+void _assert_double_not_equal(const double a,
+ const double b,
+ const double epsilon,
+ const char * const file,
+ const int line)
+{
+ if (a != b) {
__coverity_panic__();
}
}
@@ -110,9 +195,22 @@ void _assert_memory_not_equal(const void * const a, const void * const b,
}
}
-void _assert_in_range(
- const LargestIntegralType value, const LargestIntegralType minimum,
- const LargestIntegralType maximum, const char* const file, const int line)
+void _assert_int_in_range(const intmax_t value,
+ const intmax_t minimum,
+ const intmax_t maximum,
+ const char *const file,
+ const int line)
+{
+ if (value < minimum || value > maximum) {
+ __coverity_panic__();
+ }
+}
+
+void _assert_uint_in_range(const uintmax_t value,
+ const uintmax_t minimum,
+ const uintmax_t maximum,
+ const char *const file,
+ const int line)
{
if (value < minimum || value > maximum) {
__coverity_panic__();
@@ -120,17 +218,35 @@ void _assert_in_range(
}
void _assert_not_in_range(
- const LargestIntegralType value, const LargestIntegralType minimum,
- const LargestIntegralType maximum, const char* const file, const int line)
+ const uintmax_t value, const uintmax_t minimum,
+ const uintmax_t maximum, const char* const file, const int line)
{
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)
+void _assert_int_in_set(const intmax_t value,
+ const intmax_t values[],
+ const size_t number_of_values,
+ const char *const file,
+ const int line)
+{
+ size_t i;
+
+ for (i = 0; i < number_of_values; i++) {
+ if (value == values[i]) {
+ return;
+ }
+ }
+ __coverity_panic__();
+}
+
+void _assert_uint_in_set(const uintmax_t value,
+ const uintmax_t values[],
+ const size_t number_of_values,
+ const char *const file,
+ const int line)
{
size_t i;
@@ -142,9 +258,26 @@ void _assert_in_set(
__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)
+void _assert_int_not_in_set(const intmax_t value,
+ const intmax_t values[],
+ const size_t number_of_values,
+ const char *const file,
+ const int line)
+{
+ size_t i;
+
+ for (i = 0; i < number_of_values; i++) {
+ if (value == values[i]) {
+ __coverity_panic__();
+ }
+ }
+}
+
+void _assert_uint_not_in_set(const uintmax_t value,
+ const uintmax_t values[],
+ const size_t number_of_values,
+ const char *const file,
+ const int line)
{
size_t i;
diff --git a/doc/index.html b/doc/index.html
deleted file mode 100644
index 5f7c5a7..0000000
--- a/doc/index.html
+++ /dev/null
@@ -1,706 +0,0 @@
-<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
-<html><head>
-<title>cmocka</title>
-</head>
-<body>
-<h1>cmocka Unit Testing Framework</h1>
-<p>cmocka is a lightweight library that is used to author C unit tests.</p>
-
-<ul>Contents
- <li><a href="#Motivation">Motivation</a></li>
- <li><a href="#Overview">Overview</a></li>
- <li><a href="#Test_Execution">Test Execution</a>
- <li><a href="#Exception_Handling">Exception Handling</a></li>
- <li><a href="#Failure_Conditions">Failure Conditions</a></li>
- <li><a href="#Assertions">Assertions</a></li>
- <ul>
- <li><a href="#Assert_Macros">Assert Macros</a></li>
- </ul>
- <li><a href="#Dynamic_Memory_Allocation">Dynamic Memory Allocation</a></li>
- <li><a href="#Mock_Functions">Mock functions</a></li>
- <ul>
- <li><a href="#Return_Values">Return Values</a></li>
- <li><a href="#Checking_Parameters">Checking Parameters</a></li>
- </ul>
- <li><a href="#Test_State">Test State</a></li>
- <li><a href="#Example">Example</a></li>
-</ul>
-
-<a name="Motivation"><h2>Motivation</h2></a>
-<p>There are a variety of C unit testing frameworks available however many of
-them are fairly complex and require the latest compiler technology. Some
-development requires the use of old compilers which makes it difficult to
-use some unit testing frameworks. In addition many unit testing frameworks
-assume the code being tested is an application or module that is targeted to
-the same platform that will ultimately execute the test. Because of this
-assumption many frameworks require the inclusion of standard C library headers
-in the code module being tested which may collide with the custom or
-incomplete implementation of the C library utilized by the code under test.</p>
-
-<p>cmocka only requires a test application is linked with the standard C
-library which minimizes conflicts with standard C library headers. Also,
-cmocka tries avoid the use of some of the newer features of C compilers.</p>
-
-<p>This results in cmocka being a relatively small library that can be used
-to test a variety of exotic code. If a developer wishes to simply test an
-application with the latest compiler then other unit testing frameworks maybe
-preferable.</p>
-
-<a name="Overview"><h2>Overview</h2></a>
-<p>cmocka tests are compiled into stand-alone executables and linked with
-the cmocka library, the standard C library and module being tested. Any
-symbols external to the module being tested should be mocked - replaced with
-functions that return values determined by the test - within the test
-application. Even though significant differences may exist between the target
-execution environment of a code module and the environment used to test the
-code the unit testing is still valid since its goal is to test the logic of a
-code modules at a functional level and not necessarily all of its interactions
-with the target execution environment.</p>
-
-<p>It may not be possible to compile a module into a test application without
-some modification, therefore the preprocessor symbol <b>UNIT_TESTING</b> should
-be defined when cmocka unit test applications are compiled so code within the
-module can be conditionally compiled for tests.</p>
-
-<a name="Test_Execution"><h2>Test Execution</h2></a>
-<p>cmocka unit test cases are functions with the signature
-<b>void function(void **state)</b>. cmocka test applications initialize a
-table with test case function pointers using <b>unit_test*()</b> macros. This
-table is then passed to the <b>run_tests()</b> macro to execute the tests.
-
-<b>run_tests()</b> sets up the appropriate exception / signal handlers and
-other data structures prior to running each test function. When a unit test
-is complete <b>run_tests()</b> performs various checks to determine whether
-the test succeeded.</p>
-
-<h4>Using run_tests()</h4>
-<a href="../example/run_tests.c">run_tests.c</a>
-<listing>
-#include &lt;stdarg.h&gt;
-#include &lt;stddef.h&gt;
-#include &lt;setjmp.h&gt;
-#include &lt;cmocka.h&gt;
-
-// A test case that does nothing and succeeds.
-void null_test_success(void **state) {
-}
-
-int main(int argc, char* argv[]) {
- const UnitTest tests[] = {
- unit_test(null_test_success),
- };
- return run_tests(tests);
-}
-</listing>
-
-<a name="Exception_Handling"><h2>Exception Handling</h2></a>
-<p>Before a test function is executed by <b>run_tests()</b>,
-exception / signal handlers are overridden with a handler that simply
-displays an error and exits a test function if an exception occurs. If an
-exception occurs outside of a test function, for example in cmocka itself,
-the application aborts execution and returns an error code.</p>
-
-<a name="Failure_Conditions"><h2>Failure Conditions</h2></a>
-<p>If a failure occurs during a test function that's executed via
-<b>run_tests()</b>, the test function is aborted and the application's
-execution resumes with the next test function.
-
-Test failures are ultimately signalled via the cmocka function <b>fail()</b>.
-The following events will result in the cmocka library signalling a test
-failure...
-
-<ul>
- <li><a href="#Assertions">Assertions</a></li>
- <li><a href="#Exception_Handling">Exceptions</a></li>
- <li><a href="#Dynamic_Memory_Allocation">Memory leaks</a></li>
- <li><a href="#Test_State">Mismatched setup and tear down functions</a></li>
- <li><a href="#Return_Values">Missing mock return values</a></li>
- <li><a href="#Return_Values">Unused mock return values</a></li>
- <li><a href="#Checking_Parameters">Missing expected parameter values</a></li>
- <li><a href="#Checking_Parameters">Unused expected parameter values</a></li>
-</ul>
-</p>
-
-<a name="Assertions"><h2>Assertions</h2></a>
-<p>Runtime assert macros like the standard C library's <b>assert()</b> should
-be redefined in modules being tested to use cmocka's <b>mock_assert()</b>
-function. Normally <b>mock_assert()</b> signals a
-<a href="#Failure_Conditions">test failure</a>. If a function is called using
-the <b>expect_assert_failure()</b> macro, any calls to <b>mock_assert()</b>
-within the function will result in the execution of the test. If no
-calls to <b>mock_assert()</b> occur during the function called via
-<b>expect_assert_failure()</b> a test failure is signalled.</p>
-
-<h4>Using mock_assert()</h4>
-<a href="../example/assert_module.c">assert_module.c</a>
-<listing>
-#include &lt;assert.h&gt;
-
-// If unit testing is enabled override assert with mock_assert().
-#ifdef UNIT_TESTING
-extern void mock_assert(const int result, const char* const expression,
- const char * const file, const int line);
-#undef assert
-#define assert(expression) \
- mock_assert((int)(expression), #expression, __FILE__, __LINE__);
-#endif // UNIT_TESTING
-
-void increment_value(int * const value) {
- assert(value);
- (*value) ++;
-}
-
-void decrement_value(int * const value) {
- if (value) {
- *value --;
- }
-}
-</listing>
-<a href="../example/assert_module_test.c">assert_module_test.c</a>
-<listing>
-#include &lt;stdarg.h&gt;
-#include &lt;stddef.h&gt;
-#include &lt;setjmp.h&gt;
-#include &lt;cmocka.h&gt;
-
-extern void increment_value(int * const value);
-
-/* This test case will fail but the assert is caught by run_tests() and the
- * next test is executed. */
-void increment_value_fail(void **state) {
- increment_value(NULL);
-}
-
-// This test case succeeds since increment_value() asserts on the NULL pointer.
-void increment_value_assert(void **state) {
- expect_assert_failure(increment_value(NULL));
-}
-
-/* This test case fails since decrement_value() doesn't assert on a NULL
- * pointer. */
-void decrement_value_fail(void **state) {
- expect_assert_failure(decrement_value(NULL));
-}
-
-int main(int argc, char *argv[]) {
- const UnitTest tests[] = {
- unit_test(increment_value_fail),
- unit_test(increment_value_assert),
- unit_test(decrement_value_fail),
- };
- return run_tests(tests);
-}
-</listing>
-
-<h3><a name="Assert_Macros">Assert Macros</a></h3>
-
-<p>cmocka provides an assortment of assert macros that tests applications
-should use use in preference to the C standard library's assert macro. On an
-assertion failure a cmocka assert macro will write the failure to the
-standard error stream and signal a test failure. Due to limitations of the
-C language the general C standard library assert() and cmocka's
-assert_true() and assert_false() macros can only display the expression that
-caused the assert failure. cmocka's type specific assert macros,
-assert_{type}_equal() and assert_{type}_not_equal(), display the data that
-caused the assertion failure which increases data visibility aiding
-debugging of failing test cases.</p>
-
-<h4>Using assert_{type}_equal() macros</h4>
-<a href="../example/assert_macro.c">assert_macro.c</a>
-<listing>
-#include &lt;string.h&gt;
-
-static const char* status_code_strings[] = {
- "Address not found",
- "Connection dropped",
- "Connection timed out",
-};
-
-const char* get_status_code_string(const unsigned int status_code) {
- return status_code_strings[status_code];
-};
-
-unsigned int string_to_status_code(const char* const status_code_string) {
- unsigned int i;
- for (i = 0; i < sizeof(status_code_strings) /
- sizeof(status_code_strings[0]); i++) {
- if (strcmp(status_code_strings[i], status_code_string) == 0) {
- return i;
- }
- }
- return ~0U;
-}
-</listing>
-<a href="../example/assert_macro_test.c">assert_macro_test.c</a>
-<listing>
-#include &lt;stdarg.h&gt;
-#include &lt;stddef.h&gt;
-#include &lt;setjmp.h&gt;
-#include &lt;cmocka.h&gt;
-
-extern const char* get_status_code_string(const unsigned int status_code);
-extern unsigned int string_to_status_code(
- const char* const status_code_string);
-
-/* This test will fail since the string returned by get_status_code_string(0)
- * doesn't match "Connection timed out". */
-void get_status_code_string_test(void **state) {
- assert_string_equal(get_status_code_string(0), "Address not found");
- assert_string_equal(get_status_code_string(1), "Connection timed out");
-}
-
-// This test will fail since the status code of "Connection timed out" isn't 1
-void string_to_status_code_test(void **state) {
- assert_int_equal(string_to_status_code("Address not found"), 0);
- assert_int_equal(string_to_status_code("Connection timed out"), 1);
-}
-
-int main(int argc, char *argv[]) {
- const UnitTest tests[] = {
- unit_test(get_status_code_string_test),
- unit_test(string_to_status_code_test),
- };
- return run_tests(tests);
-}
-</listing>
-
-<a name="Dynamic_Memory_Allocation"><h2>Dynamic Memory Allocation</h2></a>
-
-<p>To test for memory leaks, buffer overflows and underflows a module being
-tested by cmocka should replace calls to <b>malloc()</b>, <b>calloc()</b> and
-<b>free()</b> to <b>test_malloc()</b>, <b>test_calloc()</b> and
-<b>test_free()</b> respectively. Each time a block is deallocated using
-<b>test_free()</b> it is checked for corruption, if a corrupt block is found
-a <a href="#Failure_Conditions">test failure</a> is signalled. All blocks
-allocated using the <b>test_*()</b> allocation functions are tracked by the
-cmocka library. When a test completes if any allocated blocks (memory leaks)
-remain they are reported and a test failure is signalled.</p>
-<p>For simplicity cmocka currently executes all tests in one process.
-Therefore all test cases in a test application share a single address space
-which means memory corruption from a single test case could potentially cause
-the test application to exit prematurely.</p>
-
-<h4>Using cmocka's Allocators</h4>
-<a href="../example/allocate_module.c">allocate_module.c</a>
-<listing>
-#include &lt;malloc.h&gt;
-
-#ifdef UNIT_TESTING
-extern void* _test_malloc(const size_t size, const char* file, const int line);
-extern void* _test_calloc(const size_t number_of_elements, const size_t size,
- const char* file, const int line);
-extern void _test_free(void* const ptr, const char* file, const int line);
-
-#define malloc(size) _test_malloc(size, __FILE__, __LINE__)
-#define calloc(num, size) _test_calloc(num, size, __FILE__, __LINE__)
-#define free(ptr) _test_free(ptr, __FILE__, __LINE__)
-#endif // UNIT_TESTING
-
-void leak_memory() {
- int * const temporary = (int*)malloc(sizeof(int));
- *temporary = 0;
-}
-
-void buffer_overflow() {
- char * const memory = (char*)malloc(sizeof(int));
- memory[sizeof(int)] = '!';
- free(memory);
-}
-
-void buffer_underflow() {
- char * const memory = (char*)malloc(sizeof(int));
- memory[-1] = '!';
- free(memory);
-}
-</listing>
-<a href="../example/allocate_module_test.c">allocate_module_test.c</a>
-<listing>
-#include &lt;stdarg.h&gt;
-#include &lt;stddef.h&gt;
-#include &lt;setjmp.h&gt;
-#include &lt;cmocka.h&gt;
-
-extern void leak_memory();
-extern void buffer_overflow();
-extern void buffer_underflow();
-
-// Test case that fails as leak_memory() leaks a dynamically allocated block.
-void leak_memory_test(void **state) {
- leak_memory();
-}
-
-// Test case that fails as buffer_overflow() corrupts an allocated block.
-void buffer_overflow_test(void **state) {
- buffer_overflow();
-}
-
-// Test case that fails as buffer_underflow() corrupts an allocated block.
-void buffer_underflow_test(void **state) {
- buffer_underflow();
-}
-
-int main(int argc, char* argv[]) {
- const UnitTest tests[] = {
- unit_test(leak_memory_test),
- unit_test(buffer_overflow_test),
- unit_test(buffer_underflow_test),
- };
- return run_tests(tests);
-}
-</listing>
-
-<a name="Mock_Functions"><h2>Mock Functions</h2></a>
-
-<p>A unit test should ideally isolate the function or module being tested
-from any external dependencies. This can be performed using mock functions
-that are either statically or dynamically linked with the module being tested.
-Mock functions must be statically linked when the code being tested directly
-references external functions. Dynamic linking is simply the process of
-setting a function pointer in a table used by the tested module to reference
-a mock function defined in the unit test.</p>
-
-<a name="Return_Values"><h3>Return Values</h3></a>
-
-<p>In order to simplify the implementation of mock functions cmocka provides
-functionality which stores return values for mock functions in each test
-case using <b>will_return()</b>. These values are then returned by each mock
-function using calls to <b>mock()</b>.
-
-Values passed to <b>will_return()</b> are added to a queue for each function
-specified. Each successive call to <b>mock()</b> from a function removes a
-return value from the queue. This makes it possible for a mock function to use
-multiple calls to <b>mock()</b> to return output parameters in addition to a
-return value. In addition this allows the specification of return values for
-multiple calls to a mock function.</p>
-
-<h4>Using will_return()</h4>
-<a href="../example/database.h">database.h</a>
-<listing>
-typedef struct DatabaseConnection DatabaseConnection;
-
-/* Function that takes an SQL query string and sets results to an array of
- * pointers with the result of the query. The value returned specifies the
- * number of items in the returned array of results. The returned array of
- * results are statically allocated and should not be deallocated using free()
- */
-typedef unsigned int (*QueryDatabase)(
- DatabaseConnection* const connection, const char * const query_string,
- void *** const results);
-
-// Connection to a database.
-struct DatabaseConnection {
- const char *url;
- unsigned int port;
- QueryDatabase query_database;
-};
-
-// Connect to a database.
-DatabaseConnection* connect_to_database(const char * const url,
- const unsigned int port);
-</listing>
-<a href="../example/customer_database.c">customer_database.c</a>
-<listing>
-#include &lt;stddef.h&gt;
-#include &lt;stdio.h&gt;
-#include &lt;database.h&gt;
-#ifdef _WIN32
-#define snprintf _snprintf
-#endif // _WIN32
-
-// Connect to the database containing customer information.
-DatabaseConnection* connect_to_customer_database() {
- return connect_to_database("customers.abcd.org", 321);
-}
-
-/* Find the ID of a customer by his/her name returning a value > 0 if
- * successful, 0 otherwise. */
-unsigned int get_customer_id_by_name(
- DatabaseConnection * const connection,
- const char * const customer_name) {
- char query_string[256];
- int number_of_results;
- void **results;
- snprintf(query_string, sizeof(query_string),
- "SELECT ID FROM CUSTOMERS WHERE NAME = %s", customer_name);
- number_of_results = connection->query_database(connection, query_string,
- &results);
- if (number_of_results != 1) {
- return -1;
- }
- return (unsigned int)results[0];
-}
-</listing>
-<a href="../example/customer_database_test.c">customer_database_test.c</a>
-<listing>
-#include &lt;stdarg.h&gt;
-#include &lt;stddef.h&gt;
-#include &lt;setjmp.h&gt;
-#include &lt;cmocka.h&gt;
-#include &lt;database.h&gt;
-
-
-extern DatabaseConnection* connect_to_customer_database();
-extern unsigned int get_customer_id_by_name(
- DatabaseConnection * const connection, const char * const customer_name);
-
-// Mock query database function.
-unsigned int mock_query_database(
- DatabaseConnection* const connection, const char * const query_string,
- void *** const results) {
- *results = (void**)mock();
- return (unsigned int)mock();
-}
-
-// Mock of the connect to database function.
-DatabaseConnection* connect_to_database(const char * const database_url,
- const unsigned int port) {
- return (DatabaseConnection*)mock();
-}
-
-void test_connect_to_customer_database(void **state) {
- will_return(connect_to_database, 0x0DA7ABA53);
- assert_true(connect_to_customer_database() ==
- (DatabaseConnection*)0x0DA7ABA53);
-}
-
-/* This test fails as the mock function connect_to_database() will have no
- * value to return. */
-void fail_connect_to_customer_database(void **state) {
- will_return(connect_to_database, 0x0DA7ABA53);
- assert_true(connect_to_customer_database() ==
- (DatabaseConnection*)0x0DA7ABA53);
-}
-
-void test_get_customer_id_by_name(void **state) {
- DatabaseConnection connection = {
- "somedatabase.somewhere.com", 12345678, mock_query_database
- };
- // Return a single customer ID when mock_query_database() is called.
- int customer_ids = 543;
- will_return(mock_query_database, &customer_ids);
- will_return(mock_query_database, 1);
- assert_int_equal(get_customer_id_by_name(&connection, "john doe"), 543);
-}
-
-int main(int argc, char* argv[]) {
- const UnitTest tests[] = {
- unit_test(test_connect_to_customer_database),
- unit_test(fail_connect_to_customer_database),
- unit_test(test_get_customer_id_by_name),
- };
- return run_tests(tests);
-}
-</listing>
-
-<a name="Checking_Parameters"><h3>Checking Parameters</h3></a>
-<p>In addition to storing the return values of mock functions, cmocka
-provides functionality to store expected values for mock function parameters
-using the expect_*() functions provided. A mock function parameter can then
-be validated using the check_expected() macro.
-
-<p>Successive calls to expect_*() macros for a parameter queues values to
-check the specified parameter. check_expected() checks a function parameter
-against the next value queued using expect_*(), if the parameter check fails a
-test failure is signalled. In addition if check_expected() is called and
-no more parameter values are queued a test failure occurs.</p>
-
-<h4>Using expect_*()</h4>
-<a href="../example/product_database.c">product_database.c</a>
-<listing>
-#include &lt;database.h&gt;
-
-// Connect to the database containing customer information.
-DatabaseConnection* connect_to_product_database() {
- return connect_to_database("products.abcd.org", 322);
-}
-</listing>
-<a href="../example/product_database_test.c">product_database_test.c</a>
-<listing>
-#include &lt;stdarg.h&gt;
-#include &lt;stddef.h&gt;
-#include &lt;setjmp.h&gt;
-#include &lt;cmocka.h&gt;
-#include &lt;database.h&gt;
-
-extern DatabaseConnection* connect_to_product_database();
-
-/* Mock connect to database function.
- * NOTE: This mock function is very general could be shared between tests
- * that use the imaginary database.h module. */
-DatabaseConnection* connect_to_database(const char * const url,
- const unsigned int port) {
- check_expected(url);
- check_expected(port);
- return (DatabaseConnection*)mock();
-}
-
-void test_connect_to_product_database(void **state) {
- expect_string(connect_to_database, url, "products.abcd.org");
- expect_value(connect_to_database, port, 322);
- will_return(connect_to_database, 0xDA7ABA53);
- assert_int_equal(connect_to_product_database(), 0xDA7ABA53);
-}
-
-/* This test will fail since the expected URL is different to the URL that is
- * passed to connect_to_database() by connect_to_product_database(). */
-void test_connect_to_product_database_bad_url(void **state) {
- expect_string(connect_to_database, url, "products.abcd.com");
- expect_value(connect_to_database, port, 322);
- will_return(connect_to_database, 0xDA7ABA53);
- assert_int_equal((int)connect_to_product_database(), 0xDA7ABA53);
-}
-
-/* This test will fail since the mock connect_to_database() will attempt to
- * retrieve a value for the parameter port which isn't specified by this
- * test function. */
-void test_connect_to_product_database_missing_parameter(void **state) {
- expect_string(connect_to_database, url, "products.abcd.org");
- will_return(connect_to_database, 0xDA7ABA53);
- assert_int_equal((int)connect_to_product_database(), 0xDA7ABA53);
-}
-
-int main(int argc, char* argv[]) {
- const UnitTest tests[] = {
- unit_test(test_connect_to_product_database),
- unit_test(test_connect_to_product_database_bad_url),
- unit_test(test_connect_to_product_database_missing_parameter),
- };
- return run_tests(tests);
-}
-</listing>
-
-<a name="Test_State"><h2>Test State</h2></a>
-
-<p>cmocka allows the specification of multiple setup and tear down functions
-for each test case. Setup functions, specified by the <b>unit_test_setup()</b>
-or <b>unit_test_setup_teardown()</b> macros allow common initialization to be
-shared between multiple test cases. In addition, tear down functions,
-specified by the <b>unit_test_teardown()</b> or
-<b>unit_test_setup_teardown()</b> macros provide a code path that is always
-executed for a test case even when it fails.</p>
-
-<h4>Using unit_test_setup_teardown()</h4>
-<a href="../example/key_value.c">key_value.c</a>
-<listing>
-#include &lt;stddef.h&gt;
-#include &lt;stdlib.h&gt;
-#include &lt;string.h&gt;
-
-typedef struct KeyValue {
- unsigned int key;
- const char* value;
-} KeyValue;
-
-static KeyValue *key_values = NULL;
-static unsigned int number_of_key_values = 0;
-
-void set_key_values(KeyValue * const new_key_values,
- const unsigned int new_number_of_key_values) {
- key_values = new_key_values;
- number_of_key_values = new_number_of_key_values;
-}
-
-// Compare two key members of KeyValue structures.
-int key_value_compare_keys(const void *a, const void *b) {
- return (int)((KeyValue*)a)->key - (int)((KeyValue*)b)->key;
-}
-
-// Search an array of key value pairs for the item with the specified value.
-KeyValue* find_item_by_value(const char * const value) {
- unsigned int i;
- for (i = 0; i < number_of_key_values; i++) {
- if (strcmp(key_values[i].value, value) == 0) {
- return &key_values[i];
- }
- }
- return NULL;
-}
-
-// Sort an array of key value pairs by key.
-void sort_items_by_key() {
- qsort(key_values, number_of_key_values, sizeof(*key_values),
- key_value_compare_keys);
-}
-</listing>
-<a href="../example/key_value_test.c">key_value_test.c</a>
-<listing>
-#include &lt;stdarg.h&gt;
-#include &lt;stddef.h&gt;
-#include &lt;setjmp.h&gt;
-#include &lt;string.h&gt;
-#include &lt;cmocka.h&gt;
-
-/* This is duplicated here from the module setup_teardown.c to reduce the
- * number of files used in this test. */
-typedef struct KeyValue {
- unsigned int key;
- const char* value;
-} KeyValue;
-
-void set_key_values(KeyValue * const new_key_values,
- const unsigned int new_number_of_key_values);
-extern KeyValue* find_item_by_value(const char * const value);
-extern void sort_items_by_key();
-
-static KeyValue key_values[] = {
- { 10, "this" },
- { 52, "test" },
- { 20, "a" },
- { 13, "is" },
-};
-
-void create_key_values(void **state) {
- KeyValue * const items = (KeyValue*)test_malloc(sizeof(key_values));
- memcpy(items, key_values, sizeof(key_values));
- *state = (void*)items;
- set_key_values(items, sizeof(key_values) / sizeof(key_values[0]));
-}
-
-void destroy_key_values(void **state) {
- test_free(*state);
- set_key_values(NULL, 0);
-}
-
-void test_find_item_by_value(void **state) {
- unsigned int i;
- for (i = 0; i < sizeof(key_values) / sizeof(key_values[0]); i++) {
- KeyValue * const found = find_item_by_value(key_values[i].value);
- assert_true(found);
- assert_int_equal(found->key, key_values[i].key);
- assert_string_equal(found->value, key_values[i].value);
- }
-}
-
-void test_sort_items_by_key(void **state) {
- unsigned int i;
- KeyValue * const kv = *state;
- sort_items_by_key();
- for (i = 1; i < sizeof(key_values) / sizeof(key_values[0]); i++) {
- assert_true(kv[i - 1].key < kv[i].key);
- }
-}
-
-int main(int argc, char* argv[]) {
- const UnitTest tests[] = {
- unit_test_setup_teardown(test_find_item_by_value, create_key_values,
- destroy_key_values),
- unit_test_setup_teardown(test_sort_items_by_key, create_key_values,
- destroy_key_values),
- };
- return run_tests(tests);
-}
-</listing>
-
-<a name="Example"><h2>Example</h2></a>
-
-<p>A small command line calculator
-<a href="../example/calculator.c">calculator.c</a> application
-and test application that full exercises the calculator application
-<a href="../example/calculator_test.c">calculator_test.c</a>
-are provided as an example of cmocka's features discussed in this document.
-</p>
-
-<hr>
-<address></address>
-<!-- hhmts start --> Last modified: Wed Jul 22 12:11:43 PDT 2009 <!-- hhmts end -->
-</body> </html>
diff --git a/doc/mainpage.dox b/doc/mainpage.dox
index c378bb1..ba58e6c 100644
--- a/doc/mainpage.dox
+++ b/doc/mainpage.dox
@@ -48,7 +48,9 @@ the test succeeded.
@code
#include <stdarg.h>
+#include <stdbool.h>
#include <stddef.h>
+#include <stdint.h>
#include <setjmp.h>
#include <cmocka.h>
@@ -79,9 +81,9 @@ differences are between them.
Mock objects include some logic and the test driver is able to modify the
behaviour and state. The object can call some functions or act on different
input (abort a test if it is wrong). The test driver injects what it expects
-the mock object to return. CMocka provides and API to easily mock code.
+the mock object to return. CMocka provides an API to easily mock code.
-<a href="https://lwn.net/Articles/558106/">Learn more ...</a>
+Check out the examples <a href="https://git.cryptomilk.org/projects/cmocka.git/tree/example/mock">here</a>.
@section main-embedded Embedded platforms
diff --git a/example/CMakeLists.txt b/example/CMakeLists.txt
index f983035..126a2e9 100644
--- a/example/CMakeLists.txt
+++ b/example/CMakeLists.txt
@@ -12,12 +12,15 @@ set_source_files_properties(calculator.c
add_cmocka_test(simple_test
SOURCES simple_test.c
COMPILE_OPTIONS ${DEFAULT_C_COMPILE_FLAGS}
+ LINK_OPTIONS ${DEFAULT_LINK_FLAGS}
LINK_LIBRARIES cmocka::cmocka)
add_cmocka_test_environment(simple_test)
### Allocate module test
add_cmocka_test(allocate_module_test
SOURCES allocate_module.c allocate_module_test.c
+ COMPILE_OPTIONS ${DEFAULT_C_COMPILE_FLAGS}
+ LINK_OPTIONS ${DEFAULT_LINK_FLAGS}
LINK_LIBRARIES cmocka::cmocka)
add_cmocka_test_environment(allocate_module_test)
@@ -28,6 +31,8 @@ set_tests_properties(allocate_module_test
### Assert macro test
add_cmocka_test(assert_macro_test
SOURCES assert_macro.c assert_macro_test.c
+ COMPILE_OPTIONS ${DEFAULT_C_COMPILE_FLAGS}
+ LINK_OPTIONS ${DEFAULT_LINK_FLAGS}
LINK_LIBRARIES cmocka::cmocka)
add_cmocka_test_environment(assert_macro_test)
@@ -38,6 +43,8 @@ set_tests_properties(assert_macro_test
### Assert module test
add_cmocka_test(assert_module_test
SOURCES assert_module.c assert_module_test.c
+ COMPILE_OPTIONS ${DEFAULT_C_COMPILE_FLAGS}
+ LINK_OPTIONS ${DEFAULT_LINK_FLAGS}
LINK_LIBRARIES cmocka::cmocka)
add_cmocka_test_environment(assert_module_test)
diff --git a/example/allocate_module_test.c b/example/allocate_module_test.c
index 562aea2..58ea01a 100644
--- a/example/allocate_module_test.c
+++ b/example/allocate_module_test.c
@@ -14,8 +14,10 @@
* limitations under the License.
*/
#include <stdarg.h>
+#include <stdbool.h>
#include <stddef.h>
#include <setjmp.h>
+#include <stdint.h>
#include <cmocka.h>
extern void leak_memory(void);
diff --git a/example/assert_macro_test.c b/example/assert_macro_test.c
index 2cd355c..8dadea4 100644
--- a/example/assert_macro_test.c
+++ b/example/assert_macro_test.c
@@ -14,8 +14,10 @@
* limitations under the License.
*/
#include <stdarg.h>
+#include <stdbool.h>
#include <stddef.h>
#include <setjmp.h>
+#include <stdint.h>
#include <cmocka.h>
#include "assert_macro.h"
diff --git a/example/assert_module_test.c b/example/assert_module_test.c
index f387754..69599eb 100644
--- a/example/assert_module_test.c
+++ b/example/assert_module_test.c
@@ -14,8 +14,10 @@
* limitations under the License.
*/
#include <stdarg.h>
+#include <stdbool.h>
#include <stddef.h>
#include <setjmp.h>
+#include <stdint.h>
#include <cmocka.h>
#include "assert_module.h"
diff --git a/example/calculator_test.c b/example/calculator_test.c
index ab8cad8..3728054 100644
--- a/example/calculator_test.c
+++ b/example/calculator_test.c
@@ -14,8 +14,10 @@
* limitations under the License.
*/
#include <stdarg.h>
+#include <stdbool.h>
#include <stddef.h>
#include <setjmp.h>
+#include <stdint.h>
#include "cmocka.h"
#include <stdio.h>
diff --git a/example/mock/chef_wrap/chef.c b/example/mock/chef_wrap/chef.c
index 1429cde..f893749 100644
--- a/example/mock/chef_wrap/chef.c
+++ b/example/mock/chef_wrap/chef.c
@@ -16,8 +16,10 @@
*/
#include <stdarg.h>
+#include <stdbool.h>
#include <stddef.h>
#include <setjmp.h>
+#include <stdint.h>
#include <cmocka.h>
#include <stdio.h>
#include <errno.h>
diff --git a/example/mock/chef_wrap/waiter_test_wrap.c b/example/mock/chef_wrap/waiter_test_wrap.c
index 4146818..6f2e4b3 100644
--- a/example/mock/chef_wrap/waiter_test_wrap.c
+++ b/example/mock/chef_wrap/waiter_test_wrap.c
@@ -22,8 +22,10 @@
#include <string.h>
#include <stdarg.h>
+#include <stdbool.h>
#include <stddef.h>
#include <setjmp.h>
+#include <stdint.h>
#include <cmocka.h>
#include "waiter_test_wrap.h"
@@ -120,7 +122,7 @@ static void test_order_hotdog(void **state)
will_return(__wrap_chef_cook, true);
will_return(__wrap_chef_cook, true);
/* The result will be a hotdog and the cooking process will succeed */
- will_return(__wrap_chef_cook, cast_ptr_to_largest_integral_type("hotdog"));
+ will_return_ptr_type(__wrap_chef_cook, "hotdog", char *);
will_return(__wrap_chef_cook, 0);
/* Test the waiter */
@@ -153,7 +155,7 @@ static void test_bad_dish(void **state)
* We expect the waiter to handle the bad dish and return an error
* code
*/
- will_return(__wrap_chef_cook, cast_ptr_to_largest_integral_type("burger"));
+ will_return_ptr_type(__wrap_chef_cook, "burger", char *);
will_return(__wrap_chef_cook, 0);
/* Test the waiter */
diff --git a/example/mock/uptime/CMakeLists.txt b/example/mock/uptime/CMakeLists.txt
index 967185f..d23ff77 100644
--- a/example/mock/uptime/CMakeLists.txt
+++ b/example/mock/uptime/CMakeLists.txt
@@ -1,7 +1,11 @@
add_library(proc_uptime proc_uptime.c)
add_executable(uptime uptime.c)
-target_compile_options(uptime PRIVATE ${DEFAULT_C_COMPILE_FLAGS})
+target_compile_options(uptime
+ PRIVATE
+ ${DEFAULT_C_COMPILE_FLAGS}
+ -D_GNU_SOURCE
+ -D_XOPEN_SOURCE=600)
target_link_libraries(uptime proc_uptime)
set_property(TARGET
uptime
@@ -11,7 +15,7 @@ set_property(TARGET
add_cmocka_test(test_uptime
SOURCES test_uptime.c
- COMPILE_OPTIONS ${DEFAULT_C_COMPILE_FLAGS}
+ COMPILE_OPTIONS ${DEFAULT_C_COMPILE_FLAGS} -D_GNU_SOURCE -D_XOPEN_SOURCE=600
LINK_LIBRARIES cmocka::cmocka)
set_property(TARGET
test_uptime
diff --git a/example/mock/uptime/test_uptime.c b/example/mock/uptime/test_uptime.c
index c724f95..3f08ad2 100644
--- a/example/mock/uptime/test_uptime.c
+++ b/example/mock/uptime/test_uptime.c
@@ -15,6 +15,7 @@
*/
#include <stdarg.h>
+#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
#include <setjmp.h>
diff --git a/example/mock/uptime/uptime.c b/example/mock/uptime/uptime.c
index 77776a7..f92aaff 100644
--- a/example/mock/uptime/uptime.c
+++ b/example/mock/uptime/uptime.c
@@ -26,7 +26,7 @@
static char *calc_uptime(void)
{
uint32_t up_minutes, up_hours, up_days, up_weeks, up_years;
- ssize_t pos = 0;
+ int pos = 0;
size_t comma = 0;
double uptime_secs, idle_secs;
char buf[1024] = {0};
diff --git a/example/simple_test.c b/example/simple_test.c
index cfb446c..3e56ab0 100644
--- a/example/simple_test.c
+++ b/example/simple_test.c
@@ -1,4 +1,5 @@
#include <stdarg.h>
+#include <stdbool.h>
#include <stddef.h>
#include <setjmp.h>
#include <stdint.h>
diff --git a/include/CMakeLists.txt b/include/CMakeLists.txt
index 4e38547..1365dbc 100644
--- a/include/CMakeLists.txt
+++ b/include/CMakeLists.txt
@@ -1,19 +1,14 @@
project(cmocka-header C)
+configure_file(${CMAKE_CURRENT_SOURCE_DIR}/cmocka_version.h.cmake
+ ${CMAKE_CURRENT_BINARY_DIR}/cmocka_version.h
+ @ONLY)
+
install(FILES
cmocka.h
cmocka_pbc.h
+ ${CMAKE_CURRENT_BINARY_DIR}/cmocka_version.h
DESTINATION
${CMAKE_INSTALL_INCLUDEDIR}
COMPONENT
${PROJECT_NAME})
-
-if (WITH_CMOCKERY_SUPPORT)
- install(FILES
- cmockery/cmockery.h
- cmockery/pbc.h
- DESTINATION
- ${CMAKE_INSTALL_INCLUDEDIR}/cmockery
- COMPONENT
- ${PROJECT_NAME})
-endif()
diff --git a/include/cmocka.h b/include/cmocka.h
index 0aa557e..083ea78 100644
--- a/include/cmocka.h
+++ b/include/cmocka.h
@@ -1,6 +1,6 @@
/*
* Copyright 2008 Google Inc.
- * Copyright 2014-2018 Andreas Schneider <asn@cryptomilk.org>
+ * Copyright 2014-2022 Andreas Schneider <asn@cryptomilk.org>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -20,6 +20,14 @@
#ifdef _WIN32
# ifdef _MSC_VER
+# ifndef CMOCKA_STATIC
+# ifdef CMOCKA_EXPORTS
+#define CMOCKA_DLLEXTERN __declspec(dllexport)
+# else
+#define CMOCKA_DLLEXTERN __declspec(dllimport)
+# endif /* CMOCKA_EXPORTS */
+# endif /* ndef CMOCKA_STATIC */
+
#define __func__ __FUNCTION__
# ifndef inline
@@ -39,15 +47,28 @@ int __stdcall IsDebuggerPresent();
#endif /* _WIN32 */
/**
+ * @def CMOCKA_DLLEXTERN
+ * This attribute is needed when dynamically linking to a data object in a DLL.
+ * It's optional (but increases performance) for dynamically linking to
+ * functions in a DLL.
+ * @see
+ * https://github.com/MicrosoftDocs/cpp-docs/blob/bd5a4fbd8ea3dd47b5c7a228c266cdddcaca0e00/docs/cpp/dllexport-dllimport.md
+ */
+#ifndef CMOCKA_DLLEXTERN
+#define CMOCKA_DLLEXTERN // only needed on MSVC compiler when using a DLL
+#endif /* ndef CMOCKA_DLLEXTERN */
+
+/**
* @defgroup cmocka The CMocka API
*
* These headers or their equivalents MUST be included prior to including
* this header file.
* @code
* #include <stdarg.h>
+ * #include <stdbool.h>
* #include <stddef.h>
- * #include <setjmp.h>
* #include <stdint.h>
+ * #include <setjmp.h>
* @endcode
*
* This allows test applications to use custom definitions of C standard
@@ -56,105 +77,57 @@ int __stdcall IsDebuggerPresent();
* @{
*/
-/* If __WORDSIZE is not set, try to figure it out and default to 32 bit. */
-#ifndef __WORDSIZE
-# if (defined(__x86_64__) && !defined(__ILP32__)) || defined(__sparc_v9__) || defined(__sparcv9)
-# define __WORDSIZE 64
-# else
-# define __WORDSIZE 32
-# endif
-#endif
-
-#ifdef DOXYGEN
-/**
- * Largest integral type. This type should be large enough to hold any
- * pointer or integer supported by the compiler.
- */
-typedef uintmax_t LargestIntegralType;
-#else /* DOXGEN */
-#ifndef LargestIntegralType
-# if __WORDSIZE == 64 && !defined(_WIN64)
-# define LargestIntegralType unsigned long int
-# else
-# define LargestIntegralType unsigned long long int
-# endif
-#endif /* LargestIntegralType */
-#endif /* DOXYGEN */
-
-/* Printf format used to display LargestIntegralType as a hexidecimal. */
-#ifndef LargestIntegralTypePrintfFormat
-# ifdef _WIN32
-# define LargestIntegralTypePrintfFormat "0x%I64x"
-# else
-# if __WORDSIZE == 64
-# define LargestIntegralTypePrintfFormat "%#lx"
-# else
-# define LargestIntegralTypePrintfFormat "%#llx"
-# endif
-# endif /* _WIN32 */
-#endif /* LargestIntegralTypePrintfFormat */
-
-/* Printf format used to display LargestIntegralType as a decimal. */
-#ifndef LargestIntegralTypePrintfFormatDecimal
-# ifdef _WIN32
-# define LargestIntegralTypePrintfFormatDecimal "%I64u"
-# else
-# if __WORDSIZE == 64
-# define LargestIntegralTypePrintfFormatDecimal "%lu"
-# else
-# define LargestIntegralTypePrintfFormatDecimal "%llu"
-# endif
-# endif /* _WIN32 */
-#endif /* LargestIntegralTypePrintfFormat */
-
-#ifndef FloatPrintfFormat
-# define FloatPrintfFormat "%f"
-#endif /* FloatPrintfFormat */
-
-#ifndef DoublePrintfFormat
-# define DoublePrintfFormat "%f"
-#endif /* DoublePrintfFormat */
-
-/* Perform an unsigned cast to LargestIntegralType. */
-#define cast_to_largest_integral_type(value) \
- ((LargestIntegralType)(value))
-
-/* Smallest integral type capable of holding a pointer. */
-#if !defined(_UINTPTR_T) && !defined(_UINTPTR_T_DEFINED) && !defined(HAVE_UINTPTR_T)
-# if defined(_WIN32)
- /* WIN32 is an ILP32 platform */
- typedef unsigned int uintptr_t;
-# elif defined(_WIN64)
- typedef unsigned long int uintptr_t;
-# else /* _WIN32 */
-
-/* ILP32 and LP64 platforms */
-# ifdef __WORDSIZE /* glibc */
-# if __WORDSIZE == 64
- typedef unsigned long int uintptr_t;
-# else
- typedef unsigned int uintptr_t;
-# endif /* __WORDSIZE == 64 */
-# else /* __WORDSIZE */
-# if defined(_LP64) || defined(_I32LPx)
- typedef unsigned long int uintptr_t;
-# else
- typedef unsigned int uintptr_t;
-# endif
-# endif /* __WORDSIZE */
-# endif /* _WIN32 */
+/* Perform an signed cast to intmax_t. */
+#define cast_to_intmax_type(value) \
+ ((intmax_t)(value))
-# define _UINTPTR_T
-# define _UINTPTR_T_DEFINED
-#endif /* !defined(_UINTPTR_T) || !defined(_UINTPTR_T_DEFINED) */
+/* Perform an unsigned cast to uintmax_t. */
+#define cast_to_uintmax_type(value) \
+ ((uintmax_t)(value))
-/* Perform an unsigned cast to uintptr_t. */
-#define cast_to_pointer_integral_type(value) \
- ((uintptr_t)((size_t)(value)))
+/**
+ * Perform a cast from an integer to CMockaValueData.
+ *
+ * For backwards compatibility reasons, this explicitly casts to `uintmax_t`.
+ * For most compilers, this will supress warnings about passing float/intmax_t
+ * to this macro.
+ */
+#define cast_int_to_cmocka_value(value) \
+ (CMockaValueData) \
+ { \
+ .uint_val = (uintmax_t)(value) \
+ }
+
+/** Perform a cast from a pointer to CMockaValueData. */
+#define cast_ptr_to_cmocka_value(value) \
+ (CMockaValueData) \
+ { \
+ .ptr = (value) \
+ }
-/* Perform a cast of a pointer to LargestIntegralType */
-#define cast_ptr_to_largest_integral_type(value) \
-cast_to_largest_integral_type(cast_to_pointer_integral_type(value))
+/** Assign an integer value to CMockaValueData. */
+#define assign_int_to_cmocka_value(value) \
+ (CMockaValueData) \
+ { \
+ .int_val = (value) \
+ }
+
+/** Assign an unsigned integer value to CMockaValueData. */
+#define assign_uint_to_cmocka_value(value) \
+ (CMockaValueData) \
+ { \
+ .uint_val = (value) \
+ }
+
+/** Assign a floating point value to CMockaValueData. */
+#define assign_double_to_cmocka_value(value) \
+ (CMockaValueData) \
+ { \
+ .real_val = (value) \
+ }
+
+/* Nested macros are not expanded when they appear along with # or ## */
+#define cmocka_tostring(val) #val
/* GCC have printf type attribute check. */
#ifdef __GNUC__
@@ -172,39 +145,72 @@ cast_to_largest_integral_type(cast_to_pointer_integral_type(value))
#define CMOCKA_DEPRECATED
#endif
+#if defined(__GNUC__)
+#define CMOCKA_NORETURN __attribute__ ((noreturn))
+#elif defined(_MSC_VER)
+#define CMOCKA_NORETURN __declspec(noreturn)
+#else
+#define CMOCKA_NORETURN
+#endif
+
+/**
+ * @def CMOCKA_NO_ACCESS_ATTRIBUTE
+ *
+ * Function attribute that tells the compiler that we never access the value
+ * of a/b, just the pointer address.
+ *
+ * Without this, newer compilers like GCC-12 will print
+ * `-Wmaybe-uninitialized` warnings.
+ *
+ * @see
+ * https://gcc.gnu.org/onlinedocs/gcc-12.2.0/gcc/Common-Function-Attributes.html#Common-Function-Attributes
+ */
+#ifdef __has_attribute
+#if __has_attribute(access)
+#define CMOCKA_NO_ACCESS_ATTRIBUTE \
+ __attribute__((access(none, 1), access(none, 2)))
+#endif
+#endif
+#ifndef CMOCKA_NO_ACCESS_ATTRIBUTE
+#define CMOCKA_NO_ACCESS_ATTRIBUTE
+#endif
+
#define WILL_RETURN_ALWAYS -1
#define WILL_RETURN_ONCE -2
+#define EXPECT_ALWAYS -1
+#define EXPECT_MAYBE -2
+
/**
* @defgroup cmocka_mock Mock Objects
* @ingroup cmocka
*
- * Mock objects mock objects are simulated objects that mimic the behavior of
+ * Mock objects are simulated objects that mimic the behavior of
* real objects. Instead of calling the real objects, the tested object calls a
* mock object that merely asserts that the correct methods were called, with
* the expected parameters, in the correct order.
*
* <ul>
* <li><strong>will_return(function, value)</strong> - The will_return() macro
- * pushes a value onto a stack of mock values. This macro is intended to be
+ * pushes a value onto a queue of mock values. This macro is intended to be
* used by the unit test itself, while programming the behaviour of the mocked
* object.</li>
*
- * <li><strong>mock()</strong> - the mock macro pops a value from a stack of
+ * <li><strong>mock()</strong> - the mock macro pops a value from a queue of
* test values. The user of the mock() macro is the mocked object that uses it
* to learn how it should behave.</li>
* </ul>
*
* Because the will_return() and mock() are intended to be used in pairs, the
* cmocka library would fail the test if there are more values pushed onto the
- * stack using will_return() than consumed with mock() and vice-versa.
+ * queue using will_return() than consumed with mock() and vice-versa.
*
* The following unit test stub illustrates how would a unit test instruct the
* mock object to return a particular value:
*
* @code
- * will_return(chef_cook, "hotdog");
- * will_return(chef_cook, 0);
+ * will_return_ptr_type(chef_cook, "hotdog", const char *);
+ * will_return_int(chef_cook, 0);
* @endcode
*
* Now the mock object can check if the parameter it received is the parameter
@@ -213,12 +219,15 @@ cast_to_largest_integral_type(cast_to_pointer_integral_type(value))
* @code
* int chef_cook(const char *order, char **dish_out)
* {
- * check_expected(order);
+ * *dish_out = mock_ptr_type(char *); // "hotdog"
+ * int return_code = mock_int(); // 0
+ * return return_code;
* }
* @endcode
*
* For a complete example please take a look
- * <a href="https://git.cryptomilk.org/projects/cmocka.git/tree/example/mock">here</a>.
+ * <a
+ * href="https://git.cryptomilk.org/projects/cmocka.git/tree/example/mock">here</a>.
*
* @{
*/
@@ -231,17 +240,19 @@ cast_to_largest_integral_type(cast_to_pointer_integral_type(value))
*
* @see will_return()
*/
-LargestIntegralType mock(void);
+uintmax_t mock(void);
#else
-#define mock() _mock(__func__, __FILE__, __LINE__)
+#define mock() (_mock(__func__, __FILE__, __LINE__, NULL)).uint_val
#endif
+
#ifdef DOXYGEN
/**
- * @brief Retrieve a typed return value of the current function.
+ * @brief Retrieve a value of the current function and cast it to given type.
*
* The value would be casted to type internally to avoid having the
- * caller to do the cast manually.
+ * caller to do the cast manually. Type saftey checks are disabled with that
+ * functoin.
*
* @param[in] #type The expected type of the return value
*
@@ -254,8 +265,6 @@ LargestIntegralType mock(void);
* @endcode
*
* @see will_return()
- * @see mock()
- * @see mock_ptr_type()
*/
#type mock_type(#type);
#else
@@ -264,11 +273,65 @@ LargestIntegralType mock(void);
#ifdef DOXYGEN
/**
+ * @brief Retrieve an integer return value of the current function.
+ *
+ * @return The value which was stored to return by this function.
+ *
+ * @code
+ * intmax_t param;
+ *
+ * param = mock_int();
+ * @endcode
+ *
+ * @see will_return_int()
+ */
+intmax_t mock_int();
+#else
+/* TODO: Enable type safety check by passing intmax_t instead of NULL */
+#define mock_int() (_mock(__func__, __FILE__, __LINE__, NULL)).int_val
+#endif
+
+
+#ifdef DOXYGEN
+/**
+ * @brief Retrieve an unsinged integer return value of the current function.
+ *
+ * @return The value which was stored to return by this function.
+ *
+ * @code
+ * uintmax_t param;
+ *
+ * param = mock_uint();
+ * @endcode
+ *
+ * @see will_return_uint()
+ */
+uintmax_t mock_uint(void);
+#else
+#define mock_uint() (_mock(__func__, __FILE__, __LINE__, "uintmax_t")).uint_val
+#endif
+
+
+#ifdef DOXYGEN
+/**
+ * @brief Retrieve an unsinged integer return value of the current function.
+ *
+ * @return The value which was stored to return by this function.
+ *
+ * @see will_return_float()
+ */
+double mock_float(void);
+#else
+#define mock_float() (_mock(__func__, __FILE__, __LINE__, NULL)).real_val
+#endif
+
+
+#ifdef DOXYGEN
+/**
* @brief Retrieve a typed return value of the current function.
*
* The value would be casted to type internally to avoid having the
- * caller to do the cast manually but also casted to uintptr_t to make
- * sure the result has a valid size to be used as a pointer.
+ * caller to do the cast manually.
*
* @param[in] #type The expected type of the return value
*
@@ -280,13 +343,12 @@ LargestIntegralType mock(void);
* param = mock_ptr_type(char *);
* @endcode
*
- * @see will_return()
- * @see mock()
- * @see mock_type()
+ * @see will_return_ptr_type()
*/
type mock_ptr_type(#type);
#else
-#define mock_ptr_type(type) ((type) (uintptr_t) mock())
+#define mock_ptr_type(type) \
+ ((type)(_mock(__func__, __FILE__, __LINE__, #type)).ptr)
#endif
@@ -313,15 +375,136 @@ type mock_ptr_type(#type);
* @endcode
*
* @see mock()
+ * @see mock_int()
+ * @see mock_uint()
+ * @see mock_float()
+ * @see will_return_int()
+ * @see will_return_uint()
+ * @see will_return_float()
+ * @see will_return_ptr_type()
+ * @see will_return_count()
+ * @see will_return_always()
+ * @see will_return_ptr_always()
+ */
+void will_return(#function, uintmax_t value);
+#else
+#define will_return(function, value) \
+ _will_return(cmocka_tostring(function), \
+ __FILE__, \
+ __LINE__, \
+ NULL, \
+ cast_int_to_cmocka_value(value), \
+ 1)
+#endif
+
+#ifdef DOXYGEN
+/**
+ * @brief Store an integer value to be returned by mock() later.
+ *
+ * @param[in] #function The function which should return the given value.
+ *
+ * @param[in] value The value to be returned by mock().
+ *
+ * @code
+ * int32_t return_int32(void)
+ * {
+ * return (int32_t)mock_int();
+ * }
+ *
+ * static void test_integer_return(void **state)
+ * {
+ * will_return_int(return_int32, -42);
+ *
+ * assert_int_equal(my_function_calling_return_int32(), -42);
+ * }
+ * @endcode
+ *
+ * @see mock_int()
+ */
+void will_return_int(#function, intmax_t value);
+#else
+#define will_return_int(function, value) \
+ _will_return(#function, \
+ __FILE__, \
+ __LINE__, \
+ "intmax_t", \
+ assign_int_to_cmocka_value(value), \
+ 1)
+#endif
+
+#ifdef DOXYGEN
+/**
+ * @brief Store a unsigned integer value to be returned by mock() later.
+ *
+ * @param[in] #function The function which should return the given value.
+ *
+ * @param[in] value The value to be returned by mock().
+ *
+ * @code
+ * uint32_t return_uint32(void)
+ * {
+ * return (uint32_t)mock_uint();
+ * }
+ *
+ * static void test_integer_return(void **state)
+ * {
+ * will_return_int(return_uint32, 42);
+ *
+ * assert_uint_equal(my_function_calling_return_uint32(), 42);
+ * }
+ * @endcode
+ *
+ * @see mock_uint()
* @see will_return_count()
*/
-void will_return(#function, LargestIntegralType value);
+void will_return_uint(#function, uintmax_t value);
#else
-#define will_return(function, value) \
- _will_return(#function, __FILE__, __LINE__, \
- cast_to_largest_integral_type(value), 1)
+#define will_return_uint(function, value) \
+ _will_return(#function, \
+ __FILE__, \
+ __LINE__, \
+ "uintmax_t", \
+ assign_uint_to_cmocka_value(value), \
+ 1)
#endif
+
+#ifdef DOXYGEN
+/**
+ * @brief Store a floating point value to be returned by mock() later.
+ *
+ * @param[in] #function The function which should return the given value.
+ *
+ * @param[in] value The value to be returned by mock().
+ *
+ * @code
+ * float return_float(void)
+ * {
+ * return (float)mock_double();
+ * }
+ *
+ * static void test_integer_return(void **state)
+ * {
+ * will_return_int(return_float, 1.0);
+ *
+ * assert_float_equal(my_function_calling_return_float(), 1.0);
+ * }
+ * @endcode
+ *
+ * @see mock_float()
+ */
+void will_return_float(#function, intmax_t value);
+#else
+#define will_return_float(function, value) \
+ _will_return(#function, \
+ __FILE__, \
+ __LINE__, \
+ "float", \
+ assign_double_to_cmocka_value(value), \
+ 1)
+#endif
+
+
#ifdef DOXYGEN
/**
* @brief Store a value to be returned by mock() later.
@@ -338,11 +521,15 @@ void will_return(#function, LargestIntegralType value);
*
* @see mock()
*/
-void will_return_count(#function, LargestIntegralType value, int count);
+void will_return_count(#function, uintmax_t value, int count);
#else
#define will_return_count(function, value, count) \
- _will_return(#function, __FILE__, __LINE__, \
- cast_to_largest_integral_type(value), count)
+ _will_return(cmocka_tostring(function), \
+ __FILE__, \
+ __LINE__, \
+ NULL, \
+ cast_int_to_cmocka_value(value), \
+ count)
#endif
#ifdef DOXYGEN
@@ -361,7 +548,7 @@ void will_return_count(#function, LargestIntegralType value, int count);
* @see will_return_count()
* @see mock()
*/
-void will_return_always(#function, LargestIntegralType value);
+void will_return_always(#function, uintmax_t value);
#else
#define will_return_always(function, value) \
will_return_count(function, (value), WILL_RETURN_ALWAYS)
@@ -389,11 +576,162 @@ void will_return_always(#function, LargestIntegralType value);
* @see will_return_count()
* @see mock()
*/
-void will_return_maybe(#function, LargestIntegralType value);
+void will_return_maybe(#function, uintmax_t value);
#else
#define will_return_maybe(function, value) \
will_return_count(function, (value), WILL_RETURN_ONCE)
#endif
+
+#ifdef DOXYGEN
+/**
+ * @brief Store a pointer value to be returned by mock_ptr_type() later.
+ *
+ * @param[in] #function The function which should return the given value.
+ *
+ * @param[in] value The value to be returned by mock_ptr_type().
+ *
+ * @code
+ * const char * return_pointer(void)
+ * {
+ * return mock_ptr_type(const char *);
+ * }
+ *
+ * static void test_pointer_return(void **state)
+ * {
+ * will_return(return_pointer, "hello world");
+ *
+ * assert_string_equal(my_function_calling_return_integer(), 42);
+ * }
+ * @endcode
+ *
+ * @see mock_ptr_type()
+ * @see will_return_ptr_count()
+ */
+void will_return_ptr(#function, void *value);
+#else
+#define will_return_ptr(function, value) \
+ _will_return(#function, \
+ __FILE__, \
+ __LINE__, \
+ NULL, \
+ cast_ptr_to_cmocka_value(value), \
+ 1)
+#endif
+
+#ifdef DOXYGEN
+/**
+ * @brief Store a pointer value to be returned by mock_ptr_type() later.
+ *
+ * This will also check that the type matches and if not will fail().
+ *
+ * @param[in] #function The function which should return the given value.
+ *
+ * @param[in] value The value to be returned by mock_ptr_type().
+ *
+ * @param[in] value The type of the pointer.
+ * @code
+ * const char *return_pointer(void)
+ * {
+ * return mock_ptr_type(const char *);
+ * }
+ *
+ * static void test_pointer_return(void **state)
+ * {
+ * will_return_ptr_type(return_pointer, "hello world", const char *);
+ *
+ * assert_string_equal(my_func_calling_return_pointer(), "hello world");
+ * }
+ * @endcode
+ *
+ * @see mock_ptr_type()
+ */
+void will_return_ptr_type(#function, void *value, type);
+#else
+#define will_return_ptr_type(function, value, type) \
+ _will_return(#function, \
+ __FILE__, \
+ __LINE__, \
+ #type, \
+ cast_ptr_to_cmocka_value(value), \
+ 1)
+#endif
+
+#ifdef DOXYGEN
+/**
+ * @brief Store a pointer value to be returned by mock_ptr_type() later.
+ *
+ * @param[in] #function The function which should return the given value.
+ *
+ * @param[in] value The value to be returned by mock_ptr_type().
+ *
+ * @param[in] count The parameter indicates the number of times the value should
+ * be returned by mock(). If count is set to -1, the value
+ * will always be returned but must be returned at least once.
+ * If count is set to -2, the value will always be returned
+ * by mock(), but is not required to be returned.
+ *
+ * @see mock_ptr_type()
+ */
+void will_return_ptr_count(#function, void *value, int count);
+#else
+#define will_return_ptr_count(function, value, count) \
+ _will_return(#function, \
+ __FILE__, \
+ __LINE__, \
+ NULL, \
+ cast_ptr_to_cmocka_value(value), \
+ count)
+#endif
+
+#ifdef DOXYGEN
+/**
+ * @brief Store a value that will be always returned by mock_ptr_type().
+ *
+ * @param[in] #function The function which should return the given value.
+ *
+ * @param[in] #value The value to be returned by mock_ptr_type().
+ *
+ * This is equivalent to:
+ * @code
+ * will_return_ptr_count(function, value, -1);
+ * @endcode
+ *
+ * @see will_return_ptr_count()
+ * @see mock_ptr_type()
+ */
+void will_return_ptr_always(#function, void *value);
+#else
+#define will_return_ptr_always(function, value) \
+ will_return_ptr_count(function, (value), WILL_RETURN_ALWAYS)
+#endif
+
+#ifdef DOXYGEN
+/**
+ * @brief Store a value that may be always returned by mock_ptr_type().
+ *
+ * This stores a value which will always be returned by mock_ptr_type() but is
+ * not required to be returned by at least one call to mock_ptr_type().
+ * Therefore, in contrast to will_return_ptr_always() which causes a test
+ * failure if it is not returned at least once, will_return_ptr_maybe() will
+ * never cause a test to fail if its value is not returned.
+ *
+ * @param[in] #function The function which should return the given value.
+ *
+ * @param[in] #value The value to be returned by mock_ptr_type().
+ *
+ * This is equivalent to:
+ * @code
+ * will_return_ptr_count(function, value, -2);
+ * @endcode
+ *
+ * @see will_return_ptr_count()
+ * @see mock_ptr_type()
+ */
+void will_return_ptr_maybe(#function, void *value);
+#else
+#define will_return_ptr_maybe(function, value) \
+ will_return_ptr_count(function, (value), WILL_RETURN_ONCE)
+#endif
/** @} */
/**
@@ -440,12 +778,7 @@ void will_return_maybe(#function, LargestIntegralType value);
* @{
*/
-/*
- * Add a custom parameter checking function. If the event parameter is NULL
- * the event structure is allocated internally by this function. If event
- * parameter is provided it must be allocated on the heap and doesn't need to
- * be deallocated by the caller.
- */
+
#ifdef DOXYGEN
/**
* @brief Add a custom parameter checking function.
@@ -463,11 +796,67 @@ void will_return_maybe(#function, LargestIntegralType value);
*
* @param[in] check_data The data to pass to the check function.
*/
-void expect_check(#function, #parameter, #check_function, const void *check_data);
+void expect_check(function,
+ parameter,
+ CheckParameterValue check_function,
+ CMockaValueData check_data);
#else
#define expect_check(function, parameter, check_function, check_data) \
- _expect_check(#function, #parameter, __FILE__, __LINE__, check_function, \
- cast_to_largest_integral_type(check_data), NULL, 1)
+ _expect_check(cmocka_tostring(function), \
+ cmocka_tostring(parameter), \
+ __FILE__, \
+ __LINE__, \
+ check_function, \
+ check_data, \
+ NULL, \
+ 1)
+#endif
+
+
+#ifdef DOXYGEN
+/**
+ * @brief Add a custom parameter checking function.
+ *
+ * If the event parameter is NULL the event structure is allocated internally
+ * by this function. If the parameter is provided it must be allocated on the
+ * heap and doesn't need to be deallocated by the caller.
+ *
+ * @param[in] #function The function to add a custom parameter checking
+ * function for.
+ *
+ * @param[in] #parameter The parameters passed to the function.
+ *
+ * @param[in] #check_function The check function to call.
+ *
+ * @param[in] check_data The data to pass to the check function.
+ *
+ * @param[in] count The count parameter gives the number of times the value
+ * should be validated by check_expected(). If count is set
+ * to @ref EXPECT_ALWAYS the value will always be returned,
+ * and cmocka expects check_expected() to be issued at least
+ * once. If count is set to @ref EXPECT_MAYBE, any number of
+ * calls to check_expected() is accepted, including zero.
+ *
+ */
+void expect_check_count(function,
+ parameter,
+ CheckParameterValue check_function,
+ CMockaValueData check_data,
+ size_t count);
+#else
+#define expect_check_count(function, \
+ parameter, \
+ check_function, \
+ check_data, \
+ count) \
+ _expect_check(cmocka_tostring(function), \
+ cmocka_tostring(parameter), \
+ __FILE__, \
+ __LINE__, \
+ check_function, \
+ check_data, \
+ NULL, \
+ count)
#endif
#ifdef DOXYGEN
@@ -485,7 +874,7 @@ void expect_check(#function, #parameter, #check_function, const void *check_data
*
* @see check_expected().
*/
-void expect_in_set(#function, #parameter, LargestIntegralType value_array[]);
+void expect_in_set(#function, #parameter, uintmax_t value_array[]);
#else
#define expect_in_set(function, parameter, value_array) \
expect_in_set_count(function, parameter, value_array, 1)
@@ -494,6 +883,48 @@ void expect_in_set(#function, #parameter, LargestIntegralType value_array[]);
#ifdef DOXYGEN
/**
* @brief Add an event to check if the parameter value is part of the provided
+ * integer array.
+ *
+ * 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.
+ *
+ * @param[in] value_array[] The array to check for the value.
+ *
+ * @see check_expected().
+ */
+void expect_in_set(#function, #parameter, intmax_t value_array[]);
+#else
+#define expect_int_in_set(function, parameter, value_array) \
+ expect_int_in_set_count(function, parameter, value_array, 1)
+#endif
+
+#ifdef DOXYGEN
+/**
+ * @brief Add an event to check if the parameter value is part of the provided
+ * unsigned integer array.
+ *
+ * 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.
+ *
+ * @param[in] value_array[] The array to check for the value.
+ *
+ * @see check_expected().
+ */
+void expect_in_set(#function, #parameter, intmax_t value_array[]);
+#else
+#define expect_uint_in_set(function, parameter, value_array) \
+ expect_uint_in_set_count(function, parameter, value_array, 1)
+#endif
+
+#ifdef DOXYGEN
+/**
+ * @brief Add an event to check if the parameter value is part of the provided
* array.
*
* The event is triggered by calling check_expected() in the mocked function.
@@ -510,11 +941,78 @@ void expect_in_set(#function, #parameter, LargestIntegralType value_array[]);
*
* @see check_expected().
*/
-void expect_in_set_count(#function, #parameter, LargestIntegralType value_array[], size_t count);
+void expect_in_set_count(#function, #parameter, uintmax_t value_array[], size_t count);
#else
-#define expect_in_set_count(function, parameter, value_array, count) \
- _expect_in_set(#function, #parameter, __FILE__, __LINE__, value_array, \
- sizeof(value_array) / sizeof((value_array)[0]), count)
+#define expect_in_set_count(function, parameter, value_array, count) \
+ _expect_uint_in_set(cmocka_tostring(function), \
+ cmocka_tostring(parameter), \
+ __FILE__, \
+ __LINE__, \
+ value_array, \
+ sizeof(value_array) / sizeof((value_array)[0]), \
+ count)
+#endif
+
+#ifdef DOXYGEN
+/**
+ * @brief Add an event to check if the parameter value is part of the provided
+ * integer array.
+ *
+ * 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.
+ *
+ * @param[in] value_array[] The array to check for the value.
+ *
+ * @param[in] count The count parameter returns the number of times the value
+ * should be returned by check_expected(). If count is set
+ * to -1 the value will always be returned.
+ *
+ * @see check_expected().
+ */
+void expect_int_in_set_count(#function, #parameter, intmax_t value_array[], size_t count);
+#else
+#define expect_int_in_set_count(function, parameter, value_array, count) \
+ _expect_int_in_set(cmocka_tostring(function), \
+ cmocka_tostring(parameter), \
+ __FILE__, \
+ __LINE__, \
+ value_array, \
+ sizeof(value_array) / sizeof((value_array)[0]), \
+ count)
+#endif
+
+#ifdef DOXYGEN
+/**
+ * @brief Add an event to check if the parameter value is part of the provided
+ * unsigned integer array.
+ *
+ * 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.
+ *
+ * @param[in] value_array[] The array to check for the value.
+ *
+ * @param[in] count The count parameter returns the number of times the value
+ * should be returned by check_expected(). If count is set
+ * to -1 the value will always be returned.
+ *
+ * @see check_expected().
+ */
+void expect_int_in_set_count(#function, #parameter, uintmax_t value_array[], size_t count);
+#else
+#define expect_uint_in_set_count(function, parameter, value_array, count) \
+ _expect_uint_in_set(cmocka_tostring(function), \
+ cmocka_tostring(parameter), \
+ __FILE__, \
+ __LINE__, \
+ value_array, \
+ sizeof(value_array) / sizeof((value_array)[0]), \
+ count)
#endif
#ifdef DOXYGEN
@@ -532,7 +1030,7 @@ void expect_in_set_count(#function, #parameter, LargestIntegralType value_array[
*
* @see check_expected().
*/
-void expect_not_in_set(#function, #parameter, LargestIntegralType value_array[]);
+void expect_not_in_set(#function, #parameter, uintmax_t value_array[]);
#else
#define expect_not_in_set(function, parameter, value_array) \
expect_not_in_set_count(function, parameter, value_array, 1)
@@ -557,11 +1055,11 @@ void expect_not_in_set(#function, #parameter, LargestIntegralType value_array[])
*
* @see check_expected().
*/
-void expect_not_in_set_count(#function, #parameter, LargestIntegralType value_array[], size_t count);
+void expect_not_in_set_count(#function, #parameter, uintmax_t value_array[], size_t count);
#else
#define expect_not_in_set_count(function, parameter, value_array, count) \
_expect_not_in_set( \
- #function, #parameter, __FILE__, __LINE__, value_array, \
+ cmocka_tostring(function), cmocka_tostring(parameter), __FILE__, __LINE__, value_array, \
sizeof(value_array) / sizeof((value_array)[0]), count)
#endif
@@ -583,7 +1081,7 @@ void expect_not_in_set_count(#function, #parameter, LargestIntegralType value_ar
*
* @see check_expected().
*/
-void expect_in_range(#function, #parameter, LargestIntegralType minimum, LargestIntegralType maximum);
+void expect_in_range(#function, #parameter, uintmax_t minimum, uintmax_t maximum);
#else
#define expect_in_range(function, parameter, minimum, maximum) \
expect_in_range_count(function, parameter, minimum, maximum, 1)
@@ -610,10 +1108,10 @@ void expect_in_range(#function, #parameter, LargestIntegralType minimum, Largest
*
* @see check_expected().
*/
-void expect_in_range_count(#function, #parameter, LargestIntegralType minimum, LargestIntegralType maximum, size_t count);
+void expect_in_range_count(#function, #parameter, uintmax_t minimum, uintmax_t maximum, size_t count);
#else
#define expect_in_range_count(function, parameter, minimum, maximum, count) \
- _expect_in_range(#function, #parameter, __FILE__, __LINE__, minimum, \
+ _expect_in_range(cmocka_tostring(function), cmocka_tostring(parameter), __FILE__, __LINE__, minimum, \
maximum, count)
#endif
@@ -634,7 +1132,7 @@ void expect_in_range_count(#function, #parameter, LargestIntegralType minimum, L
*
* @see check_expected().
*/
-void expect_not_in_range(#function, #parameter, LargestIntegralType minimum, LargestIntegralType maximum);
+void expect_not_in_range(#function, #parameter, uintmax_t minimum, uintmax_t maximum);
#else
#define expect_not_in_range(function, parameter, minimum, maximum) \
expect_not_in_range_count(function, parameter, minimum, maximum, 1)
@@ -661,17 +1159,17 @@ void expect_not_in_range(#function, #parameter, LargestIntegralType minimum, Lar
*
* @see check_expected().
*/
-void expect_not_in_range_count(#function, #parameter, LargestIntegralType minimum, LargestIntegralType maximum, size_t count);
+void expect_not_in_range_count(#function, #parameter, uintmax_t minimum, uintmax_t maximum, size_t count);
#else
#define expect_not_in_range_count(function, parameter, minimum, maximum, \
count) \
- _expect_not_in_range(#function, #parameter, __FILE__, __LINE__, \
+ _expect_not_in_range(cmocka_tostring(function), cmocka_tostring(parameter), __FILE__, __LINE__, \
minimum, maximum, count)
#endif
#ifdef DOXYGEN
/**
- * @brief Add an event to check if a parameter is the given value.
+ * @brief Add an event to check if a parameter is the given integer based value.
*
* The event is triggered by calling check_expected() in the mocked function.
*
@@ -681,9 +1179,12 @@ void expect_not_in_range_count(#function, #parameter, LargestIntegralType minimu
*
* @param[in] value The value to check.
*
- * @see check_expected().
+ * @see check_expected()
+ * @see expect_string()
+ * @see expect_memory()
+ * @see expect_any()
*/
-void expect_value(#function, #parameter, LargestIntegralType value);
+void expect_value(#function, #parameter, uintmax_t value);
#else
#define expect_value(function, parameter, value) \
expect_value_count(function, parameter, value, 1)
@@ -691,7 +1192,8 @@ void expect_value(#function, #parameter, LargestIntegralType value);
#ifdef DOXYGEN
/**
- * @brief Add an event to repeatedly check if a parameter is the given value.
+ * @brief Add an event to repeatedly check if a parameter is the given integer
+ * based value.
*
* The event is triggered by calling check_expected() in the mocked function.
*
@@ -706,12 +1208,14 @@ void expect_value(#function, #parameter, LargestIntegralType value);
* to -1 the value will always be returned.
*
* @see check_expected().
+ * @see expect_not_string()
+ * @see expect_not_memory()
*/
-void expect_value_count(#function, #parameter, LargestIntegralType value, size_t count);
+void expect_value_count(#function, #parameter, uintmax_t value, size_t count);
#else
#define expect_value_count(function, parameter, value, count) \
- _expect_value(#function, #parameter, __FILE__, __LINE__, \
- cast_to_largest_integral_type(value), count)
+ _expect_value(cmocka_tostring(function), cmocka_tostring(parameter), __FILE__, __LINE__, \
+ cast_to_uintmax_type(value), count)
#endif
#ifdef DOXYGEN
@@ -728,7 +1232,7 @@ void expect_value_count(#function, #parameter, LargestIntegralType value, size_t
*
* @see check_expected().
*/
-void expect_not_value(#function, #parameter, LargestIntegralType value);
+void expect_not_value(#function, #parameter, uintmax_t value);
#else
#define expect_not_value(function, parameter, value) \
expect_not_value_count(function, parameter, value, 1)
@@ -752,11 +1256,11 @@ void expect_not_value(#function, #parameter, LargestIntegralType value);
*
* @see check_expected().
*/
-void expect_not_value_count(#function, #parameter, LargestIntegralType value, size_t count);
+void expect_not_value_count(#function, #parameter, uintmax_t value, size_t count);
#else
#define expect_not_value_count(function, parameter, value, count) \
- _expect_not_value(#function, #parameter, __FILE__, __LINE__, \
- cast_to_largest_integral_type(value), count)
+ _expect_not_value(cmocka_tostring(function), cmocka_tostring(parameter), __FILE__, __LINE__, \
+ cast_to_uintmax_type(value), count)
#endif
#ifdef DOXYGEN
@@ -802,7 +1306,7 @@ void expect_string(#function, #parameter, const char *string);
void expect_string_count(#function, #parameter, const char *string, size_t count);
#else
#define expect_string_count(function, parameter, string, count) \
- _expect_string(#function, #parameter, __FILE__, __LINE__, \
+ _expect_string(cmocka_tostring(function), cmocka_tostring(parameter), __FILE__, __LINE__, \
(const char*)(string), count)
#endif
@@ -849,7 +1353,7 @@ void expect_not_string(#function, #parameter, const char *string);
void expect_not_string_count(#function, #parameter, const char *string, size_t count);
#else
#define expect_not_string_count(function, parameter, string, count) \
- _expect_not_string(#function, #parameter, __FILE__, __LINE__, \
+ _expect_not_string(cmocka_tostring(function), cmocka_tostring(parameter), __FILE__, __LINE__, \
(const char*)(string), count)
#endif
@@ -899,7 +1403,7 @@ void expect_memory(#function, #parameter, void *memory, size_t size);
void expect_memory_count(#function, #parameter, void *memory, size_t size, size_t count);
#else
#define expect_memory_count(function, parameter, memory, size, count) \
- _expect_memory(#function, #parameter, __FILE__, __LINE__, \
+ _expect_memory(cmocka_tostring(function), cmocka_tostring(parameter), __FILE__, __LINE__, \
(const void*)(memory), size, count)
#endif
@@ -950,7 +1454,7 @@ void expect_not_memory(#function, #parameter, void *memory, size_t size);
void expect_not_memory_count(#function, #parameter, void *memory, size_t size, size_t count);
#else
#define expect_not_memory_count(function, parameter, memory, size, count) \
- _expect_not_memory(#function, #parameter, __FILE__, __LINE__, \
+ _expect_not_memory(cmocka_tostring(function), cmocka_tostring(parameter), __FILE__, __LINE__, \
(const void*)(memory), size, count)
#endif
@@ -1011,7 +1515,7 @@ void expect_any_always(#function, #parameter);
void expect_any_count(#function, #parameter, size_t count);
#else
#define expect_any_count(function, parameter, count) \
- _expect_any(#function, #parameter, __FILE__, __LINE__, count)
+ _expect_any(cmocka_tostring(function), cmocka_tostring(parameter), __FILE__, __LINE__, count)
#endif
#ifdef DOXYGEN
@@ -1029,7 +1533,7 @@ void check_expected(#parameter);
#else
#define check_expected(parameter) \
_check_expected(__func__, #parameter, __FILE__, __LINE__, \
- cast_to_largest_integral_type(parameter))
+ cast_int_to_cmocka_value(parameter))
#endif
#ifdef DOXYGEN
@@ -1047,7 +1551,7 @@ void check_expected_ptr(#parameter);
#else
#define check_expected_ptr(parameter) \
_check_expected(__func__, #parameter, __FILE__, __LINE__, \
- cast_ptr_to_largest_integral_type(parameter))
+ cast_ptr_to_cmocka_value(parameter))
#endif
/** @} */
@@ -1086,7 +1590,7 @@ void check_expected_ptr(#parameter);
*/
void assert_true(scalar expression);
#else
-#define assert_true(c) _assert_true(cast_to_largest_integral_type(c), #c, \
+#define assert_true(c) _assert_true(cast_to_uintmax_type(c), #c, \
__FILE__, __LINE__)
#endif
@@ -1104,8 +1608,8 @@ void assert_true(scalar expression);
*/
void assert_false(scalar expression);
#else
-#define assert_false(c) _assert_true(!(cast_to_largest_integral_type(c)), #c, \
- __FILE__, __LINE__)
+#define assert_false(c) _assert_false(cast_to_uintmax_type(c), #c, \
+ __FILE__, __LINE__)
#endif
#ifdef DOXYGEN
@@ -1121,12 +1625,11 @@ void assert_false(scalar expression);
*
* @param[in] error Pass errno here or 0.
*/
-void assert_return_code(int rc, int error);
+void assert_return_code(intmax_t rc, int32_t error);
#else
#define assert_return_code(rc, error) \
- _assert_return_code(cast_to_largest_integral_type(rc), \
- sizeof(rc), \
- cast_to_largest_integral_type(error), \
+ _assert_return_code((rc), \
+ (error), \
#rc, __FILE__, __LINE__)
#endif
@@ -1143,8 +1646,7 @@ void assert_return_code(int rc, int error);
*/
void assert_non_null(void *pointer);
#else
-#define assert_non_null(c) _assert_true(cast_ptr_to_largest_integral_type(c), #c, \
- __FILE__, __LINE__)
+#define assert_non_null(c) assert_ptr_not_equal((c), NULL)
#endif
#ifdef DOXYGEN
@@ -1160,8 +1662,7 @@ void assert_non_null(void *pointer);
*/
void assert_null(void *pointer);
#else
-#define assert_null(c) _assert_true(!(cast_ptr_to_largest_integral_type(c)), #c, \
-__FILE__, __LINE__)
+#define assert_null(c) assert_ptr_equal((c), NULL)
#endif
#ifdef DOXYGEN
@@ -1177,10 +1678,7 @@ __FILE__, __LINE__)
*/
void assert_ptr_equal(void *a, void *b);
#else
-#define assert_ptr_equal(a, b) \
- _assert_int_equal(cast_ptr_to_largest_integral_type(a), \
- cast_ptr_to_largest_integral_type(b), \
- __FILE__, __LINE__)
+#define assert_ptr_equal(a, b) _assert_ptr_equal((a), (b), __FILE__, __LINE__)
#endif
#ifdef DOXYGEN
@@ -1197,9 +1695,7 @@ void assert_ptr_equal(void *a, void *b);
void assert_ptr_not_equal(void *a, void *b);
#else
#define assert_ptr_not_equal(a, b) \
- _assert_int_not_equal(cast_ptr_to_largest_integral_type(a), \
- cast_ptr_to_largest_integral_type(b), \
- __FILE__, __LINE__)
+ _assert_ptr_not_equal((a), (b), __FILE__, __LINE__)
#endif
#ifdef DOXYGEN
@@ -1213,11 +1709,30 @@ void assert_ptr_not_equal(void *a, void *b);
*
* @param[in] b The integer to compare against the first one.
*/
-void assert_int_equal(int a, int b);
+void assert_int_equal(intmax_t a, intmax_t b);
#else
#define assert_int_equal(a, b) \
- _assert_int_equal(cast_to_largest_integral_type(a), \
- cast_to_largest_integral_type(b), \
+ _assert_int_equal(cast_to_intmax_type(a), \
+ cast_to_intmax_type(b), \
+ __FILE__, __LINE__)
+#endif
+
+#ifdef DOXYGEN
+/**
+ * @brief Assert that the two given unsinged integers are equal.
+ *
+ * The function prints an error message to standard error and terminates the
+ * test by calling fail() if the integers are not equal.
+ *
+ * @param[in] a The first unsigned integer to compare.
+ *
+ * @param[in] b The unsigned integer to compare against the first one.
+ */
+void assert_uint_equal(uintmax_t a, uintmax_t b);
+#else
+#define assert_uint_equal(a, b) \
+ _assert_uint_equal(cast_to_uintmax_type(a), \
+ cast_to_uintmax_type(b), \
__FILE__, __LINE__)
#endif
@@ -1234,16 +1749,35 @@ void assert_int_equal(int a, int b);
*
* @see assert_int_equal()
*/
-void assert_int_not_equal(int a, int b);
+void assert_int_not_equal(intmax_t a, intmax_t b);
#else
#define assert_int_not_equal(a, b) \
- _assert_int_not_equal(cast_to_largest_integral_type(a), \
- cast_to_largest_integral_type(b), \
+ _assert_int_not_equal(cast_to_intmax_type(a), \
+ cast_to_intmax_type(b), \
__FILE__, __LINE__)
#endif
#ifdef DOXYGEN
/**
+ * @brief Assert that the two given unsinged integers are not equal.
+ *
+ * The function prints an error message to standard error and terminates the
+ * test by calling fail() if the integers are not equal.
+ *
+ * @param[in] a The first unsigned integer to compare.
+ *
+ * @param[in] b The unsigned integer to compare against the first one.
+ */
+void assert_uint_not_equal(uintmax_t a, uintmax_t b);
+#else
+#define assert_uint_not_equal(a, b) \
+ _assert_uint_not_equal(cast_to_uintmax_type(a), \
+ cast_to_uintmax_type(b), \
+ __FILE__, __LINE__)
+#endif
+
+#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
@@ -1324,7 +1858,7 @@ void assert_double_equal(double a, double b, double epsilon);
void assert_double_not_equal(double a, double b, double epsilon);
#else
#define assert_double_not_equal(a, b, epsilon) \
- _assert_double_not_equal((float)a, \
+ _assert_double_not_equal((double)a, \
(double)b, \
(double)epsilon, \
__FILE__, __LINE__)
@@ -1345,8 +1879,7 @@ void assert_double_not_equal(double a, double b, double epsilon);
void assert_string_equal(const char *a, const char *b);
#else
#define assert_string_equal(a, b) \
- _assert_string_equal((const char*)(a), (const char*)(b), __FILE__, \
- __LINE__)
+ _assert_string_equal((a), (b), __FILE__, __LINE__)
#endif
#ifdef DOXYGEN
@@ -1363,8 +1896,7 @@ void assert_string_equal(const char *a, const char *b);
void assert_string_not_equal(const char *a, const char *b);
#else
#define assert_string_not_equal(a, b) \
- _assert_string_not_equal((const char*)(a), (const char*)(b), __FILE__, \
- __LINE__)
+ _assert_string_not_equal((a), (b), __FILE__, __LINE__)
#endif
#ifdef DOXYGEN
@@ -1413,8 +1945,8 @@ void assert_memory_not_equal(const void *a, const void *b, size_t size);
#ifdef DOXYGEN
/**
- * @brief Assert that the specified value is not smaller than the minimum
- * and and not greater than the maximum.
+ * @brief Assert that the specified integer value is not smaller than the
+ * minimum and and not greater than the maximum.
*
* The function prints an error message to standard error and terminates the
* test by calling fail() if value is not in range.
@@ -1425,13 +1957,36 @@ void assert_memory_not_equal(const void *a, const void *b, size_t size);
*
* @param[in] maximum The maximum value allowed.
*/
-void assert_in_range(LargestIntegralType value, LargestIntegralType minimum, LargestIntegralType maximum);
+void assert_int_in_range(intmax_t value, intmax_t minimum, intmax_t maximum);
#else
-#define assert_in_range(value, minimum, maximum) \
- _assert_in_range( \
- cast_to_largest_integral_type(value), \
- cast_to_largest_integral_type(minimum), \
- cast_to_largest_integral_type(maximum), __FILE__, __LINE__)
+#define assert_int_in_range(value, minimum, maximum) \
+ _assert_int_in_range( \
+ cast_to_intmax_type(value), \
+ cast_to_intmax_type(minimum), \
+ cast_to_intmax_type(maximum), __FILE__, __LINE__)
+#endif
+
+#ifdef DOXYGEN
+/**
+ * @brief Assert that the specified unsigned integer value is not smaller than
+ * the minimum and and not greater than the maximum.
+ *
+ * The function prints an error message to standard error and terminates the
+ * test by calling fail() if value is not in range.
+ *
+ * @param[in] value The value to check.
+ *
+ * @param[in] minimum The minimum value allowed.
+ *
+ * @param[in] maximum The maximum value allowed.
+ */
+void assert_uint_in_range(uintmax_t value, uintmax_t minimum, uintmax_t maximum);
+#else
+#define assert_uint_in_range(value, minimum, maximum) \
+ _assert_uint_in_range( \
+ cast_to_intmax_type(value), \
+ cast_to_intmax_type(minimum), \
+ cast_to_intmax_type(maximum), __FILE__, __LINE__)
#endif
#ifdef DOXYGEN
@@ -1442,24 +1997,114 @@ void assert_in_range(LargestIntegralType value, LargestIntegralType minimum, Lar
* The function prints an error message to standard error and terminates the
* test by calling fail() if value is in range.
*
+ * The function prints an error message to standard error and terminates the
+ * test by calling fail() if value is not in range.
+ *
* @param[in] value The value to check.
*
- * @param[in] minimum The minimum value to compare.
+ * @param[in] minimum The minimum value allowed.
*
- * @param[in] maximum The maximum value to compare.
+ * @param[in] maximum The maximum value allowed.
*/
-void assert_not_in_range(LargestIntegralType value, LargestIntegralType minimum, LargestIntegralType maximum);
+void assert_int_not_in_range(intmax_t value,
+ intmax_t minimum,
+ intmax_t maximum);
+#else
+#define assert_int_not_in_range(value, minimum, maximum) \
+ _assert_int_not_in_range(cast_to_intmax_type(value), \
+ cast_to_intmax_type(minimum), \
+ cast_to_intmax_type(maximum), \
+ __FILE__, \
+ __LINE__)
+#endif
+
+#ifdef DOXYGEN
+/**
+ * @brief Assert that the specified value is smaller than the minimum or
+ * greater than the maximum.
+ *
+ * The function prints an error message to standard error and terminates the
+ * test by calling fail() if value is in range.
+ *
+ * The function prints an error message to standard error and terminates the
+ * test by calling fail() if value is not in range.
+ *
+ * @param[in] value The value to check.
+ *
+ * @param[in] minimum The minimum value allowed.
+ *
+ * @param[in] maximum The maximum value allowed.
+ */
+void assert_uint_not_in_range(uintmax_t value,
+ uintmax_t minimum,
+ uintmax_t maximum);
+#else
+#define assert_uint_not_in_range(value, minimum, maximum) \
+ _assert_uint_not_in_range(cast_to_uintmax_type(value), \
+ cast_to_uintmax_type(minimum), \
+ cast_to_uintmax_type(maximum), \
+ __FILE__, \
+ __LINE__)
+#endif
+
+#ifdef DOXYGEN
+/**
+ * @deprecated Use assert_int_in_range() and assert_uint_in_range()
+ */
+void assert_in_range(uintmax_t value, uintmax_t minimum, uintmax_t maximum);
+#else
+#define assert_in_range(value, minimum, maximum) \
+ _assert_uint_in_range( \
+ cast_to_uintmax_type(value), \
+ cast_to_uintmax_type(minimum), \
+ cast_to_uintmax_type(maximum), __FILE__, __LINE__)
+#endif
+
+#ifdef DOXYGEN
+/**
+ * @deprecated Use assert_int_not_in_range() or assert_uint_not_in_range()
+ */
+void assert_not_in_range(uintmax_t value, uintmax_t minimum, uintmax_t maximum);
#else
#define assert_not_in_range(value, minimum, maximum) \
- _assert_not_in_range( \
- cast_to_largest_integral_type(value), \
- cast_to_largest_integral_type(minimum), \
- cast_to_largest_integral_type(maximum), __FILE__, __LINE__)
+ _assert_uint_not_in_range( \
+ cast_to_uintmax_type(value), \
+ cast_to_uintmax_type(minimum), \
+ cast_to_uintmax_type(maximum), __FILE__, __LINE__)
+#endif
+
+#ifdef DOXYGEN
+/**
+ * @deprecated Use assert_int_in_set() or assert_uint_in_set()
+ */
+void assert_in_set(uintmax_t value, uintmax_t values[], size_t count);
+#else
+#define assert_in_set(value, values, number_of_values) \
+ _assert_uint_in_set(value, values, number_of_values, __FILE__, __LINE__)
+#endif
+
+#ifdef DOXYGEN
+/**
+ * @brief Assert that the specified value is not within a set.
+ *
+ * The function prints an error message to standard error and terminates the
+ * test by calling fail() if value is within a set.
+ *
+ * @param[in] value The value to look up
+ *
+ * @param[in] values[] The array to check for the value.
+ *
+ * @param[in] count The size of the values array.
+ */
+void assert_not_in_set(uintmax_t value, uintmax_t values[], size_t count);
+#else
+#define assert_not_in_set(value, values, number_of_values) \
+ _assert_not_in_set(value, values, number_of_values, __FILE__, __LINE__)
#endif
#ifdef DOXYGEN
/**
- * @brief Assert that the specified value is within a set.
+ * @brief Assert that the specified integer value is within a set.
*
* The function prints an error message to standard error and terminates the
* test by calling fail() if value is not within a set.
@@ -1470,10 +2115,16 @@ void assert_not_in_range(LargestIntegralType value, LargestIntegralType minimum,
*
* @param[in] count The size of the values array.
*/
-void assert_in_set(LargestIntegralType value, LargestIntegralType values[], size_t count);
+void assert_int_in_set(intmax_t value, intmax_t values[], size_t count);
#else
-#define assert_in_set(value, values, number_of_values) \
- _assert_in_set(value, values, number_of_values, __FILE__, __LINE__)
+#define assert_int_in_set(value, values, number_of_values) \
+ if (number_of_values > 0) { \
+ intmax_t _cmocka_set[number_of_values]; \
+ for (size_t _i = 0; _i < number_of_values; _i++) { \
+ _cmocka_set[_i] = values[_i]; \
+ } \
+ _assert_int_in_set(value, _cmocka_set, number_of_values, __FILE__, __LINE__); \
+ }
#endif
#ifdef DOXYGEN
@@ -1489,10 +2140,66 @@ void assert_in_set(LargestIntegralType value, LargestIntegralType values[], size
*
* @param[in] count The size of the values array.
*/
-void assert_not_in_set(LargestIntegralType value, LargestIntegralType values[], size_t count);
+void assert_int_not_in_set(intmax_t value, intmax_t values[], size_t count);
#else
-#define assert_not_in_set(value, values, number_of_values) \
- _assert_not_in_set(value, values, number_of_values, __FILE__, __LINE__)
+#define assert_int_not_in_set(value, values, number_of_values) \
+ if (number_of_values > 0) { \
+ intmax_t _cmocka_set[number_of_values]; \
+ for (size_t _i = 0; _i < number_of_values; _i++) { \
+ _cmocka_set[_i] = values[_i]; \
+ } \
+ _assert_int_not_in_set(value, _cmocka_set, number_of_values, __FILE__, __LINE__); \
+ }
+#endif
+
+#ifdef DOXYGEN
+/**
+ * @brief Assert that the specified unsigned integer value is within a set.
+ *
+ * The function prints an error message to standard error and terminates the
+ * test by calling fail() if value is not within a set.
+ *
+ * @param[in] value The value to look up
+ *
+ * @param[in] values[] The array to check for the value.
+ *
+ * @param[in] count The size of the values array.
+ */
+void assert_uint_in_set(uintmax_t value, uintmax_t values[], size_t count);
+#else
+#define assert_uint_in_set(value, values, number_of_values) \
+ if (number_of_values > 0) { \
+ uintmax_t _cmocka_set[number_of_values]; \
+ for (size_t _i = 0; _i < number_of_values; _i++) { \
+ _cmocka_set[_i] = values[_i]; \
+ } \
+ _assert_uint_in_set(value, _cmocka_set, number_of_values, __FILE__, __LINE__); \
+ }
+#endif
+
+#ifdef DOXYGEN
+/**
+ * @brief Assert that the specified unsigned integer value is not within a set.
+ *
+ * The function prints an error message to standard error and terminates the
+ * test by calling fail() if value is within a set.
+ *
+ * @param[in] value The value to look up
+ *
+ * @param[in] values[] The array to check for the value.
+ *
+ * @param[in] count The size of the values array.
+ */
+void assert_uint_not_in_set(uintmax_t value, uintmax_t values[], size_t count);
+#else
+#define assert_uint_not_in_set(value, values, number_of_values) \
+ if (number_of_values > 0) { \
+ uintmax_t _cmocka_set[number_of_values]; \
+ for (size_t _i = 0; _i < number_of_values; _i++) { \
+ _cmocka_set[_i] = values[_i]; \
+ } \
+ _assert_uint_not_in_set(value, _cmocka_set, number_of_values, __FILE__, __LINE__); \
+ }
#endif
/** @} */
@@ -1521,7 +2228,10 @@ void assert_not_in_set(LargestIntegralType value, LargestIntegralType values[],
* created (e.g. expect_function_call()) than consumed with function_called().
* There are provisions such as ignore_function_calls() which allow this
* restriction to be circumvented in tests where mock calls for the code under
- * test are not the focus of the test.
+ * test are not the focus of the test. function_called() must be called from
+ * the same thread as expect_function_call(), and that thread must have been
+ * initialized for use by cmocka (see also the [Threading section of the main
+ * documentation page](index.html#main-threads)).
*
* The following example illustrates how a unit test instructs cmocka
* to expect a function_called() from a particular mock,
@@ -1581,7 +2291,7 @@ void function_called(void);
void expect_function_calls(#function, const int times);
#else
#define expect_function_calls(function, times) \
- _expect_function_call(#function, __FILE__, __LINE__, times)
+ _expect_function_call(cmocka_tostring(function), __FILE__, __LINE__, times)
#endif
#ifdef DOXYGEN
@@ -1596,7 +2306,7 @@ void expect_function_calls(#function, const int times);
void expect_function_call(#function);
#else
#define expect_function_call(function) \
- _expect_function_call(#function, __FILE__, __LINE__, 1)
+ _expect_function_call(cmocka_tostring(function), __FILE__, __LINE__, 1)
#endif
#ifdef DOXYGEN
@@ -1610,7 +2320,7 @@ void expect_function_call(#function);
void expect_function_call_any(#function);
#else
#define expect_function_call_any(function) \
- _expect_function_call(#function, __FILE__, __LINE__, -1)
+ _expect_function_call(cmocka_tostring(function), __FILE__, __LINE__, -1)
#endif
#ifdef DOXYGEN
@@ -1624,7 +2334,7 @@ void expect_function_call_any(#function);
void ignore_function_calls(#function);
#else
#define ignore_function_calls(function) \
- _expect_function_call(#function, __FILE__, __LINE__, -2)
+ _expect_function_call(cmocka_tostring(function), __FILE__, __LINE__, -2)
#endif
/** @} */
@@ -1666,7 +2376,7 @@ void fail(void);
#ifdef DOXYGEN
/**
- * @brief Forces the test to not be executed, but marked as skipped
+ * @brief Forces the test to not be executed, but marked as skipped.
*/
void skip(void);
#else
@@ -1675,6 +2385,20 @@ void skip(void);
#ifdef DOXYGEN
/**
+ * @brief Forces the test to be stopped immediately.
+ *
+ * Call stop() to stop a running test.
+ * The test is considered passed if there are no leftover values, otherwise a test failure
+ * is signaled.
+ * Calling stop() is especially useful in mocked functions that do not return, e.g reset the CPU.
+ */
+void stop(void);
+#else
+#define stop() _stop()
+#endif
+
+#ifdef DOXYGEN
+/**
* @brief Forces the test to fail immediately and quit, printing the reason.
*
* @code
@@ -1691,36 +2415,11 @@ void skip(void);
void fail_msg(const char *msg, ...);
#else
#define fail_msg(msg, ...) do { \
- print_error("ERROR: " msg "\n", ##__VA_ARGS__); \
+ cmocka_print_error("ERROR: " msg "\n", ##__VA_ARGS__); \
fail(); \
} while (0)
#endif
-#ifdef DOXYGEN
-/**
- * @brief Generic method to run a single test.
- *
- * @deprecated This function was deprecated in favor of cmocka_run_group_tests
- *
- * @param[in] #function The function to test.
- *
- * @return 0 on success, 1 if an error occured.
- *
- * @code
- * // A test case that does nothing and succeeds.
- * void null_test_success(void **state) {
- * }
- *
- * int main(void) {
- * return run_test(null_test_success);
- * }
- * @endcode
- */
-int run_test(#function);
-#else
-#define run_test(f) _run_test(#f, f, NULL, UNIT_TEST_FUNCTION_TYPE_TEST, NULL)
-#endif
-
static inline void _unit_test_dummy(void **state) {
(void)state;
}
@@ -1815,9 +2514,6 @@ static inline void _unit_test_dummy(void **state) {
*/
#define cmocka_unit_test_prestate_setup_teardown(f, setup, teardown, state) { #f, f, setup, teardown, state }
-#define run_tests(tests) _run_tests(tests, sizeof(tests) / sizeof((tests)[0]))
-#define run_group_tests(tests) _run_group_tests(tests, sizeof(tests) / sizeof((tests)[0]))
-
#ifdef DOXYGEN
/**
* @brief Run tests specified by an array of CMUnitTest structures.
@@ -2144,9 +2840,8 @@ void expect_assert_failure(function fn_call);
#else
#define expect_assert_failure(function_call) \
{ \
- const int result = setjmp(global_expect_assert_env); \
global_expecting_assert = 1; \
- if (result) { \
+ if (setjmp(global_expect_assert_env) != 0) { \
print_message("Expected assertion %s occurred\n", \
global_last_failed_assert); \
global_expecting_assert = 0; \
@@ -2161,12 +2856,41 @@ void expect_assert_failure(function fn_call);
/** @} */
+/**
+ * CMocka value data type.
+ *
+ * Allows storing multiple types of values in CMocka functions without using
+ * undefined behavior.
+ */
+typedef union {
+ /** Holds signed integral types */
+ intmax_t int_val;
+ /** Holds integral types */
+ uintmax_t uint_val;
+ /** Holds real/floating-pointing types*/
+ double real_val; // TODO: Should we use `long double` instead
+ /** Holds pointer data */
+ const void *ptr;
+ // The following aren't used by CMocka currently, but are added to avoid
+ // breaking ABI compatibility in the future
+ /** Holds function pointer data */
+ void *(*func)(void);
+} CMockaValueData;
+
/* Function prototype for setup, test and teardown functions. */
typedef void (*UnitTestFunction)(void **state);
/* Function that determines whether a function parameter value is correct. */
-typedef int (*CheckParameterValue)(const LargestIntegralType value,
- const LargestIntegralType check_value_data);
+typedef int (*CheckParameterValue)(const CMockaValueData value,
+ const CMockaValueData check_value_data);
+
+/* Function that determines whether a function parameter value is correct. */
+typedef int (*CheckIntParameterValue)(const intmax_t value,
+ const intmax_t check_value_data);
+
+/* Function that determines whether a function parameter value is correct. */
+typedef int (*CheckUintParameterValue)(const uintmax_t value,
+ const uintmax_t check_value_data);
/* Type of the unit test function. */
typedef enum UnitTestFunctionType {
@@ -2220,17 +2944,19 @@ typedef struct CheckParameterEvent {
SourceLocation location;
const char *parameter_name;
CheckParameterValue check_value;
- LargestIntegralType check_value_data;
+ CMockaValueData check_value_data;
} CheckParameterEvent;
/* Used by expect_assert_failure() and mock_assert(). */
-extern int global_expecting_assert;
-extern jmp_buf global_expect_assert_env;
-extern const char * global_last_failed_assert;
+CMOCKA_DLLEXTERN extern int global_expecting_assert;
+CMOCKA_DLLEXTERN extern jmp_buf global_expect_assert_env;
+CMOCKA_DLLEXTERN extern const char * global_last_failed_assert;
/* Retrieves a value for the given function, as set by "will_return". */
-LargestIntegralType _mock(const char * const function, const char* const file,
- const int line);
+CMockaValueData _mock(const char *const function,
+ const char *const file,
+ const int line,
+ const char *name);
void _expect_function_call(
const char * const function_name,
@@ -2245,36 +2971,47 @@ void _expect_check(
const char* const function, const char* const parameter,
const char* const file, const int line,
const CheckParameterValue check_function,
- const LargestIntegralType check_data, CheckParameterEvent * const event,
+ const CMockaValueData check_data, CheckParameterEvent * const event,
const int count);
-void _expect_in_set(
- const char* const function, const char* const parameter,
- const char* const file, const int line, const LargestIntegralType values[],
- const size_t number_of_values, const int count);
+void _expect_int_in_set(const char *const function,
+ const char *const parameter,
+ const char *const file,
+ const size_t line,
+ const intmax_t values[],
+ const size_t number_of_values,
+ const size_t count);
+void _expect_uint_in_set(const char *const function,
+ const char *const parameter,
+ const char *const file,
+ const size_t line,
+ const uintmax_t values[],
+ const size_t number_of_values,
+ const size_t count);
+
void _expect_not_in_set(
const char* const function, const char* const parameter,
- const char* const file, const int line, const LargestIntegralType values[],
+ const char* const file, const int line, const uintmax_t values[],
const size_t number_of_values, const int count);
void _expect_in_range(
const char* const function, const char* const parameter,
const char* const file, const int line,
- const LargestIntegralType minimum,
- const LargestIntegralType maximum, const int count);
+ const uintmax_t minimum,
+ const uintmax_t maximum, const int count);
void _expect_not_in_range(
const char* const function, const char* const parameter,
const char* const file, const int line,
- const LargestIntegralType minimum,
- const LargestIntegralType maximum, const int count);
+ const uintmax_t minimum,
+ const uintmax_t maximum, const int count);
void _expect_value(
const char* const function, const char* const parameter,
- const char* const file, const int line, const LargestIntegralType value,
+ const char* const file, const int line, const uintmax_t value,
const int count);
void _expect_not_value(
const char* const function, const char* const parameter,
- const char* const file, const int line, const LargestIntegralType value,
+ const char* const file, const int line, const uintmax_t value,
const int count);
void _expect_string(
@@ -2301,17 +3038,22 @@ void _expect_any(
void _check_expected(
const char * const function_name, const char * const parameter_name,
- const char* file, const int line, const LargestIntegralType value);
+ const char* file, const int line, const CMockaValueData value);
-void _will_return(const char * const function_name, const char * const file,
- const int line, const LargestIntegralType value,
+void _will_return(const char *const function_name,
+ const char *const file,
+ const int line,
+ const char *name,
+ const CMockaValueData value,
const int count);
-void _assert_true(const LargestIntegralType result,
+void _assert_true(const uintmax_t result,
const char* const expression,
const char * const file, const int line);
-void _assert_return_code(const LargestIntegralType result,
- size_t rlen,
- const LargestIntegralType error,
+void _assert_false(const uintmax_t result,
+ const char * const expression,
+ const char * const file, const int line);
+void _assert_return_code(const intmax_t result,
+ const int32_t error,
const char * const expression,
const char * const file,
const int line);
@@ -2327,12 +3069,32 @@ void _assert_double_equal(const double a, const double n,
void _assert_double_not_equal(const double a, const double n,
const double 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);
-void _assert_int_not_equal(
- const LargestIntegralType a, const LargestIntegralType b,
- const char * const file, const int line);
+void _assert_int_equal(const intmax_t a,
+ const intmax_t b,
+ const char * const file,
+ const int line);
+void _assert_int_not_equal(const intmax_t a,
+ const intmax_t b,
+ const char * const file,
+ const int line);
+void _assert_uint_equal(const uintmax_t a,
+ const uintmax_t b,
+ const char * const file,
+ const int line);
+void _assert_uint_not_equal(const uintmax_t a,
+ const uintmax_t b,
+ const char * const file,
+ const int line);
+CMOCKA_NO_ACCESS_ATTRIBUTE
+void _assert_ptr_equal(const void *a,
+ const void *b,
+ const char *const file,
+ const int line);
+CMOCKA_NO_ACCESS_ATTRIBUTE
+void _assert_ptr_not_equal(const void *a,
+ const void *b,
+ const char *const file,
+ const int line);
void _assert_string_equal(const char * const a, const char * const b,
const char * const file, const int line);
void _assert_string_not_equal(const char * const a, const char * const b,
@@ -2343,18 +3105,49 @@ void _assert_memory_equal(const void * const a, const void * const b,
void _assert_memory_not_equal(const void * const a, const void * const b,
const size_t size, const char* const file,
const int line);
-void _assert_in_range(
- const LargestIntegralType value, const LargestIntegralType minimum,
- const LargestIntegralType maximum, const char* const file, const int line);
-void _assert_not_in_range(
- const LargestIntegralType value, const LargestIntegralType minimum,
- const LargestIntegralType maximum, const char* const file, const int line);
-void _assert_in_set(
- const LargestIntegralType value, const LargestIntegralType values[],
- const size_t number_of_values, const char* const file, const int line);
+void _assert_int_in_range(const intmax_t value,
+ const intmax_t minimum,
+ const intmax_t maximum,
+ const char* const file,
+ const int line);
+void _assert_int_not_in_range(const intmax_t value,
+ const intmax_t minimum,
+ const intmax_t maximum,
+ const char *const file,
+ const int line);
+void _assert_uint_in_range(const uintmax_t value,
+ const uintmax_t minimum,
+ const uintmax_t maximum,
+ const char* const file,
+ const int line);
+void _assert_uint_not_in_range(const uintmax_t value,
+ const uintmax_t minimum,
+ const uintmax_t maximum,
+ const char* const file,
+ const int line);
void _assert_not_in_set(
- const LargestIntegralType value, const LargestIntegralType values[],
+ const uintmax_t value, const uintmax_t values[],
const size_t number_of_values, const char* const file, const int line);
+void _assert_int_in_set(const intmax_t value,
+ const intmax_t values[],
+ const size_t number_of_values,
+ const char *const file,
+ const int line);
+void _assert_int_not_in_set(const intmax_t value,
+ const intmax_t values[],
+ const size_t number_of_values,
+ const char *const file,
+ const int line);
+void _assert_uint_in_set(const uintmax_t value,
+ const uintmax_t values[],
+ const size_t number_of_values,
+ const char *const file,
+ const int line);
+void _assert_uint_not_in_set(const uintmax_t value,
+ const uintmax_t values[],
+ const size_t number_of_values,
+ const char *const file,
+ const int line);
void* _test_malloc(const size_t size, const char* file, const int line);
void* _test_realloc(void *ptr, const size_t size, const char* file, const int line);
@@ -2362,18 +3155,11 @@ void* _test_calloc(const size_t number_of_elements, const size_t size,
const char* file, const int line);
void _test_free(void* const ptr, const char* file, const int line);
-void _fail(const char * const file, const int line);
+CMOCKA_NORETURN void _fail(const char * const file, const int line);
-void _skip(const char * const file, const int line);
+CMOCKA_NORETURN void _skip(const char * const file, const int line);
-int _run_test(
- const char * const function_name, const UnitTestFunction Function,
- void ** const volatile state, const UnitTestFunctionType function_type,
- const void* const heap_check_point);
-CMOCKA_DEPRECATED int _run_tests(const UnitTest * const tests,
- const size_t number_of_tests);
-CMOCKA_DEPRECATED int _run_group_tests(const UnitTest * const tests,
- const size_t number_of_tests);
+CMOCKA_NORETURN void _stop(void);
/* Test runner */
int _cmocka_run_group_tests(const char *group_name,
@@ -2389,24 +3175,50 @@ void vprint_message(const char* const format, va_list args) CMOCKA_PRINTF_ATTRIB
void vprint_error(const char* const format, va_list args) CMOCKA_PRINTF_ATTRIBUTE(1, 0);
enum cm_message_output {
- CM_OUTPUT_STDOUT,
- CM_OUTPUT_SUBUNIT,
- CM_OUTPUT_TAP,
- CM_OUTPUT_XML,
+ CM_OUTPUT_STANDARD = 1,
+ CM_OUTPUT_STDOUT = 1, /* API compatiblity */
+ CM_OUTPUT_SUBUNIT = 2,
+ CM_OUTPUT_TAP = 4,
+ CM_OUTPUT_XML = 8,
};
+#ifdef DOXYGEN
+/**
+ * @deprecated Use cmocka_print_error()
+ */
+void cm_print_error(const char* const format, ...);
+#else
+#define cm_print_error(format, ...) \
+ cmocka_print_error(format, ##__VA_ARGS__)
+#endif
+
+/**
+ * @brief Print error message using the cmocka output format.
+ *
+ * This prints an error message using the message output defined by the
+ * environment variable CMOCKA_MESSAGE_OUTPUT or cmocka_set_message_output().
+ *
+ * @param format The formant string fprintf(3) uses.
+
+ * @param ... The parameters used to fill format.
+ */
+void cmocka_print_error(const char* const format, ...) CMOCKA_PRINTF_ATTRIBUTE(1, 2);
+
/**
* @brief Function to set the output format for a test.
*
- * The ouput format for the test can either be set globally using this
- * function or overriden with environment variable CMOCKA_MESSAGE_OUTPUT.
+ * The output format(s) for the test can either be set globally using this
+ * function or overwritten with environment variable CMOCKA_MESSAGE_OUTPUT.
*
- * The environment variable can be set to either STDOUT, SUBUNIT, TAP or XML.
+ * The environment variable can be set to STANDARD, SUBUNIT, TAP or XML.
+ * Multiple outputs separated with comma are permitted.
+ * (e.g. export CMOCKA_MESSAGE_OUTPUT=STANDARD,XML)
*
- * @param[in] output The output format to use for the test.
+ * @param[in] output The output format from cm_message_output to use for the
+ * test. For multiple outputs OR options together.
*
*/
-void cmocka_set_message_output(enum cm_message_output output);
+void cmocka_set_message_output(uint32_t output);
/**
@@ -2414,7 +3226,7 @@ void cmocka_set_message_output(enum cm_message_output output);
*
* 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
+ * zero or more characters, or '?', a wildcard that matches exactly one
* character.
*
* @param[in] pattern The pattern to match, e.g. "test_wurst*"
@@ -2426,7 +3238,7 @@ void cmocka_set_test_filter(const char *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
+ * zero or more characters, or '?', a wildcard that matches exactly one
* character.
*
* @param[in] pattern The pattern to match, e.g. "test_wurst*"
diff --git a/include/cmocka_private.h b/include/cmocka_private.h
index d20d841..5b1bea9 100644
--- a/include/cmocka_private.h
+++ b/include/cmocka_private.h
@@ -28,6 +28,7 @@
# ifdef _MSC_VER
# include <stdio.h> /* _snprintf */
+# include <string.h> /* strtok_s */
# undef inline
# define inline __inline
@@ -38,6 +39,8 @@
# define strcasecmp _stricmp
# define strncasecmp _strnicmp
+# define strtok_r strtok_s
+# define strdup _strdup
# if defined(HAVE__SNPRINTF_S)
# undef snprintf
@@ -68,12 +71,6 @@
# endif /* HAVE__VSNPRINTF_S */
# endif /* _MSC_VER */
-/*
- * Backwards compatibility with headers shipped with Visual Studio 2005 and
- * earlier.
- */
-WINBASEAPI BOOL WINAPI IsDebuggerPresent(VOID);
-
#ifndef PRIdS
# define PRIdS "Id"
#endif
diff --git a/include/cmocka_version.h.cmake b/include/cmocka_version.h.cmake
new file mode 100644
index 0000000..5cdf2b9
--- /dev/null
+++ b/include/cmocka_version.h.cmake
@@ -0,0 +1,37 @@
+/*
+ * Copyright 2022 Andreas Schneider <asn@cryptomilk.org>
+ *
+ * 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.
+ */
+
+#ifndef _CMOCKA_VERSION_H
+#define _CMOCKA_VERSION_H
+
+/* cmocka version macros */
+#define CM_VERSION_INT(a, b, c) ((a) << 16 | (b) << 8 | (c))
+#define CM_VERSION_DOT(a, b, c) a ##.## b ##.## c
+#define CM_VERSION(a, b, c) CMOCKA_VERSION_DOT(a, b, c)
+
+/* cmocka version */
+#define CMOCKA_VERSION_MAJOR @cmocka_VERSION_MAJOR@
+#define CMOCKA_VERSION_MINOR @cmocka_VERSION_MINOR@
+#define CMOCKA_VERSION_MICRO @cmocka_VERSION_PATCH@
+
+#define CMOCKA_VERSION_INT CM_VERSION_INT(CMOCKA_VERSION_MAJOR, \
+ CMOCKA_VERSION_MINOR, \
+ CMOCKA_VERSION_MICRO)
+#define CMOCKA_VERSION CM_VERSION(CMOCKA_VERSION_MAJOR, \
+ CMOCKA_VERSION_MINOR, \
+ CMOCKA_VERSION_MICRO)
+
+#endif /* _CMOCKA_VERSION_H */
diff --git a/include/cmockery/cmockery.h b/include/cmockery/cmockery.h
deleted file mode 100644
index a252a5f..0000000
--- a/include/cmockery/cmockery.h
+++ /dev/null
@@ -1 +0,0 @@
-#include <cmocka.h>
diff --git a/include/cmockery/pbc.h b/include/cmockery/pbc.h
deleted file mode 100644
index 50bac87..0000000
--- a/include/cmockery/pbc.h
+++ /dev/null
@@ -1 +0,0 @@
-#include <cmocka_pbc.h>
diff --git a/meson.build b/meson.build
index 28fdc08..33be57c 100644
--- a/meson.build
+++ b/meson.build
@@ -1,46 +1,64 @@
-project('cmocka', 'c', version: '1.1.5', license: 'Apache-2.0')
+project('cmocka', 'c',
+ version : '1.1.5',
+ license : 'Apache-2.0')
cc = meson.get_compiler('c')
conf = configuration_data()
-foreach hdr: ['assert.h', 'inttypes.h', 'io.h', 'malloc.h', 'memory.h', 'setjmp.h', 'signal.h', 'stdarg.h', 'stddef.h', 'stdint.h', 'stdio.h', 'stdlib.h', 'string.h', 'strings.h', 'sys/stat.h', 'sys/types.h', 'time.h', 'unistd.h']
- conf.set('HAVE_@0@'.format(hdr.underscorify().to_upper()), cc.has_header(hdr))
+foreach hdr : ['assert.h', 'inttypes.h', 'io.h', 'malloc.h', 'memory.h',
+ 'setjmp.h', 'signal.h', 'stdarg.h', 'stddef.h', 'stdint.h',
+ 'stdio.h', 'stdlib.h', 'string.h', 'strings.h', 'sys/stat.h',
+ 'sys/types.h', 'time.h', 'unistd.h']
+ conf.set('HAVE_@0@'.format(hdr.underscorify().to_upper()), cc.has_header(hdr))
endforeach
code = '''#include <time.h>
int a = sizeof(struct timespec);
'''
-conf.set('HAVE_STRUCT_TIMESPEC', cc.compiles(code, name: 'struct timepec'))
+conf.set('HAVE_STRUCT_TIMESPEC', cc.compiles(code, name : 'struct timepec'))
-foreach func: ['calloc', 'exit', 'fprintf', 'free', 'longjmp', 'siglongjmp', 'malloc', 'memcpy', 'memset', 'printf', 'setjmp', 'signal', 'strsignal', 'strcmp', 'clock_gettime']
- conf.set('HAVE_@0@'.format(func.to_upper()), cc.has_function(func))
+foreach func: ['calloc', 'exit', 'fprintf', 'free', 'longjmp', 'siglongjmp',
+ 'malloc', 'memcpy', 'memset', 'printf', 'setjmp', 'signal',
+ 'strsignal', 'strcmp', 'clock_gettime']
+ conf.set('HAVE_@0@'.format(func.to_upper()), cc.has_function(func))
endforeach
+install_lib = true
+if meson.is_subproject()
+ install_lib = false
+endif
+
code = '__thread int tls;'
-conf.set('HAVE_GCC_THREAD_LOCAL_STORAGE', cc.compiles(code, name: '__thread'))
+conf.set('HAVE_GCC_THREAD_LOCAL_STORAGE', cc.compiles(code, name : '__thread'))
code = '''#include <time.h>
clockid_t t = CLOCK_REALTIME;'''
-conf.set('HAVE_CLOCK_REALTIME', cc.compiles(code, name: 'CLOCK_REALTIME'))
+conf.set('HAVE_CLOCK_REALTIME', cc.compiles(code, name : 'CLOCK_REALTIME'))
-configure_file(output: 'config.h', configuration : conf)
+configure_file(output : 'config.h', configuration : conf)
cmocka_includes = [include_directories('.'), include_directories('include')]
-libcmocka = library('cmocka',
- 'src/cmocka.c',
- c_args: ['-DHAVE_CONFIG_H'],
- include_directories: cmocka_includes,
- install: true,
- dependencies: [cc.find_library('rt', required: false)])
-install_headers('include/cmocka.h')
-
-pkgconfig = import('pkgconfig')
-pkgconfig.generate(libraries : [libcmocka],
- version : '1.1.5',
- name : 'cmocka',
- filebase : 'cmocka',
- description : 'The cmocka unit testing library')
+libcmocka = library('cmocka', 'src/cmocka.c',
+ c_args : ['-DHAVE_CONFIG_H'],
+ include_directories : cmocka_includes,
+ install : install_lib,
+ override_options : ['c_std=gnu99'],
+ dependencies : [cc.find_library('rt', required : false)])
+
+if meson.is_subproject()
+ cmocka_dep = declare_dependency(include_directories : cmocka_includes,
+ link_with : libcmocka)
+else
+ install_headers('include/cmocka.h')
+
+ pkgconfig = import('pkgconfig')
+ pkgconfig.generate(libraries : [libcmocka],
+ version : meson.project_version(),
+ name : 'cmocka',
+ filebase : 'cmocka',
+ description : 'The cmocka unit testing library')
+endif
if get_option('unit_testing')
subdir('tests')
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 155c347..fac4365 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -12,13 +12,6 @@ set(cmocka_SRCS
cmocka.c
)
-if (WIN32)
- set(cmocka_SRCS
- ${cmocka_SRCS}
- cmocka.def
- )
-endif (WIN32)
-
add_library(cmocka ${cmocka_SRCS})
target_include_directories(cmocka
@@ -33,6 +26,16 @@ target_compile_options(cmocka
PRIVATE
${DEFAULT_C_COMPILE_FLAGS}
-DHAVE_CONFIG_H)
+
+target_compile_definitions(cmocka
+ PRIVATE
+ _GNU_SOURCE
+ _XOPEN_SOURCE=700
+ PUBLIC
+ # hides a warning on Windows when using static lib
+ "$<$<NOT:$<BOOL:${BUILD_SHARED_LIBS}>>:CMOCKA_STATIC>"
+ )
+
if (CMOCKA_PLATFORM_INCLUDE)
target_compile_options(cmocka
PRIVATE
@@ -40,41 +43,29 @@ if (CMOCKA_PLATFORM_INCLUDE)
endif()
target_link_libraries(cmocka PRIVATE ${CMOCKA_LINK_LIBRARIES})
-set_property(TARGET
- cmocka
- PROPERTY
- DEFINE_SYMBOL
- CMOCKA_EXPORTS
+set_target_properties(cmocka PROPERTIES
+ DEFINE_SYMBOL CMOCKA_EXPORTS
+ VERSION ${LIBRARY_VERSION}
+ SOVERSION ${LIBRARY_SOVERSION}
+ LINK_FLAGS "${DEFAULT_LINK_FLAGS}"
+ C_STANDARD 99
+ C_STANDARD_REQUIRED ON
+ # cmocka uses POSIX-2008 C extensions
+ C_EXTENSIONS ON
+ # automatically export all global objects into DLL on Windows
+ WINDOWS_EXPORT_ALL_SYMBOLS ON
)
-set_property(TARGET
- cmocka
- PROPERTY
- VERSION
- ${LIBRARY_VERSION}
-)
-set_property(TARGET
- cmocka
- PROPERTY
- SOVERSION
- ${LIBRARY_SOVERSION})
-
-set_property(TARGET
- cmocka
- PROPERTY
- LINK_FLAGS
- "${DEFAULT_LINK_FLAGS}")
-
add_library(cmocka::cmocka ALIAS cmocka)
install(TARGETS cmocka
- EXPORT cmocka-config
+ EXPORT cmocka-targets
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
COMPONENT ${PROJECT_NAME})
-install(EXPORT cmocka-config
+install(EXPORT cmocka-targets
NAMESPACE cmocka::
DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/cmocka)
@@ -94,6 +85,15 @@ if (UNIT_TESTING)
PRIVATE
${DEFAULT_C_COMPILE_FLAGS}
-DHAVE_CONFIG_H)
+
+ target_compile_definitions(cmocka-static
+ PRIVATE
+ _GNU_SOURCE
+ _XOPEN_SOURCE=700
+ PUBLIC
+ CMOCKA_STATIC # hides a warning on Windows
+ )
+
if (CMOCKA_PLATFORM_INCLUDE)
target_compile_options(cmocka-static
PRIVATE
diff --git a/src/cmocka.c b/src/cmocka.c
index 32f7360..8af5391 100644
--- a/src/cmocka.c
+++ b/src/cmocka.c
@@ -1,6 +1,6 @@
/*
* Copyright 2008 Google Inc.
- * Copyright 2014-2018 Andreas Schneider <asn@cryptomilk.org>
+ * Copyright 2014-2020 Andreas Schneider <asn@cryptomilk.org>
* Copyright 2015 Jakub Hrozek <jakub.hrozek@posteo.se>
*
* Licensed under the Apache License, Version 2.0 (the "License");
@@ -38,12 +38,17 @@
#include <stdint.h>
#include <setjmp.h>
#include <stdarg.h>
+#include <stdbool.h>
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include <stdbool.h>
#include <time.h>
#include <float.h>
+#include <errno.h>
+#include <limits.h>
+#include <ctype.h>
/*
* This allows to add a platform specific header file. Some embedded platforms
@@ -71,7 +76,12 @@
#define MALLOC_FREE_PATTERN 0xCD
/* Alignment of allocated blocks. NOTE: This must be base2. */
#ifndef MALLOC_ALIGNMENT
-#define MALLOC_ALIGNMENT sizeof(size_t)
+// TODO: switch to alignof(max_align_t) once C11 is the minimum supported
+// version On most platforms, `long double` is the largest scalar type, and has
+// an alignment of 16 bytes. However, sizeof(long double) may be 12, which is
+// not a power of 2. As a temporary measure, we can over-align to 16-bytes on
+// all platforms.
+#define MALLOC_ALIGNMENT 16
#endif
/* Printf formatting for source code locations. */
@@ -91,6 +101,10 @@
#define CMOCKA_CLOCK_GETTIME(clock_id, ts)
#endif
+#ifndef MIN
+#define MIN(a, b) (((a) < (b)) ? (a) : (b))
+#endif
+
#ifndef MAX
#define MAX(a,b) ((a) < (b) ? (b) : (a))
#endif
@@ -108,39 +122,16 @@
# define cm_longjmp(env, val) longjmp(env, val)
#endif
-
/*
- * Declare and initialize the pointer member of ValuePointer variable name
- * with ptr.
+ * Declare and initialize a CMockaValueData variable name
+ * with value the conversion of ptr.
*/
-#define declare_initialize_value_pointer_pointer(name, ptr) \
- ValuePointer name ; \
- name.value = 0; \
- name.x.pointer = (void*)(ptr)
+#define declare_initialize_value_pointer_pointer(name, ptr_value) \
+ CMockaValueData name = {.ptr = (ptr_value)};
-/*
- * Declare and initialize the value member of ValuePointer variable name
- * with val.
- */
-#define declare_initialize_value_pointer_value(name, val) \
- ValuePointer name ; \
- name.value = val
-
-/* Cast a LargestIntegralType to pointer_type via a ValuePointer. */
-#define cast_largest_integral_type_to_pointer( \
- pointer_type, largest_integral_type) \
- ((pointer_type)((ValuePointer*)&(largest_integral_type))->x.pointer)
-
-/* Used to cast LargetIntegralType to void* and vice versa. */
-typedef union ValuePointer {
- LargestIntegralType value;
- struct {
-#if defined(WORDS_BIGENDIAN) && (WORDS_SIZEOF_VOID_P == 4)
- unsigned int padding;
-#endif
- void *pointer;
- } x;
-} ValuePointer;
+/* Cast a uintmax_t to pointer_type. */
+#define cast_cmocka_value_to_pointer(pointer_type, cmocka_value_data) \
+ ((pointer_type)((cmocka_value_data).ptr))
/* Doubly linked list node. */
typedef struct ListNode {
@@ -172,12 +163,14 @@ typedef struct TestState {
} TestState;
/* Determines whether two values are the same. */
-typedef int (*EqualityFunction)(const void *left, const void *right);
+typedef bool (*EqualityFunction)(const void *left, const void *right);
/* Value of a symbol and the place it was declared. */
typedef struct SymbolValue {
+ /* The name will be used to implement some kind of type safety. */
+ const char *name;
SourceLocation location;
- LargestIntegralType value;
+ CMockaValueData value;
} SymbolValue;
/*
@@ -202,17 +195,29 @@ typedef void (*CleanupListValue)(const void *value, void *cleanup_value_data);
/* Structure used to check the range of integer types.a */
typedef struct CheckIntegerRange {
CheckParameterEvent event;
- LargestIntegralType minimum;
- LargestIntegralType maximum;
+ uintmax_t minimum;
+ uintmax_t maximum;
} CheckIntegerRange;
/* Structure used to check whether an integer value is in a set. */
typedef struct CheckIntegerSet {
CheckParameterEvent event;
- const LargestIntegralType *set;
+ const uintmax_t *set;
size_t size_of_set;
} CheckIntegerSet;
+struct check_integer_set {
+ CheckParameterEvent event;
+ const intmax_t *set;
+ size_t size_of_set;
+};
+
+struct check_unsigned_integer_set {
+ CheckParameterEvent event;
+ const uintmax_t *set;
+ size_t size_of_set;
+};
+
/* Used to check whether a parameter matches the area of memory referenced by
* this structure. */
typedef struct CheckMemoryData {
@@ -231,11 +236,11 @@ static ListNode* list_remove(
static void list_remove_free(
ListNode * const node, const CleanupListValue cleanup_value,
void * const cleanup_value_data);
-static int list_empty(const ListNode * const head);
-static int list_find(
+static bool list_empty(const ListNode * const head);
+static bool list_find(
ListNode * const head, const void *value,
const EqualityFunction equal_func, ListNode **output);
-static int list_first(ListNode * const head, ListNode **output);
+static bool list_first(ListNode * const head, ListNode **output);
static ListNode* list_free(
ListNode * const head, const CleanupListValue cleanup_value,
void * const cleanup_value_data);
@@ -270,13 +275,11 @@ static void initialize_testing(const char *test_name);
/* This must be called at the end of a test to free() allocated structures. */
static void teardown_testing(const char *test_name);
-static enum cm_message_output cm_get_output(void);
+static uint32_t cm_get_output(void);
static int cm_error_message_enabled = 1;
static CMOCKA_THREAD char *cm_error_message;
-void cm_print_error(const char * const format, ...) CMOCKA_PRINTF_ATTRIBUTE(1, 2);
-
/*
* Keeps track of the calling context returned by setenv() so that the fail()
* method can jump out of a test.
@@ -290,6 +293,7 @@ jmp_buf global_expect_assert_env;
int global_expecting_assert = 0;
const char *global_last_failed_assert = NULL;
static int global_skip_test;
+static int global_stop_test;
/* Keeps a map of the values that functions will have to return to provide */
/* mocked interfaces. */
@@ -311,13 +315,13 @@ static CMOCKA_THREAD SourceLocation global_last_call_ordering_location;
/* List of all currently allocated blocks. */
static CMOCKA_THREAD ListNode global_allocated_blocks;
-static enum cm_message_output global_msg_output = CM_OUTPUT_STDOUT;
+static uint32_t global_msg_output = CM_OUTPUT_STANDARD;
static const char *global_test_filter_pattern;
static const char *global_skip_filter_pattern;
-#ifndef _WIN32
+#ifdef HAVE_SIGNAL_H
/* Signals caught by exception_handler(). */
static const int exception_signals[] = {
SIGFPE,
@@ -336,8 +340,9 @@ typedef void (*SignalFunction)(int signal);
static SignalFunction default_signal_functions[
ARRAY_SIZE(exception_signals)];
-#else /* _WIN32 */
+#else /* HAVE_SIGNAL_H */
+# ifdef _WIN32
/* The default exception filter. */
static LPTOP_LEVEL_EXCEPTION_FILTER previous_exception_filter;
@@ -371,7 +376,12 @@ static const ExceptionCodeInfo exception_codes[] = {
EXCEPTION_CODE_INFO(EXCEPTION_PRIV_INSTRUCTION),
EXCEPTION_CODE_INFO(EXCEPTION_STACK_OVERFLOW),
};
-#endif /* !_WIN32 */
+# else
+# if defined(__GNUC__) || defined(__clang__)
+# warning "Support for exception handling available on this platform!"
+# endif
+# endif /* _WIN32 */
+#endif /* HAVE_SIGNAL_H */
enum CMUnitTestStatus {
CM_TEST_NOT_STARTED,
@@ -391,7 +401,7 @@ struct CMUnitTestState {
};
/* Exit the currently executing test. */
-static void exit_test(const int quit_application)
+static void exit_test(const bool quit_application)
{
const char *env = getenv("CMOCKA_TEST_ABORT");
int abort_test = 0;
@@ -400,22 +410,35 @@ static void exit_test(const int quit_application)
abort_test = (env[0] == '1');
}
- if (global_skip_test == 0 &&
- abort_test == 1) {
- print_error("%s", cm_error_message);
+ if (global_skip_test == 0 && abort_test == 1) {
+ if (cm_error_message != NULL) {
+ print_error("%s", cm_error_message);
+ }
abort();
} else if (global_running_test) {
cm_longjmp(global_run_test_env, 1);
} else if (quit_application) {
- exit(-1);
+ exit(EXIT_FAILURE);
}
}
void _skip(const char * const file, const int line)
{
- cm_print_error(SOURCE_LOCATION_FORMAT ": Skipped!\n", file, line);
+ cmocka_print_error(SOURCE_LOCATION_FORMAT ": Skipped!\n", file, line);
global_skip_test = 1;
- exit_test(1);
+ exit_test(true);
+
+ /* Unreachable */
+ exit(EXIT_FAILURE);
+}
+
+void _stop(void)
+{
+ global_stop_test = 1;
+ exit_test(true);
+
+ /* Unreachable */
+ exit(EXIT_FAILURE);
}
/* Initialize a SourceLocation structure. */
@@ -427,7 +450,7 @@ static void initialize_source_location(SourceLocation * const location) {
/* Determine whether a source location is currently set. */
-static int source_location_is_set(const SourceLocation * const location) {
+static bool source_location_is_set(const SourceLocation * const location) {
assert_non_null(location);
return location->file && location->line;
}
@@ -443,51 +466,60 @@ static void set_source_location(
}
-static int c_strreplace(char *src,
+static bool c_strreplace(char *src,
size_t src_len,
const char *pattern,
const char *repl,
- int *str_replaced)
+ bool *str_replaced)
{
char *p = NULL;
+ // Terminate if there is no valid data
+ if (src == NULL || src_len == 0 || pattern == NULL || repl == NULL) {
+ errno = EINVAL;
+ return false;
+ }
+
p = strstr(src, pattern);
+ /* There is nothing to replace */
if (p == NULL) {
- return -1;
+ return true;
}
+ const size_t pattern_len = strlen(pattern);
+ const size_t repl_len = strlen(repl);
do {
- size_t of = p - src;
+ size_t offset = p - src;
size_t l = strlen(src);
- size_t pl = strlen(pattern);
- size_t rl = strlen(repl);
/* overflow check */
- if (src_len <= l + MAX(pl, rl) + 1) {
- return -1;
+ if (src_len <= l + MAX(pattern_len, repl_len) + 1) {
+ return false;
}
- if (rl != pl) {
- memmove(src + of + rl, src + of + pl, l - of - pl + 1);
+ if (repl_len != pattern_len) {
+ memmove(src + offset + repl_len,
+ src + offset + pattern_len,
+ l - offset - pattern_len + 1);
}
- memcpy(src + of, repl, rl);
+ memcpy(src + offset, repl, repl_len);
if (str_replaced != NULL) {
- *str_replaced = 1;
+ *str_replaced = true;
}
- p = strstr(src, pattern);
+ p = strstr(src + offset + repl_len, pattern);
} while (p != NULL);
- return 0;
+ return true;
}
-static int c_strmatch(const char *str, const char *pattern)
+static bool c_strmatch(const char *str, const char *pattern)
{
int ok;
if (str == NULL || pattern == NULL) {
- return 0;
+ return false;
}
for (;;) {
@@ -495,10 +527,10 @@ static int c_strmatch(const char *str, const char *pattern)
if (*pattern == '\0') {
/* If string is at the end, we're good */
if (*str == '\0') {
- return 1;
+ return true;
}
- return 0;
+ return false;
}
if (*pattern == '*') {
@@ -507,29 +539,29 @@ static int c_strmatch(const char *str, const char *pattern)
/* If we are at the end, everything is fine */
if (*pattern == '\0') {
- return 1;
+ return true;
}
/* Try to match each position */
for (; *str != '\0'; str++) {
ok = c_strmatch(str, pattern);
if (ok) {
- return 1;
+ return true;
}
}
/* No match */
- return 0;
+ return false;
}
/* If we are at the end, leave */
if (*str == '\0') {
- return 0;
+ return false;
}
/* Check if we have a single wildcard or matching char */
if (*pattern != '?' && *str != *pattern) {
- return 0;
+ return false;
}
/* Move string and pattern */
@@ -537,7 +569,7 @@ static int c_strmatch(const char *str, const char *pattern)
pattern++;
}
- return 0;
+ return false;
}
/* Create function results and expected parameter lists. */
@@ -551,46 +583,52 @@ void initialize_testing(const char *test_name) {
initialize_source_location(&global_last_parameter_location);
}
-
-static void fail_if_leftover_values(const char *test_name) {
- int error_occurred = 0;
+static int has_leftover_values(const char *test_name) {
+ bool leftover_values = false;
(void)test_name;
remove_always_return_values(&global_function_result_map_head, 1);
if (check_for_leftover_values(
&global_function_result_map_head,
- "%s() has remaining non-returned values.\n", 1)) {
- error_occurred = 1;
+ "Has remaining non-returned values", 1)) {
+ leftover_values = true;
}
remove_always_return_values(&global_function_parameter_map_head, 2);
if (check_for_leftover_values(
&global_function_parameter_map_head,
- "'%s' parameter still has values that haven't been checked.\n",
+ "Parameter still has values that haven't been checked",
2)) {
- error_occurred = 1;
+ leftover_values = true;
}
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.\n")) {
- error_occurred = 1;
+ "Function was expected to be called but was not")) {
+ leftover_values = true;
}
- if (error_occurred) {
- exit_test(1);
+ return leftover_values;
+}
+
+static void fail_if_leftover_values(const char *test_name) {
+ if (has_leftover_values(test_name)) {
+ exit_test(true);
}
}
static void teardown_testing(const char *test_name) {
(void)test_name;
- list_free(&global_function_result_map_head, free_symbol_map_value,
- (void*)0);
+ uintmax_t symbol_map_value_data = 0;
+ list_free(&global_function_result_map_head,
+ free_symbol_map_value,
+ &symbol_map_value_data);
initialize_source_location(&global_last_mock_value_location);
- list_free(&global_function_parameter_map_head, free_symbol_map_value,
- (void*)1);
+ uintmax_t symbol_map_value_data_1 = 1;
+ list_free(&global_function_parameter_map_head,
+ free_symbol_map_value,
+ &symbol_map_value_data_1);
initialize_source_location(&global_last_parameter_location);
- list_free(&global_call_ordering_head, free_value,
- (void*)0);
+ list_free(&global_call_ordering_head, free_value, NULL);
initialize_source_location(&global_last_call_ordering_location);
}
@@ -672,7 +710,7 @@ static ListNode* list_free(
/* Determine whether a list is empty. */
-static int list_empty(const ListNode * const head) {
+static bool list_empty(const ListNode * const head) {
assert_non_null(head);
return head->next == head;
}
@@ -682,29 +720,29 @@ static int list_empty(const ListNode * const head) {
* Find a value in the list using the equal_func to compare each node with the
* value.
*/
-static int list_find(ListNode * const head, const void *value,
+static bool list_find(ListNode * const head, const void *value,
const EqualityFunction equal_func, ListNode **output) {
ListNode *current;
assert_non_null(head);
for (current = head->next; current != head; current = current->next) {
if (equal_func(current->value, value)) {
*output = current;
- return 1;
+ return true;
}
}
- return 0;
+ return false;
}
/* Returns the first node of a list */
-static int list_first(ListNode * const head, ListNode **output) {
+static bool list_first(ListNode * const head, ListNode **output) {
ListNode *target_node = NULL;
assert_non_null(head);
if (list_empty(head)) {
- return 0;
+ return false;
}
target_node = head->next;
*output = target_node;
- return 1;
+ return true;
}
@@ -720,11 +758,19 @@ static void free_value(const void *value, void *cleanup_value_data) {
static void free_symbol_map_value(const void *value,
void *cleanup_value_data) {
SymbolMapValue * const map_value = (SymbolMapValue*)value;
- const LargestIntegralType children = cast_ptr_to_largest_integral_type(cleanup_value_data);
+ const uintmax_t children = *(uintmax_t *)cleanup_value_data;
assert_non_null(value);
- list_free(&map_value->symbol_values_list_head,
- children ? free_symbol_map_value : free_value,
- (void *) ((uintptr_t)children - 1));
+ if (children == 0) {
+ list_free(&map_value->symbol_values_list_head,
+ free_value,
+ NULL);
+ } else {
+ uintmax_t new_children_value = children - 1;
+ list_free(&map_value->symbol_values_list_head,
+ free_symbol_map_value,
+ &new_children_value);
+ }
+
free(map_value);
}
@@ -733,7 +779,7 @@ static void free_symbol_map_value(const void *value,
* Determine whether a symbol name referenced by a symbol_map_value matches the
* specified function name.
*/
-static int symbol_names_match(const void *map_value, const void *symbol) {
+static bool symbol_names_match(const void *map_value, const void *symbol) {
return !strcmp(((SymbolMapValue*)map_value)->symbol_name,
(const char*)symbol);
}
@@ -824,12 +870,15 @@ static int get_symbol_value(
output);
}
if (list_empty(child_list)) {
- list_remove_free(target_node, free_symbol_map_value, (void*)0);
+ uintmax_t symbol_map_value_data = 0;
+ list_remove_free(target_node,
+ free_symbol_map_value,
+ &symbol_map_value_data);
}
return return_value;
}
out:
- cm_print_error("No entries for symbol %s.\n", symbol_name);
+ cmocka_print_error("No entries for symbol %s.\n", symbol_name);
return 0;
}
@@ -903,8 +952,8 @@ 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, "%s", o->function);
- cm_print_error(SOURCE_LOCATION_FORMAT
+ cmocka_print_error("%s: %s\n", error_message, o->function);
+ cmocka_print_error(SOURCE_LOCATION_FORMAT
": note: remaining item was declared here\n",
o->location.file, o->location.line);
}
@@ -935,18 +984,18 @@ 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, "%s", value->symbol_name);
+ cmocka_print_error("%s: %s\n", error_message, value->symbol_name);
for (child_node = child_list->next; child_node != child_list;
child_node = child_node->next) {
const SourceLocation * const location =
(const SourceLocation*)child_node->value;
- cm_print_error(SOURCE_LOCATION_FORMAT
+ cmocka_print_error(SOURCE_LOCATION_FORMAT
": note: remaining item was declared here\n",
location->file, location->line);
}
} else {
- cm_print_error("%s: ", value->symbol_name);
+ cmocka_print_error("%s: ", value->symbol_name);
check_for_leftover_values(child_list, error_message,
number_of_symbol_names - 1);
}
@@ -958,34 +1007,59 @@ static size_t check_for_leftover_values(
/* Get the next return value for the specified mock function. */
-LargestIntegralType _mock(const char * const function, const char* const file,
- const int line) {
+CMockaValueData _mock(const char *const function,
+ const char *const file,
+ const int line,
+ const char *name)
+{
void *result;
const int rc = get_symbol_value(&global_function_result_map_head,
&function, 1, &result);
if (rc) {
SymbolValue * const symbol = (SymbolValue*)result;
- const LargestIntegralType value = symbol->value;
+ /* If a name will be passed, check for type safety. */
+ if (name != NULL) {
+ if (symbol->name == NULL || strcmp(name, symbol->name) != 0) {
+ cmocka_print_error(
+ SOURCE_LOCATION_FORMAT
+ ": error: Type mismatch: name[%s] expected[%s]in %s\n",
+ file,
+ line,
+ symbol->name ? symbol->name : "NULL",
+ name,
+ function);
+ if (source_location_is_set(&global_last_mock_value_location)) {
+ cmocka_print_error("NOTE: The value to be returned by mock "
+ "declared here: " SOURCE_LOCATION_FORMAT
+ "\n",
+ global_last_mock_value_location.file,
+ global_last_mock_value_location.line);
+ }
+ free(symbol);
+ exit_test(true);
+ }
+ }
+ const CMockaValueData value = symbol->value;
global_last_mock_value_location = symbol->location;
if (rc == 1) {
free(symbol);
}
return value;
} else {
- cm_print_error(SOURCE_LOCATION_FORMAT ": error: Could not get value "
+ cmocka_print_error(SOURCE_LOCATION_FORMAT ": error: Could not get value "
"to mock function %s\n", file, line, function);
if (source_location_is_set(&global_last_mock_value_location)) {
- cm_print_error(SOURCE_LOCATION_FORMAT
+ cmocka_print_error(SOURCE_LOCATION_FORMAT
": note: Previously returned mock value was declared here\n",
global_last_mock_value_location.file,
global_last_mock_value_location.line);
} else {
- cm_print_error("There were no previously returned mock values for "
+ cmocka_print_error("There were no previously returned mock values for "
"this test.\n");
}
- exit_test(1);
+ exit_test(true);
}
- return 0;
+ return (CMockaValueData){.ptr = NULL};
}
/* Ensure that function is being called in proper order */
@@ -993,91 +1067,89 @@ void _function_called(const char *const function,
const char *const file,
const int line)
{
- ListNode *first_value_node = NULL;
- ListNode *value_node = NULL;
- int rc;
-
- rc = list_first(&global_call_ordering_head, &value_node);
- first_value_node = value_node;
- if (rc) {
+ if (list_empty(&global_call_ordering_head)) {
+ cmocka_print_error(SOURCE_LOCATION_FORMAT
+ ": error: No mock calls expected but called() was "
+ "invoked in %s\n",
+ file, line,
+ function);
+ exit_test(true);
+ } else {
+ const ListNode * const head = &global_call_ordering_head;
+ ListNode *current = head->next;
FuncOrderingValue *expected_call;
- int cmp;
-
- expected_call = (FuncOrderingValue *)value_node->value;
+ bool found = false;
+
+ /*
+ * Search through value nodes until either function is found or
+ * encounter a non-zero refcount greater than -2
+ */
+ do {
+ expected_call = (FuncOrderingValue *)current->value;
+ if (expected_call != NULL) {
+ found = strcmp(expected_call->function, function) == 0;
+ } else {
+ found = false;
+ }
+ if (found || current->refcount > -2) {
+ break;
+ }
- cmp = strcmp(expected_call->function, function);
- if (value_node->refcount < -1) {
- /*
- * Search through value nodes until either function is found or
- * encounter a non-zero refcount greater than -2
- */
- if (cmp != 0) {
- value_node = value_node->next;
- expected_call = (FuncOrderingValue *)value_node->value;
-
- cmp = strcmp(expected_call->function, function);
- while (value_node->refcount < -1 &&
- cmp != 0 &&
- value_node != first_value_node->prev) {
- value_node = value_node->next;
- if (value_node == NULL) {
- break;
- }
- expected_call = (FuncOrderingValue *)value_node->value;
- if (expected_call == NULL) {
- continue;
- }
- cmp = strcmp(expected_call->function, function);
- }
+ current = current->next;
+ } while (current != NULL && current != head);
- if (expected_call == NULL || value_node == first_value_node->prev) {
- cm_print_error(SOURCE_LOCATION_FORMAT
- ": error: No expected mock calls matching "
- "called() invocation in %s",
- file, line,
- function);
- exit_test(1);
- }
- }
+ if (expected_call == NULL || current == head) {
+ cmocka_print_error(SOURCE_LOCATION_FORMAT
+ ": error: No expected mock calls matching "
+ "called() invocation in %s\n",
+ file, line,
+ function);
+ exit_test(true);
}
- if (cmp == 0) {
- if (value_node->refcount > -2 && --value_node->refcount == 0) {
- list_remove_free(value_node, free_value, NULL);
+ if (found) {
+ if (current->refcount > -2) {
+ current->refcount--;
+ if (current->refcount == 0) {
+ list_remove_free(current, free_value, NULL);
+ }
}
} else {
- cm_print_error(SOURCE_LOCATION_FORMAT
+ cmocka_print_error(SOURCE_LOCATION_FORMAT
": error: Expected call to %s but received called() "
"in %s\n",
file, line,
- expected_call->function,
+ expected_call != NULL ?
+ expected_call->function : "(null)",
function);
- exit_test(1);
+ exit_test(true);
}
- } else {
- cm_print_error(SOURCE_LOCATION_FORMAT
- ": error: No mock calls expected but called() was "
- "invoked in %s\n",
- file, line,
- function);
- exit_test(1);
}
}
/* Add a return value for the specified mock function name. */
-void _will_return(const char * const function_name, const char * const file,
- const int line, const LargestIntegralType value,
- const int count) {
- SymbolValue * const return_value =
- (SymbolValue*)malloc(sizeof(*return_value));
+void _will_return(const char *const function_name,
+ const char *const file,
+ const int line,
+ const char *name,
+ const CMockaValueData value,
+ const int count)
+{
+ SymbolValue *const return_value = calloc(1, sizeof(SymbolValue));
+ assert_non_null(return_value);
assert_true(count != 0);
+
+ /* Store name for type safety checks. */
+ if (name != NULL) {
+ return_value->name = name;
+ }
return_value->value = value;
+
set_source_location(&return_value->location, file, line);
add_symbol_value(&global_function_result_map_head, &function_name, 1,
return_value, count);
}
-
/*
* Add a custom parameter checking function. If the event parameter is NULL
* the event structure is allocated internally by this function. If event
@@ -1088,11 +1160,12 @@ void _expect_check(
const char* const function, const char* const parameter,
const char* const file, const int line,
const CheckParameterValue check_function,
- const LargestIntegralType check_data,
+ const CMockaValueData check_data,
CheckParameterEvent * const event, const int count) {
CheckParameterEvent * const check =
event ? event : (CheckParameterEvent*)malloc(sizeof(*check));
const char* symbols[] = {function, parameter};
+ assert_non_null(check);
check->parameter_name = parameter;
check->check_value = check_function;
check->check_value_data = check_data;
@@ -1127,8 +1200,8 @@ 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,
+/* Returns true if the specified float values are equal, else returns false. */
+static bool float_compare(const float left,
const float right,
const float epsilon) {
float absLeft;
@@ -1140,9 +1213,9 @@ static int float_compare(const float left,
diff = (diff >= 0.f) ? diff : -diff;
// Check if the numbers are really close -- needed
- // when comparing numbers near zero.
- if (diff <= epsilon) {
- return 1;
+ // when comparing numbers near zero.
+ if (diff <= epsilon) {
+ return true;
}
absLeft = (left >= 0.f) ? left : -left;
@@ -1152,39 +1225,37 @@ static int float_compare(const float left,
relDiff = largest * FLT_EPSILON;
if (diff > relDiff) {
- return 0;
+ return false;
}
- return 1;
+ return true;
}
-/* 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,
+/* Returns true if the specified float values are equal. If the values are not
+ * equal an error is displayed and false is returned. */
+static bool float_values_equal_display_error(const float left,
const float right,
const float epsilon) {
- const int equal = float_compare(left, right, epsilon);
+ const bool equal = float_compare(left, right, epsilon);
if (!equal) {
- cm_print_error(FloatPrintfFormat " != "
- FloatPrintfFormat "\n", left, right);
+ cmocka_print_error("%f != %f\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,
+/* Returns true if the specified float values are different. If the values are
+ * equal an error is displayed and false is returned. */
+static bool 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);
+ const int not_equal = !float_compare(left, right, epsilon);
if (!not_equal) {
- cm_print_error(FloatPrintfFormat " == "
- FloatPrintfFormat "\n", left, right);
+ cmocka_print_error("%f == %f\n", left, right);
}
return not_equal;
}
-/* Returns 1 if the specified double values are equal, else returns 0. */
-static int double_compare(const double left,
+/* Returns true if the specified double values are equal, else returns false. */
+static bool double_compare(const double left,
const double right,
const double epsilon) {
double absLeft;
@@ -1200,7 +1271,7 @@ static int double_compare(const double left,
* when comparing numbers near zero.
*/
if (diff <= epsilon) {
- return 1;
+ return true;
}
absLeft = (left >= 0.f) ? left : -left;
@@ -1210,215 +1281,506 @@ static int double_compare(const double left,
relDiff = largest * FLT_EPSILON;
if (diff > relDiff) {
- return 0;
+ return false;
}
- return 1;
+ return true;
}
/*
- * Returns 1 if the specified double values are equal. If the values are not
- * equal an error is displayed and 0 is returned.
+ * Returns true if the specified double values are equal. If the values are not
+ * equal an error is displayed and false is returned.
*/
-static int double_values_equal_display_error(const double left,
+static bool double_values_equal_display_error(const double left,
const double right,
const double epsilon) {
- const int equal = double_compare(left, right, epsilon);
+ const bool equal = double_compare(left, right, epsilon);
if (!equal) {
- cm_print_error(DoublePrintfFormat " != "
- DoublePrintfFormat "\n", left, right);
+ cmocka_print_error("%f != %f\n", left, right);
}
return equal;
}
/*
- * Returns 1 if the specified double values are different. If the values are
- * equal an error is displayed and 0 is returned.
+ * Returns true if the specified double values are different. If the values are
+ * equal an error is displayed and false is returned.
*/
-static int double_values_not_equal_display_error(const double left,
+static bool double_values_not_equal_display_error(const double left,
const double right,
const double epsilon) {
- const int not_equal = (double_compare(left, right, epsilon) == 0);
+ const bool not_equal = !double_compare(left, right, epsilon);
if (!not_equal) {
- cm_print_error(DoublePrintfFormat " == "
- DoublePrintfFormat "\n", left, right);
+ cmocka_print_error("%f == %f\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,
- const LargestIntegralType right) {
- const int equal = left == right;
+/* Returns true if the specified values are equal. If the values are not equal
+ * an error is displayed and false is returned. */
+static bool uint_values_equal_display_error(const uintmax_t left,
+ const uintmax_t right)
+{
+ const bool equal = left == right;
if (!equal) {
- cm_print_error(LargestIntegralTypePrintfFormat " != "
- LargestIntegralTypePrintfFormat "\n", left, right);
+ cmocka_print_error("%ju (%#jx) != %ju (%#jx)\n",
+ left,
+ left,
+ right,
+ right);
}
return equal;
}
+
+/* Returns true if the specified values are equal. If the values are not equal
+ * an error is displayed and false is returned. */
+static bool int_values_equal_display_error(const intmax_t left,
+ const intmax_t right)
+{
+ const bool equal = left == right;
+ if (!equal) {
+ cmocka_print_error("%jd != %jd\n", left, right);
+ }
+ return equal;
+}
+
+
/*
- * Returns 1 if the specified values are not equal. If the values are equal
- * an error is displayed and 0 is returned. */
-static int values_not_equal_display_error(const LargestIntegralType left,
- const LargestIntegralType right) {
- const int not_equal = left != right;
+ * Returns true if the specified values are not equal. If the values are equal
+ * an error is displayed and false is returned. */
+static bool uint_values_not_equal_display_error(const uintmax_t left,
+ const uintmax_t right) {
+ const bool not_equal = left != right;
if (!not_equal) {
- cm_print_error(LargestIntegralTypePrintfFormat " == "
- LargestIntegralTypePrintfFormat "\n", left, right);
+ cmocka_print_error("%ju (%#jx) == %ju (%#jx)\n",
+ left,
+ left,
+ right,
+ right);
}
return not_equal;
}
/*
+ * Returns true if the specified values are not equal. If the values are equal
+ * an error is displayed and false is returned. */
+static bool int_values_not_equal_display_error(const intmax_t left,
+ const intmax_t right)
+{
+ const bool not_equal = left != right;
+ if (!not_equal) {
+ cmocka_print_error("%jd == %jd\n", left, right);
+ }
+ return not_equal;
+}
+
+/* Returns true if the specified pointers are equal. If the pointers are not equal
+ * an error is displayed and false is returned. */
+CMOCKA_NO_ACCESS_ATTRIBUTE
+static bool ptr_values_equal_display_error(const void *left, const void *right)
+{
+ const bool equal = left == right;
+ if (!equal) {
+ cmocka_print_error("%p != %p\n", left, right);
+ }
+ return equal;
+}
+
+/* Returns true if the specified pointers are equal. If the pointers are not equal
+ * an error is displayed and false is returned. */
+CMOCKA_NO_ACCESS_ATTRIBUTE
+static bool ptr_values_not_equal_display_error(const void *left,
+ const void *right)
+{
+ const bool equal = left != right;
+ if (!equal) {
+ cmocka_print_error("%p == %p\n", left, right);
+ }
+ return equal;
+}
+
+/*
* Determine whether value is contained within check_integer_set.
- * If invert is 0 and the value is in the set 1 is returned, otherwise 0 is
- * returned and an error is displayed. If invert is 1 and the value is not
- * in the set 1 is returned, otherwise 0 is returned and an error is
- * displayed.
+ * If invert is false and the value is in the set true is returned,
+ * otherwise false is returned and an error is displayed.
+ * If invert is true and the value is not in the set true is returned,
+ * otherwise false is returned and an error is displayed.
*/
-static int value_in_set_display_error(
- const LargestIntegralType value,
- const CheckIntegerSet * const check_integer_set, const int invert) {
- int succeeded = invert;
+static bool value_in_set_display_error(
+ const uintmax_t value,
+ const CheckIntegerSet * const check_integer_set, const bool invert) {
+ bool succeeded = invert;
assert_non_null(check_integer_set);
{
- const LargestIntegralType * const set = check_integer_set->set;
+ const uintmax_t * const set = check_integer_set->set;
const size_t size_of_set = check_integer_set->size_of_set;
size_t i;
for (i = 0; i < size_of_set; i++) {
if (set[i] == value) {
- /* If invert = 0 and item is found, succeeded = 1. */
- /* If invert = 1 and item is found, succeeded = 0. */
+ /* If invert = false and item is found, succeeded = true. */
+ /* If invert = true and item is found, succeeded = false. */
succeeded = !succeeded;
break;
}
}
if (succeeded) {
- return 1;
+ return true;
}
- cm_print_error(LargestIntegralTypePrintfFormatDecimal
- " is %sin the set (",
+ cmocka_print_error("%ju is %sin the set (",
value, invert ? "" : "not ");
for (i = 0; i < size_of_set; i++) {
- cm_print_error(LargestIntegralTypePrintfFormat ", ", set[i]);
+ cmocka_print_error("%#jx, ", set[i]);
}
- cm_print_error(")\n");
+ cmocka_print_error(")\n");
}
- return 0;
+ return false;
}
+static bool int_value_in_set_display_error(
+ const intmax_t value,
+ const struct check_integer_set *const check_integer_set,
+ const bool invert)
+{
+ bool succeeded = invert;
+
+ assert_non_null(check_integer_set);
+
+ {
+ const intmax_t *const set = check_integer_set->set;
+ const size_t size_of_set = check_integer_set->size_of_set;
+ size_t i;
+
+ for (i = 0; i < size_of_set; i++) {
+ if (set[i] == value) {
+ /* If invert = false and item is found, succeeded = true. */
+ /* If invert = true and item is found, succeeded = false. */
+ succeeded = !succeeded;
+ break;
+ }
+ }
+ if (succeeded) {
+ return true;
+ }
+ cmocka_print_error("%jd is %sin the set (",
+ value,
+ invert ? "" : "not ");
+
+ for (i = 0; i < size_of_set; i++) {
+ if (i == size_of_set - 1) {
+ cmocka_print_error("%jd", set[i]);
+ } else {
+ cmocka_print_error("%jd, ", set[i]);
+ }
+ }
+ cmocka_print_error(")\n");
+ }
+ return false;
+}
+
+static bool uint_value_in_set_display_error(
+ const uintmax_t value,
+ const struct check_unsigned_integer_set *const check_uint_set,
+ const bool invert)
+{
+ bool succeeded = invert;
+
+ assert_non_null(check_uint_set);
+
+ {
+ const uintmax_t *const set = check_uint_set->set;
+ const size_t size_of_set = check_uint_set->size_of_set;
+ size_t i;
+
+ for (i = 0; i < size_of_set; i++) {
+ if (set[i] == value) {
+ /* If invert = false and item is found, succeeded = true. */
+ /* If invert = true and item is found, succeeded = false. */
+ succeeded = !succeeded;
+ break;
+ }
+ }
+ if (succeeded) {
+ return true;
+ }
+ cmocka_print_error("%ju is %sin the set (",
+ value,
+ invert ? "" : "not ");
+
+ for (i = 0; i < size_of_set; i++) {
+ cmocka_print_error("%ju%s",
+ set[i],
+ i != size_of_set - 1 ? ", " : "");
+ }
+ cmocka_print_error(")\n");
+ }
+
+ return false;
+}
/*
- * Determine whether a value is within the specified range. If the value is
- * within the specified range 1 is returned. If the value isn't within the
- * specified range an error is displayed and 0 is returned.
+ * Determine whether a value is within the specified range.
*/
-static int integer_in_range_display_error(
- const LargestIntegralType value, const LargestIntegralType range_min,
- const LargestIntegralType range_max) {
+static bool uint_in_range_display_error(const uintmax_t value,
+ const uintmax_t range_min,
+ const uintmax_t range_max)
+{
if (value >= range_min && value <= range_max) {
- return 1;
+ return true;
}
- cm_print_error(LargestIntegralTypePrintfFormatDecimal
- " is not within the range "
- LargestIntegralTypePrintfFormatDecimal "-"
- LargestIntegralTypePrintfFormatDecimal "\n",
- value, range_min, range_max);
- return 0;
+
+ cmocka_print_error("%ju is not within the range [%ju, %ju]\n",
+ value,
+ range_min,
+ range_max);
+
+ return false;
+}
+
+
+/*
+ * Determine whether a value is within the specified range.
+ */
+static bool int_in_range_display_error(const intmax_t value,
+ const intmax_t range_min,
+ const intmax_t range_max)
+{
+ if (value >= range_min && value <= range_max) {
+ return true;
+ }
+
+ cmocka_print_error("%jd is not within the range [%jd, %jd]\n",
+ value,
+ range_min,
+ range_max);
+
+ return false;
+}
+
+static bool int_not_in_range_display_error(const intmax_t value,
+ const intmax_t range_min,
+ const intmax_t range_max)
+{
+ if (value < range_min || value > range_max) {
+ return true;
+ }
+
+ cmocka_print_error("%jd is within the range [%jd, %jd]\n",
+ value,
+ range_min,
+ range_max);
+
+ return false;
+}
+
+static bool uint_not_in_range_display_error(const uintmax_t value,
+ const uintmax_t range_min,
+ const uintmax_t range_max)
+{
+ if (value < range_min || value > range_max) {
+ return true;
+ }
+
+ cmocka_print_error("%ju is within the range [%ju, %ju]\n",
+ value,
+ range_min,
+ range_max);
+
+ return false;
}
/*
* Determine whether a value is within the specified range. If the value
- * is not within the range 1 is returned. If the value is within the
- * specified range an error is displayed and zero is returned.
+ * is not within the range true is returned. If the value is within the
+ * specified range an error is displayed and false is returned.
*/
-static int integer_not_in_range_display_error(
- const LargestIntegralType value, const LargestIntegralType range_min,
- const LargestIntegralType range_max) {
+static bool integer_not_in_range_display_error(
+ const uintmax_t value, const uintmax_t range_min,
+ const uintmax_t range_max) {
if (value < range_min || value > range_max) {
- return 1;
+ return true;
}
- cm_print_error(LargestIntegralTypePrintfFormatDecimal
- " is within the range "
- LargestIntegralTypePrintfFormatDecimal "-"
- LargestIntegralTypePrintfFormatDecimal "\n",
- value, range_min, range_max);
- return 0;
+ cmocka_print_error("%ju is within the range %ju-%ju\n",
+ value,
+ range_min,
+ range_max);
+ return false;
}
/*
* Determine whether the specified strings are equal. If the strings are equal
- * 1 is returned. If they're not equal an error is displayed and 0 is
+ * true is returned. If they're not equal an error is displayed and false is
* returned.
*/
-static int string_equal_display_error(
+static bool string_equal_display_error(
const char * const left, const char * const right) {
if (strcmp(left, right) == 0) {
- return 1;
+ return true;
}
- cm_print_error("\"%s\" != \"%s\"\n", left, right);
- return 0;
+ cmocka_print_error("\"%s\" != \"%s\"\n", left, right);
+ return false;
}
/*
* Determine whether the specified strings are equal. If the strings are not
- * equal 1 is returned. If they're not equal an error is displayed and 0 is
- * returned
+ * equal true is returned. If they're not equal an error is displayed and
+ * false is returned.
*/
-static int string_not_equal_display_error(
+static bool string_not_equal_display_error(
const char * const left, const char * const right) {
if (strcmp(left, right) != 0) {
- return 1;
+ return true;
}
- cm_print_error("\"%s\" == \"%s\"\n", left, right);
- return 0;
+ cmocka_print_error("\"%s\" == \"%s\"\n", left, right);
+ return false;
}
+static bool all_zero(const uint8_t *buf, size_t len)
+{
+ if (buf == NULL || len == 0) {
+ return true;
+ }
-/*
- * Determine whether the specified areas of memory are equal. If they're equal
- * 1 is returned otherwise an error is displayed and 0 is returned.
- */
-static int memory_equal_display_error(const char* const a, const char* const b,
- const size_t size) {
- size_t differences = 0;
+ return buf[0] == '\0' && memcmp(buf, buf + 1, len - 1) == 0;
+}
+
+static void cmocka_print_ascii(const uint8_t *buf, size_t len)
+{
size_t i;
- for (i = 0; i < size; i++) {
- const char l = a[i];
- const char r = b[i];
- if (l != r) {
- if (differences < 16) {
- cm_print_error("difference at offset %" PRIdS " 0x%02x 0x%02x\n",
- i, l, r);
- }
- differences ++;
+
+ for (i = 0; i < len; i++) {
+ /* Print any printable ASCII character including space. */
+ cmocka_print_error("%c", isprint(buf[i]) ? buf[i] : '.');
+ }
+}
+
+static void print_data_block16(const char *prefix,
+ size_t idx,
+ const uint8_t *buf,
+ size_t len)
+{
+ size_t i;
+
+ assert_true(len <= 16);
+
+ cmocka_print_error("%s[%08zx]", prefix, idx);
+ for (i = 0; i < 16; i++) {
+ if (i == 8) {
+ cmocka_print_error(" ");
+ }
+ if (i < len) {
+ cmocka_print_error(" %02hhx", buf[i]);
+ } else {
+ cmocka_print_error(" ");
}
}
- if (differences > 0) {
- if (differences >= 16) {
- cm_print_error("...\n");
+ cmocka_print_error(" ");
+
+ if (len == 0) {
+ cmocka_print_error("EMPTY BLOCK\n");
+ return;
+ }
+
+ for (i = 0; i < len; i++) {
+ if (i == 8) {
+ cmocka_print_error(" ");
}
- cm_print_error("%"PRIdS " bytes of %p and %p differ\n",
- differences, (void *)a, (void *)b);
- return 0;
+ cmocka_print_ascii(&buf[i], 1);
+ }
+
+ cmocka_print_error("\n");
+}
+
+static void print_data_diff(const uint8_t *buf1,
+ const size_t buf_len1,
+ const uint8_t *buf2,
+ const size_t buf_len2,
+ bool omit_zero_bytes)
+{
+ const size_t len = MAX(buf_len1, buf_len2);
+ size_t i;
+ bool skipped = false;
+
+ for (i = 0; i < len; i += 16) {
+ const size_t remaining_len = len - i;
+ size_t remaining_len1 = 0;
+ size_t remaining_len2 = 0;
+ size_t this_len1 = 0;
+ size_t this_len2 = 0;
+ const uint8_t *this_buf1 = NULL;
+ const uint8_t *this_buf2 = NULL;
+
+ if (i < buf_len1) {
+ remaining_len1 = buf_len1 - i;
+ this_len1 = MIN(remaining_len1, 16);
+ this_buf1 = &buf1[i];
+ }
+
+ if (i < buf_len2) {
+ remaining_len2 = buf_len2 - i;
+ this_len2 = MIN(remaining_len2, 16);
+ this_buf2 = &buf2[i];
+ }
+
+ if (omit_zero_bytes &&
+ i > 0 &&
+ remaining_len > 16 &&
+ this_len1 == 16 &&
+ all_zero(this_buf1, 16) &&
+ this_len2 == 16 &&
+ all_zero(this_buf2, 16)) {
+ if (!skipped) {
+ cmocka_print_error("SKIPPING ZERO BUFFER BYTES\n");
+ skipped = true;
+ }
+
+ continue;
+ }
+ skipped = false;
+
+ if (this_len1 == this_len2) {
+ int cmp = memcmp(this_buf1, this_buf2, this_len1);
+ if (cmp == 0) {
+ print_data_block16(" ", i, this_buf1, this_len1);
+ continue;
+ }
+ }
+
+ print_data_block16("- ", i, this_buf1, this_len1);
+ print_data_block16("+ ", i, this_buf2, this_len2);
}
- return 1;
}
+/*
+ * Determine whether the specified areas of memory are equal. If they're
+ * equal true is returned otherwise an error is displayed and false is returned.
+ */
+static bool memory_equal_display_error(const uint8_t *const a,
+ const uint8_t *const b,
+ const size_t size)
+{
+ int cmp = memcmp(a, b, size);
+ if (cmp == 0) {
+ return true;
+ }
+
+ cmocka_print_error("Memory is not equal:\n\n");
+ print_data_diff(a, size, b, size, true);
+ cmocka_print_error("\n");
+
+ return false;
+}
/*
* Determine whether the specified areas of memory are not equal. If they're
- * not equal 1 is returned otherwise an error is displayed and 0 is
+ * not equal true is returned otherwise an error is displayed and false is
* returned.
*/
static int memory_not_equal_display_error(
@@ -1433,29 +1795,40 @@ static int memory_not_equal_display_error(
}
}
if (same == size) {
- cm_print_error("%"PRIdS "bytes of %p and %p the same\n",
+ cmocka_print_error("%"PRIdS "bytes of %p and %p the same\n",
same, (void *)a, (void *)b);
- return 0;
+ return false;
}
- return 1;
+ return true;
}
/* CheckParameterValue callback to check whether a value is within a set. */
-static int check_in_set(const LargestIntegralType value,
- const LargestIntegralType check_value_data) {
- return value_in_set_display_error(value,
- cast_largest_integral_type_to_pointer(CheckIntegerSet*,
- check_value_data), 0);
+static int check_int_in_set(const CMockaValueData value,
+ const CMockaValueData check_value_data) {
+ return int_value_in_set_display_error(
+ value.int_val,
+ cast_cmocka_value_to_pointer(struct check_integer_set *,
+ check_value_data),
+ false);
}
+static int check_uint_in_set(const CMockaValueData value,
+ const CMockaValueData check_value_data)
+{
+ return uint_value_in_set_display_error(
+ value.uint_val,
+ cast_cmocka_value_to_pointer(struct check_unsigned_integer_set *,
+ check_value_data),
+ false);
+}
/* CheckParameterValue callback to check whether a value isn't within a set. */
-static int check_not_in_set(const LargestIntegralType value,
- const LargestIntegralType check_value_data) {
- return value_in_set_display_error(value,
- cast_largest_integral_type_to_pointer(CheckIntegerSet*,
- check_value_data), 1);
+static int check_not_in_set(const CMockaValueData value,
+ const CMockaValueData check_value_data) {
+ return value_in_set_display_error(value.uint_val,
+ cast_cmocka_value_to_pointer(CheckIntegerSet*,
+ check_value_data), true);
}
@@ -1464,12 +1837,12 @@ static int check_not_in_set(const LargestIntegralType value,
static void expect_set(
const char* const function, const char* const parameter,
const char* const file, const int line,
- const LargestIntegralType values[], const size_t number_of_values,
+ const uintmax_t values[], const size_t number_of_values,
const CheckParameterValue check_function, const int count) {
CheckIntegerSet * const check_integer_set =
(CheckIntegerSet*)malloc(sizeof(*check_integer_set) +
(sizeof(values[0]) * number_of_values));
- LargestIntegralType * const set = (LargestIntegralType*)(
+ uintmax_t * const set = (uintmax_t*)(
check_integer_set + 1);
declare_initialize_value_pointer_pointer(check_data, check_integer_set);
assert_non_null(values);
@@ -1479,26 +1852,119 @@ static void expect_set(
check_integer_set->size_of_set = number_of_values;
_expect_check(
function, parameter, file, line, check_function,
- check_data.value, &check_integer_set->event, count);
+ check_data, &check_integer_set->event, count);
}
+static void __expect_int_in_set(const char *const function,
+ const char *const parameter,
+ const char *const file,
+ const size_t line,
+ const intmax_t values[],
+ const size_t number_of_values,
+ const CheckParameterValue check_function,
+ const size_t count)
+{
+ struct check_integer_set *const check_integer_set =
+ calloc(number_of_values,
+ sizeof(struct check_integer_set) + sizeof(values[0]));
+ intmax_t *const set = (intmax_t *)(check_integer_set + 1);
+ declare_initialize_value_pointer_pointer(check_data, check_integer_set);
-/* Add an event to check whether a value is in a set. */
-void _expect_in_set(
- const char* const function, const char* const parameter,
- const char* const file, const int line,
- const LargestIntegralType values[], const size_t number_of_values,
- const int count) {
- expect_set(function, parameter, file, line, values, number_of_values,
- check_in_set, count);
+ assert_non_null(check_integer_set);
+ assert_non_null(values);
+ assert_true(number_of_values);
+
+ memcpy(set, values, number_of_values * sizeof(values[0]));
+
+ check_integer_set->set = set;
+ check_integer_set->size_of_set = number_of_values;
+
+ _expect_check(function,
+ parameter,
+ file,
+ line,
+ check_function,
+ check_data,
+ &check_integer_set->event,
+ count);
+}
+
+static void __expect_uint_in_set(const char *const function,
+ const char *const parameter,
+ const char *const file,
+ const size_t line,
+ const uintmax_t values[],
+ const size_t number_of_values,
+ const CheckParameterValue check_function,
+ const size_t count)
+{
+ struct check_unsigned_integer_set *const check_uint_set =
+ calloc(number_of_values,
+ sizeof(struct check_integer_set) + sizeof(values[0]));
+ uintmax_t *const set = (uintmax_t *)(check_uint_set + 1);
+ declare_initialize_value_pointer_pointer(check_data, check_uint_set);
+
+ assert_non_null(check_uint_set);
+ assert_non_null(values);
+ assert_true(number_of_values);
+
+ memcpy(set, values, number_of_values * sizeof(values[0]));
+
+ check_uint_set->set = set;
+ check_uint_set->size_of_set = number_of_values;
+
+ _expect_check(function,
+ parameter,
+ file,
+ line,
+ check_function,
+ check_data,
+ &check_uint_set->event,
+ count);
}
+/* Add an event to check whether a value is in a set. */
+void _expect_int_in_set(const char *const function,
+ const char *const parameter,
+ const char *const file,
+ const size_t line,
+ const intmax_t values[],
+ const size_t number_of_values,
+ const size_t count)
+{
+ __expect_int_in_set(function,
+ parameter,
+ file,
+ line,
+ values,
+ number_of_values,
+ check_int_in_set,
+ count);
+}
+
+void _expect_uint_in_set(const char *const function,
+ const char *const parameter,
+ const char *const file,
+ const size_t line,
+ const uintmax_t values[],
+ const size_t number_of_values,
+ const size_t count)
+{
+ __expect_uint_in_set(function,
+ parameter,
+ file,
+ line,
+ values,
+ number_of_values,
+ check_uint_in_set,
+ count);
+}
/* Add an event to check whether a value isn't in a set. */
void _expect_not_in_set(
const char* const function, const char* const parameter,
const char* const file, const int line,
- const LargestIntegralType values[], const size_t number_of_values,
+ const uintmax_t values[], const size_t number_of_values,
const int count) {
expect_set(function, parameter, file, line, values, number_of_values,
check_not_in_set, count);
@@ -1506,26 +1972,28 @@ void _expect_not_in_set(
/* CheckParameterValue callback to check whether a value is within a range. */
-static int check_in_range(const LargestIntegralType value,
- const LargestIntegralType check_value_data) {
+static int check_in_range(const CMockaValueData value,
+ const CMockaValueData check_value_data) {
CheckIntegerRange * const check_integer_range =
- cast_largest_integral_type_to_pointer(CheckIntegerRange*,
+ cast_cmocka_value_to_pointer(CheckIntegerRange*,
check_value_data);
assert_non_null(check_integer_range);
- return integer_in_range_display_error(value, check_integer_range->minimum,
- check_integer_range->maximum);
+
+ return uint_in_range_display_error(value.uint_val,
+ check_integer_range->minimum,
+ check_integer_range->maximum);
}
/* CheckParameterValue callback to check whether a value is not within a range. */
-static int check_not_in_range(const LargestIntegralType value,
- const LargestIntegralType check_value_data) {
+static int check_not_in_range(const CMockaValueData value,
+ const CMockaValueData check_value_data) {
CheckIntegerRange * const check_integer_range =
- cast_largest_integral_type_to_pointer(CheckIntegerRange*,
+ cast_cmocka_value_to_pointer(CheckIntegerRange*,
check_value_data);
assert_non_null(check_integer_range);
return integer_not_in_range_display_error(
- value, check_integer_range->minimum, check_integer_range->maximum);
+ value.uint_val, check_integer_range->minimum, check_integer_range->maximum);
}
@@ -1534,7 +2002,7 @@ static int check_not_in_range(const LargestIntegralType value,
static void expect_range(
const char* const function, const char* const parameter,
const char* const file, const int line,
- const LargestIntegralType minimum, const LargestIntegralType maximum,
+ const uintmax_t minimum, const uintmax_t maximum,
const CheckParameterValue check_function, const int count) {
CheckIntegerRange * const check_integer_range =
(CheckIntegerRange*)malloc(sizeof(*check_integer_range));
@@ -1542,7 +2010,7 @@ static void expect_range(
check_integer_range->minimum = minimum;
check_integer_range->maximum = maximum;
_expect_check(function, parameter, file, line, check_function,
- check_data.value, &check_integer_range->event, count);
+ check_data, &check_integer_range->event, count);
}
@@ -1550,7 +2018,7 @@ static void expect_range(
void _expect_in_range(
const char* const function, const char* const parameter,
const char* const file, const int line,
- const LargestIntegralType minimum, const LargestIntegralType maximum,
+ const uintmax_t minimum, const uintmax_t maximum,
const int count) {
expect_range(function, parameter, file, line, minimum, maximum,
check_in_range, count);
@@ -1561,7 +2029,7 @@ void _expect_in_range(
void _expect_not_in_range(
const char* const function, const char* const parameter,
const char* const file, const int line,
- const LargestIntegralType minimum, const LargestIntegralType maximum,
+ const uintmax_t minimum, const uintmax_t maximum,
const int count) {
expect_range(function, parameter, file, line, minimum, maximum,
check_not_in_range, count);
@@ -1570,9 +2038,9 @@ void _expect_not_in_range(
/* CheckParameterValue callback to check whether a value is equal to an
* expected value. */
-static int check_value(const LargestIntegralType value,
- const LargestIntegralType check_value_data) {
- return values_equal_display_error(value, check_value_data);
+static int check_value(const CMockaValueData value,
+ const CMockaValueData check_value_data) {
+ return uint_values_equal_display_error(value.uint_val, check_value_data.uint_val);
}
@@ -1580,17 +2048,17 @@ static int check_value(const LargestIntegralType value,
void _expect_value(
const char* const function, const char* const parameter,
const char* const file, const int line,
- const LargestIntegralType value, const int count) {
- _expect_check(function, parameter, file, line, check_value, value, NULL,
+ const uintmax_t value, const int count) {
+ _expect_check(function, parameter, file, line, check_value, (CMockaValueData){.uint_val = value}, NULL,
count);
}
/* CheckParameterValue callback to check whether a value is not equal to an
* expected value. */
-static int check_not_value(const LargestIntegralType value,
- const LargestIntegralType check_value_data) {
- return values_not_equal_display_error(value, check_value_data);
+static int check_not_value(const CMockaValueData value,
+ const CMockaValueData check_value_data) {
+ return uint_values_not_equal_display_error(value.uint_val, check_value_data.uint_val);
}
@@ -1598,18 +2066,19 @@ static int check_not_value(const LargestIntegralType value,
void _expect_not_value(
const char* const function, const char* const parameter,
const char* const file, const int line,
- const LargestIntegralType value, const int count) {
- _expect_check(function, parameter, file, line, check_not_value, value,
+ const uintmax_t value, const int count) {
+ _expect_check(function, parameter, file, line, check_not_value,
+ (CMockaValueData){.uint_val = value},
NULL, count);
}
/* CheckParameterValue callback to check whether a parameter equals a string. */
-static int check_string(const LargestIntegralType value,
- const LargestIntegralType check_value_data) {
+static int check_string(const CMockaValueData value,
+ const CMockaValueData check_value_data) {
return string_equal_display_error(
- cast_largest_integral_type_to_pointer(char*, value),
- cast_largest_integral_type_to_pointer(char*, check_value_data));
+ cast_cmocka_value_to_pointer(char*, value),
+ cast_cmocka_value_to_pointer(char*, check_value_data));
}
@@ -1621,17 +2090,17 @@ void _expect_string(
declare_initialize_value_pointer_pointer(string_pointer,
discard_const(string));
_expect_check(function, parameter, file, line, check_string,
- string_pointer.value, NULL, count);
+ string_pointer, NULL, count);
}
/* CheckParameterValue callback to check whether a parameter is not equals to
* a string. */
-static int check_not_string(const LargestIntegralType value,
- const LargestIntegralType check_value_data) {
+static int check_not_string(const CMockaValueData value,
+ const CMockaValueData check_value_data) {
return string_not_equal_display_error(
- cast_largest_integral_type_to_pointer(char*, value),
- cast_largest_integral_type_to_pointer(char*, check_value_data));
+ cast_cmocka_value_to_pointer(char*, value),
+ cast_cmocka_value_to_pointer(char*, check_value_data));
}
@@ -1643,19 +2112,19 @@ void _expect_not_string(
declare_initialize_value_pointer_pointer(string_pointer,
discard_const(string));
_expect_check(function, parameter, file, line, check_not_string,
- string_pointer.value, NULL, count);
+ string_pointer, NULL, count);
}
/* CheckParameterValue callback to check whether a parameter equals an area of
* memory. */
-static int check_memory(const LargestIntegralType value,
- const LargestIntegralType check_value_data) {
- CheckMemoryData * const check = cast_largest_integral_type_to_pointer(
+static int check_memory(const CMockaValueData value,
+ const CMockaValueData check_value_data) {
+ CheckMemoryData * const check = cast_cmocka_value_to_pointer(
CheckMemoryData*, check_value_data);
assert_non_null(check);
return memory_equal_display_error(
- cast_largest_integral_type_to_pointer(const char*, value),
- (const char*)check->memory, check->size);
+ cast_cmocka_value_to_pointer(const uint8_t *, value),
+ (const uint8_t *)check->memory, check->size);
}
@@ -1676,7 +2145,7 @@ static void expect_memory_setup(
check_data->memory = mem;
check_data->size = size;
_expect_check(function, parameter, file, line, check_function,
- check_data_pointer.value, &check_data->event, count);
+ check_data_pointer, &check_data->event, count);
}
@@ -1692,13 +2161,13 @@ void _expect_memory(
/* CheckParameterValue callback to check whether a parameter is not equal to
* an area of memory. */
-static int check_not_memory(const LargestIntegralType value,
- const LargestIntegralType check_value_data) {
- CheckMemoryData * const check = cast_largest_integral_type_to_pointer(
+static int check_not_memory(const CMockaValueData value,
+ const CMockaValueData check_value_data) {
+ CheckMemoryData * const check = cast_cmocka_value_to_pointer(
CheckMemoryData*, check_value_data);
assert_non_null(check);
return memory_not_equal_display_error(
- cast_largest_integral_type_to_pointer(const char*, value),
+ cast_cmocka_value_to_pointer(const char*, value),
(const char*)check->memory,
check->size);
}
@@ -1714,9 +2183,9 @@ void _expect_not_memory(
}
-/* CheckParameterValue callback that always returns 1. */
-static int check_any(const LargestIntegralType value,
- const LargestIntegralType check_value_data) {
+/* CheckParameterValue callback that always returns true. */
+static int check_any(const CMockaValueData value,
+ const CMockaValueData check_value_data) {
(void)value;
(void)check_value_data;
return 1;
@@ -1727,14 +2196,14 @@ static int check_any(const LargestIntegralType value,
void _expect_any(
const char* const function, const char* const parameter,
const char* const file, const int line, const int count) {
- _expect_check(function, parameter, file, line, check_any, 0, NULL,
+ _expect_check(function, parameter, file, line, check_any, (CMockaValueData){.ptr = NULL}, NULL,
count);
}
void _check_expected(
const char * const function_name, const char * const parameter_name,
- const char* file, const int line, const LargestIntegralType value) {
+ const char* file, const int line, const CMockaValueData value) {
void *result = NULL;
const char* symbols[] = {function_name, parameter_name};
const int rc = get_symbol_value(&global_function_parameter_map_head,
@@ -1748,7 +2217,7 @@ void _check_expected(
free(check);
}
if (!check_succeeded) {
- cm_print_error(SOURCE_LOCATION_FORMAT
+ cmocka_print_error(SOURCE_LOCATION_FORMAT
": error: Check of parameter %s, function %s failed\n"
SOURCE_LOCATION_FORMAT
": note: Expected parameter declared here\n",
@@ -1759,19 +2228,19 @@ void _check_expected(
_fail(file, line);
}
} else {
- cm_print_error(SOURCE_LOCATION_FORMAT ": error: Could not get value "
+ cmocka_print_error(SOURCE_LOCATION_FORMAT ": error: Could not get value "
"to check parameter %s of function %s\n", file, line,
parameter_name, function_name);
if (source_location_is_set(&global_last_parameter_location)) {
- cm_print_error(SOURCE_LOCATION_FORMAT
+ cmocka_print_error(SOURCE_LOCATION_FORMAT
": note: Previously declared parameter value was declared here\n",
global_last_parameter_location.file,
global_last_parameter_location.line);
} else {
- cm_print_error("There were no previously declared parameter values "
+ cmocka_print_error("There were no previously declared parameter values "
"for this test.\n");
}
- exit_test(1);
+ exit_test(true);
}
}
@@ -1782,61 +2251,48 @@ void mock_assert(const int result, const char* const expression,
if (!result) {
if (global_expecting_assert) {
global_last_failed_assert = expression;
- longjmp(global_expect_assert_env, result);
+ longjmp(global_expect_assert_env, 1);
} else {
- cm_print_error("ASSERT: %s\n", expression);
+ cmocka_print_error("ASSERT: %s\n", expression);
_fail(file, line);
}
}
}
-void _assert_true(const LargestIntegralType result,
+void _assert_true(const uintmax_t result,
const char * const expression,
const char * const file, const int line) {
if (!result) {
- cm_print_error("%s\n", expression);
+ cmocka_print_error("%s is not true\n", expression);
_fail(file, line);
}
}
-void _assert_return_code(const LargestIntegralType result,
- size_t rlen,
- const LargestIntegralType error,
+void _assert_false(const uintmax_t result,
+ const char * const expression,
+ const char * const file, const int line)
+{
+ if (result) {
+ cmocka_print_error("%s is not false\n", expression);
+ _fail(file, line);
+ }
+}
+
+void _assert_return_code(const intmax_t result,
+ const int32_t error,
const char * const expression,
const char * const file,
const int line)
{
- LargestIntegralType valmax;
-
-
- switch (rlen) {
- case 1:
- valmax = 255;
- break;
- case 2:
- valmax = 32767;
- break;
- case 4:
- valmax = 2147483647;
- break;
- case 8:
- default:
- if (rlen > sizeof(valmax)) {
- valmax = 2147483647;
- } else {
- valmax = 9223372036854775807L;
- }
- break;
- }
-
- if (result > valmax - 1) {
+ if (result < 0) {
if (error > 0) {
- cm_print_error("%s < 0, errno("
- LargestIntegralTypePrintfFormatDecimal "): %s\n",
- expression, error, strerror((int)error));
+ cmocka_print_error("%s < 0, errno(%d): %s\n",
+ expression,
+ error,
+ strerror(error));
} else {
- cm_print_error("%s < 0\n", expression);
+ cmocka_print_error("%s < 0\n", expression);
}
_fail(file, line);
}
@@ -1882,23 +2338,68 @@ void _assert_double_not_equal(const double a,
}
}
-void _assert_int_equal(
- const LargestIntegralType a, const LargestIntegralType b,
- const char * const file, const int line) {
- if (!values_equal_display_error(a, b)) {
+void _assert_int_equal(const intmax_t a,
+ const intmax_t b,
+ const char * const file,
+ const int line)
+{
+ if (!int_values_equal_display_error(a, b)) {
+ _fail(file, line);
+ }
+}
+
+
+void _assert_int_not_equal(const intmax_t a,
+ const intmax_t b,
+ const char * const file,
+ const int line)
+{
+ if (!int_values_not_equal_display_error(a, b)) {
+ _fail(file, line);
+ }
+}
+
+
+void _assert_uint_equal(const uintmax_t a,
+ const uintmax_t b,
+ const char * const file,
+ const int line)
+{
+ if (!uint_values_equal_display_error(a, b)) {
_fail(file, line);
}
}
-void _assert_int_not_equal(
- const LargestIntegralType a, const LargestIntegralType b,
- const char * const file, const int line) {
- if (!values_not_equal_display_error(a, b)) {
+void _assert_uint_not_equal(const uintmax_t a,
+ const uintmax_t b,
+ const char * const file,
+ const int line)
+{
+ if (!uint_values_not_equal_display_error(a, b)) {
_fail(file, line);
}
}
+void _assert_ptr_equal(const void *a,
+ const void *b,
+ const char *const file,
+ const int line)
+{
+ if (!ptr_values_equal_display_error(a, b)) {
+ _fail(file, line);
+ }
+}
+
+void _assert_ptr_not_equal(const void *a,
+ const void *b,
+ const char *const file,
+ const int line)
+{
+ if (!ptr_values_not_equal_display_error(a, b)) {
+ _fail(file, line);
+ }
+}
void _assert_string_equal(const char * const a, const char * const b,
const char * const file, const int line) {
@@ -1919,7 +2420,7 @@ void _assert_string_not_equal(const char * const a, const char * const b,
void _assert_memory_equal(const void * const a, const void * const b,
const size_t size, const char* const file,
const int line) {
- if (!memory_equal_display_error((const char*)a, (const char*)b, size)) {
+ if (!memory_equal_display_error((const uint8_t*)a, (const uint8_t*)b, size)) {
_fail(file, line);
}
}
@@ -1935,48 +2436,139 @@ void _assert_memory_not_equal(const void * const a, const void * const b,
}
-void _assert_in_range(
- const LargestIntegralType value, const LargestIntegralType minimum,
- const LargestIntegralType maximum, const char* const file,
- const int line) {
- if (!integer_in_range_display_error(value, minimum, maximum)) {
+void _assert_int_in_range(const intmax_t value,
+ const intmax_t minimum,
+ const intmax_t maximum,
+ const char* const file,
+ const int line)
+{
+ if (!int_in_range_display_error(value, minimum, maximum)) {
+ _fail(file, line);
+ }
+}
+
+void _assert_int_not_in_range(const intmax_t value,
+ const intmax_t minimum,
+ const intmax_t maximum,
+ const char *const file,
+ const int line)
+{
+ if (!int_not_in_range_display_error(value, minimum, maximum)) {
_fail(file, line);
}
}
-void _assert_not_in_range(
- const LargestIntegralType value, const LargestIntegralType minimum,
- const LargestIntegralType maximum, const char* const file,
- const int line) {
- if (!integer_not_in_range_display_error(value, minimum, maximum)) {
+void _assert_uint_in_range(const uintmax_t value,
+ const uintmax_t minimum,
+ const uintmax_t maximum,
+ const char* const file,
+ const int line)
+{
+ if (!uint_in_range_display_error(value, minimum, maximum)) {
_fail(file, line);
}
}
-void _assert_in_set(const LargestIntegralType value,
- const LargestIntegralType values[],
- const size_t number_of_values, const char* const file,
- const int line) {
- CheckIntegerSet check_integer_set;
- check_integer_set.set = values;
- check_integer_set.size_of_set = number_of_values;
- if (!value_in_set_display_error(value, &check_integer_set, 0)) {
+
+void _assert_uint_not_in_range(const uintmax_t value,
+ const uintmax_t minimum,
+ const uintmax_t maximum,
+ const char* const file,
+ const int line)
+{
+ if (!uint_not_in_range_display_error(value, minimum, maximum)) {
_fail(file, line);
}
}
-void _assert_not_in_set(const LargestIntegralType value,
- const LargestIntegralType values[],
+
+void _assert_not_in_set(const uintmax_t value,
+ const uintmax_t values[],
const size_t number_of_values, const char* const file,
const int line) {
- CheckIntegerSet check_integer_set;
- check_integer_set.set = values;
- check_integer_set.size_of_set = number_of_values;
- if (!value_in_set_display_error(value, &check_integer_set, 1)) {
+ struct check_unsigned_integer_set check_uint_set = {
+ .set = values,
+ .size_of_set = number_of_values,
+ };
+ bool ok;
+
+ ok = uint_value_in_set_display_error(value, &check_uint_set, true);
+ if (!ok) {
+ _fail(file, line);
+ }
+}
+
+void _assert_int_in_set(const intmax_t value,
+ const intmax_t values[],
+ const size_t number_of_values,
+ const char *const file,
+ const int line)
+{
+ struct check_integer_set check_integer_set = {
+ .set = values,
+ .size_of_set = number_of_values,
+ };
+ bool ok;
+
+ ok = int_value_in_set_display_error(value, &check_integer_set, false);
+ if (!ok) {
+ _fail(file, line);
+ }
+}
+
+void _assert_int_not_in_set(const intmax_t value,
+ const intmax_t values[],
+ const size_t number_of_values,
+ const char *const file,
+ const int line)
+{
+ struct check_integer_set check_integer_set = {
+ .set = values,
+ .size_of_set = number_of_values,
+ };
+ bool ok;
+
+ ok = int_value_in_set_display_error(value, &check_integer_set, true);
+ if (!ok) {
+ _fail(file, line);
+ }
+}
+
+void _assert_uint_in_set(const uintmax_t value,
+ const uintmax_t values[],
+ const size_t number_of_values,
+ const char *const file,
+ const int line)
+{
+ struct check_unsigned_integer_set check_uint_set = {
+ .set = values,
+ .size_of_set = number_of_values,
+ };
+ bool ok;
+
+ ok = uint_value_in_set_display_error(value, &check_uint_set, false);
+ if (!ok) {
_fail(file, line);
}
}
+void _assert_uint_not_in_set(const uintmax_t value,
+ const uintmax_t values[],
+ const size_t number_of_values,
+ const char *const file,
+ const int line)
+{
+ struct check_unsigned_integer_set check_uint_set = {
+ .set = values,
+ .size_of_set = number_of_values,
+ };
+ bool ok;
+
+ ok = uint_value_in_set_display_error(value, &check_uint_set, true);
+ if (!ok) {
+ _fail(file, line);
+ }
+}
/* Get the list of allocated blocks. */
static ListNode* get_allocated_blocks_list(void) {
@@ -2009,15 +2601,15 @@ static void *libc_realloc(void *ptr, size_t size)
#define realloc test_realloc
}
-static void vcm_print_error(const char* const format,
+static void vcmocka_print_error(const char* const format,
va_list args) CMOCKA_PRINTF_ATTRIBUTE(1, 0);
/* It's important to use the libc malloc and free here otherwise
* the automatic free of leaked blocks can reap the error messages
*/
-static void vcm_print_error(const char* const format, va_list args)
+static void vcmocka_print_error(const char* const format, va_list args)
{
- char buffer[1024];
+ char buffer[256];
size_t msg_len = 0;
va_list ap;
int len;
@@ -2065,9 +2657,16 @@ static void vcm_free_error(char *err_msg)
libc_free(err_msg);
}
+/* Rounds the given pointer down to a multiple of the given alignment. */
+#ifdef HAVE_BUILTIN_ALIGN_DOWN
+#define ALIGN_DOWN(x, a) (__builtin_align_down((x), (a)))
+#else
+#define ALIGN_DOWN(x, a) ((uintptr_t)(x) & ~((a)-1))
+#endif
+
/* Use the real malloc in this function. */
#undef malloc
-void* _test_malloc(const size_t size, const char* file, const int line) {
+void* _test_malloc(const size_t size, const char *file, const int line) {
char *ptr = NULL;
MallocBlockInfo block_info;
ListNode * const block_list = get_allocated_blocks_list();
@@ -2082,9 +2681,10 @@ void* _test_malloc(const size_t size, const char* file, const int line) {
assert_non_null(block);
/* Calculate the returned address. */
- ptr = (char*)(((size_t)block + MALLOC_GUARD_SIZE +
- sizeof(struct MallocBlockInfoData) +
- MALLOC_ALIGNMENT) & ~(MALLOC_ALIGNMENT - 1));
+ ptr = (char *)(ALIGN_DOWN((block + MALLOC_GUARD_SIZE +
+ sizeof(struct MallocBlockInfoData) +
+ MALLOC_ALIGNMENT),
+ MALLOC_ALIGNMENT));
/* Initialize the guard blocks. */
memset(ptr - MALLOC_GUARD_SIZE, MALLOC_GUARD_PATTERN, MALLOC_GUARD_SIZE);
@@ -2106,7 +2706,14 @@ void* _test_malloc(const size_t size, const char* file, const int line) {
void* _test_calloc(const size_t number_of_elements, const size_t size,
const char* file, const int line) {
- void* const ptr = _test_malloc(number_of_elements * size, file, line);
+ void *ptr = NULL;
+
+ if (size > 0 && number_of_elements > SIZE_MAX / size) {
+ errno = ENOMEM;
+ return NULL;
+ }
+
+ ptr = _test_malloc(number_of_elements * size, file, line);
if (ptr) {
memset(ptr, 0, number_of_elements * size);
}
@@ -2126,7 +2733,7 @@ void _test_free(void* const ptr, const char* file, const int line) {
return;
}
- _assert_true(cast_ptr_to_largest_integral_type(ptr), "ptr", file, line);
+ _assert_ptr_not_equal(ptr, NULL, file, line);
block_info.ptr = block - (MALLOC_GUARD_SIZE +
sizeof(struct MallocBlockInfoData));
/* Check the guard blocks. */
@@ -2139,7 +2746,7 @@ void _test_free(void* const ptr, const char* file, const int line) {
for (j = 0; j < MALLOC_GUARD_SIZE; j++) {
const char diff = guard[j] - MALLOC_GUARD_PATTERN;
if (diff) {
- cm_print_error(SOURCE_LOCATION_FORMAT
+ cmocka_print_error(SOURCE_LOCATION_FORMAT
": error: Guard block of %p size=%lu is corrupt\n"
SOURCE_LOCATION_FORMAT ": note: allocated here at %p\n",
file,
@@ -2225,9 +2832,9 @@ static size_t display_allocated_blocks(const ListNode * const check_point) {
assert_non_null(block_info.ptr);
if (allocated_blocks == 0) {
- cm_print_error("Blocks allocated...\n");
+ cmocka_print_error("Blocks allocated...\n");
}
- cm_print_error(SOURCE_LOCATION_FORMAT ": note: block %p allocated here\n",
+ cmocka_print_error(SOURCE_LOCATION_FORMAT ": note: block %p allocated here\n",
block_info.data->location.file,
block_info.data->location.line,
block_info.data->block);
@@ -2264,43 +2871,50 @@ static void fail_if_blocks_allocated(const ListNode * const check_point,
const size_t allocated_blocks = display_allocated_blocks(check_point);
if (allocated_blocks > 0) {
free_allocated_blocks(check_point);
- cm_print_error("ERROR: %s leaked %zu block(s)\n", test_name,
+ cmocka_print_error("ERROR: %s leaked %zu block(s)\n", test_name,
allocated_blocks);
- exit_test(1);
+ exit_test(true);
}
}
void _fail(const char * const file, const int line) {
- enum cm_message_output output = cm_get_output();
+ uint32_t output = cm_get_output();
- switch(output) {
- case CM_OUTPUT_STDOUT:
- cm_print_error("[ LINE ] --- " SOURCE_LOCATION_FORMAT ": error: Failure!", file, line);
- break;
- default:
- cm_print_error(SOURCE_LOCATION_FORMAT ": error: Failure!", file, line);
- break;
+ if (output & CM_OUTPUT_STANDARD) {
+ cmocka_print_error("[ LINE ] --- " SOURCE_LOCATION_FORMAT
+ ": error: Failure!",
+ file, line);
}
- exit_test(1);
-}
+ if ((output & CM_OUTPUT_SUBUNIT) || (output & CM_OUTPUT_TAP) ||
+ (output & CM_OUTPUT_XML)) {
+ cmocka_print_error(SOURCE_LOCATION_FORMAT ": error: Failure!", file, line);
+ }
+ exit_test(true);
+ /* Unreachable */
+ exit(EXIT_FAILURE);
+}
-#ifndef _WIN32
-static void exception_handler(int sig) {
+#ifdef HAVE_SIGNAL_H
+CMOCKA_NORETURN static void exception_handler(int sig) {
const char *sig_strerror = "";
#ifdef HAVE_STRSIGNAL
sig_strerror = strsignal(sig);
#endif
- cm_print_error("Test failed with exception: %s(%d)",
+ cmocka_print_error("Test failed with exception: %s(%d)",
sig_strerror, sig);
- exit_test(1);
+ exit_test(true);
+
+ /* Unreachable */
+ exit(EXIT_FAILURE);
}
-#else /* _WIN32 */
+#else
+# ifdef _WIN32
static LONG WINAPI exception_filter(EXCEPTION_POINTERS *exception_pointers) {
EXCEPTION_RECORD * const exception_record =
exception_pointers->ExceptionRecord;
@@ -2311,10 +2925,10 @@ static LONG WINAPI exception_filter(EXCEPTION_POINTERS *exception_pointers) {
if (code == code_info->code) {
static int shown_debug_message = 0;
fflush(stdout);
- cm_print_error("%s occurred at %p.\n", code_info->description,
+ cmocka_print_error("%s occurred at %p.\n", code_info->description,
exception_record->ExceptionAddress);
if (!shown_debug_message) {
- cm_print_error(
+ cmocka_print_error(
"\n"
"To debug in Visual Studio...\n"
"1. Select menu item File->Open Project\n"
@@ -2328,20 +2942,21 @@ static LONG WINAPI exception_filter(EXCEPTION_POINTERS *exception_pointers) {
"\n");
shown_debug_message = 1;
}
- exit_test(0);
+ exit_test(false);
return EXCEPTION_EXECUTE_HANDLER;
}
}
return EXCEPTION_CONTINUE_SEARCH;
}
-#endif /* !_WIN32 */
+# endif /* _WIN32 */
+#endif /* HAVE_SIGNAL_H */
-void cm_print_error(const char * const format, ...)
+void cmocka_print_error(const char * const format, ...)
{
va_list args;
va_start(args, format);
if (cm_error_message_enabled) {
- vcm_print_error(format, args);
+ vcmocka_print_error(format, args);
} else {
vprint_error(format, args);
}
@@ -2349,23 +2964,27 @@ void cm_print_error(const char * const format, ...)
}
/* Standard output and error print methods. */
-void vprint_message(const char* const format, va_list args) {
- char buffer[1024];
- vsnprintf(buffer, sizeof(buffer), format, args);
- printf("%s", buffer);
+void vprint_message(const char* const format, va_list args)
+{
+ vprintf(format, args);
fflush(stdout);
#ifdef _WIN32
+ char buffer[4096];
+
+ vsnprintf(buffer, sizeof(buffer), format, args);
OutputDebugString(buffer);
#endif /* _WIN32 */
}
-void vprint_error(const char* const format, va_list args) {
- char buffer[1024];
- vsnprintf(buffer, sizeof(buffer), format, args);
- fprintf(stderr, "%s", buffer);
+void vprint_error(const char* const format, va_list args)
+{
+ vfprintf(stderr, format, args);
fflush(stderr);
#ifdef _WIN32
+ char buffer[4096];
+
+ vsnprintf(buffer, sizeof(buffer), format, args);
OutputDebugString(buffer);
#endif /* _WIN32 */
}
@@ -2387,25 +3006,60 @@ void print_error(const char* const format, ...) {
}
/* New formatter */
-static enum cm_message_output cm_get_output(void)
+static uint32_t cm_get_output(void)
{
- enum cm_message_output output = global_msg_output;
- char *env;
+ static bool env_checked = false;
+ char *env = NULL;
+ size_t len = 0;
+ uint32_t new_output = 0;
+ char *str_output_list = NULL;
+ char *str_output = NULL;
+ char *saveptr = NULL;
+
+ if (env_checked) {
+ return global_msg_output;
+ }
env = getenv("CMOCKA_MESSAGE_OUTPUT");
- if (env != NULL) {
- if (strcasecmp(env, "STDOUT") == 0) {
- output = CM_OUTPUT_STDOUT;
- } else if (strcasecmp(env, "SUBUNIT") == 0) {
- output = CM_OUTPUT_SUBUNIT;
- } else if (strcasecmp(env, "TAP") == 0) {
- output = CM_OUTPUT_TAP;
- } else if (strcasecmp(env, "XML") == 0) {
- output = CM_OUTPUT_XML;
+ if (env == NULL) {
+ return global_msg_output;
+ }
+
+ len = strlen(env);
+ if (len == 0 || len > 32) {
+ return global_msg_output;
+ }
+
+ str_output_list = strdup(env);
+ if (str_output_list == NULL) {
+ return global_msg_output;
+ }
+
+ for (str_output = strtok_r(str_output_list, ",", &saveptr);
+ str_output != NULL;
+ str_output = strtok_r(NULL, ",", &saveptr)) {
+ if (strcasecmp(str_output, "STANDARD") == 0) {
+ new_output |= CM_OUTPUT_STANDARD;
+ } else if (strcasecmp(str_output, "STDOUT") == 0) {
+ new_output |= CM_OUTPUT_STANDARD;
+ } else if (strcasecmp(str_output, "SUBUNIT") == 0) {
+ new_output |= CM_OUTPUT_SUBUNIT;
+ } else if (strcasecmp(str_output, "TAP") == 0) {
+ new_output |= CM_OUTPUT_TAP;
+ } else if (strcasecmp(str_output, "XML") == 0) {
+ new_output |= CM_OUTPUT_XML;
}
}
- return output;
+ libc_free(str_output_list);
+
+ if (new_output != 0) {
+ global_msg_output = new_output;
+ }
+
+ env_checked = true;
+
+ return global_msg_output;
}
enum cm_printf_type {
@@ -2419,6 +3073,16 @@ enum cm_printf_type {
static int xml_printed;
static int file_append;
+static void cmprepare_xml_attribute_string(char *buf, size_t buf_len, const char *src)
+{
+ snprintf(buf, buf_len, "%s", src);
+ c_strreplace(buf, buf_len, "&", "&amp;", NULL);
+ c_strreplace(buf, buf_len, "\"", "&quot;", NULL);
+ c_strreplace(buf, buf_len, "\'", "&apos;", NULL);
+ c_strreplace(buf, buf_len, "<", "&lt;", NULL);
+ c_strreplace(buf, buf_len, ">", "&gt;", NULL);
+}
+
static void cmprintf_group_finish_xml(const char *group_name,
size_t total_executed,
size_t total_failed,
@@ -2429,19 +3093,16 @@ static void cmprintf_group_finish_xml(const char *group_name,
{
FILE *fp = stdout;
int file_opened = 0;
- int multiple_files = 0;
char *env;
size_t i;
env = getenv("CMOCKA_XML_FILE");
if (env != NULL) {
char buf[1024];
- int rc;
snprintf(buf, sizeof(buf), "%s", env);
- rc = c_strreplace(buf, sizeof(buf), "%g", group_name, &multiple_files);
- if (rc < 0) {
+ if (!c_strreplace(buf, sizeof(buf), "%g", group_name, NULL)) {
snprintf(buf, sizeof(buf), "%s", env);
}
@@ -2477,10 +3138,15 @@ static void cmprintf_group_finish_xml(const char *group_name,
}
}
+ char group_name_escaped[1024];
+ cmprepare_xml_attribute_string(group_name_escaped,
+ sizeof(group_name_escaped),
+ group_name);
+
fprintf(fp, "<testsuites>\n");
fprintf(fp, " <testsuite name=\"%s\" time=\"%.3f\" "
"tests=\"%u\" failures=\"%u\" errors=\"%u\" skipped=\"%u\" >\n",
- group_name,
+ group_name_escaped,
total_runtime, /* seconds */
(unsigned)total_executed,
(unsigned)total_failed,
@@ -2490,8 +3156,14 @@ static void cmprintf_group_finish_xml(const char *group_name,
for (i = 0; i < total_executed; i++) {
struct CMUnitTestState *cmtest = &cm_tests[i];
+ /* Escape double quotes and remove spaces in test name */
+ char test_name_escaped[1024];
+ cmprepare_xml_attribute_string(test_name_escaped,
+ sizeof(test_name_escaped),
+ cmtest->test->name);
+
fprintf(fp, " <testcase name=\"%s\" time=\"%.3f\" >\n",
- cmtest->test->name, cmtest->runtime);
+ test_name_escaped, cmtest->runtime);
switch (cmtest->status) {
case CM_TEST_ERROR:
@@ -2608,6 +3280,12 @@ static void cmprintf_standard(enum cm_printf_type type,
static void cmprintf_group_start_tap(const size_t num_tests)
{
+ static bool version_printed = false;
+ if (!version_printed) {
+ print_message("TAP version 13\n");
+ version_printed = true;
+ }
+
print_message("1..%u\n", (unsigned)num_tests);
}
@@ -2665,7 +3343,7 @@ static void cmprintf_tap(enum cm_printf_type type,
}
break;
case PRINTF_TEST_SKIPPED:
- print_message("not ok %u # SKIP %s\n", (unsigned)test_number, test_name);
+ print_message("ok %u # SKIP %s\n", (unsigned)test_number, test_name);
break;
case PRINTF_TEST_ERROR:
print_message("not ok %u - %s %s\n",
@@ -2703,21 +3381,15 @@ static void cmprintf_subunit(enum cm_printf_type type,
static void cmprintf_group_start(const char *group_name,
const size_t num_tests)
{
- enum cm_message_output output;
+ uint32_t output;
output = cm_get_output();
- switch (output) {
- case CM_OUTPUT_STDOUT:
+ if (output & CM_OUTPUT_STANDARD) {
cmprintf_group_start_standard(group_name, num_tests);
- break;
- case CM_OUTPUT_SUBUNIT:
- break;
- case CM_OUTPUT_TAP:
+ }
+ if (output & CM_OUTPUT_TAP) {
cmprintf_group_start_tap(num_tests);
- break;
- case CM_OUTPUT_XML:
- break;
}
}
@@ -2730,12 +3402,11 @@ static void cmprintf_group_finish(const char *group_name,
double total_runtime,
struct CMUnitTestState *cm_tests)
{
- enum cm_message_output output;
+ uint32_t output;
output = cm_get_output();
- switch (output) {
- case CM_OUTPUT_STDOUT:
+ if (output & CM_OUTPUT_STANDARD) {
cmprintf_group_finish_standard(group_name,
total_executed,
total_passed,
@@ -2743,16 +3414,14 @@ static void cmprintf_group_finish(const char *group_name,
total_errors,
total_skipped,
cm_tests);
- break;
- case CM_OUTPUT_SUBUNIT:
- break;
- case CM_OUTPUT_TAP:
+ }
+ if (output & CM_OUTPUT_TAP) {
cmprintf_group_finish_tap(group_name,
total_executed,
total_passed,
total_skipped);
- break;
- case CM_OUTPUT_XML:
+ }
+ if (output & CM_OUTPUT_XML) {
cmprintf_group_finish_xml(group_name,
total_executed,
total_failed,
@@ -2760,7 +3429,6 @@ static void cmprintf_group_finish(const char *group_name,
total_skipped,
total_runtime,
cm_tests);
- break;
}
}
@@ -2769,26 +3437,22 @@ static void cmprintf(enum cm_printf_type type,
const char *test_name,
const char *error_message)
{
- enum cm_message_output output;
+ uint32_t output;
output = cm_get_output();
- switch (output) {
- case CM_OUTPUT_STDOUT:
+ if (output & CM_OUTPUT_STANDARD) {
cmprintf_standard(type, test_name, error_message);
- break;
- case CM_OUTPUT_SUBUNIT:
+ }
+ if (output & CM_OUTPUT_SUBUNIT) {
cmprintf_subunit(type, test_name, error_message);
- break;
- case CM_OUTPUT_TAP:
+ }
+ if (output & CM_OUTPUT_TAP) {
cmprintf_tap(type, test_number, test_name, error_message);
- break;
- case CM_OUTPUT_XML:
- break;
}
}
-void cmocka_set_message_output(enum cm_message_output output)
+void cmocka_set_message_output(uint32_t output)
{
global_msg_output = output;
}
@@ -2866,7 +3530,7 @@ static int cmocka_run_one_test_or_fixture(const char *function_name,
const ListNode * const volatile check_point = (const ListNode*)
(heap_check_point != NULL ?
heap_check_point : check_point_allocated_blocks());
- int handle_exceptions = 1;
+ bool handle_exceptions = true;
void *current_state = NULL;
int rc = 0;
@@ -2877,21 +3541,23 @@ static int cmocka_run_one_test_or_fixture(const char *function_name,
handle_exceptions = !IsDebuggerPresent();
#endif /* _WIN32 */
#ifdef UNIT_TESTING_DEBUG
- handle_exceptions = 0;
+ handle_exceptions = false;
#endif /* UNIT_TESTING_DEBUG */
if (handle_exceptions) {
-#ifndef _WIN32
+#ifdef HAVE_SIGNAL_H
unsigned int i;
for (i = 0; i < ARRAY_SIZE(exception_signals); i++) {
default_signal_functions[i] = signal(
exception_signals[i], exception_handler);
}
-#else /* _WIN32 */
+#else /* HAVE_SIGNAL_H */
+# ifdef _WIN32
previous_exception_filter = SetUnhandledExceptionFilter(
exception_filter);
-#endif /* !_WIN32 */
+# endif /* _WIN32 */
+#endif /* HAVE_SIGNAL_H */
}
/* Init the test structure */
@@ -2925,21 +3591,29 @@ static int cmocka_run_one_test_or_fixture(const char *function_name,
/* TEST FAILED */
global_running_test = 0;
rc = -1;
+ if (global_stop_test) {
+ if (has_leftover_values(function_name) == 0) {
+ rc = 0;
+ }
+ global_stop_test = 0;
+ }
}
teardown_testing(function_name);
if (handle_exceptions) {
-#ifndef _WIN32
+#ifdef HAVE_SIGNAL_H
unsigned int i;
for (i = 0; i < ARRAY_SIZE(exception_signals); i++) {
signal(exception_signals[i], default_signal_functions[i]);
}
-#else /* _WIN32 */
+#else /* HAVE_SIGNAL_H */
+# ifdef _WIN32
if (previous_exception_filter) {
SetUnhandledExceptionFilter(previous_exception_filter);
previous_exception_filter = NULL;
}
-#endif /* !_WIN32 */
+# endif /* _WIN32 */
+#endif /* HAVE_SIGNAL_H */
}
return rc;
@@ -2999,7 +3673,7 @@ static int cmocka_run_one_tests(struct CMUnitTestState *test_state)
test_state->check_point);
if (rc != 0) {
test_state->status = CM_TEST_ERROR;
- cm_print_error("Test setup failed");
+ cmocka_print_error("Test setup failed");
}
}
@@ -3045,7 +3719,7 @@ static int cmocka_run_one_tests(struct CMUnitTestState *test_state)
test_state->check_point);
if (rc != 0) {
test_state->status = CM_TEST_ERROR;
- cm_print_error("Test teardown failed");
+ cmocka_print_error("Test teardown failed");
}
}
@@ -3074,9 +3748,6 @@ int _cmocka_run_group_tests(const char *group_name,
size_t i;
int rc;
- /* Make sure LargestIntegralType is at least the size of a pointer. */
- assert_true(sizeof(LargestIntegralType) >= sizeof(void*));
-
cm_tests = libc_calloc(1, sizeof(struct CMUnitTestState) * num_tests);
if (cm_tests == NULL) {
return -1;
@@ -3234,394 +3905,3 @@ int _cmocka_run_group_tests(const char *group_name,
return (int)(total_failed + total_errors);
}
-
-/****************************************************************************
- * DEPRECATED TEST RUNNER
- ****************************************************************************/
-
-int _run_test(
- const char * const function_name, const UnitTestFunction Function,
- void ** const volatile state, const UnitTestFunctionType function_type,
- const void* const heap_check_point) {
- const ListNode * const volatile check_point = (const ListNode*)
- (heap_check_point ?
- heap_check_point : check_point_allocated_blocks());
- void *current_state = NULL;
- volatile int rc = 1;
- int handle_exceptions = 1;
-#ifdef _WIN32
- handle_exceptions = !IsDebuggerPresent();
-#endif /* _WIN32 */
-#ifdef UNIT_TESTING_DEBUG
- handle_exceptions = 0;
-#endif /* UNIT_TESTING_DEBUG */
-
- cm_error_message_enabled = 0;
-
- if (handle_exceptions) {
-#ifndef _WIN32
- unsigned int i;
- for (i = 0; i < ARRAY_SIZE(exception_signals); i++) {
- default_signal_functions[i] = signal(
- exception_signals[i], exception_handler);
- }
-#else /* _WIN32 */
- previous_exception_filter = SetUnhandledExceptionFilter(
- exception_filter);
-#endif /* !_WIN32 */
- }
-
- if (function_type == UNIT_TEST_FUNCTION_TYPE_TEST) {
- print_message("[ RUN ] %s\n", function_name);
- }
- initialize_testing(function_name);
- global_running_test = 1;
- if (cm_setjmp(global_run_test_env) == 0) {
- Function(state ? state : &current_state);
- fail_if_leftover_values(function_name);
-
- /* If this is a setup function then ignore any allocated blocks
- * only ensure they're deallocated on tear down. */
- if (function_type != UNIT_TEST_FUNCTION_TYPE_SETUP) {
- fail_if_blocks_allocated(check_point, function_name);
- }
-
- global_running_test = 0;
-
- if (function_type == UNIT_TEST_FUNCTION_TYPE_TEST) {
- print_message("[ OK ] %s\n", function_name);
- }
- rc = 0;
- } else {
- global_running_test = 0;
- print_message("[ FAILED ] %s\n", function_name);
- }
- teardown_testing(function_name);
-
- if (handle_exceptions) {
-#ifndef _WIN32
- unsigned int i;
- for (i = 0; i < ARRAY_SIZE(exception_signals); i++) {
- signal(exception_signals[i], default_signal_functions[i]);
- }
-#else /* _WIN32 */
- if (previous_exception_filter) {
- SetUnhandledExceptionFilter(previous_exception_filter);
- previous_exception_filter = NULL;
- }
-#endif /* !_WIN32 */
- }
-
- return rc;
-}
-
-
-int _run_tests(const UnitTest * const tests, const size_t number_of_tests) {
- /* Whether to execute the next test. */
- int run_next_test = 1;
- /* Whether the previous test failed. */
- int previous_test_failed = 0;
- /* Whether the previous setup failed. */
- int previous_setup_failed = 0;
- /* Check point of the heap state. */
- const ListNode * const check_point = check_point_allocated_blocks();
- /* Current test being executed. */
- size_t current_test = 0;
- /* Number of tests executed. */
- size_t tests_executed = 0;
- /* Number of failed tests. */
- size_t total_failed = 0;
- /* Number of setup functions. */
- size_t setups = 0;
- /* Number of teardown functions. */
- size_t teardowns = 0;
- size_t i;
- /*
- * A stack of test states. A state is pushed on the stack
- * when a test setup occurs and popped on tear down.
- */
- TestState* test_states =
- (TestState*)malloc(number_of_tests * sizeof(*test_states));
- /* The number of test states which should be 0 at the end */
- long number_of_test_states = 0;
- /* Names of the tests that failed. */
- const char** failed_names = (const char**)malloc(number_of_tests *
- sizeof(*failed_names));
- void **current_state = NULL;
-
- /* Count setup and teardown functions */
- for (i = 0; i < number_of_tests; i++) {
- const UnitTest * const test = &tests[i];
-
- if (test->function_type == UNIT_TEST_FUNCTION_TYPE_SETUP) {
- setups++;
- }
-
- if (test->function_type == UNIT_TEST_FUNCTION_TYPE_TEARDOWN) {
- teardowns++;
- }
- }
-
- print_message("[==========] Running %"PRIdS " test(s).\n",
- number_of_tests - setups - teardowns);
-
- /* Make sure LargestIntegralType is at least the size of a pointer. */
- assert_true(sizeof(LargestIntegralType) >= sizeof(void*));
-
- while (current_test < number_of_tests) {
- const ListNode *test_check_point = NULL;
- TestState *current_TestState;
- const UnitTest * const test = &tests[current_test++];
- if (!test->function) {
- continue;
- }
-
- switch (test->function_type) {
- case UNIT_TEST_FUNCTION_TYPE_TEST:
- if (! previous_setup_failed) {
- run_next_test = 1;
- }
- break;
- case UNIT_TEST_FUNCTION_TYPE_SETUP: {
- /* Checkpoint the heap before the setup. */
- current_TestState = &test_states[number_of_test_states++];
- current_TestState->check_point = check_point_allocated_blocks();
- test_check_point = current_TestState->check_point;
- current_state = &current_TestState->state;
- *current_state = NULL;
- run_next_test = 1;
- break;
- }
- case UNIT_TEST_FUNCTION_TYPE_TEARDOWN:
- /* Check the heap based on the last setup checkpoint. */
- assert_true(number_of_test_states);
- current_TestState = &test_states[--number_of_test_states];
- test_check_point = current_TestState->check_point;
- current_state = &current_TestState->state;
- break;
- default:
- print_error("Invalid unit test function type %d\n",
- test->function_type);
- exit_test(1);
- break;
- }
-
- if (run_next_test) {
- int failed = _run_test(test->name, test->function, current_state,
- test->function_type, test_check_point);
- if (failed) {
- failed_names[total_failed] = test->name;
- }
-
- switch (test->function_type) {
- case UNIT_TEST_FUNCTION_TYPE_TEST:
- previous_test_failed = failed;
- total_failed += failed;
- tests_executed ++;
- break;
-
- case UNIT_TEST_FUNCTION_TYPE_SETUP:
- if (failed) {
- total_failed ++;
- tests_executed ++;
- /* Skip forward until the next test or setup function. */
- run_next_test = 0;
- previous_setup_failed = 1;
- }
- previous_test_failed = 0;
- break;
-
- case UNIT_TEST_FUNCTION_TYPE_TEARDOWN:
- /* If this test failed. */
- if (failed && !previous_test_failed) {
- total_failed ++;
- }
- break;
- default:
-#ifndef _HPUX
- assert_null("BUG: shouldn't be here!");
-#endif
- break;
- }
- }
- }
-
- print_message("[==========] %"PRIdS " test(s) run.\n", tests_executed);
- print_error("[ PASSED ] %"PRIdS " test(s).\n", tests_executed - total_failed);
-
- if (total_failed > 0) {
- print_error("[ FAILED ] %"PRIdS " test(s), listed below:\n", total_failed);
- for (i = 0; i < total_failed; i++) {
- print_error("[ FAILED ] %s\n", failed_names[i]);
- }
- } else {
- print_error("\n %"PRIdS " FAILED TEST(S)\n", total_failed);
- }
-
- if (number_of_test_states != 0) {
- print_error("[ ERROR ] Mismatched number of setup %"PRIdS " and "
- "teardown %"PRIdS " functions\n", setups, teardowns);
- total_failed = (size_t)-1;
- }
-
- free(test_states);
- free((void*)failed_names);
-
- fail_if_blocks_allocated(check_point, "run_tests");
- return (int)total_failed;
-}
-
-int _run_group_tests(const UnitTest * const tests, const size_t number_of_tests)
-{
- UnitTestFunction setup = NULL;
- const char *setup_name = NULL;
- size_t num_setups = 0;
- UnitTestFunction teardown = NULL;
- const char *teardown_name = NULL;
- size_t num_teardowns = 0;
- size_t current_test = 0;
- size_t i;
-
- /* Number of tests executed. */
- size_t tests_executed = 0;
- /* Number of failed tests. */
- size_t total_failed = 0;
- /* Check point of the heap state. */
- const ListNode * const check_point = check_point_allocated_blocks();
- const char **failed_names = NULL;
- void **current_state = NULL;
- TestState group_state = {
- .check_point = NULL,
- };
-
- if (number_of_tests == 0) {
- return -1;
- }
-
- failed_names = (const char **)malloc(number_of_tests *
- sizeof(*failed_names));
- if (failed_names == NULL) {
- return -2;
- }
-
- /* Find setup and teardown function */
- for (i = 0; i < number_of_tests; i++) {
- const UnitTest * const test = &tests[i];
-
- if (test->function_type == UNIT_TEST_FUNCTION_TYPE_GROUP_SETUP) {
- if (setup == NULL) {
- setup = test->function;
- setup_name = test->name;
- num_setups = 1;
- } else {
- print_error("[ ERROR ] More than one group setup function detected\n");
- exit_test(1);
- }
- }
-
- if (test->function_type == UNIT_TEST_FUNCTION_TYPE_GROUP_TEARDOWN) {
- if (teardown == NULL) {
- teardown = test->function;
- teardown_name = test->name;
- num_teardowns = 1;
- } else {
- print_error("[ ERROR ] More than one group teardown function detected\n");
- exit_test(1);
- }
- }
- }
-
- print_message("[==========] Running %"PRIdS " test(s).\n",
- number_of_tests - num_setups - num_teardowns);
-
- if (setup != NULL) {
- int failed;
-
- group_state.check_point = check_point_allocated_blocks();
- current_state = &group_state.state;
- *current_state = NULL;
- failed = _run_test(setup_name,
- setup,
- current_state,
- UNIT_TEST_FUNCTION_TYPE_SETUP,
- group_state.check_point);
- if (failed) {
- failed_names[total_failed] = setup_name;
- }
-
- total_failed += failed;
- tests_executed++;
- }
-
- while (current_test < number_of_tests) {
- int run_test = 0;
- const UnitTest * const test = &tests[current_test++];
- if (test->function == NULL) {
- continue;
- }
-
- switch (test->function_type) {
- case UNIT_TEST_FUNCTION_TYPE_TEST:
- run_test = 1;
- break;
- case UNIT_TEST_FUNCTION_TYPE_SETUP:
- case UNIT_TEST_FUNCTION_TYPE_TEARDOWN:
- case UNIT_TEST_FUNCTION_TYPE_GROUP_SETUP:
- case UNIT_TEST_FUNCTION_TYPE_GROUP_TEARDOWN:
- break;
- default:
- print_error("Invalid unit test function type %d\n",
- test->function_type);
- break;
- }
-
- if (run_test) {
- int failed;
-
- failed = _run_test(test->name,
- test->function,
- current_state,
- test->function_type,
- NULL);
- if (failed) {
- failed_names[total_failed] = test->name;
- }
-
- total_failed += failed;
- tests_executed++;
- }
- }
-
- if (teardown != NULL) {
- int failed;
-
- failed = _run_test(teardown_name,
- teardown,
- current_state,
- UNIT_TEST_FUNCTION_TYPE_GROUP_TEARDOWN,
- group_state.check_point);
- if (failed) {
- failed_names[total_failed] = teardown_name;
- }
-
- total_failed += failed;
- tests_executed++;
- }
-
- print_message("[==========] %"PRIdS " test(s) run.\n", tests_executed);
- print_error("[ PASSED ] %"PRIdS " test(s).\n", tests_executed - total_failed);
-
- if (total_failed) {
- print_error("[ FAILED ] %"PRIdS " test(s), listed below:\n", total_failed);
- for (i = 0; i < total_failed; i++) {
- print_error("[ FAILED ] %s\n", failed_names[i]);
- }
- } else {
- print_error("\n %"PRIdS " FAILED TEST(S)\n", total_failed);
- }
-
- free((void*)failed_names);
- fail_if_blocks_allocated(check_point, "run_group_tests");
-
- return (int)total_failed;
-}
diff --git a/src/cmocka.def b/src/cmocka.def
deleted file mode 100644
index 1c2c653..0000000
--- a/src/cmocka.def
+++ /dev/null
@@ -1,56 +0,0 @@
-LIBRARY cmocka
-EXPORTS
- _assert_double_equal
- _assert_double_not_equal
- _assert_float_equal
- _assert_float_not_equal
- _assert_in_range
- _assert_in_set
- _assert_int_equal
- _assert_int_not_equal
- _assert_memory_equal
- _assert_memory_not_equal
- _assert_not_in_range
- _assert_not_in_set
- _assert_return_code
- _assert_string_equal
- _assert_string_not_equal
- _assert_true
- _check_expected
- _cmocka_run_group_tests
- _expect_any
- _expect_check
- _expect_function_call
- _expect_in_range
- _expect_in_set
- _expect_memory
- _expect_not_in_range
- _expect_not_in_set
- _expect_not_memory
- _expect_not_string
- _expect_not_value
- _expect_string
- _expect_value
- _fail
- _function_called
- _mock
- _run_test
- _run_tests
- _skip
- _test_calloc
- _test_free
- _test_malloc
- _test_realloc
- _will_return
- 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
- mock_assert
- print_error
- print_message
- vprint_error
- vprint_message
diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt
index e016d6a..01ebf31 100644
--- a/tests/CMakeLists.txt
+++ b/tests/CMakeLists.txt
@@ -1,6 +1,13 @@
project(tests C)
-set(TEST_EXCEPTION_HANDLER TRUE)
+set(TEST_EXCEPTION_HANDLER FALSE)
+if (HAVE_SIGNAL_H)
+ set(TEST_EXCEPTION_HANDLER TRUE)
+endif()
+if (WIN32)
+ # FIXME: The exception handler doesn't work on Windows
+ set(TEST_EXCEPTION_HANDLER FALSE)
+endif()
if (CMAKE_BUILD_TYPE)
string(TOLOWER "${CMAKE_BUILD_TYPE}" CMAKE_BUILD_TYPE_LOWER)
if (CMAKE_BUILD_TYPE_LOWER STREQUAL "undefinedsanitizer")
@@ -10,6 +17,10 @@ endif()
set(CMOCKA_TESTS
test_alloc
+ test_buffer
+ test_expect_check
+ test_expect_u_int_in_set
+ test_expect_check_fail
test_group_setup_assert
test_group_setup_fail
test_fixtures
@@ -17,19 +28,36 @@ set(CMOCKA_TESTS
test_groups
test_float_macros
test_double_macros
+ test_assert_true
+ test_assert_true_fail
+ test_assert_false
+ test_assert_false_fail
test_assert_macros
test_assert_macros_fail
+ test_assert_memory
+ test_assert_memory_fail
+ test_assert_ptr
+ test_assert_ptr_fail
+ test_assert_u_int
+ test_assert_u_int_fail
+ test_assert_range
+ test_assert_range_fail
+ test_assert_set
+ test_assert_set_fail
test_basics
test_skip
+ test_stop
+ test_stop_fail
test_strmatch
+ test_strreplace
test_setup_fail
test_ordering
test_ordering_fail
test_returns
test_returns_fail
+ test_string
test_wildcard
test_skip_filter
- test_cmockery
)
if (TEST_EXCEPTION_HANDLER)
@@ -39,7 +67,7 @@ endif()
foreach(_CMOCKA_TEST ${CMOCKA_TESTS})
add_cmocka_test(${_CMOCKA_TEST}
SOURCES ${_CMOCKA_TEST}.c
- COMPILE_OPTIONS ${DEFAULT_C_COMPILE_FLAGS}
+ COMPILE_OPTIONS ${DEFAULT_C_COMPILE_FLAGS} -D_GNU_SOURCE -D_XOPEN_SOURCE=700
LINK_LIBRARIES cmocka::static
LINK_OPTIONS ${DEFAULT_LINK_FLAGS})
target_include_directories(${_CMOCKA_TEST} PRIVATE ${cmocka_BINARY_DIR})
@@ -47,11 +75,6 @@ foreach(_CMOCKA_TEST ${CMOCKA_TESTS})
add_cmocka_test_environment(${_CMOCKA_TEST})
endforeach()
-### Special Cases
-if (${CMAKE_C_COMPILER_ID} MATCHES "(GNU|Clang)")
- set_source_files_properties(test_cmockery.c PROPERTIES COMPILE_FLAGS "-Wno-deprecated-declarations")
-endif()
-
### Exceptions
# test_skip
@@ -62,6 +85,38 @@ set_tests_properties(
"\\[ SKIPPED \\] test_check_skip"
)
+# test_assert_true
+set_tests_properties(
+ test_assert_true
+ PROPERTIES
+ PASS_REGULAR_EXPRESSION
+ "\\[ PASSED \\] 1 test\\(s\\)."
+)
+
+# test_assert_true_fail
+set_tests_properties(
+ test_assert_true_fail
+ PROPERTIES
+ PASS_REGULAR_EXPRESSION
+ "x != 10 is not true"
+)
+
+# test_assert_false
+set_tests_properties(
+ test_assert_false
+ PROPERTIES
+ PASS_REGULAR_EXPRESSION
+ "\\[ PASSED \\] 1 test\\(s\\)."
+)
+
+# test_assert_false_fail
+set_tests_properties(
+ test_assert_false_fail
+ PROPERTIES
+ PASS_REGULAR_EXPRESSION
+ "x == 10 is not false"
+)
+
# test_assert_macros_fail
set_tests_properties(
test_assert_macros_fail
@@ -70,12 +125,65 @@ set_tests_properties(
"\\[ FAILED \\] tests: 1 test"
)
-# test_ordering ensure proper failures
+set_tests_properties(
+ test_assert_memory_fail
+ PROPERTIES
+ PASS_REGULAR_EXPRESSION
+ "\\[ FAILED \\] memory_tests: 1 test"
+)
+
+set_tests_properties(
+ test_assert_ptr_fail
+ PROPERTIES
+ PASS_REGULAR_EXPRESSION
+ "\\[ FAILED \\] ptr_tests: 4 test"
+)
+
+set_tests_properties(
+ test_assert_u_int_fail
+ PROPERTIES
+ PASS_REGULAR_EXPRESSION
+ "\\[ FAILED \\] integer_tests: 4 test"
+)
+
+set_tests_properties(
+ test_assert_range_fail
+ PROPERTIES
+ PASS_REGULAR_EXPRESSION
+ "\\[ FAILED \\] range_fail_tests: 6 test"
+)
+
+set_tests_properties(
+ test_assert_set_fail
+ PROPERTIES
+ PASS_REGULAR_EXPRESSION
+ "\\[ FAILED \\] set_fail_tests: 5 test"
+)
+
+# test_expect_check_fail
+set_tests_properties(
+ test_expect_check_fail
+ PROPERTIES
+ PASS_REGULAR_EXPRESSION
+ "\\[ FAILED \\] tests: 3 test"
+)
+
+# stop_fail
+set_tests_properties(
+ test_stop_fail
+ PROPERTIES
+ PASS_REGULAR_EXPRESSION
+ "\\[ FAILED \\] tests: 3 test"
+)
+
+# test_ordering_fail ensure proper failures
set_tests_properties(
test_ordering_fail
PROPERTIES
PASS_REGULAR_EXPRESSION
- "\\[ FAILED \\] tests: 7 test"
+ "\\[ FAILED \\] tests: 8 test"
+ FAIL_REGULAR_EXPRESSION
+ "Test failed with exception: (Segmentation fault|Segmentation Fault|11|Illegal instruction)"
)
# test_returns_fail ensure proper failures
@@ -83,22 +191,15 @@ set_tests_properties(
test_returns_fail
PROPERTIES
PASS_REGULAR_EXPRESSION
- "\\[ FAILED \\] alloc_tests: 3 test"
+ "\\[ FAILED \\] will_return_mock_tests: 6 test"
)
# test_exception_handler
if (TEST_EXCEPTION_HANDLER)
- if (WIN32)
- set_tests_properties(test_exception_handler
- PROPERTIES
- PASS_REGULAR_EXPRESSION
- "EXCEPTION_ACCESS_VIOLATION occurred at")
- else()
- set_tests_properties(test_exception_handler
- PROPERTIES
- PASS_REGULAR_EXPRESSION
- "Test failed with exception: (Segmentation fault|Segmentation Fault|11|Illegal instruction)")
- endif (WIN32)
+ set_tests_properties(test_exception_handler
+ PROPERTIES
+ PASS_REGULAR_EXPRESSION
+ "Test failed with exception")
endif (TEST_EXCEPTION_HANDLER)
set_tests_properties(
@@ -174,23 +275,26 @@ set(TEST_OUTPUT_FMTS
xml)
set(test_basics_tap_out
- "^1\\.\\.2"
+ "^TAP version 13"
+ "1\\.\\.2"
"ok 1 - null_test_success"
"ok 2 - int_test_success"
"# ok - tests")
set(test_assert_macros_fail_tap_out
- "^1\\.\\.1"
+ "^TAP version 13"
+ "1\\.\\.1"
"not ok 1 - test_assert_return_code_fail"
"#[^\n\r]+[\n\r]#[^\n\r]+[\n\r]# not ok - tests")
set(test_groups_tap_out
- "^1\\.\\.1"
+ "^TAP version 13"
+ "1\\.\\.1"
"ok 1 - null_test_success"
"# ok - test_group1"
"1\\.\\.1"
"ok 1 - int_test_success"
- "# ok - test_group2")
+ "# ok - test_group2 num=<'\"2&2'\">")
set(test_skip_tap_out
- "not ok 1 # SKIP")
+ "ok 1 # SKIP")
set(test_setup_fail_tap_out
"not ok 1 - int_test_ignored Could not run test: Test setup failed")
@@ -221,7 +325,7 @@ set(test_groups_xml_out
"<testcase name=\"null_test_success\" time=\"[0-9.]+\" >"
"</testcase>"
"</testsuite>"
- ".*<testsuite name=\"test_group2\" time=\"[0-9.]+\" tests=\"1\" failures=\"0\" errors=\"0\" skipped=\"0\" >"
+ ".*<testsuite name=\"test_group2 num=&lt[;]&apos[;]&quot[;]2&amp[;]2&apos[;]&quot[;]&gt[;]\" time=\"[0-9.]+\" tests=\"1\" failures=\"0\" errors=\"0\" skipped=\"0\" >"
"<testcase name=\"int_test_success\" time=\"[0-9.]+\" >"
"</testcase>"
"</testsuite>"
diff --git a/tests/cmocka_test.cmake b/tests/cmocka_test.cmake
index 53ffcca..d660979 100644
--- a/tests/cmocka_test.cmake
+++ b/tests/cmocka_test.cmake
@@ -155,7 +155,6 @@ endif()
### Add project default build options here !!!
add_cmake_cache_entry(UNIT_TESTING ON)
-add_cmake_cache_entry(WITH_CMOCKERY_SUPPORT ON)
### Add project default build options here ^^^
diff --git a/tests/ctest-default.cmake b/tests/ctest-default.cmake
index e21e93c..95c751a 100644
--- a/tests/ctest-default.cmake
+++ b/tests/ctest-default.cmake
@@ -13,7 +13,7 @@ set(CTEST_CMAKE_GENERATOR "Unix Makefiles")
set(CTEST_BUILD_CONFIGURATION "Debug")
## The build options for the project
-set(CTEST_BUILD_OPTIONS "-DUNIT_TESTING=ON -DWITH_CMOCKERY_SUPPORT=ON")
+set(CTEST_BUILD_OPTIONS "-DUNIT_TESTING=ON)
#set(CTEST_CUSTOM_MEMCHECK_IGNORE torture_rand)
diff --git a/tests/meson.build b/tests/meson.build
index b49066b..39313c2 100644
--- a/tests/meson.build
+++ b/tests/meson.build
@@ -1,24 +1,37 @@
tests = {
'alloc': false,
+ 'expect_check': false,
+ 'expect_check_fail': true,
'group_setup_assert': true,
'group_setup_fail': true,
'fixtures': false,
'group_fixtures': false,
'groups': false,
'float_macros': false,
+ 'double_macros': false,
'assert_macros': false,
'assert_macros_fail': true,
+ 'assert_ptr': false,
+ 'assert_ptr_fail': true,
+ 'assert_u_int': false,
+ 'assert_u_int_fail': true,
+ 'assert_range': false,
+ 'assert_range_fail': true,
+ 'assert_set': false,
+ 'assert_set_fail': true,
'basics': false,
'skip': false,
+ 'stop': false,
+ 'stop_fail': true,
'strmatch': false,
'setup_fail': true,
'ordering': false,
'ordering_fail': true,
'returns': false,
'returns_fail': true,
+ 'string': false,
'wildcard': false,
'skip_filter': false,
- 'cmockery': false
}
foreach name, should_fail: tests
diff --git a/tests/test_alloc.c b/tests/test_alloc.c
index 966814a..ad99fa0 100644
--- a/tests/test_alloc.c
+++ b/tests/test_alloc.c
@@ -1,8 +1,10 @@
#include "config.h"
#include <stdarg.h>
+#include <stdbool.h>
#include <stddef.h>
#include <setjmp.h>
+#include <stdint.h>
#include <cmocka.h>
#include <cmocka_private.h>
@@ -10,6 +12,25 @@
#include <stdio.h>
#include <string.h>
+static void torture_test_calloc(void **state)
+{
+ void *ptr;
+
+ (void)state; /* unsused */
+
+ ptr = test_calloc(2, SIZE_MAX);
+ assert_null(ptr);
+ ptr = test_calloc(SIZE_MAX, 2);
+ assert_null(ptr);
+
+ /* overflows to 0 */
+ ptr = test_calloc(2, (SIZE_MAX/2)+1);
+ assert_null(ptr);
+
+ ptr = test_calloc(3, (SIZE_MAX/2)+42);
+ assert_null(ptr);
+}
+
static void torture_test_malloc(void **state)
{
char *str;
@@ -82,6 +103,7 @@ static void torture_test_realloc_set0(void **state)
int main(void) {
const struct CMUnitTest alloc_tests[] = {
+ cmocka_unit_test(torture_test_calloc),
cmocka_unit_test(torture_test_malloc),
cmocka_unit_test(torture_test_realloc),
cmocka_unit_test(torture_test_realloc_set0),
diff --git a/tests/test_assert_false.c b/tests/test_assert_false.c
new file mode 100644
index 0000000..86571b4
--- /dev/null
+++ b/tests/test_assert_false.c
@@ -0,0 +1,27 @@
+#include "config.h"
+
+#include <stdarg.h>
+#include <stdbool.h>
+#include <stddef.h>
+#include <setjmp.h>
+#include <stdint.h>
+
+#include <cmocka.h>
+#include <cmocka_private.h>
+
+static void test_assert_false(void **state)
+{
+ int x = 10;
+
+ (void)state; /* unused */
+ assert_false(x != 10);
+}
+
+int main(void)
+{
+ const struct CMUnitTest tests[] = {
+ cmocka_unit_test(test_assert_false),
+ };
+
+ return cmocka_run_group_tests(tests, NULL, NULL);
+}
diff --git a/tests/test_assert_false_fail.c b/tests/test_assert_false_fail.c
new file mode 100644
index 0000000..3cfef6f
--- /dev/null
+++ b/tests/test_assert_false_fail.c
@@ -0,0 +1,27 @@
+#include "config.h"
+
+#include <stdarg.h>
+#include <stdbool.h>
+#include <stddef.h>
+#include <setjmp.h>
+#include <stdint.h>
+
+#include <cmocka.h>
+#include <cmocka_private.h>
+
+static void test_assert_false_fail(void **state)
+{
+ int x = 10;
+
+ (void)state; /* unused */
+ assert_false(x == 10);
+}
+
+int main(void)
+{
+ const struct CMUnitTest tests[] = {
+ cmocka_unit_test(test_assert_false_fail),
+ };
+
+ return cmocka_run_group_tests(tests, NULL, NULL);
+}
diff --git a/tests/test_assert_macros.c b/tests/test_assert_macros.c
index 85b0a38..cd468dd 100644
--- a/tests/test_assert_macros.c
+++ b/tests/test_assert_macros.c
@@ -1,8 +1,10 @@
#include "config.h"
#include <stdarg.h>
+#include <stdbool.h>
#include <stddef.h>
#include <setjmp.h>
+#include <stdint.h>
#include <cmocka.h>
#include <cmocka_private.h>
@@ -19,7 +21,7 @@
**************************************/
static void test_assert_return_code(void **state)
{
- struct stat sb;
+ struct stat sb = {0};
int rc;
(void)state; /* unused */
diff --git a/tests/test_assert_macros_fail.c b/tests/test_assert_macros_fail.c
index aea919a..d492034 100644
--- a/tests/test_assert_macros_fail.c
+++ b/tests/test_assert_macros_fail.c
@@ -1,8 +1,10 @@
#include "config.h"
#include <stdarg.h>
+#include <stdbool.h>
#include <stddef.h>
#include <setjmp.h>
+#include <stdint.h>
#include <cmocka.h>
#include <cmocka_private.h>
diff --git a/tests/test_assert_memory.c b/tests/test_assert_memory.c
new file mode 100644
index 0000000..85ce888
--- /dev/null
+++ b/tests/test_assert_memory.c
@@ -0,0 +1,49 @@
+#include "config.h"
+
+#include <stdarg.h>
+#include <stdbool.h>
+#include <stddef.h>
+#include <setjmp.h>
+#include <stdint.h>
+#include <cmocka.h>
+#include <cmocka_private.h>
+
+static const uint8_t buf1[] = {
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x1f,
+ 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+ 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
+ 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
+ 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
+ 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
+ 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
+};
+
+static const uint8_t buf2[] = {
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x1f,
+ 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+ 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
+ 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
+ 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
+ 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
+ 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
+};
+
+static void test_memory_equal(void **state)
+{
+ (void)state;
+
+ assert_memory_equal(buf1, buf2, sizeof(buf1));
+}
+
+int main(int argc, char **argv) {
+ const struct CMUnitTest memory_tests[] = {
+ cmocka_unit_test(test_memory_equal),
+ };
+
+ (void)argc;
+ (void)argv;
+
+ return cmocka_run_group_tests(memory_tests, NULL, NULL);
+}
diff --git a/tests/test_assert_memory_fail.c b/tests/test_assert_memory_fail.c
new file mode 100644
index 0000000..e05b79a
--- /dev/null
+++ b/tests/test_assert_memory_fail.c
@@ -0,0 +1,49 @@
+#include "config.h"
+
+#include <stdarg.h>
+#include <stdbool.h>
+#include <stddef.h>
+#include <setjmp.h>
+#include <stdint.h>
+#include <cmocka.h>
+#include <cmocka_private.h>
+
+static const uint8_t buf1[] = {
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x1f,
+ 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+ 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
+ 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
+ 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
+ 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
+ 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
+};
+
+static const uint8_t buf2[] = {
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x1f,
+ 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+ 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
+ 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0xf7,
+ 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
+ 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
+ 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
+};
+
+static void test_memory_equal(void **state)
+{
+ (void)state;
+
+ assert_memory_equal(buf1, buf2, sizeof(buf1));
+}
+
+int main(int argc, char **argv) {
+ const struct CMUnitTest memory_tests[] = {
+ cmocka_unit_test(test_memory_equal),
+ };
+
+ (void)argc;
+ (void)argv;
+
+ return cmocka_run_group_tests(memory_tests, NULL, NULL);
+}
diff --git a/tests/test_assert_ptr.c b/tests/test_assert_ptr.c
new file mode 100644
index 0000000..0608410
--- /dev/null
+++ b/tests/test_assert_ptr.c
@@ -0,0 +1,48 @@
+#include "config.h"
+
+#include <setjmp.h>
+#include <stdarg.h>
+#include <stdbool.h>
+#include <stddef.h>
+#include <stdint.h>
+#include <cmocka.h>
+
+static void test_ptr_equal(void **state)
+{
+ (void)state; /* unused */
+
+ const char *my_pointer = "wurst";
+ assert_ptr_equal(my_pointer, my_pointer);
+}
+
+static void test_ptr_not_equal(void **state)
+{
+ (void)state; /* unused */
+ assert_ptr_not_equal("wurst", "brot");
+}
+
+static void test_null(void **state)
+{
+ (void)state; /* unused */
+ void *my_pointer = NULL;
+ assert_null(my_pointer);
+}
+
+static void test_non_null(void **state)
+{
+ (void)state; /* unused */
+ const char *my_pointer = "hello world";
+ assert_non_null(my_pointer);
+}
+
+int main(void)
+{
+ const struct CMUnitTest ptr_tests[] = {
+ cmocka_unit_test(test_ptr_equal),
+ cmocka_unit_test(test_ptr_not_equal),
+ cmocka_unit_test(test_null),
+ cmocka_unit_test(test_non_null),
+ };
+
+ return cmocka_run_group_tests(ptr_tests, NULL, NULL);
+}
diff --git a/tests/test_assert_ptr_fail.c b/tests/test_assert_ptr_fail.c
new file mode 100644
index 0000000..0e26771
--- /dev/null
+++ b/tests/test_assert_ptr_fail.c
@@ -0,0 +1,49 @@
+#include "config.h"
+
+#include <setjmp.h>
+#include <stdarg.h>
+#include <stdbool.h>
+#include <stddef.h>
+#include <stdint.h>
+#include <cmocka.h>
+
+static void test_ptr_equal_fail(void **state)
+{
+ (void)state; /* unused */
+
+ const char *my_pointer = "wurst";
+ assert_ptr_equal(my_pointer, my_pointer + 1);
+}
+
+static void test_ptr_not_equal_fail(void **state)
+{
+ (void)state; /* unused */
+
+ const char *my_pointer = "wurst";
+ assert_ptr_not_equal(my_pointer, my_pointer);
+}
+
+static void test_null_fail(void **state)
+{
+ (void)state; /* unused */
+ assert_null("wurst");
+}
+
+static void test_non_null_fail(void **state)
+{
+ (void)state; /* unused */
+ const char *my_pointer = NULL;
+ assert_non_null(my_pointer);
+}
+
+int main(void)
+{
+ const struct CMUnitTest ptr_tests[] = {
+ cmocka_unit_test(test_ptr_equal_fail),
+ cmocka_unit_test(test_ptr_not_equal_fail),
+ cmocka_unit_test(test_null_fail),
+ cmocka_unit_test(test_non_null_fail),
+ };
+
+ return cmocka_run_group_tests(ptr_tests, NULL, NULL);
+}
diff --git a/tests/test_assert_range.c b/tests/test_assert_range.c
new file mode 100644
index 0000000..554e64a
--- /dev/null
+++ b/tests/test_assert_range.c
@@ -0,0 +1,54 @@
+#include "config.h"
+
+#include <stdarg.h>
+#include <stdbool.h>
+#include <stddef.h>
+#include <setjmp.h>
+#include <stdint.h>
+#include <cmocka.h>
+#include <cmocka_private.h>
+
+static void test_assert_int_in_range(void **state)
+{
+ (void)state; /* unused */
+ assert_int_in_range(0, 0, 1);
+ assert_int_in_range(1, 0, 1);
+ assert_int_in_range(0, -1, 1);
+ assert_int_in_range(0, INTMAX_MIN, INTMAX_MAX);
+}
+
+static void test_assert_int_not_in_range(void **state)
+{
+ (void)state; /* unused */
+ assert_int_not_in_range(-1, 0, 1);
+ assert_int_not_in_range(2, 0, 1);
+ assert_int_not_in_range(2, -1, 1);
+ assert_int_not_in_range(INTMAX_MIN, INTMAX_MIN + 1, INTMAX_MAX);
+}
+
+static void test_assert_uint_in_range(void **state)
+{
+ (void)state; /* unused */
+ assert_uint_in_range(0, 0, 1);
+ assert_uint_in_range(1, 0, 1);
+ assert_uint_in_range(1, 0, 1);
+ assert_uint_in_range(100, 0, UINTMAX_MAX);
+}
+
+static void test_assert_uint_not_in_range(void **state)
+{
+ (void)state; /* unused */
+ assert_int_not_in_range(2, 0, 1);
+ assert_int_not_in_range(0, 1, UINTMAX_MAX);
+}
+
+int main(void) {
+ const struct CMUnitTest range_tests[] = {
+ cmocka_unit_test(test_assert_int_in_range),
+ cmocka_unit_test(test_assert_int_not_in_range),
+ cmocka_unit_test(test_assert_uint_in_range),
+ cmocka_unit_test(test_assert_uint_not_in_range),
+ };
+
+ return cmocka_run_group_tests(range_tests, NULL, NULL);
+}
diff --git a/tests/test_assert_range_fail.c b/tests/test_assert_range_fail.c
new file mode 100644
index 0000000..c9cc45f
--- /dev/null
+++ b/tests/test_assert_range_fail.c
@@ -0,0 +1,58 @@
+#include "config.h"
+
+#include <stdarg.h>
+#include <stdbool.h>
+#include <stddef.h>
+#include <setjmp.h>
+#include <stdint.h>
+#include <cmocka.h>
+#include <cmocka_private.h>
+
+static void test_assert_int_in_range_fail_1(void **state)
+{
+ (void)state; /* unused */
+ assert_int_in_range(0, 1, 2);
+}
+
+static void test_assert_int_in_range_fail_2(void **state)
+{
+ (void)state; /* unused */
+ assert_int_in_range(2, -1, 1);
+}
+
+static void test_assert_int_in_range_fail_3(void **state)
+{
+ (void)state; /* unused */
+ assert_int_in_range(0, 1, INTMAX_MAX);
+}
+
+static void test_assert_int_in_range_fail_4(void **state)
+{
+ (void)state; /* unused */
+ assert_int_in_range(0, INTMAX_MIN, -1);
+}
+
+static void test_assert_int_not_in_range_fail_1(void **state)
+{
+ (void)state; /* unused */
+ assert_int_not_in_range(0, INTMAX_MIN, INTMAX_MAX);
+}
+
+static void test_assert_uint_not_in_range_fail_1(void **state)
+{
+ (void)state; /* unused */
+ assert_uint_not_in_range(1, 0, UINTMAX_MAX);
+}
+
+int main(void) {
+ const struct CMUnitTest range_fail_tests[] = {
+ cmocka_unit_test(test_assert_int_in_range_fail_1),
+ cmocka_unit_test(test_assert_int_in_range_fail_2),
+ cmocka_unit_test(test_assert_int_in_range_fail_3),
+ cmocka_unit_test(test_assert_int_in_range_fail_4),
+ cmocka_unit_test(test_assert_int_not_in_range_fail_1),
+ cmocka_unit_test(test_assert_uint_not_in_range_fail_1),
+ };
+
+ return cmocka_run_group_tests(range_fail_tests, NULL, NULL);
+}
diff --git a/tests/test_assert_set.c b/tests/test_assert_set.c
new file mode 100644
index 0000000..ebdf7f7
--- /dev/null
+++ b/tests/test_assert_set.c
@@ -0,0 +1,120 @@
+#include "config.h"
+
+#include <stdarg.h>
+#include <stdbool.h>
+#include <stddef.h>
+#include <setjmp.h>
+#include <stdint.h>
+#include <cmocka.h>
+#include <cmocka_private.h>
+
+static void test_assert_int_in_set_8(void **state)
+{
+ int8_t set[] = {1, 2, 3, INT8_MAX};
+
+ (void)state; /* unused */
+
+ assert_int_in_set(1, set, ARRAY_SIZE(set));
+}
+
+static void test_assert_int_in_set_16(void **state)
+{
+ int16_t set[] = {1, 2, 3, INT16_MAX};
+
+ (void)state; /* unused */
+
+ assert_int_in_set(INT16_MAX, set, ARRAY_SIZE(set));
+}
+
+static void test_assert_int_in_set_32(void **state)
+{
+ int32_t set[] = {INT32_MIN, -2, -1, 0, 1, 2, 3, INT32_MAX};
+
+ (void)state; /* unused */
+
+ assert_int_in_set(INT32_MIN, set, ARRAY_SIZE(set));
+ assert_int_in_set(-1, set, ARRAY_SIZE(set));
+ assert_int_in_set(0, set, ARRAY_SIZE(set));
+ assert_int_in_set(1, set, ARRAY_SIZE(set));
+ assert_int_in_set(INT32_MAX, set, ARRAY_SIZE(set));
+}
+
+static void test_assert_int_in_set_64(void **state)
+{
+ int64_t set[] = {1, 2, 3, INT64_MAX};
+
+ (void)state; /* unused */
+
+ assert_int_in_set(INT64_MAX, set, ARRAY_SIZE(set));
+}
+
+static void test_assert_int_not_in_set_32(void **state)
+{
+ int32_t set[] = {INT32_MIN + 1, -2, -1, 0, 1, 2, 3, INT32_MAX - 1};
+
+ (void)state; /* unused */
+
+ assert_int_not_in_set(INT32_MIN, set, ARRAY_SIZE(set));
+ assert_int_not_in_set(-3, set, ARRAY_SIZE(set));
+ assert_int_not_in_set(4, set, ARRAY_SIZE(set));
+ assert_int_not_in_set(INT32_MAX, set, ARRAY_SIZE(set));
+}
+
+
+static void test_assert_int_not_in_set_64(void **state)
+{
+ int64_t set[] = {INT64_MIN + 1, -2, -1, 0, 1, 2, 3, INT64_MAX - 1};
+
+ (void)state; /* unused */
+
+ assert_int_not_in_set(INT64_MIN, set, ARRAY_SIZE(set));
+ assert_int_not_in_set(-3, set, ARRAY_SIZE(set));
+ assert_int_not_in_set(4, set, ARRAY_SIZE(set));
+ assert_int_not_in_set(INT64_MAX, set, ARRAY_SIZE(set));
+}
+
+static void test_assert_uint_in_set_32(void **state)
+{
+ uint32_t set[] = {0, 1, 2, 3, UINT32_MAX};
+
+ (void)state; /* unused */
+
+ assert_int_in_set(0, set, ARRAY_SIZE(set));
+ assert_int_in_set(1, set, ARRAY_SIZE(set));
+ assert_int_in_set(UINT32_MAX, set, ARRAY_SIZE(set));
+}
+
+static void test_assert_uint_in_set_64(void **state)
+{
+ uint64_t set[] = {1, 2, 3, UINT64_MAX};
+
+ (void)state; /* unused */
+
+ assert_int_in_set(UINT64_MAX, set, ARRAY_SIZE(set));
+}
+
+static void test_assert_uint_not_in_set_64(void **state)
+{
+ uint64_t set[] = {0, 1, 2, 3, UINT64_MAX - 1};
+
+ (void)state; /* unused */
+
+ assert_uint_not_in_set(UINT64_MAX, set, ARRAY_SIZE(set));
+ assert_uint_not_in_set(4, set, ARRAY_SIZE(set));
+}
+
+int main(void) {
+ const struct CMUnitTest set_tests[] = {
+ cmocka_unit_test(test_assert_int_in_set_8),
+ cmocka_unit_test(test_assert_int_in_set_16),
+ cmocka_unit_test(test_assert_int_in_set_32),
+ cmocka_unit_test(test_assert_int_in_set_64),
+ cmocka_unit_test(test_assert_int_not_in_set_32),
+ cmocka_unit_test(test_assert_int_not_in_set_64),
+ cmocka_unit_test(test_assert_uint_in_set_32),
+ cmocka_unit_test(test_assert_uint_in_set_64),
+ cmocka_unit_test(test_assert_uint_not_in_set_64),
+ };
+
+ return cmocka_run_group_tests(set_tests, NULL, NULL);
+}
diff --git a/tests/test_assert_set_fail.c b/tests/test_assert_set_fail.c
new file mode 100644
index 0000000..4af9423
--- /dev/null
+++ b/tests/test_assert_set_fail.c
@@ -0,0 +1,66 @@
+#include "config.h"
+
+#include <stdarg.h>
+#include <stdbool.h>
+#include <stddef.h>
+#include <setjmp.h>
+#include <stdint.h>
+#include <cmocka.h>
+#include <cmocka_private.h>
+
+static void test_assert_int_in_set_fail(void **state)
+{
+ int32_t set[] = {1, 2, 3, INT32_MIN, INT32_MAX};
+
+ (void)state; /* unused */
+
+ assert_int_in_set(4, set, ARRAY_SIZE(set));
+}
+
+static void test_assert_int_not_in_set_fail(void **state)
+{
+ int32_t set[] = {1, 2, 3, INT32_MIN, INT32_MAX};
+
+ (void)state; /* unused */
+
+ assert_int_not_in_set(3, set, ARRAY_SIZE(set));
+}
+
+static void test_assert_uint_in_set_fail(void **state)
+{
+ uint32_t set[] = {1, 2, 3, UINT32_MAX};
+
+ (void)state; /* unused */
+
+ assert_int_in_set(0, set, ARRAY_SIZE(set));
+}
+
+static void test_assert_uint_not_in_set_fail_1(void **state)
+{
+ uint32_t set[] = {1, 2, 3, UINT32_MAX};
+
+ (void)state; /* unused */
+
+ assert_uint_not_in_set(3, set, ARRAY_SIZE(set));
+}
+
+static void test_assert_uint_not_in_set_fail_2(void **state)
+{
+ uint64_t set[] = {1, 2, 3, UINT64_MAX};
+
+ (void)state; /* unused */
+
+ assert_uint_not_in_set(UINT64_MAX, set, ARRAY_SIZE(set));
+}
+
+int main(void) {
+ const struct CMUnitTest set_fail_tests[] = {
+ cmocka_unit_test(test_assert_int_in_set_fail),
+ cmocka_unit_test(test_assert_int_not_in_set_fail),
+ cmocka_unit_test(test_assert_uint_in_set_fail),
+ cmocka_unit_test(test_assert_uint_not_in_set_fail_1),
+ cmocka_unit_test(test_assert_uint_not_in_set_fail_2),
+ };
+
+ return cmocka_run_group_tests(set_fail_tests, NULL, NULL);
+}
diff --git a/tests/test_assert_true.c b/tests/test_assert_true.c
new file mode 100644
index 0000000..b6f2644
--- /dev/null
+++ b/tests/test_assert_true.c
@@ -0,0 +1,27 @@
+#include "config.h"
+
+#include <stdarg.h>
+#include <stdbool.h>
+#include <stddef.h>
+#include <setjmp.h>
+#include <stdint.h>
+
+#include <cmocka.h>
+#include <cmocka_private.h>
+
+static void test_assert_true(void **state)
+{
+ int x = 10;
+
+ (void)state; /* unused */
+ assert_true(x == 10);
+}
+
+int main(void)
+{
+ const struct CMUnitTest tests[] = {
+ cmocka_unit_test(test_assert_true),
+ };
+
+ return cmocka_run_group_tests(tests, NULL, NULL);
+}
diff --git a/tests/test_assert_true_fail.c b/tests/test_assert_true_fail.c
new file mode 100644
index 0000000..7b49b25
--- /dev/null
+++ b/tests/test_assert_true_fail.c
@@ -0,0 +1,27 @@
+#include "config.h"
+
+#include <stdarg.h>
+#include <stdbool.h>
+#include <stddef.h>
+#include <setjmp.h>
+#include <stdint.h>
+
+#include <cmocka.h>
+#include <cmocka_private.h>
+
+static void test_assert_true_fail(void **state)
+{
+ int x = 10;
+
+ (void)state; /* unused */
+ assert_true(x != 10);
+}
+
+int main(void)
+{
+ const struct CMUnitTest tests[] = {
+ cmocka_unit_test(test_assert_true_fail),
+ };
+
+ return cmocka_run_group_tests(tests, NULL, NULL);
+}
diff --git a/tests/test_assert_u_int.c b/tests/test_assert_u_int.c
new file mode 100644
index 0000000..d1e548a
--- /dev/null
+++ b/tests/test_assert_u_int.c
@@ -0,0 +1,53 @@
+#include "config.h"
+
+#include <stdarg.h>
+#include <stdbool.h>
+#include <stddef.h>
+#include <setjmp.h>
+#include <stdint.h>
+#include <cmocka.h>
+#include <cmocka_private.h>
+
+static void test_assert_int_equal(void **state)
+{
+ (void)state; /* unused */
+ assert_int_equal(0, 0);
+ assert_int_equal(-1, -1);
+ assert_int_equal(INTMAX_MIN, INTMAX_MIN);
+ assert_int_equal(INTMAX_MAX, INTMAX_MAX);
+}
+
+static void test_assert_int_not_equal(void **state)
+{
+ (void)state; /* unused */
+ assert_int_not_equal(0, 1);
+ assert_int_not_equal(-1, 1);
+ assert_int_not_equal(INTMAX_MIN, INTMAX_MAX);
+ assert_int_not_equal(INTMAX_MAX, INTMAX_MIN);
+}
+
+static void test_assert_uint_equal(void **state)
+{
+ (void)state; /* unused */
+ assert_uint_equal(0, 0);
+ assert_uint_equal(1, 1);
+ assert_uint_equal(UINTMAX_MAX, UINTMAX_MAX);
+}
+
+static void test_assert_uint_not_equal(void **state)
+{
+ (void)state; /* unused */
+ assert_uint_not_equal(0, 1);
+ assert_uint_not_equal(0, UINTMAX_MAX);
+}
+
+int main(void) {
+ const struct CMUnitTest integer_tests[] = {
+ cmocka_unit_test(test_assert_int_equal),
+ cmocka_unit_test(test_assert_int_not_equal),
+ cmocka_unit_test(test_assert_uint_equal),
+ cmocka_unit_test(test_assert_uint_not_equal),
+ };
+
+ return cmocka_run_group_tests(integer_tests, NULL, NULL);
+}
diff --git a/tests/test_assert_u_int_fail.c b/tests/test_assert_u_int_fail.c
new file mode 100644
index 0000000..5fbeb15
--- /dev/null
+++ b/tests/test_assert_u_int_fail.c
@@ -0,0 +1,55 @@
+#include "config.h"
+
+#include <stdarg.h>
+#include <stdbool.h>
+#include <stddef.h>
+#include <setjmp.h>
+#include <stdint.h>
+#include <cmocka.h>
+#include <cmocka_private.h>
+
+static void test_assert_int_equal_fail(void **state)
+{
+ (void)state; /* unused */
+ assert_int_equal(0, 1);
+ assert_int_equal(-1, -2);
+ assert_int_equal(INTMAX_MIN, INTMAX_MAX);
+ assert_int_equal(INTMAX_MAX, INTMAX_MIN);
+}
+
+static void test_assert_int_not_equal_fail(void **state)
+{
+ (void)state; /* unused */
+ assert_int_not_equal(0, 0);
+ assert_int_not_equal(1, 1);
+ assert_int_not_equal(INTMAX_MIN, INTMAX_MIN);
+ assert_int_not_equal(INTMAX_MAX, INTMAX_MAX);
+}
+
+static void test_assert_uint_equal_fail(void **state)
+{
+ (void)state; /* unused */
+ assert_uint_equal(0, 1);
+ assert_uint_equal(1, 2);
+ assert_uint_equal(0, UINTMAX_MAX);
+}
+
+static void test_assert_uint_not_equal_fail(void **state)
+{
+ (void)state; /* unused */
+ assert_uint_not_equal(0, 0);
+ assert_uint_not_equal(1, 1);
+ assert_uint_not_equal(UINTMAX_MAX, UINTMAX_MAX);
+}
+
+int main(void) {
+ const struct CMUnitTest integer_tests[] = {
+ cmocka_unit_test(test_assert_int_equal_fail),
+ cmocka_unit_test(test_assert_int_not_equal_fail),
+ cmocka_unit_test(test_assert_uint_equal_fail),
+ cmocka_unit_test(test_assert_uint_not_equal_fail),
+ };
+
+ return cmocka_run_group_tests(integer_tests, NULL, NULL);
+}
+
diff --git a/tests/test_basics.c b/tests/test_basics.c
index 1bb493f..efdbcf3 100644
--- a/tests/test_basics.c
+++ b/tests/test_basics.c
@@ -18,8 +18,10 @@
#define UNIT_TESTING 1
#include <stdarg.h>
+#include <stdbool.h>
#include <stddef.h>
#include <setjmp.h>
+#include <stdint.h>
#include <cmocka.h>
static int setup(void **state) {
diff --git a/tests/test_buffer.c b/tests/test_buffer.c
new file mode 100644
index 0000000..ce32757
--- /dev/null
+++ b/tests/test_buffer.c
@@ -0,0 +1,49 @@
+#include "config.h"
+
+#include <stdarg.h>
+#include <stdbool.h>
+#include <stddef.h>
+#include <setjmp.h>
+#include <stdint.h>
+#include <cmocka.h>
+#include <cmocka_private.h>
+
+#include "../src/cmocka.c"
+
+static const uint8_t buf0[] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+};
+
+static const uint8_t buf1[] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+};
+
+static void test_all_zero(void **state)
+{
+ (void)state;
+
+ assert_true(all_zero(buf0, sizeof(buf0)));
+
+ assert_true(all_zero(NULL, 0));
+
+ assert_true(all_zero(buf0, 0));
+
+ assert_false(all_zero(buf1, sizeof(buf1)));
+}
+
+int main(int argc, char **argv) {
+ const struct CMUnitTest buffer_tests[] = {
+ cmocka_unit_test(test_all_zero),
+ };
+
+ (void)argc;
+ (void)argv;
+
+ return cmocka_run_group_tests(buffer_tests, NULL, NULL);
+}
diff --git a/tests/test_double_macros.c b/tests/test_double_macros.c
index 138c579..ab60f30 100644
--- a/tests/test_double_macros.c
+++ b/tests/test_double_macros.c
@@ -18,8 +18,10 @@
#define UNIT_TESTING 1
#include <stdarg.h>
+#include <stdbool.h>
#include <stddef.h>
#include <setjmp.h>
+#include <stdint.h>
#include <cmocka.h>
/* A test case that does check if double is equal. */
diff --git a/tests/test_exception_handler.c b/tests/test_exception_handler.c
index 5652095..2eab315 100644
--- a/tests/test_exception_handler.c
+++ b/tests/test_exception_handler.c
@@ -1,22 +1,18 @@
#include <stdarg.h>
+#include <stdbool.h>
#include <stddef.h>
#include <setjmp.h>
+#include <stdint.h>
#include <cmocka.h>
-#include <stdlib.h>
-
-struct test_segv {
- int x;
- int y;
-};
+#include <signal.h>
static void test_segfault_recovery(void **state)
{
- struct test_segv *s = NULL;
-
- (void) state; /* unused */
+ (void)state; /* unused */
- s->x = 1;
+ /* Raise segmentation fault */
+ raise(SIGSEGV);
}
static void test_segfault_recovery1(void **state)
@@ -35,11 +31,11 @@ static void test_segfault_recovery3(void **state)
}
int main(void) {
- const struct CMUnitTest tests[] = {
+ const struct CMUnitTest exception_tests[] = {
cmocka_unit_test(test_segfault_recovery1),
cmocka_unit_test(test_segfault_recovery2),
cmocka_unit_test(test_segfault_recovery3),
};
- return cmocka_run_group_tests(tests, NULL, NULL);
+ return cmocka_run_group_tests(exception_tests, NULL, NULL);
}
diff --git a/tests/test_expect_check.c b/tests/test_expect_check.c
new file mode 100644
index 0000000..4ce8bea
--- /dev/null
+++ b/tests/test_expect_check.c
@@ -0,0 +1,139 @@
+#include "config.h"
+
+#include <stdarg.h>
+#include <stdbool.h>
+#include <stddef.h>
+#include <setjmp.h>
+#include <stdint.h>
+#include <cmocka.h>
+#include <cmocka_private.h>
+#include <stdio.h>
+#include <string.h>
+
+
+static void mock_test_a(int value)
+{
+ check_expected(value);
+}
+
+int custom_checker(CMockaValueData param, CMockaValueData check);
+int custom_checker(CMockaValueData param, CMockaValueData check)
+{
+ assert_int_equal(param.uint_val, check.uint_val);
+ return true;
+}
+
+static void test_expect_check(void **state)
+{
+ (void)state; /* unused */
+ expect_check(mock_test_a, value, custom_checker, cast_int_to_cmocka_value(0));
+ mock_test_a(0);
+}
+
+static void test_expect_check_count(void **state)
+{
+ (void)state; /* unused */
+ expect_check_count(mock_test_a, value, custom_checker, cast_int_to_cmocka_value(0), 2);
+ mock_test_a(0);
+ mock_test_a(0);
+}
+
+static void test_expect_check_count_always(void **state)
+{
+ (void)state; /* unused */
+ expect_check_count(mock_test_a, value, custom_checker, cast_int_to_cmocka_value(0), EXPECT_ALWAYS);
+ mock_test_a(0);
+ mock_test_a(0);
+ mock_test_a(0);
+ mock_test_a(0);
+}
+
+static void test_expect_check_count_maybe_1(void **state)
+{
+ (void)state; /* unused */
+ expect_check_count(mock_test_a, value, custom_checker, cast_int_to_cmocka_value(0), EXPECT_MAYBE);
+ mock_test_a(0);
+ mock_test_a(0);
+ mock_test_a(0);
+ mock_test_a(0);
+}
+
+static void test_expect_check_count_maybe_2(void **state)
+{
+ (void)state; /* unused */
+ expect_check_count(mock_test_a, value, custom_checker, cast_int_to_cmocka_value(0), EXPECT_MAYBE);
+}
+
+static void mock_test_ptr(const void *value)
+{
+ check_expected_ptr(value);
+}
+
+static void test_expect_string(void **state)
+{
+ (void)state; /* unused */
+ char string[64];
+ snprintf(string, sizeof(string), "hello world");
+ assert_ptr_not_equal(string,
+ "hello world"); // should be different memory addresses
+
+ expect_string(mock_test_ptr, value, string);
+ mock_test_ptr("hello world");
+
+ expect_not_string(mock_test_ptr, value, string);
+ mock_test_ptr("hello world with extra bytes");
+
+ expect_memory(mock_test_ptr, value, string, strlen(string));
+ mock_test_ptr("hello world");
+
+ expect_not_memory(mock_test_ptr, value, string, strlen(string));
+ mock_test_ptr("different data");
+}
+
+static void test_expect_string_count_always(void **state)
+{
+ (void)state; /* unused */
+ char string[64];
+ snprintf(string, sizeof(string), "hello world");
+ assert_ptr_not_equal(string,
+ "hello world"); // should be different memory addresses
+
+ expect_string_count(mock_test_ptr, value, string, EXPECT_ALWAYS);
+ mock_test_ptr("hello world");
+ mock_test_ptr("hello world");
+}
+
+static void test_expect_string_count_maybe_1(void **state)
+{
+ (void)state; /* unused */
+ char string[64];
+ snprintf(string, sizeof(string), "hello world");
+ assert_ptr_not_equal(string,
+ "hello world"); // should be different memory addresses
+
+ expect_string_count(mock_test_ptr, value, string, EXPECT_MAYBE);
+ mock_test_ptr("hello world");
+ mock_test_ptr("hello world");
+}
+
+static void test_expect_string_count_maybe_2(void **state)
+{
+ (void)state; /* unused */
+ const char string[] = "hello world";
+ expect_string_count(mock_test_ptr, value, string, EXPECT_MAYBE);
+}
+
+int main(void) {
+ const struct CMUnitTest tests[] = {
+ cmocka_unit_test(test_expect_check),
+ cmocka_unit_test(test_expect_check_count),
+ cmocka_unit_test(test_expect_check_count_always),
+ cmocka_unit_test(test_expect_check_count_maybe_1),
+ cmocka_unit_test(test_expect_check_count_maybe_2),
+ cmocka_unit_test(test_expect_string),
+ cmocka_unit_test(test_expect_string_count_always),
+ cmocka_unit_test(test_expect_string_count_maybe_1),
+ cmocka_unit_test(test_expect_string_count_maybe_2)};
+
+ return cmocka_run_group_tests(tests, NULL, NULL);
+}
diff --git a/tests/test_expect_check_fail.c b/tests/test_expect_check_fail.c
new file mode 100644
index 0000000..54a7565
--- /dev/null
+++ b/tests/test_expect_check_fail.c
@@ -0,0 +1,50 @@
+#include "config.h"
+
+#include <stdarg.h>
+#include <stdbool.h>
+#include <stddef.h>
+#include <setjmp.h>
+#include <stdint.h>
+#include <cmocka.h>
+#include <cmocka_private.h>
+
+static void mock_test_a(int value)
+{
+ check_expected(value);
+}
+
+int custom_checker(CMockaValueData param, CMockaValueData check);
+int custom_checker(CMockaValueData param, CMockaValueData check)
+{
+ assert_int_equal(param.uint_val, check.uint_val);
+ return true;
+}
+
+static void test_no_expects_fail(void **state)
+{
+ (void)state; /* unused */
+ mock_test_a(0);
+}
+
+static void test_expect_check_count_remaining_fail(void **state)
+{
+ (void)state; /* unused */
+ expect_check_count(mock_test_a, value, custom_checker, cast_int_to_cmocka_value(0), 2);
+ mock_test_a(0);
+}
+
+static void test_expect_check_count_always_remaining_fail(void **state)
+{
+ (void)state; /* unused */
+ expect_check_count(mock_test_a, value, custom_checker, cast_int_to_cmocka_value(0), EXPECT_ALWAYS);
+}
+
+int main(void) {
+ const struct CMUnitTest tests[] = {
+ cmocka_unit_test(test_no_expects_fail),
+ cmocka_unit_test(test_expect_check_count_remaining_fail),
+ cmocka_unit_test(test_expect_check_count_always_remaining_fail),
+ };
+
+ return cmocka_run_group_tests(tests, NULL, NULL);
+}
diff --git a/tests/test_expect_u_int_in_set.c b/tests/test_expect_u_int_in_set.c
new file mode 100644
index 0000000..46e2e4c
--- /dev/null
+++ b/tests/test_expect_u_int_in_set.c
@@ -0,0 +1,50 @@
+#include "config.h"
+
+#include <stdarg.h>
+#include <stdbool.h>
+#include <stddef.h>
+#include <setjmp.h>
+#include <stdint.h>
+#include <cmocka.h>
+#include <cmocka_private.h>
+#include <stdio.h>
+#include <string.h>
+
+
+static void mock_test_int(intmax_t value)
+{
+ check_expected(value);
+}
+
+static void mock_test_uint(uintmax_t value)
+{
+ check_expected(value);
+}
+
+static void test_expect_int_in_set_count(void **state)
+{
+ intmax_t set[] = { -1, 0, 1 };
+ (void)state; /* unused */
+
+ expect_int_in_set_count(mock_test_int, value, set, 1);
+
+ mock_test_int(-1);
+}
+
+static void test_expect_uint_in_set_count(void **state)
+{
+ uintmax_t set[] = { 0, 1, 42, UINTMAX_MAX };
+ (void)state; /* unused */
+
+ expect_uint_in_set_count(mock_test_uint, value, set, 1);
+
+ mock_test_uint(42);
+}
+
+int main(void) {
+ const struct CMUnitTest tests[] = {
+ cmocka_unit_test(test_expect_int_in_set_count),
+ cmocka_unit_test(test_expect_uint_in_set_count)};
+
+ return cmocka_run_group_tests(tests, NULL, NULL);
+}
diff --git a/tests/test_fixtures.c b/tests/test_fixtures.c
index 6d39487..c8ce641 100644
--- a/tests/test_fixtures.c
+++ b/tests/test_fixtures.c
@@ -1,6 +1,8 @@
#include <stdarg.h>
+#include <stdbool.h>
#include <stddef.h>
#include <setjmp.h>
+#include <stdint.h>
#include <cmocka.h>
#include <stdlib.h>
@@ -28,6 +30,12 @@ static void malloc_setup_test(void **state)
static void malloc_teardown_test(void **state)
{
*state = malloc(1);
+ if (*state == NULL) {
+ // do nothing, we're just checking this because otherwise GCC 11
+ // sometimes incorrectly throws a -Werror=maybe-uninitialized error
+ // This is fixed in GCC 12
+ assert_null(NULL);
+ }
assert_non_null(*state);
}
diff --git a/tests/test_float_macros.c b/tests/test_float_macros.c
index a9c7251..063a6db 100644
--- a/tests/test_float_macros.c
+++ b/tests/test_float_macros.c
@@ -18,8 +18,10 @@
#define UNIT_TESTING 1
#include <stdarg.h>
+#include <stdbool.h>
#include <stddef.h>
#include <setjmp.h>
+#include <stdint.h>
#include <cmocka.h>
/* A test case that does check if float is equal. */
diff --git a/tests/test_group_fixtures.c b/tests/test_group_fixtures.c
index 64f0ab7..1ed71ce 100644
--- a/tests/test_group_fixtures.c
+++ b/tests/test_group_fixtures.c
@@ -2,8 +2,10 @@
#define UNIT_TESTING 1
#include <stdarg.h>
+#include <stdbool.h>
#include <stddef.h>
#include <setjmp.h>
+#include <stdint.h>
#include <cmocka.h>
static int group_setup(void **state)
diff --git a/tests/test_group_setup_assert.c b/tests/test_group_setup_assert.c
index eef61f8..7ed19e7 100644
--- a/tests/test_group_setup_assert.c
+++ b/tests/test_group_setup_assert.c
@@ -2,8 +2,10 @@
#define UNIT_TESTING 1
#include <stdarg.h>
+#include <stdbool.h>
#include <stddef.h>
#include <setjmp.h>
+#include <stdint.h>
#include <cmocka.h>
static int group_setup_failing(void **state)
diff --git a/tests/test_group_setup_fail.c b/tests/test_group_setup_fail.c
index 7815c03..2992a78 100644
--- a/tests/test_group_setup_fail.c
+++ b/tests/test_group_setup_fail.c
@@ -2,8 +2,10 @@
#define UNIT_TESTING 1
#include <stdarg.h>
+#include <stdbool.h>
#include <stddef.h>
#include <setjmp.h>
+#include <stdint.h>
#include <cmocka.h>
static int group_setup_failing(void **state)
diff --git a/tests/test_groups.c b/tests/test_groups.c
index af9e2b8..e7f3f9c 100644
--- a/tests/test_groups.c
+++ b/tests/test_groups.c
@@ -18,8 +18,10 @@
#define UNIT_TESTING 1
#include <stdarg.h>
+#include <stdbool.h>
#include <stddef.h>
#include <setjmp.h>
+#include <stdint.h>
#include <cmocka.h>
static int setup(void **state) {
@@ -63,7 +65,7 @@ int main(void) {
int result = 0;
result += cmocka_run_group_tests(test_group1, NULL, NULL);
- result += cmocka_run_group_tests(test_group2, NULL, NULL);
+ result += cmocka_run_group_tests_name("test_group2 num=<'\"2&2'\">", test_group2, NULL, NULL);
return result;
}
diff --git a/tests/test_ordering.c b/tests/test_ordering.c
index 817c0ba..4d55652 100644
--- a/tests/test_ordering.c
+++ b/tests/test_ordering.c
@@ -1,8 +1,10 @@
#include "config.h"
#include <stdarg.h>
+#include <stdbool.h>
#include <stddef.h>
#include <setjmp.h>
+#include <stdint.h>
#include <cmocka.h>
#include <cmocka_private.h>
diff --git a/tests/test_ordering_fail.c b/tests/test_ordering_fail.c
index 652f5ad..f9e7de7 100644
--- a/tests/test_ordering_fail.c
+++ b/tests/test_ordering_fail.c
@@ -1,8 +1,10 @@
#include "config.h"
#include <stdarg.h>
+#include <stdbool.h>
#include <stddef.h>
#include <setjmp.h>
+#include <stdint.h>
#include <cmocka.h>
#include <cmocka_private.h>
@@ -80,6 +82,14 @@ static void test_fails_if_zero_count_used(void **state)
mock_test_a_called();
}
+static void test_fails_for_unexpected_call_with_ignored_calls(void **state)
+{
+ (void)state;
+ ignore_function_calls(mock_test_a_called);
+
+ mock_test_b_called();
+}
+
int main(void) {
const struct CMUnitTest tests[] = {
cmocka_unit_test(test_does_fail_for_unexpected_call)
@@ -89,6 +99,7 @@ int main(void) {
,cmocka_unit_test(test_ordering_fails_out_of_order_for_at_least_once_calls)
,cmocka_unit_test(test_fails_out_of_order_if_no_calls_found_on_any)
,cmocka_unit_test(test_fails_if_zero_count_used)
+ ,cmocka_unit_test(test_fails_for_unexpected_call_with_ignored_calls)
};
return cmocka_run_group_tests(tests, NULL, NULL);
diff --git a/tests/test_returns.c b/tests/test_returns.c
index b9370c9..8ea7c40 100644
--- a/tests/test_returns.c
+++ b/tests/test_returns.c
@@ -1,8 +1,10 @@
#include "config.h"
#include <stdarg.h>
+#include <stdbool.h>
#include <stddef.h>
#include <setjmp.h>
+#include <stdint.h>
#include <cmocka.h>
#include <cmocka_private.h>
@@ -13,7 +15,37 @@ void mock_function_call_times(size_t times, int expectedValue);
int mock_function(void)
{
- return (int) mock();
+ return (int) mock();
+}
+
+intmax_t mock_function_int(void);
+intmax_t mock_function_int(void)
+{
+ return mock_int();
+}
+
+uintmax_t mock_function_uint(void);
+uintmax_t mock_function_uint(void)
+{
+ return mock_uint();
+}
+
+uint64_t mock_function_uint64(void);
+uint64_t mock_function_uint64(void)
+{
+ return (uint64_t)mock_uint();
+}
+
+double mock_function_float(void);
+double mock_function_float(void)
+{
+ return mock_float();
+}
+
+const char *mock_function_ptr(void);
+const char *mock_function_ptr(void)
+{
+ return mock_ptr_type(const char *);
}
void mock_function_call_times(size_t times, int expectedValue)
@@ -55,11 +87,70 @@ static void test_will_return_maybe_for_more_than_one_call(void **state)
mock_function_call_times(numberOfCalls, value);
}
+static void test_will_return_int(void **state)
+{
+ intmax_t value;
+
+ (void)state; /* unused */
+
+ value = rand();
+ will_return_int(mock_function_int, value);
+ assert_int_equal(value, mock_function_int());
+}
+
+static void test_will_return_uint(void **state)
+{
+ uintmax_t value;
+
+ (void)state; /* unused */
+
+ value = rand();
+ will_return_uint(mock_function_uint, value);
+ assert_uint_equal(value, mock_function_uint());
+}
+
+static void test_will_return_uint64(void **state)
+{
+ uint64_t value = 86405000000UL;
+ uint64_t ret;
+
+ (void)state; /* unused */
+
+ will_return_uint(mock_function_uint64, value);
+ ret = mock_function_uint64();
+ assert_uint_equal(ret, 86405000000UL);
+}
+
+static void test_will_return_float(void **state)
+{
+ double value = 1.0;
+
+ (void)state; /* unused */
+
+ will_return_float(mock_function_float, value);
+ assert_float_equal(value, mock_function_float(), 0.0);
+}
+
+static void test_will_return_ptr(void **state)
+{
+ const char *value = "What a Wurst!";
+
+ (void)state; /* unused */
+
+ will_return_ptr_type(mock_function_ptr, value, const char *);
+ assert_string_equal(value, mock_function_ptr());
+}
+
int main(int argc, char **argv) {
const struct CMUnitTest alloc_tests[] = {
- cmocka_unit_test(test_will_return_maybe_for_no_calls)
- ,cmocka_unit_test(test_will_return_maybe_for_one_mock_call)
- ,cmocka_unit_test(test_will_return_maybe_for_more_than_one_call)
+ cmocka_unit_test(test_will_return_maybe_for_no_calls),
+ cmocka_unit_test(test_will_return_maybe_for_one_mock_call),
+ cmocka_unit_test(test_will_return_maybe_for_more_than_one_call),
+ cmocka_unit_test(test_will_return_int),
+ cmocka_unit_test(test_will_return_uint),
+ cmocka_unit_test(test_will_return_uint64),
+ cmocka_unit_test(test_will_return_float),
+ cmocka_unit_test(test_will_return_ptr),
};
(void)argc;
diff --git a/tests/test_returns_fail.c b/tests/test_returns_fail.c
index 81197d3..56b2d61 100644
--- a/tests/test_returns_fail.c
+++ b/tests/test_returns_fail.c
@@ -1,8 +1,10 @@
#include "config.h"
#include <stdarg.h>
+#include <stdbool.h>
#include <stddef.h>
#include <setjmp.h>
+#include <stdint.h>
#include <cmocka.h>
#include <cmocka_private.h>
@@ -16,6 +18,19 @@ int mock_function(void)
return (int) mock();
}
+uintmax_t mock_function_uint(void);
+uintmax_t mock_function_uint(void)
+{
+ return mock_uint();
+}
+
+void *mock_function_ptr(void);
+void *mock_function_ptr(void)
+{
+ return mock_ptr_type(void *);
+}
+
+
void mock_function_call_times(size_t times, int expectedValue)
{
size_t i;
@@ -63,15 +78,36 @@ static int teardown(void **state) {
return 0;
}
-int main(int argc, char **argv) {
- const struct CMUnitTest alloc_tests[] = {
- cmocka_unit_test_teardown(test_will_return_fails_for_no_calls, teardown)
- ,cmocka_unit_test_teardown(test_will_return_count_fails_for_unreturned_items, teardown)
- ,cmocka_unit_test_teardown(test_will_return_always_fails_for_no_calls, teardown)
- };
+static void test_will_return_int_type_mismatch(void **state)
+{
+ intmax_t value = rand();
+
+ (void) state;
- (void)argc;
- (void)argv;
+ will_return_int(mock_function_uint, value);
+ mock_function_uint();
+}
+
+static void test_will_return_ptr_type_mismatch(void **state)
+{
+ const char *value = "What a Wurst!";
+
+ (void) state;
+
+ will_return_ptr_type(mock_function_uint, value, const char *);
+ mock_function_ptr();
+}
+
+int main(void)
+{
+ const struct CMUnitTest will_return_mock_tests[] = {
+ cmocka_unit_test_teardown(test_will_return_fails_for_no_calls, teardown),
+ cmocka_unit_test_teardown(test_will_return_count_fails_for_unreturned_items, teardown),
+ cmocka_unit_test_teardown(test_will_return_always_fails_for_no_calls, teardown),
+ cmocka_unit_test_teardown(test_will_return_fails_for_no_calls, teardown),
+ cmocka_unit_test(test_will_return_int_type_mismatch),
+ cmocka_unit_test(test_will_return_ptr_type_mismatch),
+ };
- return cmocka_run_group_tests(alloc_tests, NULL, NULL);
+ return cmocka_run_group_tests(will_return_mock_tests, NULL, NULL);
}
diff --git a/tests/test_setup_fail.c b/tests/test_setup_fail.c
index e3f8df8..e9c4ca2 100644
--- a/tests/test_setup_fail.c
+++ b/tests/test_setup_fail.c
@@ -1,8 +1,10 @@
#define UNIT_TESTING 1
#include <stdarg.h>
+#include <stdbool.h>
#include <stddef.h>
#include <setjmp.h>
+#include <stdint.h>
#include <cmocka.h>
static int setup_fail(void **state) {
diff --git a/tests/test_skip.c b/tests/test_skip.c
index 127161a..9f63441 100644
--- a/tests/test_skip.c
+++ b/tests/test_skip.c
@@ -15,8 +15,10 @@
*/
#include <stdarg.h>
+#include <stdbool.h>
#include <stddef.h>
#include <setjmp.h>
+#include <stdint.h>
#include <cmocka.h>
/* A test case that does check if an int is equal. */
diff --git a/tests/test_skip_filter.c b/tests/test_skip_filter.c
index e40209e..273b6bd 100644
--- a/tests/test_skip_filter.c
+++ b/tests/test_skip_filter.c
@@ -17,8 +17,10 @@
*/
#include <stdarg.h>
+#include <stdbool.h>
#include <stddef.h>
#include <setjmp.h>
+#include <stdint.h>
#include <cmocka.h>
static void test_skip1(void **state)
diff --git a/tests/test_stop.c b/tests/test_stop.c
new file mode 100644
index 0000000..9f65d97
--- /dev/null
+++ b/tests/test_stop.c
@@ -0,0 +1,51 @@
+/*
+ * Copyright 2022 Carsten Lange
+ *
+ * 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 <stdarg.h>
+#include <stdbool.h>
+#include <stddef.h>
+#include <setjmp.h>
+#include <stdint.h>
+#include <cmocka.h>
+
+static void mock_test_a_called(void)
+{
+ function_called();
+}
+
+static void mock_test_b_called(void)
+{
+ function_called();
+}
+
+static void test_check_stop(void **state) {
+ (void)state; /* unused */
+
+ expect_function_call(mock_test_a_called);
+
+ mock_test_a_called();
+ stop();
+ mock_test_b_called(); /* not called due to calling stop() */
+}
+
+
+int main(void) {
+ const struct CMUnitTest tests[] = {
+ cmocka_unit_test(test_check_stop),
+ };
+
+ return cmocka_run_group_tests(tests, NULL, NULL);
+}
diff --git a/tests/test_stop_fail.c b/tests/test_stop_fail.c
new file mode 100644
index 0000000..c2fbcc1
--- /dev/null
+++ b/tests/test_stop_fail.c
@@ -0,0 +1,95 @@
+/*
+ * Copyright 2022 Carsten Lange
+ *
+ * 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 <stdarg.h>
+#include <stdbool.h>
+#include <stddef.h>
+#include <setjmp.h>
+#include <stdint.h>
+#include <cmocka.h>
+
+static void mock_test_a_called(void)
+{
+ function_called();
+}
+
+static void mock_test_b_called(void)
+{
+ function_called();
+}
+
+static void mock_test_a_expected(int value)
+{
+ check_expected(value);
+}
+
+static void mock_test_b_expected(int value)
+{
+ check_expected(value);
+}
+
+static int mock_test_a_will_return(void)
+{
+ return mock_type(int);
+}
+
+static int mock_test_b_will_return(void)
+{
+ return mock_type(int);
+}
+
+static void test_stop_fails_when_not_returned_values_exist(void **state) {
+ (void)state; /* unused */
+
+ will_return(mock_test_a_will_return, 5);
+ will_return(mock_test_b_will_return, 7);
+
+ (void) mock_test_a_will_return();
+ stop();
+ (void) mock_test_b_will_return();
+}
+
+static void test_stop_fails_when_not_checked_values_exist(void **state) {
+ (void)state; /* unused */
+
+ expect_value(mock_test_a_expected, value, 5);
+ expect_value(mock_test_b_expected, value, 7);
+
+ mock_test_a_expected(5);
+ stop();
+ mock_test_b_expected(7);
+}
+
+static void test_stop_fails_when_unmade_expected_call_exist(void **state) {
+ (void)state; /* unused */
+
+ expect_function_call(mock_test_a_called);
+ expect_function_call(mock_test_b_called);
+
+ mock_test_a_called();
+ stop();
+ mock_test_b_called();
+}
+
+int main(void) {
+ const struct CMUnitTest tests[] = {
+ cmocka_unit_test(test_stop_fails_when_not_returned_values_exist),
+ cmocka_unit_test(test_stop_fails_when_not_checked_values_exist),
+ cmocka_unit_test(test_stop_fails_when_unmade_expected_call_exist),
+ };
+
+ return cmocka_run_group_tests(tests, NULL, NULL);
+}
diff --git a/tests/test_cmockery.c b/tests/test_string.c
index 83a7451..495d113 100644
--- a/tests/test_cmockery.c
+++ b/tests/test_string.c
@@ -1,5 +1,5 @@
/*
- * Copyright 2008 Google Inc.
+ * Copyright 2020 Andreas Schneider <asn@cryptomilk.org>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -15,18 +15,29 @@
*/
#include <stdarg.h>
+#include <stdbool.h>
#include <stddef.h>
+#include <stdint.h>
#include <setjmp.h>
-#include <cmockery/cmockery.h>
+#include <cmocka.h>
-/* A test case that does nothing and succeeds. */
-static void null_test_success(void **state) {
- (void) state; /* unused */
+static void torture_string_equal(void **state)
+{
+ (void)state; /* unused */
+ assert_string_equal("wurst", "wurst");
+}
+
+static void torture_string_not_equal(void **state)
+{
+ (void)state; /* unused */
+ assert_string_not_equal("wurst", "brot");
}
int main(void) {
- const UnitTest tests[] = {
- unit_test(null_test_success),
+ const struct CMUnitTest tests[] = {
+ cmocka_unit_test(torture_string_equal),
+ cmocka_unit_test(torture_string_not_equal),
};
- return run_tests(tests);
+
+ return cmocka_run_group_tests(tests, NULL, NULL);
}
diff --git a/tests/test_strmatch.c b/tests/test_strmatch.c
index f2d966b..5dea70c 100644
--- a/tests/test_strmatch.c
+++ b/tests/test_strmatch.c
@@ -17,8 +17,10 @@
#include "config.h"
#include <stdarg.h>
+#include <stdbool.h>
#include <stddef.h>
#include <setjmp.h>
+#include <stdint.h>
#include <cmocka.h>
#include "../src/cmocka.c"
diff --git a/tests/test_strreplace.c b/tests/test_strreplace.c
new file mode 100644
index 0000000..9f7545c
--- /dev/null
+++ b/tests/test_strreplace.c
@@ -0,0 +1,129 @@
+/*
+ * Copyright 2024 Jakub Czapiga <mordijc@gmail.com>
+ *
+ * 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 "config.h"
+
+#include <stdarg.h>
+#include <stdbool.h>
+#include <stddef.h>
+#include <setjmp.h>
+#include <stdint.h>
+#include <errno.h>
+#include <cmocka.h>
+
+#include "../src/cmocka.c"
+
+static void test_strreplace_null(void **state)
+{
+ bool ok = false;
+ char data[64] = "DATA";
+ bool out = false;
+
+ (void)state;
+
+ ok = c_strreplace(NULL, sizeof(data), "A", "B", &out);
+ assert_false(ok);
+ assert_false(out);
+ assert_int_equal(errno, EINVAL);
+
+ ok = c_strreplace(data, 0, "A", "B", &out);
+ assert_false(ok);
+ assert_false(out);
+ assert_int_equal(errno, EINVAL);
+
+ ok = c_strreplace(data, sizeof(data), NULL, "B", &out);
+ assert_false(ok);
+ assert_false(out);
+ assert_int_equal(errno, EINVAL);
+
+ ok = c_strreplace(data, sizeof(data), "A", NULL, &out);
+ assert_false(ok);
+ assert_false(out);
+ assert_int_equal(errno, EINVAL);
+}
+
+static void test_strreplace_no_pattern(void **state)
+{
+ bool ok = false;
+ char data[64] = "DATA";
+ bool out = false;
+
+ (void) state;
+
+ ok = c_strreplace(data, sizeof(data), "X", "Y", &out);
+ assert_true(ok);
+ assert_false(out);
+}
+
+static void test_strreplace_patterns(void **state)
+{
+ bool ok = false;
+ const char base_data[] = "THIS IS THE DATA";
+ char data[64] = "THIS IS THE DATA";
+ bool out = false;
+
+ (void) state;
+
+ // Simple character substitution
+ ok = c_strreplace(data, sizeof(data), "T", "D", &out);
+ assert_true(ok);
+ assert_true(out);
+ assert_string_equal(data, "DHIS IS DHE DADA");
+
+ // Reset data
+ memcpy(data, base_data, sizeof(base_data));
+
+ // Superset pattern
+ out = false;
+ ok = c_strreplace(data, sizeof(data), " IS", " ISN'T", &out);
+ assert_true(ok);
+ assert_true(out);
+ assert_string_equal(data, "THIS ISN'T THE DATA");
+
+ // Subset pattern
+ memcpy(data, base_data, sizeof(base_data));
+ out = false;
+ ok = c_strreplace(data, sizeof(data), "THIS", "TIS", &out);
+ assert_true(ok);
+ assert_true(out);
+ assert_string_equal(data, "TIS IS THE DATA");
+
+ // Partial replacement
+ memcpy(data, base_data, sizeof(base_data));
+ out = false;
+ ok = c_strreplace(data, sizeof(data), "THIS", "THOSE", &out);
+ assert_true(ok);
+ assert_true(out);
+ assert_string_equal(data, "THOSE IS THE DATA");
+
+ // Outer extension
+ memcpy(data, base_data, sizeof(base_data));
+ out = false;
+ ok = c_strreplace(data, sizeof(data), "THE", "_THE_", &out);
+ assert_true(ok);
+ assert_true(out);
+ assert_string_equal(data, "THIS IS _THE_ DATA");
+}
+
+int main(void) {
+ const struct CMUnitTest tests[] = {
+ cmocka_unit_test(test_strreplace_null),
+ cmocka_unit_test(test_strreplace_no_pattern),
+ cmocka_unit_test(test_strreplace_patterns),
+ };
+
+ return cmocka_run_group_tests(tests, NULL, NULL);
+}
diff --git a/tests/test_wildcard.c b/tests/test_wildcard.c
index 10ee195..17517f8 100644
--- a/tests/test_wildcard.c
+++ b/tests/test_wildcard.c
@@ -15,8 +15,10 @@
*/
#include <stdarg.h>
+#include <stdbool.h>
#include <stddef.h>
#include <setjmp.h>
+#include <stdint.h>
#include <cmocka.h>
static void test_ok1(void **state)