@@ -0,0 +1,2 @@ | |||
-Iinclude | |||
-Iobj |
@@ -0,0 +1,7 @@ | |||
*.swp | |||
*~$ | |||
tags | |||
cscope.* | |||
.ycm_extra_conf.pyc | |||
/build | |||
/obj* |
@@ -0,0 +1,109 @@ | |||
import os | |||
import ycm_core | |||
flags = [ | |||
'-Wall', | |||
'-Wextra', | |||
'-Werror', | |||
'-x', 'c', | |||
'-Iinclude', | |||
] | |||
# Set this to the absolute path to the folder (NOT the file!) containing the | |||
# compile_commands.json file to use that instead of 'flags'. See here for | |||
# more details: http://clang.llvm.org/docs/JSONCompilationDatabase.html | |||
# | |||
# Most projects will NOT need to set this to anything; you can just change the | |||
# 'flags' list of compilation flags. Notice that YCM itself uses that approach. | |||
compilation_database_folder = 'obj' | |||
if os.path.exists( compilation_database_folder ): | |||
database = ycm_core.CompilationDatabase( compilation_database_folder ) | |||
else: | |||
database = None | |||
SOURCE_EXTENSIONS = [ '.cpp', '.cxx', '.cc', '.c', '.m', '.mm' ] | |||
def DirectoryOfThisScript(): | |||
return os.path.dirname( os.path.abspath( __file__ ) ) | |||
def MakeRelativePathsInFlagsAbsolute( flags, working_directory ): | |||
if not working_directory: | |||
return list( flags ) | |||
new_flags = [] | |||
make_next_absolute = False | |||
path_flags = [ '-isystem', '-I', '-iquote', '--sysroot=' ] | |||
for flag in flags: | |||
new_flag = flag | |||
if make_next_absolute: | |||
make_next_absolute = False | |||
if not flag.startswith( '/' ): | |||
new_flag = os.path.join( working_directory, flag ) | |||
for path_flag in path_flags: | |||
if flag == path_flag: | |||
make_next_absolute = True | |||
break | |||
if flag.startswith( path_flag ): | |||
path = flag[ len( path_flag ): ] | |||
new_flag = path_flag + os.path.join( working_directory, path ) | |||
break | |||
if new_flag: | |||
new_flags.append( new_flag ) | |||
return new_flags | |||
def IsHeaderFile( filename ): | |||
extension = os.path.splitext( filename )[ 1 ] | |||
return extension in [ '.h', '.hxx', '.hpp', '.hh' ] | |||
def GetCompilationInfoForFile( filename ): | |||
# The compilation_commands.json file generated by CMake does not have entries | |||
# for header files. So we do our best by asking the db for flags for a | |||
# corresponding source file, if any. If one exists, the flags for that file | |||
# should be good enough. | |||
if IsHeaderFile( filename ): | |||
basename = os.path.splitext( filename )[ 0 ] | |||
for extension in SOURCE_EXTENSIONS: | |||
replacement_file = basename + extension | |||
if os.path.exists( replacement_file ): | |||
compilation_info = database.GetCompilationInfoForFile( | |||
replacement_file ) | |||
if compilation_info.compiler_flags_: | |||
return compilation_info | |||
return None | |||
return database.GetCompilationInfoForFile( filename ) | |||
def FlagsForFile( filename, **kwargs ): | |||
if database: | |||
# Bear in mind that compilation_info.compiler_flags_ does NOT return a | |||
# python list, but a "list-like" StringVec object | |||
compilation_info = GetCompilationInfoForFile( filename ) | |||
if not compilation_info: | |||
return None | |||
final_flags = MakeRelativePathsInFlagsAbsolute( | |||
compilation_info.compiler_flags_, | |||
compilation_info.compiler_working_dir_ ) | |||
# NOTE: This is just for YouCompleteMe; it's highly likely that your project | |||
# does NOT need to remove the stdlib flag. DO NOT USE THIS IN YOUR | |||
# ycm_extra_conf IF YOU'RE NOT 100% SURE YOU NEED IT. | |||
try: | |||
final_flags.remove( '-stdlib=libc++' ) | |||
except ValueError: | |||
pass | |||
else: | |||
relative_to = DirectoryOfThisScript() | |||
final_flags = MakeRelativePathsInFlagsAbsolute( flags, relative_to ) | |||
return { | |||
'flags': final_flags, | |||
'do_cache': True | |||
} |
@@ -0,0 +1,3 @@ | |||
opensource@google.com | |||
Andreas Schneider <asn@cryptomilk.org> | |||
Jakub Hrozek <jakub.hrozek@posteo.se> |
@@ -0,0 +1,88 @@ | |||
project(cmocka C) | |||
# Required cmake version | |||
cmake_minimum_required(VERSION 2.6.0) | |||
# global needed variables | |||
set(APPLICATION_NAME ${PROJECT_NAME}) | |||
set(APPLICATION_VERSION_MAJOR "1") | |||
set(APPLICATION_VERSION_MINOR "1") | |||
set(APPLICATION_VERSION_PATCH "1") | |||
set(APPLICATION_VERSION "${APPLICATION_VERSION_MAJOR}.${APPLICATION_VERSION_MINOR}.${APPLICATION_VERSION_PATCH}") | |||
# SOVERSION scheme: CURRENT.AGE.REVISION | |||
# If there was an incompatible interface change: | |||
# Increment CURRENT. Set AGE and REVISION to 0 | |||
# If there was a compatible interface change: | |||
# Increment AGE. Set REVISION to 0 | |||
# If the source code was changed, but there were no interface changes: | |||
# Increment REVISION. | |||
set(LIBRARY_VERSION "0.4.1") | |||
set(LIBRARY_SOVERSION "0") | |||
# where to look first for cmake modules, before ${CMAKE_ROOT}/Modules/ is checked | |||
set(CMAKE_MODULE_PATH | |||
${CMAKE_CURRENT_SOURCE_DIR}/cmake/Modules | |||
) | |||
# add definitions | |||
include(DefineCMakeDefaults) | |||
include(DefinePlatformDefaults) | |||
include(DefineCompilerFlags) | |||
include(DefineInstallationPaths) | |||
include(DefineOptions.cmake) | |||
include(CPackConfig.cmake) | |||
include(CheckSymbolExists) | |||
# disallow in-source build | |||
include(MacroEnsureOutOfSourceBuild) | |||
macro_ensure_out_of_source_build("${PROJECT_NAME} requires an out of source build. Please create a separate build directory and run 'cmake /path/to/${PROJECT_NAME} [options]' there.") | |||
# config.h checks | |||
include(ConfigureChecks.cmake) | |||
configure_file(config.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/config.h) | |||
# MinGW DLL Naming Workaround | |||
if (MINGW) | |||
set(CMAKE_SHARED_LIBRARY_PREFIX "") | |||
endif (MINGW) | |||
# check subdirectories | |||
add_subdirectory(doc) | |||
add_subdirectory(include) | |||
add_subdirectory(src) | |||
if (UNIT_TESTING) | |||
include(AddCMockaTest) | |||
add_subdirectory(tests) | |||
endif (UNIT_TESTING) | |||
add_subdirectory(example) | |||
# pkg-config file | |||
configure_file(cmocka.pc.cmake ${CMAKE_CURRENT_BINARY_DIR}/cmocka.pc) | |||
install( | |||
FILES | |||
${CMAKE_CURRENT_BINARY_DIR}/cmocka.pc | |||
DESTINATION | |||
${LIB_INSTALL_DIR}/pkgconfig | |||
COMPONENT | |||
pkgconfig | |||
) | |||
# cmake config files | |||
set(CMOCKA_LIBRARY_NAME ${CMAKE_SHARED_LIBRARY_PREFIX}${PROJECT_NAME}${CMAKE_SHARED_LIBRARY_SUFFIX}) | |||
configure_file(${PROJECT_NAME}-config.cmake.in ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}-config.cmake @ONLY) | |||
configure_file(${PROJECT_NAME}-config-version.cmake.in ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}-config-version.cmake @ONLY) | |||
install( | |||
FILES | |||
${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}-config.cmake | |||
${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}-config-version.cmake | |||
DESTINATION | |||
${CMAKE_INSTALL_DIR}/${PROJECT_NAME} | |||
COMPONENT | |||
devel | |||
) |
@@ -0,0 +1,202 @@ | |||
Apache License | |||
Version 2.0, January 2004 | |||
http://www.apache.org/licenses/ | |||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION | |||
1. Definitions. | |||
"License" shall mean the terms and conditions for use, reproduction, | |||
and distribution as defined by Sections 1 through 9 of this document. | |||
"Licensor" shall mean the copyright owner or entity authorized by | |||
the copyright owner that is granting the License. | |||
"Legal Entity" shall mean the union of the acting entity and all | |||
other entities that control, are controlled by, or are under common | |||
control with that entity. For the purposes of this definition, | |||
"control" means (i) the power, direct or indirect, to cause the | |||
direction or management of such entity, whether by contract or | |||
otherwise, or (ii) ownership of fifty percent (50%) or more of the | |||
outstanding shares, or (iii) beneficial ownership of such entity. | |||
"You" (or "Your") shall mean an individual or Legal Entity | |||
exercising permissions granted by this License. | |||
"Source" form shall mean the preferred form for making modifications, | |||
including but not limited to software source code, documentation | |||
source, and configuration files. | |||
"Object" form shall mean any form resulting from mechanical | |||
transformation or translation of a Source form, including but | |||
not limited to compiled object code, generated documentation, | |||
and conversions to other media types. | |||
"Work" shall mean the work of authorship, whether in Source or | |||
Object form, made available under the License, as indicated by a | |||
copyright notice that is included in or attached to the work | |||
(an example is provided in the Appendix below). | |||
"Derivative Works" shall mean any work, whether in Source or Object | |||
form, that is based on (or derived from) the Work and for which the | |||
editorial revisions, annotations, elaborations, or other modifications | |||
represent, as a whole, an original work of authorship. For the purposes | |||
of this License, Derivative Works shall not include works that remain | |||
separable from, or merely link (or bind by name) to the interfaces of, | |||
the Work and Derivative Works thereof. | |||
"Contribution" shall mean any work of authorship, including | |||
the original version of the Work and any modifications or additions | |||
to that Work or Derivative Works thereof, that is intentionally | |||
submitted to Licensor for inclusion in the Work by the copyright owner | |||
or by an individual or Legal Entity authorized to submit on behalf of | |||
the copyright owner. For the purposes of this definition, "submitted" | |||
means any form of electronic, verbal, or written communication sent | |||
to the Licensor or its representatives, including but not limited to | |||
communication on electronic mailing lists, source code control systems, | |||
and issue tracking systems that are managed by, or on behalf of, the | |||
Licensor for the purpose of discussing and improving the Work, but | |||
excluding communication that is conspicuously marked or otherwise | |||
designated in writing by the copyright owner as "Not a Contribution." | |||
"Contributor" shall mean Licensor and any individual or Legal Entity | |||
on behalf of whom a Contribution has been received by Licensor and | |||
subsequently incorporated within the Work. | |||
2. Grant of Copyright License. Subject to the terms and conditions of | |||
this License, each Contributor hereby grants to You a perpetual, | |||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable | |||
copyright license to reproduce, prepare Derivative Works of, | |||
publicly display, publicly perform, sublicense, and distribute the | |||
Work and such Derivative Works in Source or Object form. | |||
3. Grant of Patent License. Subject to the terms and conditions of | |||
this License, each Contributor hereby grants to You a perpetual, | |||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable | |||
(except as stated in this section) patent license to make, have made, | |||
use, offer to sell, sell, import, and otherwise transfer the Work, | |||
where such license applies only to those patent claims licensable | |||
by such Contributor that are necessarily infringed by their | |||
Contribution(s) alone or by combination of their Contribution(s) | |||
with the Work to which such Contribution(s) was submitted. If You | |||
institute patent litigation against any entity (including a | |||
cross-claim or counterclaim in a lawsuit) alleging that the Work | |||
or a Contribution incorporated within the Work constitutes direct | |||
or contributory patent infringement, then any patent licenses | |||
granted to You under this License for that Work shall terminate | |||
as of the date such litigation is filed. | |||
4. Redistribution. You may reproduce and distribute copies of the | |||
Work or Derivative Works thereof in any medium, with or without | |||
modifications, and in Source or Object form, provided that You | |||
meet the following conditions: | |||
(a) You must give any other recipients of the Work or | |||
Derivative Works a copy of this License; and | |||
(b) You must cause any modified files to carry prominent notices | |||
stating that You changed the files; and | |||
(c) You must retain, in the Source form of any Derivative Works | |||
that You distribute, all copyright, patent, trademark, and | |||
attribution notices from the Source form of the Work, | |||
excluding those notices that do not pertain to any part of | |||
the Derivative Works; and | |||
(d) If the Work includes a "NOTICE" text file as part of its | |||
distribution, then any Derivative Works that You distribute must | |||
include a readable copy of the attribution notices contained | |||
within such NOTICE file, excluding those notices that do not | |||
pertain to any part of the Derivative Works, in at least one | |||
of the following places: within a NOTICE text file distributed | |||
as part of the Derivative Works; within the Source form or | |||
documentation, if provided along with the Derivative Works; or, | |||
within a display generated by the Derivative Works, if and | |||
wherever such third-party notices normally appear. The contents | |||
of the NOTICE file are for informational purposes only and | |||
do not modify the License. You may add Your own attribution | |||
notices within Derivative Works that You distribute, alongside | |||
or as an addendum to the NOTICE text from the Work, provided | |||
that such additional attribution notices cannot be construed | |||
as modifying the License. | |||
You may add Your own copyright statement to Your modifications and | |||
may provide additional or different license terms and conditions | |||
for use, reproduction, or distribution of Your modifications, or | |||
for any such Derivative Works as a whole, provided Your use, | |||
reproduction, and distribution of the Work otherwise complies with | |||
the conditions stated in this License. | |||
5. Submission of Contributions. Unless You explicitly state otherwise, | |||
any Contribution intentionally submitted for inclusion in the Work | |||
by You to the Licensor shall be under the terms and conditions of | |||
this License, without any additional terms or conditions. | |||
Notwithstanding the above, nothing herein shall supersede or modify | |||
the terms of any separate license agreement you may have executed | |||
with Licensor regarding such Contributions. | |||
6. Trademarks. This License does not grant permission to use the trade | |||
names, trademarks, service marks, or product names of the Licensor, | |||
except as required for reasonable and customary use in describing the | |||
origin of the Work and reproducing the content of the NOTICE file. | |||
7. Disclaimer of Warranty. Unless required by applicable law or | |||
agreed to in writing, Licensor provides the Work (and each | |||
Contributor provides its Contributions) on an "AS IS" BASIS, | |||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or | |||
implied, including, without limitation, any warranties or conditions | |||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A | |||
PARTICULAR PURPOSE. You are solely responsible for determining the | |||
appropriateness of using or redistributing the Work and assume any | |||
risks associated with Your exercise of permissions under this License. | |||
8. Limitation of Liability. In no event and under no legal theory, | |||
whether in tort (including negligence), contract, or otherwise, | |||
unless required by applicable law (such as deliberate and grossly | |||
negligent acts) or agreed to in writing, shall any Contributor be | |||
liable to You for damages, including any direct, indirect, special, | |||
incidental, or consequential damages of any character arising as a | |||
result of this License or out of the use or inability to use the | |||
Work (including but not limited to damages for loss of goodwill, | |||
work stoppage, computer failure or malfunction, or any and all | |||
other commercial damages or losses), even if such Contributor | |||
has been advised of the possibility of such damages. | |||
9. Accepting Warranty or Additional Liability. While redistributing | |||
the Work or Derivative Works thereof, You may choose to offer, | |||
and charge a fee for, acceptance of support, warranty, indemnity, | |||
or other liability obligations and/or rights consistent with this | |||
License. However, in accepting such obligations, You may act only | |||
on Your own behalf and on Your sole responsibility, not on behalf | |||
of any other Contributor, and only if You agree to indemnify, | |||
defend, and hold each Contributor harmless for any liability | |||
incurred by, or claims asserted against, such Contributor by reason | |||
of your accepting any such warranty or additional liability. | |||
END OF TERMS AND CONDITIONS | |||
APPENDIX: How to apply the Apache License to your work. | |||
To apply the Apache License to your work, attach the following | |||
boilerplate notice, with the fields enclosed by brackets "[]" | |||
replaced with your own identifying information. (Don't include | |||
the brackets!) The text should be enclosed in the appropriate | |||
comment syntax for the file format. We also recommend that a | |||
file or class name and description of purpose be included on the | |||
same "printed page" as the copyright notice for easier | |||
identification within third-party archives. | |||
Copyright [yyyy] [name of copyright owner] | |||
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. |
@@ -0,0 +1,53 @@ | |||
# For help take a look at: | |||
# http://www.cmake.org/Wiki/CMake:CPackConfiguration | |||
### general settings | |||
set(CPACK_PACKAGE_NAME ${APPLICATION_NAME}) | |||
set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "Unit testing framework for C with mock objects") | |||
set(CPACK_PACKAGE_DESCRIPTION_FILE "${CMAKE_CURRENT_SOURCE_DIR}/README") | |||
set(CPACK_PACKAGE_VENDOR "Andreas Schneider") | |||
set(CPACK_PACKAGE_INSTALL_DIRECTORY ${CPACK_PACKAGE_NAME}) | |||
set(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_CURRENT_SOURCE_DIR}/COPYING") | |||
### versions | |||
set(CPACK_PACKAGE_VERSION_MAJOR "${APPLICATION_VERSION_MAJOR}") | |||
set(CPACK_PACKAGE_VERSION_MINOR "${APPLICATION_VERSION_MINOR}") | |||
set(CPACK_PACKAGE_VERSION_PATCH "${APPLICATION_VERSION_PATCH}") | |||
set(CPACK_PACKAGE_VERSION "${CPACK_PACKAGE_VERSION_MAJOR}.${CPACK_PACKAGE_VERSION_MINOR}.${CPACK_PACKAGE_VERSION_PATCH}") | |||
### source generator | |||
set(CPACK_SOURCE_GENERATOR "TGZ") | |||
set(CPACK_SOURCE_IGNORE_FILES "~$;[.]swp$;/[.]svn/;/[.]git/;.gitignore;/obj*;tags;cscope.*;.ycm_extra_conf.pyc") | |||
set(CPACK_SOURCE_PACKAGE_FILE_NAME "${CPACK_PACKAGE_NAME}-${CPACK_PACKAGE_VERSION}") | |||
if (WIN32) | |||
set(CPACK_GENERATOR "ZIP") | |||
### nsis generator | |||
find_package(NSIS) | |||
if (NSIS_MAKE) | |||
set(CPACK_GENERATOR "${CPACK_GENERATOR};NSIS") | |||
set(CPACK_NSIS_DISPLAY_NAME "CMocka") | |||
set(CPACK_NSIS_COMPRESSOR "/SOLID zlib") | |||
set(CPACK_NSIS_MENU_LINKS "http://cmocka.org/" "cmocka homepage") | |||
endif (NSIS_MAKE) | |||
endif (WIN32) | |||
set(CPACK_PACKAGE_INSTALL_DIRECTORY "cmocka") | |||
set(CPACK_PACKAGE_FILE_NAME ${APPLICATION_NAME}-${CPACK_PACKAGE_VERSION}) | |||
set(CPACK_COMPONENT_LIBRARIES_DISPLAY_NAME "Libraries") | |||
set(CPACK_COMPONENT_HEADERS_DISPLAY_NAME "C/C++ Headers") | |||
set(CPACK_COMPONENT_LIBRARIES_DESCRIPTION | |||
"Libraries used to build programs which use cmocka") | |||
set(CPACK_COMPONENT_HEADERS_DESCRIPTION | |||
"C/C++ header files for use with cmocka") | |||
set(CPACK_COMPONENT_HEADERS_DEPENDS libraries) | |||
#set(CPACK_COMPONENT_APPLICATIONS_GROUP "Runtime") | |||
set(CPACK_COMPONENT_LIBRARIES_GROUP "Development") | |||
set(CPACK_COMPONENT_HEADERS_GROUP "Development") | |||
include(CPack) |
@@ -0,0 +1,10 @@ | |||
set(UPDATE_TYPE "true") | |||
set(CTEST_PROJECT_NAME "cmocka") | |||
set(CTEST_NIGHTLY_START_TIME "01:00:00 UTC") | |||
set(CTEST_DROP_METHOD "https") | |||
set(CTEST_DROP_SITE "mock.cryptomilk.org") | |||
set(CTEST_DROP_LOCATION "/submit.php?project=${CTEST_PROJECT_NAME}") | |||
set(CTEST_DROP_SITE_CDASH TRUE) | |||
@@ -0,0 +1,98 @@ | |||
Fri Apr 07 2016 Andreas Schneider <asn@cryptomilk.org> | |||
* cmocka: version 1.1.1 | |||
* Fixed TAP output | |||
* Fixed cmocka on Windows x64 | |||
* Fixed xUnit output durations | |||
Wed Sep 21 2016 Andreas Schneider <asn@cryptomilk.org> | |||
* cmocka: version 1.1.0 | |||
* Added support to catch multiple exceptions | |||
* Added support to verify call ordering | |||
* Added support to pass initial data to test cases | |||
* Added will_return_maybe() for ignoring mock returns | |||
* Added subtests for groups using TAP output | |||
* Added support to write multiple XML files for groups | |||
* Improved documentation | |||
* Fixed XML output generataion | |||
* Fixed Windows builds with VS2015 | |||
Thu Mar 12 2015 Andreas Schneider <asn@cryptomilk.org> | |||
* cmocka: version 1.0.1 | |||
* Added a macro for assert_ptr_equal(). | |||
* Fixed test_realloc() if 0 size is passed. | |||
* Fixed objects packaging bug. | |||
* Fixed building with newer gcc versions. | |||
Sun Feb 16 2015 Andreas Schneider <asn@cryptomilk.org> | |||
* cmocka: version 1.0.0 | |||
* Added new test runner with group fixtures. The old runner is deprecated | |||
* Added an extensible message output formatter | |||
* Added jUnit XML message output | |||
* Added subunit message output | |||
* Added Test Anything Protocol message output | |||
* Added skip() command | |||
* Added test_realloc() | |||
* Added a cmockery compat header | |||
* Fixed a lot of bugs on Windows | |||
Thu May 22 2014 Andreas Schneider <asn@cryptomilk.org> | |||
* cmocka: version 0.4.1 | |||
* Added CMOCKA_TEST_ABORT env variable to leave threading apps. | |||
* Fixed count parameter of expect_check() macro. | |||
* Fixed reporting the number of tests. | |||
* Fixed cmake config files. | |||
Fri Apr 11 2014 Andreas Schneider <asn@cryptomilk.org> | |||
* cmocka: version 0.4.0 | |||
* Added support for group testing. | |||
* Added assert_return_code(). | |||
* Added better messages for errors. | |||
* Added cmake config mode support. | |||
* Fixed bug with unit_test_setup and unit_test_teardown. | |||
* Fixed a lot of small bugs. | |||
Wed Nov 06 2013 Andreas Schneider <asn@cryptomilk.org> | |||
* cmocka: version 0.3.2 | |||
* Fixed FindNSIS detection. | |||
* Fixed unit_test_setup() and unit_test_teardown(). | |||
* Fixed GTest and GCC message style conformance | |||
* Fixed stringification in will_return_always(). | |||
Wed Jul 10 15:24 2013 Andreas Schneider <asn@cryptomilk.org> | |||
* cmocka: version 0.3.1 | |||
* Fixed pointer conversion on s390 and ppc (32bit big endian). | |||
* Fixed the customer_database test on big endian. | |||
Wed Jun 05 08:14 2013 Andreas Schneider <asn@cryptomilk.org> | |||
* cmocka: version 0.3.0 | |||
* Added a better mock object example. | |||
* Added pkgconfig file. | |||
* Added new macros mock_type() and mock_ptr_type(). | |||
* Added more documentation. | |||
* Fixed installation problems on some platforms. | |||
Mon Jan 14 11:16 2013 Andreas Schneider <asn@cryptomilk.org> | |||
* cmocka: version 0.2.0 | |||
* Added doxygen api documentation. | |||
* Added new cmake build system. | |||
* Added support to create windows NSIS installer. | |||
* Fixed examples which didn't work. | |||
* Fixed a huge amount of bugs. | |||
Mon Sep 15 17:21:22 2008 Google Inc. <opensource@google.com> | |||
* cmockery: version 0.12 | |||
* Made it possible to specify additional compiler, lib tool and link | |||
flags on Windows. | |||
* Added Windows makefile to the tar ball. | |||
Fri Aug 29 10:50:46 2008 Google Inc. <opensource@google.com> | |||
* cmockery: version 0.11 | |||
* Made it possible to specify executable, library and object output | |||
directories. | |||
Tue Aug 26 10:18:02 2008 Google Inc. <opensource@google.com> | |||
* cmockery: initial release: | |||
A lightweight library to simplify and generalize the process of | |||
writing unit tests for C applications. |
@@ -0,0 +1,149 @@ | |||
include(CheckIncludeFile) | |||
include(CheckSymbolExists) | |||
include(CheckFunctionExists) | |||
include(CheckLibraryExists) | |||
include(CheckTypeSize) | |||
include(CheckCXXSourceCompiles) | |||
include(CheckStructHasMember) | |||
include(TestBigEndian) | |||
set(PACKAGE ${APPLICATION_NAME}) | |||
set(VERSION ${APPLICATION_VERSION}) | |||
set(DATADIR ${DATA_INSTALL_DIR}) | |||
set(LIBDIR ${LIB_INSTALL_DIR}) | |||
set(PLUGINDIR "${PLUGIN_INSTALL_DIR}-${LIBRARY_SOVERSION}") | |||
set(SYSCONFDIR ${SYSCONF_INSTALL_DIR}) | |||
set(BINARYDIR ${CMAKE_BINARY_DIR}) | |||
set(SOURCEDIR ${CMAKE_SOURCE_DIR}) | |||
function(COMPILER_DUMPVERSION _OUTPUT_VERSION) | |||
# Remove whitespaces from the argument. | |||
# This is needed for CC="ccache gcc" cmake .. | |||
string(REPLACE " " "" _C_COMPILER_ARG "${CMAKE_C_COMPILER_ARG1}") | |||
execute_process( | |||
COMMAND | |||
${CMAKE_C_COMPILER} ${_C_COMPILER_ARG} -dumpversion | |||
OUTPUT_VARIABLE _COMPILER_VERSION | |||
) | |||
string(REGEX REPLACE "([0-9])\\.([0-9])(\\.[0-9])?" "\\1\\2" | |||
_COMPILER_VERSION ${_COMPILER_VERSION}) | |||
set(${_OUTPUT_VERSION} ${_COMPILER_VERSION} PARENT_SCOPE) | |||
endfunction() | |||
if(CMAKE_COMPILER_IS_GNUCC AND NOT MINGW) | |||
compiler_dumpversion(GNUCC_VERSION) | |||
if (NOT GNUCC_VERSION EQUAL 34) | |||
check_c_compiler_flag("-fvisibility=hidden" WITH_VISIBILITY_HIDDEN) | |||
endif (NOT GNUCC_VERSION EQUAL 34) | |||
endif(CMAKE_COMPILER_IS_GNUCC AND NOT MINGW) | |||
# DEFINITIONS | |||
if (SOLARIS) | |||
add_definitions(-D__EXTENSIONS__) | |||
endif (SOLARIS) | |||
# HEADER FILES | |||
check_include_file(assert.h HAVE_ASSERT_H) | |||
check_include_file(inttypes.h HAVE_INTTYPES_H) | |||
check_include_file(io.h HAVE_IO_H) | |||
check_include_file(malloc.h HAVE_MALLOC_H) | |||
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(stddef.h HAVE_STDDEF_H) | |||
check_include_file(stdint.h HAVE_STDINT_H) | |||
check_include_file(stdio.h HAVE_STDIO_H) | |||
check_include_file(stdlib.h HAVE_STDLIB_H) | |||
check_include_file(string.h HAVE_STRING_H) | |||
check_include_file(strings.h HAVE_STRINGS_H) | |||
check_include_file(sys/stat.h HAVE_SYS_STAT_H) | |||
check_include_file(sys/types.h HAVE_SYS_TYPES_H) | |||
check_include_file(time.h HAVE_TIME_H) | |||
check_include_file(unistd.h HAVE_UNISTD_H) | |||
if (HAVE_TIME_H) | |||
check_struct_has_member("struct timespec" tv_sec "time.h" HAVE_STRUCT_TIMESPEC) | |||
endif (HAVE_TIME_H) | |||
# FUNCTIONS | |||
check_function_exists(calloc HAVE_CALLOC) | |||
check_function_exists(exit HAVE_EXIT) | |||
check_function_exists(fprintf HAVE_FPRINTF) | |||
check_function_exists(free HAVE_FREE) | |||
check_function_exists(longjmp HAVE_LONGJMP) | |||
check_function_exists(siglongjmp HAVE_SIGLONGJMP) | |||
check_function_exists(malloc HAVE_MALLOC) | |||
check_function_exists(memcpy HAVE_MEMCPY) | |||
check_function_exists(memset HAVE_MEMSET) | |||
check_function_exists(printf HAVE_PRINTF) | |||
check_function_exists(setjmp HAVE_SETJMP) | |||
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) | |||
if (WIN32) | |||
check_function_exists(_vsnprintf_s HAVE__VSNPRINTF_S) | |||
check_function_exists(_vsnprintf HAVE__VSNPRINTF) | |||
check_function_exists(_snprintf HAVE__SNPRINTF) | |||
check_function_exists(_snprintf_s HAVE__SNPRINTF_S) | |||
check_symbol_exists(snprintf stdio.h HAVE_SNPRINTF) | |||
check_symbol_exists(vsnprintf stdio.h HAVE_VSNPRINTF) | |||
else (WIN32) | |||
check_function_exists(sprintf HAVE_SNPRINTF) | |||
check_function_exists(vsnprintf HAVE_VSNPRINTF) | |||
endif (WIN32) | |||
find_library(RT_LIBRARY rt) | |||
if (RT_LIBRARY AND NOT LINUX) | |||
set(CMOCKA_REQUIRED_LIBRARIES ${RT_LIBRARY} CACHE INTERNAL "cmocka required system libraries") | |||
endif () | |||
# OPTIONS | |||
check_c_source_compiles(" | |||
__thread int tls; | |||
int main(void) { | |||
return 0; | |||
}" HAVE_GCC_THREAD_LOCAL_STORAGE) | |||
if (WIN32) | |||
check_c_source_compiles(" | |||
__declspec(thread) int tls; | |||
int main(void) { | |||
return 0; | |||
}" HAVE_MSVC_THREAD_LOCAL_STORAGE) | |||
endif(WIN32) | |||
if (HAVE_TIME_H AND HAVE_STRUCT_TIMESPEC AND HAVE_CLOCK_GETTIME) | |||
if (RT_LIBRARY) | |||
set(CMAKE_REQUIRED_LIBRARIES ${RT_LIBRARY}) | |||
endif() | |||
check_c_source_compiles(" | |||
#include <time.h> | |||
int main(void) { | |||
struct timespec ts; | |||
clock_gettime(CLOCK_REALTIME, &ts); | |||
return 0; | |||
}" HAVE_CLOCK_REALTIME) | |||
# reset cmake requirements | |||
set(CMAKE_REQUIRED_INCLUDES) | |||
set(CMAKE_REQUIRED_LIBRARIES) | |||
endif () | |||
# ENDIAN | |||
if (NOT WIN32) | |||
set(WORDS_SIZEOF_VOID_P ${CMAKE_SIZEOF_VOID_P}) | |||
test_big_endian(WORDS_BIGENDIAN) | |||
endif (NOT WIN32) |
@@ -0,0 +1,7 @@ | |||
option(WITH_STATIC_LIB "Build with a static library" OFF) | |||
option(WITH_CMOCKERY_SUPPORT "Install a cmockery header" OFF) | |||
option(UNIT_TESTING "Build with unit testing" OFF) | |||
if (UNIT_TESTING) | |||
set(WITH_STATIC_LIB ON) | |||
endif() |
@@ -0,0 +1,102 @@ | |||
# How to build from source | |||
## Requirements | |||
### Common requirements | |||
In order to build cmocka, you need to install several components: | |||
- A C compiler | |||
- [CMake](http://www.cmake.org) >= 2.8.0. | |||
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 | |||
First, you need to configure the compilation, using CMake. Go inside the | |||
`build` dir. Create it if it doesn't exist. | |||
GNU/Linux, MacOS X, MSYS/MinGW: | |||
cmake -DCMAKE_INSTALL_PREFIX=/usr -DCMAKE_BUILD_TYPE=Debug .. | |||
make | |||
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 | |||
You can also use the CMake GUI which is shipped with CMake. It will list all | |||
available generators for MSVC on Windows. | |||
### CMake standard options | |||
Here is a list of the most interesting options provided out of the box by | |||
CMake. | |||
- CMAKE_BUILD_TYPE: The type of build (can be Debug Release MinSizeRel | |||
RelWithDebInfo) | |||
- CMAKE_INSTALL_PREFIX: The prefix to use when running make install (Default | |||
to /usr/local on GNU/Linux and MacOS X) | |||
- CMAKE_C_COMPILER: The path to the C compiler | |||
- CMAKE_CXX_COMPILER: The path to the C++ compiler | |||
### CMake options defined for cmocka | |||
Options are defined in the following files: | |||
- DefineOptions.cmake | |||
They can be changed with the -D option: | |||
`cmake -DCMAKE_INSTALL_PREFIX=/usr -DCMAKE_BUILD_TYPE=Debug -DUNIT_TESTING=ON ..` | |||
### 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 | |||
and MacOS X). | |||
- Go to the build dir | |||
- On Windows: run `cmakesetup` | |||
- On GNU/Linux and MacOS X: run `ccmake ..` | |||
## Installing | |||
If you want to install cmocka after compilation run: | |||
make install | |||
## Running | |||
The cmocka library can be found in the `build/src` directory. | |||
You can run the binaries in `build/examples/*` which is a | |||
are exsample tests. | |||
## Testing | |||
As mention above you can turn on the unit tests and make it possible to easily | |||
execute them: | |||
`cmake -DCMAKE_BUILD_TYPE=Debug -DUNIT_TESTING=ON ..` | |||
After that you can simply call `make test` in the build directory or if you | |||
want more output simply call `ctest -V`. | |||
If you want to enable the generation of coverage files you can do this by | |||
using the following options: | |||
`cmake -DCMAKE_BUILD_TYPE=Profiling -DUNIT_TESTING=ON ..` | |||
After building it you will see that you have several coverage options in | |||
`make help` | |||
You should have `make ExperimentalCoverage` and running it will create | |||
coverage files. The result is stored in Testing directory. | |||
## About this document | |||
This document is written using [Markdown][] syntax, making it possible to | |||
provide usable information in both plain text and HTML format. Whenever | |||
modifying this document please use [Markdown][] syntax. | |||
[markdown]: http://www.daringfireball.net/projects/markdown |
@@ -0,0 +1,15 @@ | |||
CMOCKA | |||
======= | |||
cmocka is a fork for Google's cmockery unit testing framework to fix bugs and | |||
support it in future. | |||
See https://code.google.com/p/cmockery/ | |||
For information about how to use the cmocka unit testing framework see | |||
doc/index.html. | |||
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. |
@@ -0,0 +1,23 @@ | |||
# - ADD_CMOCKA_TEST(test_name test_source linklib1 ... linklibN) | |||
# Copyright (c) 2007 Daniel Gollub <dgollub@suse.de> | |||
# Copyright (c) 2007-2010 Andreas Schneider <asn@cynapses.org> | |||
# | |||
# Redistribution and use is allowed according to the terms of the BSD license. | |||
# For details see the accompanying COPYING-CMAKE-SCRIPTS file. | |||
enable_testing() | |||
include(CTest) | |||
if(CMAKE_COMPILER_IS_GNUCC AND NOT MINGW) | |||
set(CMAKE_C_FLAGS_PROFILING "-g -O0 -Wall -W -Wshadow -Wunused-variable -Wunused-parameter -Wunused-function -Wunused -Wno-system-headers -Wwrite-strings -fprofile-arcs -ftest-coverage" CACHE STRING "Profiling Compiler Flags") | |||
set(CMAKE_SHARED_LINKER_FLAGS_PROFILING " -fprofile-arcs -ftest-coverage" CACHE STRING "Profiling Linker Flags") | |||
set(CMAKE_MODULE_LINKER_FLAGS_PROFILING " -fprofile-arcs -ftest-coverage" CACHE STRING "Profiling Linker Flags") | |||
set(CMAKE_EXEC_LINKER_FLAGS_PROFILING " -fprofile-arcs -ftest-coverage" CACHE STRING "Profiling Linker Flags") | |||
endif(CMAKE_COMPILER_IS_GNUCC AND NOT MINGW) | |||
function (ADD_CMOCKA_TEST _testName _testSource) | |||
add_executable(${_testName} ${_testSource}) | |||
target_link_libraries(${_testName} ${ARGN}) | |||
add_test(${_testName} ${CMAKE_CURRENT_BINARY_DIR}/${_testName}) | |||
endfunction (ADD_CMOCKA_TEST) |
@@ -0,0 +1,22 @@ | |||
Redistribution and use in source and binary forms, with or without | |||
modification, are permitted provided that the following conditions | |||
are met: | |||
1. Redistributions of source code must retain the copyright | |||
notice, this list of conditions and the following disclaimer. | |||
2. Redistributions in binary form must reproduce the copyright | |||
notice, this list of conditions and the following disclaimer in the | |||
documentation and/or other materials provided with the distribution. | |||
3. The name of the author may not be used to endorse or promote products | |||
derived from this software without specific prior written permission. | |||
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR | |||
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES | |||
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. | |||
IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, | |||
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT | |||
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | |||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | |||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | |||
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
@@ -0,0 +1,26 @@ | |||
# - Check whether the C compiler supports a given flag in the | |||
# context of a stack checking compiler option. | |||
# CHECK_C_COMPILER_FLAG_SSP(FLAG VARIABLE) | |||
# | |||
# FLAG - the compiler flag | |||
# VARIABLE - variable to store the result | |||
# | |||
# This actually calls check_c_source_compiles. | |||
# See help for CheckCSourceCompiles for a listing of variables | |||
# that can modify the build. | |||
# Copyright (c) 2006, Alexander Neundorf, <neundorf@kde.org> | |||
# | |||
# Redistribution and use is allowed according to the terms of the BSD license. | |||
# For details see the accompanying COPYING-CMAKE-SCRIPTS file. | |||
include(CheckCSourceCompiles) | |||
function(CHECK_C_COMPILER_FLAG_SSP _FLAG _RESULT) | |||
set(SAFE_CMAKE_REQUIRED_DEFINITIONS "${CMAKE_REQUIRED_DEFINITIONS}") | |||
set(CMAKE_REQUIRED_DEFINITIONS "${_FLAG}") | |||
check_c_source_compiles("int main(int argc, char **argv) { char buffer[256]; return buffer[argc]=0;}" ${_RESULT}) | |||
set(CMAKE_REQUIRED_DEFINITIONS "${SAFE_CMAKE_REQUIRED_DEFINITIONS}") | |||
endfunction(CHECK_C_COMPILER_FLAG_SSP) |
@@ -0,0 +1,36 @@ | |||
# Always include srcdir and builddir in include path | |||
# This saves typing ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY} in | |||
# about every subdir | |||
# since cmake 2.4.0 | |||
set(CMAKE_INCLUDE_CURRENT_DIR ON) | |||
# Put the include dirs which are in the source or build tree | |||
# before all other include dirs, so the headers in the sources | |||
# are prefered over the already installed ones | |||
# since cmake 2.4.1 | |||
set(CMAKE_INCLUDE_DIRECTORIES_PROJECT_BEFORE ON) | |||
# Use colored output | |||
# since cmake 2.4.0 | |||
set(CMAKE_COLOR_MAKEFILE ON) | |||
# Define the generic version of the libraries here | |||
set(GENERIC_LIB_VERSION "0.1.0") | |||
set(GENERIC_LIB_SOVERSION "0") | |||
# Set the default build type to release with debug info | |||
if (NOT CMAKE_BUILD_TYPE) | |||
set(CMAKE_BUILD_TYPE RelWithDebInfo | |||
CACHE STRING | |||
"Choose the type of build, options are: None Debug Release RelWithDebInfo MinSizeRel." | |||
) | |||
endif (NOT CMAKE_BUILD_TYPE) | |||
# Create the compile command database for clang by default | |||
set(CMAKE_EXPORT_COMPILE_COMMANDS ON) | |||
if (APPLE) | |||
set(CMAKE_MACOSX_RPATH ON) | |||
set(CMAKE_SKIP_BUILD_RPATH FALSE) | |||
set(CMAKE_BUILD_WITH_INSTALL_RPATH FALSE) | |||
endif(APPLE) |
@@ -0,0 +1,79 @@ | |||
# define system dependent compiler flags | |||
include(CheckCCompilerFlag) | |||
include(CheckCCompilerFlagSSP) | |||
if (UNIX AND NOT WIN32) | |||
# | |||
# Define GNUCC compiler flags | |||
# | |||
if (${CMAKE_C_COMPILER_ID} MATCHES "(GNU|Clang)") | |||
# add -Wconversion ? | |||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=gnu99 -pedantic -pedantic-errors") | |||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wextra -Wshadow -Wmissing-prototypes -Wdeclaration-after-statement") | |||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wunused -Wfloat-equal -Wpointer-arith -Wwrite-strings -Wformat-security") | |||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wmissing-format-attribute -Wundef -Wstrict-prototypes") | |||
# with -fPIC | |||
check_c_compiler_flag("-fPIC" WITH_FPIC) | |||
if (WITH_FPIC) | |||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fPIC") | |||
endif (WITH_FPIC) | |||
check_c_compiler_flag_ssp("-fstack-protector" WITH_STACK_PROTECTOR) | |||
if (WITH_STACK_PROTECTOR) | |||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fstack-protector") | |||
endif (WITH_STACK_PROTECTOR) | |||
if (CMAKE_BUILD_TYPE) | |||
string(TOLOWER "${CMAKE_BUILD_TYPE}" CMAKE_BUILD_TYPE_LOWER) | |||
if (CMAKE_BUILD_TYPE_LOWER MATCHES (release|relwithdebinfo|minsizerel)) | |||
check_c_compiler_flag("-Wp,-D_FORTIFY_SOURCE=2" WITH_FORTIFY_SOURCE) | |||
if (WITH_FORTIFY_SOURCE) | |||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wp,-D_FORTIFY_SOURCE=2") | |||
endif (WITH_FORTIFY_SOURCE) | |||
endif() | |||
endif() | |||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -D_GNU_SOURCE") | |||
endif (${CMAKE_C_COMPILER_ID} MATCHES "(GNU|Clang)") | |||
# | |||
# Check for large filesystem support | |||
# | |||
if (CMAKE_SIZEOF_VOID_P MATCHES "8") | |||
# with large file support | |||
execute_process( | |||
COMMAND | |||
getconf LFS64_CFLAGS | |||
OUTPUT_VARIABLE | |||
_lfs_CFLAGS | |||
ERROR_QUIET | |||
OUTPUT_STRIP_TRAILING_WHITESPACE | |||
) | |||
else (CMAKE_SIZEOF_VOID_P MATCHES "8") | |||
# with large file support | |||
execute_process( | |||
COMMAND | |||
getconf LFS_CFLAGS | |||
OUTPUT_VARIABLE | |||
_lfs_CFLAGS | |||
ERROR_QUIET | |||
OUTPUT_STRIP_TRAILING_WHITESPACE | |||
) | |||
endif (CMAKE_SIZEOF_VOID_P MATCHES "8") | |||
if (_lfs_CFLAGS) | |||
string(REGEX REPLACE "[\r\n]" " " "${_lfs_CFLAGS}" "${${_lfs_CFLAGS}}") | |||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${_lfs_CFLAGS}") | |||
endif (_lfs_CFLAGS) | |||
endif (UNIX AND NOT WIN32) | |||
if (MSVC) | |||
# Use secure functions by defaualt and suppress warnings about | |||
#"deprecated" functions | |||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /D _CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES=1") | |||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /D _CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES_COUNT=1") | |||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /D _CRT_NONSTDC_NO_WARNINGS=1 /D _CRT_SECURE_NO_WARNINGS=1") | |||
endif (MSVC) |
@@ -0,0 +1,109 @@ | |||
if (UNIX OR OS2) | |||
IF (NOT APPLICATION_NAME) | |||
MESSAGE(STATUS "${PROJECT_NAME} is used as APPLICATION_NAME") | |||
SET(APPLICATION_NAME ${PROJECT_NAME}) | |||
ENDIF (NOT APPLICATION_NAME) | |||
# Suffix for Linux | |||
SET(LIB_SUFFIX | |||
CACHE STRING "Define suffix of directory name (32/64)" | |||
) | |||
SET(EXEC_INSTALL_PREFIX | |||
"${CMAKE_INSTALL_PREFIX}" | |||
CACHE PATH "Base directory for executables and libraries" | |||
) | |||
SET(SHARE_INSTALL_PREFIX | |||
"${CMAKE_INSTALL_PREFIX}/share" | |||
CACHE PATH "Base directory for files which go to share/" | |||
) | |||
SET(DATA_INSTALL_PREFIX | |||
"${SHARE_INSTALL_PREFIX}/${APPLICATION_NAME}" | |||
CACHE PATH "The parent directory where applications can install their data") | |||
# The following are directories where stuff will be installed to | |||
SET(BIN_INSTALL_DIR | |||
"${EXEC_INSTALL_PREFIX}/bin" | |||
CACHE PATH "The ${APPLICATION_NAME} binary install dir (default prefix/bin)" | |||
) | |||
SET(SBIN_INSTALL_DIR | |||
"${EXEC_INSTALL_PREFIX}/sbin" | |||
CACHE PATH "The ${APPLICATION_NAME} sbin install dir (default prefix/sbin)" | |||
) | |||
SET(LIB_INSTALL_DIR | |||
"${EXEC_INSTALL_PREFIX}/lib${LIB_SUFFIX}" | |||
CACHE PATH "The subdirectory relative to the install prefix where libraries will be installed (default is prefix/lib)" | |||
) | |||
SET(LIBEXEC_INSTALL_DIR | |||
"${EXEC_INSTALL_PREFIX}/libexec" | |||
CACHE PATH "The subdirectory relative to the install prefix where libraries will be installed (default is prefix/libexec)" | |||
) | |||
SET(PLUGIN_INSTALL_DIR | |||
"${LIB_INSTALL_DIR}/${APPLICATION_NAME}" | |||
CACHE PATH "The subdirectory relative to the install prefix where plugins will be installed (default is prefix/lib/${APPLICATION_NAME})" | |||
) | |||
SET(INCLUDE_INSTALL_DIR | |||
"${CMAKE_INSTALL_PREFIX}/include" | |||
CACHE PATH "The subdirectory to the header prefix (default prefix/include)" | |||
) | |||
set(CMAKE_INSTALL_DIR | |||
"${LIB_INSTALL_DIR}/cmake" | |||
CACHE PATH "The subdirectory to install cmake config files") | |||
SET(DATA_INSTALL_DIR | |||
"${DATA_INSTALL_PREFIX}" | |||
CACHE PATH "The parent directory where applications can install their data (default prefix/share/${APPLICATION_NAME})" | |||
) | |||
SET(HTML_INSTALL_DIR | |||
"${DATA_INSTALL_PREFIX}/doc/HTML" | |||
CACHE PATH "The HTML install dir for documentation (default data/doc/html)" | |||
) | |||
SET(ICON_INSTALL_DIR | |||
"${DATA_INSTALL_PREFIX}/icons" | |||
CACHE PATH "The icon install dir (default data/icons/)" | |||
) | |||
SET(SOUND_INSTALL_DIR | |||
"${DATA_INSTALL_PREFIX}/sounds" | |||
CACHE PATH "The install dir for sound files (default data/sounds)" | |||
) | |||
SET(LOCALE_INSTALL_DIR | |||
"${SHARE_INSTALL_PREFIX}/locale" | |||
CACHE PATH "The install dir for translations (default prefix/share/locale)" | |||
) | |||
SET(XDG_APPS_DIR | |||
"${SHARE_INSTALL_PREFIX}/applications/" | |||
CACHE PATH "The XDG apps dir" | |||
) | |||
SET(XDG_DIRECTORY_DIR | |||
"${SHARE_INSTALL_PREFIX}/desktop-directories" | |||
CACHE PATH "The XDG directory" | |||
) | |||
SET(SYSCONF_INSTALL_DIR | |||
"${EXEC_INSTALL_PREFIX}/etc" | |||
CACHE PATH "The ${APPLICATION_NAME} sysconfig install dir (default prefix/etc)" | |||
) | |||
SET(MAN_INSTALL_DIR | |||
"${SHARE_INSTALL_PREFIX}/man" | |||
CACHE PATH "The ${APPLICATION_NAME} man install dir (default prefix/man)" | |||
) | |||
SET(INFO_INSTALL_DIR | |||
"${SHARE_INSTALL_PREFIX}/info" | |||
CACHE PATH "The ${APPLICATION_NAME} info install dir (default prefix/info)" | |||
) | |||
else() | |||
# Same same | |||
set(BIN_INSTALL_DIR "bin" CACHE PATH "-") | |||
set(SBIN_INSTALL_DIR "sbin" CACHE PATH "-") | |||
set(LIB_INSTALL_DIR "lib${LIB_SUFFIX}" CACHE PATH "-") | |||
set(INCLUDE_INSTALL_DIR "include" CACHE PATH "-") | |||
set(CMAKE_INSTALL_DIR "CMake" CACHE PATH "-") | |||
set(PLUGIN_INSTALL_DIR "plugins" CACHE PATH "-") | |||
set(HTML_INSTALL_DIR "doc/HTML" CACHE PATH "-") | |||
set(ICON_INSTALL_DIR "icons" CACHE PATH "-") | |||
set(SOUND_INSTALL_DIR "soudns" CACHE PATH "-") | |||
set(LOCALE_INSTALL_DIR "lang" CACHE PATH "-") | |||
endif () |
@@ -0,0 +1,21 @@ | |||
# Set system vars | |||
if (CMAKE_SYSTEM_NAME MATCHES "Linux") | |||
set(LINUX TRUE) | |||
endif(CMAKE_SYSTEM_NAME MATCHES "Linux") | |||
if (CMAKE_SYSTEM_NAME MATCHES "FreeBSD") | |||
set(FREEBSD TRUE) | |||
endif (CMAKE_SYSTEM_NAME MATCHES "FreeBSD") | |||
if (CMAKE_SYSTEM_NAME MATCHES "OpenBSD") | |||
set(OPENBSD TRUE) | |||
endif (CMAKE_SYSTEM_NAME MATCHES "OpenBSD") | |||
if (CMAKE_SYSTEM_NAME MATCHES "NetBSD") | |||
set(NETBSD TRUE) | |||
endif (CMAKE_SYSTEM_NAME MATCHES "NetBSD") | |||
if (CMAKE_SYSTEM_NAME MATCHES "(Solaris|SunOS)") | |||
set(SOLARIS TRUE) | |||
endif (CMAKE_SYSTEM_NAME MATCHES "(Solaris|SunOS)") |
@@ -0,0 +1,51 @@ | |||
# - Try to find NSIS | |||
# Once done this will define | |||
# | |||
# NSIS_FOUND - system has NSIS | |||
# NSIS_MAKE - NSIS creator executable | |||
# | |||
#============================================================================= | |||
# Copyright (c) 2010-2013 Andreas Schneider <asn@cryptomilk.org> | |||
# | |||
# Distributed under the OSI-approved BSD License (the "License"); | |||
# see accompanying file Copyright.txt for details. | |||
# | |||
# This software is distributed WITHOUT ANY WARRANTY; without even the | |||
# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. | |||
# See the License for more information. | |||
#============================================================================= | |||
# | |||
if (WIN32) | |||
set(_NSIS_ROOT_HINTS | |||
"[HKEY_LOCAL_MACHINE\\SOFTWARE\\Wow6432Node\\NSIS;Default]") | |||
set(_NSIS_ROOT_PATHS | |||
$ENV{PROGRAMFILES}/NSIS) | |||
find_path(NSIS_ROOT_PATH | |||
NAMES | |||
Include/Library.nsh | |||
HINTS | |||
${_NSIS_ROOT_HINTS} | |||
PATHS | |||
${_NSIS_ROOT_PATHS} | |||
) | |||
mark_as_advanced(NSIS_ROOT_PATH) | |||
endif (WIN32) | |||
find_program(NSIS_MAKE | |||
NAMES | |||
makensis | |||
PATHS | |||
${NSIS_ROOT_PATH} | |||
) | |||
include(FindPackageHandleStandardArgs) | |||
find_package_handle_standard_args(NSIS DEFAULT_MSG NSIS_MAKE) | |||
if (NSIS_MAKE) | |||
set(NSIS_FOUND TRUE) | |||
endif (NSIS_MAKE) | |||
mark_as_advanced(NSIS_MAKE) |
@@ -0,0 +1,17 @@ | |||
# - MACRO_ENSURE_OUT_OF_SOURCE_BUILD(<errorMessage>) | |||
# MACRO_ENSURE_OUT_OF_SOURCE_BUILD(<errorMessage>) | |||
# Copyright (c) 2006, Alexander Neundorf, <neundorf@kde.org> | |||
# | |||
# Redistribution and use is allowed according to the terms of the BSD license. | |||
# For details see the accompanying COPYING-CMAKE-SCRIPTS file. | |||
macro (MACRO_ENSURE_OUT_OF_SOURCE_BUILD _errorMessage) | |||
string(COMPARE EQUAL "${CMAKE_SOURCE_DIR}" "${CMAKE_BINARY_DIR}" _insource) | |||
if (_insource) | |||
message(SEND_ERROR "${_errorMessage}") | |||
message(FATAL_ERROR "Remove the file CMakeCache.txt in ${CMAKE_SOURCE_DIR} first.") | |||
endif (_insource) | |||
endmacro (MACRO_ENSURE_OUT_OF_SOURCE_BUILD) |
@@ -0,0 +1,140 @@ | |||
# - Run Doxygen | |||
# | |||
# Adds a doxygen target that runs doxygen to generate the html | |||
# and optionally the LaTeX API documentation. | |||
# The doxygen target is added to the doc target as a dependency. | |||
# i.e.: the API documentation is built with: | |||
# make doc | |||
# | |||
# USAGE: GLOBAL INSTALL | |||
# | |||
# Install it with: | |||
# cmake ./ && sudo make install | |||
# Add the following to the CMakeLists.txt of your project: | |||
# include(UseDoxygen OPTIONAL) | |||
# Optionally copy Doxyfile.in in the directory of CMakeLists.txt and edit it. | |||
# | |||
# USAGE: INCLUDE IN PROJECT | |||
# | |||
# set(CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}) | |||
# include(UseDoxygen) | |||
# Add the Doxyfile.in and UseDoxygen.cmake files to the projects source directory. | |||
# | |||
# | |||
# CONFIGURATION | |||
# | |||
# To configure Doxygen you can edit Doxyfile.in and set some variables in cmake. | |||
# Variables you may define are: | |||
# DOXYFILE_SOURCE_DIR - Path where the Doxygen input files are. | |||
# Defaults to the current source directory. | |||
# DOXYFILE_EXTRA_SOURCES - Additional source diretories/files for Doxygen to scan. | |||
# The Paths should be in double quotes and separated by space. e.g.: | |||
# "${CMAKE_CURRENT_BINARY_DIR}/foo.c" "${CMAKE_CURRENT_BINARY_DIR}/bar/" | |||
# | |||
# DOXYFILE_OUTPUT_DIR - Path where the Doxygen output is stored. | |||
# Defaults to "${CMAKE_CURRENT_BINARY_DIR}/doc". | |||
# | |||
# DOXYFILE_LATEX - ON/OFF; Set to "ON" if you want the LaTeX documentation | |||
# to be built. | |||
# DOXYFILE_LATEX_DIR - Directory relative to DOXYFILE_OUTPUT_DIR where | |||
# the Doxygen LaTeX output is stored. Defaults to "latex". | |||
# | |||
# DOXYFILE_HTML_DIR - Directory relative to DOXYFILE_OUTPUT_DIR where | |||
# the Doxygen html output is stored. Defaults to "html". | |||
# | |||
# | |||
# Copyright (c) 2009, 2010, 2011 Tobias Rautenkranz <tobias@rautenkranz.ch> | |||
# | |||
# Redistribution and use is allowed according to the terms of the New | |||
# BSD license. | |||
# For details see the accompanying COPYING-CMAKE-SCRIPTS file. | |||
# | |||
macro(usedoxygen_set_default name value type docstring) | |||
if(NOT DEFINED "${name}") | |||
set("${name}" "${value}" CACHE "${type}" "${docstring}") | |||
endif() | |||
endmacro() | |||
find_package(Doxygen) | |||
if(DOXYGEN_FOUND) | |||
find_file(DOXYFILE_IN "Doxyfile.in" | |||
PATHS "${CMAKE_CURRENT_SOURCE_DIR}" "${CMAKE_ROOT}/Modules/" | |||
NO_DEFAULT_PATH | |||
DOC "Path to the doxygen configuration template file") | |||
set(DOXYFILE "${CMAKE_CURRENT_BINARY_DIR}/Doxyfile") | |||
include(FindPackageHandleStandardArgs) | |||
find_package_handle_standard_args(DOXYFILE_IN DEFAULT_MSG "DOXYFILE_IN") | |||
endif() | |||
if(DOXYGEN_FOUND AND DOXYFILE_IN_FOUND) | |||
usedoxygen_set_default(DOXYFILE_OUTPUT_DIR "${CMAKE_CURRENT_BINARY_DIR}/doc" | |||
PATH "Doxygen output directory") | |||
usedoxygen_set_default(DOXYFILE_HTML_DIR "html" | |||
STRING "Doxygen HTML output directory") | |||
usedoxygen_set_default(DOXYFILE_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}" | |||
PATH "Input files source directory") | |||
usedoxygen_set_default(DOXYFILE_EXTRA_SOURCE_DIRS "" | |||
STRING "Additional source files/directories separated by space") | |||
set(DOXYFILE_SOURCE_DIRS "\"${DOXYFILE_SOURCE_DIR}\" ${DOXYFILE_EXTRA_SOURCES}") | |||
usedoxygen_set_default(DOXYFILE_LATEX YES BOOL "Generate LaTeX API documentation" OFF) | |||
usedoxygen_set_default(DOXYFILE_LATEX_DIR "latex" STRING "LaTex output directory") | |||
mark_as_advanced(DOXYFILE_OUTPUT_DIR DOXYFILE_HTML_DIR DOXYFILE_LATEX_DIR | |||
DOXYFILE_SOURCE_DIR DOXYFILE_EXTRA_SOURCE_DIRS DOXYFILE_IN) | |||
set_property(DIRECTORY | |||
APPEND PROPERTY | |||
ADDITIONAL_MAKE_CLEAN_FILES | |||
"${DOXYFILE_OUTPUT_DIR}/${DOXYFILE_HTML_DIR}") | |||
add_custom_target(doxygen | |||
COMMAND "${DOXYGEN_EXECUTABLE}" | |||
"${DOXYFILE}" | |||
COMMENT "Writing documentation to ${DOXYFILE_OUTPUT_DIR}..." | |||
WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}") | |||
set(DOXYFILE_DOT "NO") | |||
if(DOXYGEN_DOT_EXECUTABLE) | |||
set(DOXYFILE_DOT "YES") | |||
endif() | |||
## LaTeX | |||
set(DOXYFILE_PDFLATEX "NO") | |||
set_property(DIRECTORY APPEND PROPERTY | |||
ADDITIONAL_MAKE_CLEAN_FILES | |||
"${DOXYFILE_OUTPUT_DIR}/${DOXYFILE_LATEX_DIR}") | |||
if(DOXYFILE_LATEX STREQUAL "ON") | |||
set(DOXYFILE_GENERATE_LATEX "YES") | |||
find_package(LATEX) | |||
find_program(DOXYFILE_MAKE make) | |||
mark_as_advanced(DOXYFILE_MAKE) | |||
if(LATEX_COMPILER AND MAKEINDEX_COMPILER AND DOXYFILE_MAKE) | |||
if(PDFLATEX_COMPILER) | |||
set(DOXYFILE_PDFLATEX "YES") | |||
endif() | |||
add_custom_command(TARGET doxygen | |||
POST_BUILD | |||
COMMAND "${DOXYFILE_MAKE}" | |||
COMMENT "Running LaTeX for Doxygen documentation in ${DOXYFILE_OUTPUT_DIR}/${DOXYFILE_LATEX_DIR}..." | |||
WORKING_DIRECTORY "${DOXYFILE_OUTPUT_DIR}/${DOXYFILE_LATEX_DIR}") | |||
else() | |||
set(DOXYGEN_LATEX "NO") | |||
endif() | |||
else() | |||
set(DOXYFILE_GENERATE_LATEX "NO") | |||
endif() | |||
configure_file("${DOXYFILE_IN}" "${DOXYFILE}" @ONLY) | |||
add_custom_target(doc) | |||
add_dependencies(doc doxygen) | |||
endif() |
@@ -0,0 +1 @@ | |||
set(CMOCKA_INLUDE_DIR @PROJECT_SOURCE_DIR@/include) |
@@ -0,0 +1,11 @@ | |||
set(PACKAGE_VERSION @APPLICATION_VERSION@) | |||
# Check whether the requested PACKAGE_FIND_VERSION is compatible | |||
if("${PACKAGE_VERSION}" VERSION_LESS "${PACKAGE_FIND_VERSION}") | |||
set(PACKAGE_VERSION_COMPATIBLE FALSE) | |||
else() | |||
set(PACKAGE_VERSION_COMPATIBLE TRUE) | |||
if ("${PACKAGE_VERSION}" VERSION_EQUAL "${PACKAGE_FIND_VERSION}") | |||
set(PACKAGE_VERSION_EXACT TRUE) | |||
endif() | |||
endif() |
@@ -0,0 +1,11 @@ | |||
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(CMOCKA_INCLUDE_DIR @INCLUDE_INSTALL_DIR@) | |||
endif() | |||
set(CMOCKA_LIBRARY @LIB_INSTALL_DIR@/@CMOCKA_LIBRARY_NAME@) | |||
set(CMOCKA_LIBRARIES @LIB_INSTALL_DIR@/@CMOCKA_LIBRARY_NAME@) |
@@ -0,0 +1,6 @@ | |||
Name: ${APPLICATION_NAME} | |||
Description: The cmocka unit testing library | |||
Version: ${APPLICATION_VERSION} | |||
Libs: -L${LIB_INSTALL_DIR} -lcmocka | |||
Cflags: -I${INCLUDE_INSTALL_DIR} | |||
@@ -0,0 +1,169 @@ | |||
/* Name of package */ | |||
#cmakedefine PACKAGE "${APPLICATION_NAME}" | |||
/* Version number of package */ | |||
#cmakedefine VERSION "${APPLICATION_VERSION}" | |||
#cmakedefine LOCALEDIR "${LOCALE_INSTALL_DIR}" | |||
#cmakedefine DATADIR "${DATADIR}" | |||
#cmakedefine LIBDIR "${LIBDIR}" | |||
#cmakedefine PLUGINDIR "${PLUGINDIR}" | |||
#cmakedefine SYSCONFDIR "${SYSCONFDIR}" | |||
#cmakedefine BINARYDIR "${BINARYDIR}" | |||
#cmakedefine SOURCEDIR "${SOURCEDIR}" | |||
/************************** HEADER FILES *************************/ | |||
/* Define to 1 if you have the <assert.h> header file. */ | |||
#cmakedefine HAVE_ASSERT_H 1 | |||
/* Define to 1 if you have the <dlfcn.h> header file. */ | |||
#cmakedefine HAVE_DLFCN_H 1 | |||
/* Define to 1 if you have the <inttypes.h> header file. */ | |||
#cmakedefine HAVE_INTTYPES_H 1 | |||
/* Define to 1 if you have the <io.h> header file. */ | |||
#cmakedefine HAVE_IO_H 1 | |||
/* Define to 1 if you have the <malloc.h> header file. */ | |||
#cmakedefine HAVE_MALLOC_H 1 | |||
/* Define to 1 if you have the <memory.h> header file. */ | |||
#cmakedefine HAVE_MEMORY_H 1 | |||
/* Define to 1 if you have the <setjmp.h> header file. */ | |||
#cmakedefine HAVE_SETJMP_H 1 | |||
/* Define to 1 if you have the <signal.h> header file. */ | |||
#cmakedefine HAVE_SIGNAL_H 1 | |||
/* Define to 1 if you have the <stdarg.h> header file. */ | |||
#cmakedefine HAVE_STDARG_H 1 | |||
/* Define to 1 if you have the <stddef.h> header file. */ | |||
#cmakedefine HAVE_STDDEF_H 1 | |||
/* Define to 1 if you have the <stdint.h> header file. */ | |||
#cmakedefine HAVE_STDINT_H 1 | |||
/* Define to 1 if you have the <stdio.h> header file. */ | |||
#cmakedefine HAVE_STDIO_H 1 | |||
/* Define to 1 if you have the <stdlib.h> header file. */ | |||
#cmakedefine HAVE_STDLIB_H 1 | |||
/* Define to 1 if you have the <strings.h> header file. */ | |||
#cmakedefine HAVE_STRINGS_H 1 | |||
/* Define to 1 if you have the <string.h> header file. */ | |||
#cmakedefine HAVE_STRING_H 1 | |||
/* Define to 1 if you have the <sys/stat.h> header file. */ | |||
#cmakedefine HAVE_SYS_STAT_H 1 | |||
/* Define to 1 if you have the <sys/types.h> header file. */ | |||
#cmakedefine HAVE_SYS_TYPES_H 1 | |||
/* Define to 1 if you have the <time.h> header file. */ | |||
#cmakedefine HAVE_TIME_H 1 | |||
/* Define to 1 if you have the <unistd.h> header file. */ | |||
#cmakedefine HAVE_UNISTD_H 1 | |||
/**************************** STRUCTS ****************************/ | |||
#cmakedefine HAVE_STRUCT_TIMESPEC 1 | |||
/*************************** FUNCTIONS ***************************/ | |||
/* Define to 1 if you have the `calloc' function. */ | |||
#cmakedefine HAVE_CALLOC 1 | |||
/* Define to 1 if you have the `exit' function. */ | |||
#cmakedefine HAVE_EXIT 1 | |||
/* Define to 1 if you have the `fprintf' function. */ | |||
#cmakedefine HAVE_FPRINTF 1 | |||
/* Define to 1 if you have the `snprintf' function. */ | |||
#cmakedefine HAVE_SNPRINTF 1 | |||
/* Define to 1 if you have the `_snprintf' function. */ | |||
#cmakedefine HAVE__SNPRINTF 1 | |||
/* Define to 1 if you have the `_snprintf_s' function. */ | |||
#cmakedefine HAVE__SNPRINTF_S 1 | |||
/* Define to 1 if you have the `vsnprintf' function. */ | |||
#cmakedefine HAVE_VSNPRINTF 1 | |||
/* Define to 1 if you have the `_vsnprintf' function. */ | |||
#cmakedefine HAVE__VSNPRINTF 1 | |||
/* Define to 1 if you have the `_vsnprintf_s' function. */ | |||
#cmakedefine HAVE__VSNPRINTF_S 1 | |||
/* Define to 1 if you have the `free' function. */ | |||
#cmakedefine HAVE_FREE 1 | |||
/* Define to 1 if you have the `longjmp' function. */ | |||
#cmakedefine HAVE_LONGJMP 1 | |||
/* Define to 1 if you have the `siglongjmp' function. */ | |||
#cmakedefine HAVE_SIGLONGJMP 1 | |||
/* Define to 1 if you have the `malloc' function. */ | |||
#cmakedefine HAVE_MALLOC 1 | |||
/* Define to 1 if you have the `memcpy' function. */ | |||
#cmakedefine HAVE_MEMCPY 1 | |||
/* Define to 1 if you have the `memset' function. */ | |||
#cmakedefine HAVE_MEMSET 1 | |||
/* Define to 1 if you have the `printf' function. */ | |||
#cmakedefine HAVE_PRINTF 1 | |||
/* Define to 1 if you have the `setjmp' function. */ | |||
#cmakedefine HAVE_SETJMP 1 | |||
/* Define to 1 if you have the `signal' function. */ | |||
#cmakedefine HAVE_SIGNAL 1 | |||
/* Define to 1 if you have the `snprintf' function. */ | |||
#cmakedefine HAVE_SNPRINTF 1 | |||
/* Define to 1 if you have the `strcmp' function. */ | |||
#cmakedefine HAVE_STRCMP 1 | |||
/* Define to 1 if you have the `strcpy' function. */ | |||
#cmakedefine HAVE_STRCPY 1 | |||
/* Define to 1 if you have the `vsnprintf' function. */ | |||
#cmakedefine HAVE_VSNPRINTF 1 | |||
/* Define to 1 if you have the `strsignal' function. */ | |||
#cmakedefine HAVE_STRSIGNAL 1 | |||
/* Define to 1 if you have the `clock_gettime' function. */ | |||
#cmakedefine HAVE_CLOCK_GETTIME 1 | |||
/**************************** OPTIONS ****************************/ | |||
/* Check if we have TLS support with GCC */ | |||
#cmakedefine HAVE_GCC_THREAD_LOCAL_STORAGE 1 | |||
/* Check if we have TLS support with MSVC */ | |||
#cmakedefine HAVE_MSVC_THREAD_LOCAL_STORAGE 1 | |||
/* Check if we have CLOCK_REALTIME for clock_gettime() */ | |||
#cmakedefine HAVE_CLOCK_REALTIME 1 | |||
/*************************** ENDIAN *****************************/ | |||
#cmakedefine WORDS_SIZEOF_VOID_P ${WORDS_SIZEOF_VOID_P} | |||
/* Define WORDS_BIGENDIAN to 1 if your processor stores words with the most | |||
significant byte first (like Motorola and SPARC, unlike Intel). */ | |||
#cmakedefine WORDS_BIGENDIAN 1 |
@@ -0,0 +1,9 @@ | |||
coverity_assert_model.c: | |||
This file is a Coverity Modeling file for projects using CMocka for unit | |||
testing. The assert functiions could create false positives, to avoid that you | |||
can load this modeling file in the Coverity web interface. | |||
coverity_internal_model.c: | |||
This file is for the CMocka source code itself. |
@@ -0,0 +1,87 @@ | |||
#define LargestIntegralType unsigned long long | |||
void _assert_true(const LargestIntegralType result, | |||
const char* const expression, | |||
const char * const file, const int line) | |||
{ | |||
__coverity_panic__(); | |||
} | |||
void _assert_int_equal( | |||
const LargestIntegralType a, const LargestIntegralType b, | |||
const char * const file, const int line) | |||
{ | |||
__coverity_panic__(); | |||
} | |||
void _assert_int_not_equal( | |||
const LargestIntegralType a, const LargestIntegralType b, | |||
const char * const file, const int line) | |||
{ | |||
__coverity_panic__(); | |||
} | |||
void _assert_return_code(const LargestIntegralType result, | |||
size_t rlen, | |||
const LargestIntegralType error, | |||
const char * const expression, | |||
const char * const file, | |||
const int line) | |||
{ | |||
__coverity_panic__(); | |||
} | |||
void _assert_string_equal(const char * const a, const char * const b, | |||
const char * const file, const int line) | |||
{ | |||
__coverity_panic__(); | |||
} | |||
void _assert_string_not_equal(const char * const a, const char * const b, | |||
const char *file, const int line) | |||
{ | |||
__coverity_panic__(); | |||
} | |||
void _assert_memory_equal(const void * const a, const void * const b, | |||
const size_t size, const char* const file, | |||
const int line) | |||
{ | |||
__coverity_panic__(); | |||
} | |||
void _assert_memory_not_equal(const void * const a, const void * const b, | |||
const size_t size, const char* const file, | |||
const int line) | |||
{ | |||
__coverity_panic__(); | |||
} | |||
void _assert_in_range( | |||
const LargestIntegralType value, const LargestIntegralType minimum, | |||
const LargestIntegralType maximum, const char* const file, const int line) | |||
{ | |||
__coverity_panic__(); | |||
} | |||
void _assert_not_in_range( | |||
const LargestIntegralType value, const LargestIntegralType minimum, | |||
const LargestIntegralType maximum, const char* const file, const int line) | |||
{ | |||
__coverity_panic__(); | |||
} | |||
void _assert_in_set( | |||
const LargestIntegralType value, const LargestIntegralType values[], | |||
const size_t number_of_values, const char* const file, const int line) | |||
{ | |||
__coverity_panic__(); | |||
} | |||
void _assert_not_in_set( | |||
const LargestIntegralType value, const LargestIntegralType values[], | |||
const size_t number_of_values, const char* const file, const int line) | |||
{ | |||
__coverity_panic__(); | |||
} | |||
@@ -0,0 +1,5 @@ | |||
/* Functions to help coverity do static analysis on cmocka */ | |||
void exit_test(const int quit_application) | |||
{ | |||
__coverity_panic__(); | |||
} |
@@ -0,0 +1,5 @@ | |||
# | |||
# Build the documentation | |||
# | |||
include(UseDoxygen OPTIONAL) | |||
@@ -0,0 +1,706 @@ | |||
<!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 <stdarg.h> | |||
#include <stddef.h> | |||
#include <setjmp.h> | |||
#include <cmocka.h> | |||
// 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 <assert.h> | |||
// 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 <stdarg.h> | |||
#include <stddef.h> | |||
#include <setjmp.h> | |||
#include <cmocka.h> | |||
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 <string.h> | |||
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 <stdarg.h> | |||
#include <stddef.h> | |||
#include <setjmp.h> | |||
#include <cmocka.h> | |||
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 <malloc.h> | |||
#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 <stdarg.h> | |||
#include <stddef.h> | |||
#include <setjmp.h> | |||
#include <cmocka.h> | |||
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 <stddef.h> | |||
#include <stdio.h> | |||
#include <database.h> | |||
#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 <stdarg.h> | |||
#include <stddef.h> | |||
#include <setjmp.h> | |||
#include <cmocka.h> | |||
#include <database.h> | |||
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 <database.h> | |||
// 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 <stdarg.h> | |||
#include <stddef.h> | |||
#include <setjmp.h> | |||
#include <cmocka.h> | |||
#include <database.h> | |||
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 <stddef.h> | |||
#include <stdlib.h> | |||
#include <string.h> | |||
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 <stdarg.h> | |||
#include <stddef.h> | |||
#include <setjmp.h> | |||
#include <string.h> | |||
#include <cmocka.h> | |||
/* 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> |
@@ -0,0 +1,133 @@ | |||
/** | |||
@mainpage | |||
This is the online reference for developing with the cmocka library. It | |||
documents the cmocka C API. | |||
cmocka is an elegant unit testing framework for C with support for mock | |||
objects. It only requires the standard C library, works on a lot of platforms | |||
(including embedded) and with different compilers. | |||
http://cmocka.org/ | |||
@section main-features Features | |||
Tests written with cmocka are compiled into stand-alone executables and linked with the | |||
CMock 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. | |||
The CMocka library provides: | |||
- Support for mock objects. | |||
- Test fixtures. | |||
- Only requires a C library | |||
- Exception handling for signals (SIGSEGV, SIGILL, ...) | |||
- No use of fork() | |||
- Very well tested | |||
- Testing of memory leaks, buffer overflows and underflows. | |||
- A set of assert macros. | |||
- Several supported output formats (stdout, TAP, xUnit XML, Subunit) | |||
- License: Apache License 2.0 | |||
@section main-test A cmocka test | |||
Test cases are functions with the signature void function(void **state). Test | |||
applications initialize a table with test case function pointers using | |||
unit_test() macros. This table is then passed to the run_tests() macro to | |||
execute the tests. run_tests() sets up the appropriate exception / signal | |||
handlers and other data structures prior to running each test function. When a | |||
unit test is complete run_tests() performs various checks to determine whether | |||
the test succeeded. | |||
@code | |||
#include <stdarg.h> | |||
#include <stddef.h> | |||
#include <setjmp.h> | |||
#include <cmocka.h> | |||
/* A test case that does nothing and succeeds. */ | |||
static void null_test_success(void **state) { | |||
(void) state; /* unused */ | |||
} | |||
int main(void) { | |||
const struct CMUnitTest tests[] = { | |||
cmocka_unit_test(null_test_success), | |||
}; | |||
return cmocka_run_group_tests(tests, NULL, NULL); | |||
} | |||
@endcode | |||
@section main-mock Mock objects | |||
You may already have heard the term "Mock Object". It describes a special case | |||
of an object that mimics a real instance of an interface in order to provide | |||
enough of that interface for testing. While there are several unit testing | |||
frameworks that already provide some easy to use interface for creating | |||
different kinds of "fake" objects for testing, there may be some confusion in | |||
terms of how these test objects are programmed and what the behavioral | |||
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. | |||
<a href="https://lwn.net/Articles/558106/">Learn more ...</a> | |||
@section main-embedded Embedded platforms | |||
It is possible that some embedded platforms do not provide definitions for | |||
required types or that the guards to protect them are not defined. To address | |||
this issue you can create a header file name 'cmocka_platform.h' with the | |||
required types and definitions. After that point cmake to the include directory | |||
using: | |||
<pre> | |||
cmake -DCMOCKA_PLATFORM_INCLUDE=/home/compiler/my/include_directory .. | |||
</pre> | |||
@section main-threads Threading | |||
cmocka is not fully thread safe and it is not the goal of it to be it. We have | |||
several global variables to track test states. They are marked as thread local | |||
but it is possible that you still run into issues. However if you use cmocka | |||
for writing tests in an application which uses threads, you can set the | |||
following envionment variable: | |||
<pre> | |||
CMOCKA_TEST_ABORT='1' ./my_threading_test | |||
</pre> | |||
With this environment variable set to '1', cmocka will call <tt>abort()</tt> if | |||
a test fails. | |||
@section main-output Output formats | |||
By default, cmocka prints human-readable test output to stderr. It is | |||
possible to configure several other output formats. The configuration is | |||
done using the <tt>CMOCKA_MESSAGE_OUTPUT</tt> environment variable. The | |||
supported values are: | |||
- <tt>STDOUT</tt> for the default standard output printer | |||
- <tt>SUBUNIT</tt> for subunit output | |||
- <tt>TAP</tt> for Test Anything Protocol (TAP) output | |||
- <tt>XML</tt> for xUnit XML format | |||
The case doesn't matter. | |||
The XML output goes to stderr by default. If the environment variable | |||
<tt>CMOCKA_XML_FILE</tt> exists and the file specified by this variable | |||
doesn't exist yet, then cmocka will put the output to this file. Note | |||
that if you are have several groups you should set <tt>CMOCKA_XML_FILE</tt> | |||
to <tt>CMOCKA_XML_FILE=cm_%%g.xml</tt>. In this %g will be replaced by | |||
the group_name of the test and a file will be created for each group, | |||
othwerwise all groups will be printed into the same file. | |||
*/ |
@@ -0,0 +1,140 @@ | |||
project(cmocka-examples C) | |||
include_directories( | |||
${CMAKE_BINARY_DIR} | |||
${CMAKE_CURRENT_SOURCE_DIR} | |||
${CMOCKA_PUBLIC_INCLUDE_DIRS} | |||
) | |||
set_source_files_properties( | |||
calculator.c | |||
allocate_module.c | |||
assert_module.c | |||
PROPERTIES | |||
COMPILE_DEFINITIONS UNIT_TESTING=1) | |||
if (WIN32 OR CYGWIN OR MINGW) | |||
set(CMOCKA_DLL_LIB ${CMAKE_BINARY_DIR}/src) | |||
file(TO_NATIVE_PATH "${CMOCKA_DLL_PATH}" CMOCKA_DLL_PATH) | |||
set(DLL_PATH_ENV "${CMOCKA_DLL_PATH};$ENV{PATH}") | |||
# | |||
# IMPORTANT NOTE: The set_tests_properties(), below, internally | |||
# stores its name/value pairs with a semicolon delimiter. | |||
# because of this we must protect the semicolons in the path | |||
# | |||
string(REPLACE ";" "\\;" DLL_PATH_ENV "${DLL_PATH_ENV}") | |||
endif (WIN32 OR CYGWIN OR MINGW) | |||
### The most simple test | |||
add_executable(simple_test simple_test.c) | |||
target_link_libraries(simple_test ${CMOCKA_SHARED_LIBRARY}) | |||
add_test(simple_test ${CMAKE_CURRENT_BINARY_DIR}/simple_test) | |||
if (WIN32 OR CYGWIN OR MINGW) | |||
set_tests_properties(simple_test PROPERTIES ENVIRONMENT "PATH=${DLL_PATH_ENV}") | |||
endif (WIN32 OR CYGWIN OR MINGW) | |||
### Calulator test | |||
#TODO investigate dll jmp issue on MinGW | |||
if (NOT MINGW OR WITH_STATIC_LIB) | |||
add_executable(calculator_test calculator.c calculator_test.c) | |||
add_test(calculator_test ${CMAKE_CURRENT_BINARY_DIR}/calculator_test) | |||
if (WIN32 OR CYGWIN) | |||
set_tests_properties(calculator_test PROPERTIES ENVIRONMENT "PATH=${DLL_PATH_ENV}") | |||
endif (WIN32 OR CYGWIN) | |||
if (MINGW) | |||
target_link_libraries(calculator_test ${CMOCKA_STATIC_LIBRARY}) | |||
else (MINGW) | |||
target_link_libraries(calculator_test ${CMOCKA_SHARED_LIBRARY}) | |||
endif (MINGW) | |||
if (WIN32 OR CYGWIN OR MINGW) | |||
set_tests_properties(calculator_test PROPERTIES ENVIRONMENT "PATH=${DLL_PATH_ENV}") | |||
endif (WIN32 OR CYGWIN OR MINGW) | |||
endif (NOT MINGW OR WITH_STATIC_LIB) | |||
### Allocate module test | |||
add_executable(allocate_module_test allocate_module.c allocate_module_test.c) | |||
target_link_libraries(allocate_module_test ${CMOCKA_SHARED_LIBRARY}) | |||
# This is a test that should detect leaks and overflows and will fail for that | |||
add_test(allocate_module_test ${CMAKE_CURRENT_BINARY_DIR}/allocate_module_test) | |||
if (WIN32 OR CYGWIN OR MINGW) | |||
set_tests_properties(allocate_module_test PROPERTIES ENVIRONMENT "PATH=${DLL_PATH_ENV}") | |||
endif (WIN32 OR CYGWIN OR MINGW) | |||
set_tests_properties( | |||
allocate_module_test | |||
PROPERTIES | |||
WILL_FAIL 1 | |||
) | |||
### Assert macro test | |||
add_executable(assert_macro_test assert_macro.c assert_macro_test.c) | |||
target_link_libraries(assert_macro_test ${CMOCKA_SHARED_LIBRARY}) | |||
add_test(assert_macro_test ${CMAKE_CURRENT_BINARY_DIR}/assert_macro_test) | |||
set_tests_properties( | |||
assert_macro_test | |||
PROPERTIES | |||
WILL_FAIL 1 | |||
) | |||
if (WIN32 OR CYGWIN OR MINGW) | |||
set_tests_properties(assert_macro_test PROPERTIES ENVIRONMENT "PATH=${DLL_PATH_ENV}") | |||
endif (WIN32 OR CYGWIN OR MINGW) | |||
### Assert module test | |||
add_executable(assert_module_test assert_module.c assert_module_test.c) | |||
target_link_libraries(assert_module_test ${CMOCKA_SHARED_LIBRARY}) | |||
add_test(assert_module_test ${CMAKE_CURRENT_BINARY_DIR}/assert_module_test) | |||
set_tests_properties( | |||
assert_module_test | |||
PROPERTIES | |||
WILL_FAIL 1 | |||
) | |||
if (WIN32 OR CYGWIN OR MINGW) | |||
set_tests_properties(assert_module_test PROPERTIES ENVIRONMENT "PATH=${DLL_PATH_ENV}") | |||
endif (WIN32 OR CYGWIN OR MINGW) | |||
### Customer database test | |||
add_executable(customer_database_test customer_database.c customer_database_test.c) | |||
target_link_libraries(customer_database_test ${CMOCKA_SHARED_LIBRARY}) | |||
add_test(customer_database_test ${CMAKE_CURRENT_BINARY_DIR}/customer_database_test) | |||
if (WIN32 OR CYGWIN OR MINGW) | |||
set_tests_properties(customer_database_test PROPERTIES ENVIRONMENT "PATH=${DLL_PATH_ENV}") | |||
endif (WIN32 OR CYGWIN OR MINGW) | |||
### Key Value Test | |||
add_executable(key_value_test key_value.c key_value_test.c) | |||
target_link_libraries(key_value_test ${CMOCKA_SHARED_LIBRARY}) | |||
add_test(key_value_test ${CMAKE_CURRENT_BINARY_DIR}/key_value_test) | |||
if (WIN32 OR CYGWIN OR MINGW) | |||
set_tests_properties(key_value_test PROPERTIES ENVIRONMENT "PATH=${DLL_PATH_ENV}") | |||
endif (WIN32 OR CYGWIN OR MINGW) | |||
### Product database test | |||
add_executable(product_database_test product_database.c product_database_test.c) | |||
target_link_libraries(product_database_test ${CMOCKA_SHARED_LIBRARY}) | |||
add_test(product_database_test ${CMAKE_CURRENT_BINARY_DIR}/product_database_test) | |||
set_tests_properties( | |||
product_database_test | |||
PROPERTIES | |||
PASS_REGULAR_EXPRESSION | |||
"\\[ FAILED \\] 2 test" | |||
) | |||
if (WIN32 OR CYGWIN OR MINGW) | |||
set_tests_properties(product_database_test PROPERTIES ENVIRONMENT "PATH=${DLL_PATH_ENV}") | |||
endif (WIN32 OR CYGWIN OR MINGW) | |||
# TODO Execute "$CMAKE_LINKER --help" and check for --wrap | |||
if (${CMAKE_C_COMPILER_ID} MATCHES "(GNU|Clang)" AND NOT APPLE) | |||
add_subdirectory(chef_wrap) | |||
endif() |
@@ -0,0 +1,55 @@ | |||
/* | |||
* Copyright 2008 Google Inc. | |||
* | |||
* 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. | |||
*/ | |||
#ifdef HAVE_CONFIG_H | |||
#include "config.h" | |||
#endif | |||
#ifdef HAVE_MALLOC_H | |||
#include <malloc.h> | |||
#endif | |||
#include <sys/types.h> | |||
#include <stdlib.h> | |||
#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(void); | |||
void buffer_overflow(void); | |||
void buffer_underflow(void); | |||
void leak_memory(void) { | |||
int * const temporary = (int*)malloc(sizeof(int)); | |||
*temporary = 0; | |||
} | |||
void buffer_overflow(void) { | |||
char * const memory = (char*)malloc(sizeof(int)); | |||
memory[sizeof(int)] = '!'; | |||
free(memory); | |||
} | |||
void buffer_underflow(void) { | |||
char * const memory = (char*)malloc(sizeof(int)); | |||
memory[-1] = '!'; | |||
free(memory); | |||
} |
@@ -0,0 +1,53 @@ | |||
/* | |||
* Copyright 2008 Google Inc. | |||
* | |||
* 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 <stddef.h> | |||
#include <setjmp.h> | |||
#include <cmocka.h> | |||
extern void leak_memory(void); | |||
extern void buffer_overflow(void); | |||
extern void buffer_underflow(void); | |||
/* Test case that fails as leak_memory() leaks a dynamically allocated block. */ | |||
static void leak_memory_test(void **state) { | |||
(void) state; /* unused */ | |||
leak_memory(); | |||
} | |||
/* Test case that fails as buffer_overflow() corrupts an allocated block. */ | |||
static void buffer_overflow_test(void **state) { | |||
(void) state; /* unused */ | |||
buffer_overflow(); | |||
} | |||
/* Test case that fails as buffer_underflow() corrupts an allocated block. */ | |||
static void buffer_underflow_test(void **state) { | |||
(void) state; /* unused */ | |||
buffer_underflow(); | |||
} | |||
int main(void) { | |||
const struct CMUnitTest tests[] = { | |||
cmocka_unit_test(leak_memory_test), | |||
cmocka_unit_test(buffer_overflow_test), | |||
cmocka_unit_test(buffer_underflow_test), | |||
}; | |||
return cmocka_run_group_tests(tests, NULL, NULL); | |||
} |
@@ -0,0 +1,39 @@ | |||
/* | |||
* Copyright 2008 Google Inc. | |||
* | |||
* 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 <string.h> | |||
#include "assert_macro.h" | |||
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; | |||
} |
@@ -0,0 +1,2 @@ | |||
const char* get_status_code_string(const unsigned int status_code); | |||
unsigned int string_to_status_code(const char* const status_code_string); |
@@ -0,0 +1,46 @@ | |||
/* | |||
* Copyright 2008 Google Inc. | |||
* | |||
* 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 <stddef.h> | |||
#include <setjmp.h> | |||
#include <cmocka.h> | |||
#include "assert_macro.h" | |||
/* This test will fail since the string returned by get_status_code_string(0) | |||
* doesn't match "Connection timed out". */ | |||
static void get_status_code_string_test(void **state) { | |||
(void) state; /* unused */ | |||
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 */ | |||
static void string_to_status_code_test(void **state) { | |||
(void) state; /* unused */ | |||
assert_int_equal(string_to_status_code("Address not found"), 0); | |||
assert_int_equal(string_to_status_code("Connection timed out"), 1); | |||
} | |||
int main(void) { | |||
const struct CMUnitTest tests[] = { | |||
cmocka_unit_test(get_status_code_string_test), | |||
cmocka_unit_test(string_to_status_code_test), | |||
}; | |||
return cmocka_run_group_tests(tests, NULL, NULL); | |||
} |
@@ -0,0 +1,38 @@ | |||
/* | |||
* Copyright 2008 Google Inc. | |||
* | |||
* 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 <assert.h> | |||
#include "assert_module.h" | |||
/* 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(((expression) ? 1 : 0), #expression, __FILE__, __LINE__); | |||
#endif /* UNIT_TESTING */ | |||
void increment_value(int * const value) { | |||
assert(value); | |||
(*value) ++; | |||
} | |||
void decrement_value(int * const value) { | |||
if (value) { | |||
(*value) --; | |||
} | |||
} |
@@ -0,0 +1,18 @@ | |||
/* | |||
* Copyright 2008 Google Inc. | |||
* | |||
* 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. | |||
*/ | |||
void increment_value(int * const value); | |||
void decrement_value(int * const value); |
@@ -0,0 +1,56 @@ | |||
/* | |||
* Copyright 2008 Google Inc. | |||
* | |||
* 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 <stddef.h> | |||
#include <setjmp.h> | |||
#include <cmocka.h> | |||
#include "assert_module.h" | |||
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. */ | |||
static void increment_value_fail(void **state) { | |||
(void) state; | |||
increment_value(NULL); | |||
} | |||
/* This test case succeeds since increment_value() asserts on the NULL | |||
* pointer. */ | |||
static void increment_value_assert(void **state) { | |||
(void) state; | |||
expect_assert_failure(increment_value(NULL)); | |||
} | |||
/* This test case fails since decrement_value() doesn't assert on a NULL | |||
* pointer. */ | |||
static void decrement_value_fail(void **state) { | |||
(void) state; | |||
expect_assert_failure(decrement_value(NULL)); | |||
} | |||
int main(void) { | |||
const struct CMUnitTest tests[] = { | |||
cmocka_unit_test(increment_value_fail), | |||
cmocka_unit_test(increment_value_assert), | |||
cmocka_unit_test(decrement_value_fail), | |||
}; | |||
return cmocka_run_group_tests(tests, NULL, NULL); | |||
} |
@@ -0,0 +1,286 @@ | |||
/* | |||
* Copyright 2008 Google Inc. | |||
* | |||
* 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. | |||
*/ | |||
/* A calculator example used to demonstrate the cmocka testing library. */ | |||
#ifdef HAVE_CONFIG_H | |||
#include "config.h" | |||
#endif | |||
#include <assert.h> | |||
#ifdef HAVE_MALLOC_H | |||
#include <malloc.h> | |||
#endif | |||
#include <stdio.h> | |||
#include <stdlib.h> | |||
#include <string.h> | |||
/* If this is being built for a unit test. */ | |||
#ifdef UNIT_TESTING | |||
/* Redirect printf to a function in the test application so it's possible to | |||
* test the standard output. */ | |||
#ifdef printf | |||
#undef printf | |||
#endif /* printf */ | |||
extern int example_test_printf(const char *format, ...); | |||
#define printf example_test_printf | |||
extern void print_message(const char *format, ...); | |||
/* Redirect fprintf to a function in the test application so it's possible to | |||
* test error messages. */ | |||
#ifdef fprintf | |||
#undef fprintf | |||
#endif /* fprintf */ | |||
#define fprintf example_test_fprintf | |||
extern int example_test_fprintf(FILE * const file, const char *format, ...); | |||
/* Redirect assert to mock_assert() so assertions can be caught by cmocka. */ | |||
#ifdef assert | |||
#undef assert | |||
#endif /* assert */ | |||
#define assert(expression) \ | |||
mock_assert((int)(expression), #expression, __FILE__, __LINE__) | |||
void mock_assert(const int result, const char* expression, const char *file, | |||
const int line); | |||
/* Redirect calloc and free to test_calloc() and test_free() so cmocka can | |||
* check for memory leaks. */ | |||
#ifdef calloc | |||
#undef calloc | |||
#endif /* calloc */ | |||
#define calloc(num, size) _test_calloc(num, size, __FILE__, __LINE__) | |||
#ifdef free | |||
#undef free | |||
#endif /* free */ | |||
#define free(ptr) _test_free(ptr, __FILE__, __LINE__) | |||
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); | |||
int example_main(int argc, char *argv[]); | |||
/* main is defined in the unit test so redefine name of the the main function | |||
* here. */ | |||
#define main example_main | |||
/* All functions in this object need to be exposed to the test application, | |||
* so redefine static to nothing. */ | |||
#define static | |||
#endif /* UNIT_TESTING */ | |||
/* A binary arithmetic integer operation (add, subtract etc.) */ | |||
typedef int (*BinaryOperator)(int a, int b); | |||
/* Structure which maps operator strings to functions. */ | |||
typedef struct OperatorFunction { | |||
const char* operator; | |||
BinaryOperator function; | |||
} OperatorFunction; | |||
BinaryOperator find_operator_function_by_string( | |||
const size_t number_of_operator_functions, | |||
const OperatorFunction * const operator_functions, | |||
const char* const operator_string); | |||
int perform_operation( | |||
int number_of_arguments, char *arguments[], | |||
const size_t number_of_operator_functions, | |||
const OperatorFunction * const operator_functions, | |||
int * const number_of_intermediate_values, | |||
int ** const intermediate_values, int * const error_occurred); | |||
static int add(int a, int b); | |||
static int subtract(int a, int b); | |||
static int multiply(int a, int b); | |||
static int divide(int a, int b); | |||
/* Associate operator strings to functions. */ | |||
static OperatorFunction operator_function_map[] = { | |||
{"+", add}, | |||
{"-", subtract}, | |||
{"*", multiply}, | |||
{"/", divide}, | |||
}; | |||
static int add(int a, int b) { | |||
return a + b; | |||
} | |||
static int subtract(int a, int b) { | |||
return a - b; | |||
} | |||
static int multiply(int a, int b) { | |||
return a * b; | |||
} | |||
static int divide(int a, int b) { | |||
assert(b); /* Check for divide by zero. */ | |||
return a / b; | |||
} | |||
/* Searches the specified array of operator_functions for the function | |||
* associated with the specified operator_string. This function returns the | |||
* function associated with operator_string if successful, NULL otherwise. | |||
*/ | |||
BinaryOperator find_operator_function_by_string( | |||
const size_t number_of_operator_functions, | |||
const OperatorFunction * const operator_functions, | |||
const char* const operator_string) { | |||
size_t i; | |||
assert(!number_of_operator_functions || operator_functions); | |||
assert(operator_string != NULL); | |||
for (i = 0; i < number_of_operator_functions; i++) { | |||
const OperatorFunction *const operator_function = | |||
&operator_functions[i]; | |||
if (strcmp(operator_function->operator, operator_string) == 0) { | |||
return operator_function->function; | |||
} | |||
} | |||
return NULL; | |||
} | |||
/* Perform a series of binary arithmetic integer operations with no operator | |||
* precedence. | |||
* | |||
* The input expression is specified by arguments which is an array of | |||
* containing number_of_arguments strings. Operators invoked by the expression | |||
* are specified by the array operator_functions containing | |||
* number_of_operator_functions, OperatorFunction structures. The value of | |||
* each binary operation is stored in a pointer returned to intermediate_values | |||
* which is allocated by malloc(). | |||
* | |||
* If successful, this function returns the integer result of the operations. | |||
* If an error occurs while performing the operation error_occurred is set to | |||
* 1, the operation is aborted and 0 is returned. | |||
*/ | |||
int perform_operation( | |||
int number_of_arguments, char *arguments[], | |||
const size_t number_of_operator_functions, | |||
const OperatorFunction * const operator_functions, | |||
int * const number_of_intermediate_values, | |||
int ** const intermediate_values, int * const error_occurred) { | |||
char *end_of_integer; | |||
int value; | |||
int i; | |||
assert(!number_of_arguments || arguments); | |||
assert(!number_of_operator_functions || operator_functions); | |||
assert(error_occurred != NULL); | |||
assert(number_of_intermediate_values != NULL); | |||
assert(intermediate_values != NULL); | |||
*error_occurred = 0; | |||
*number_of_intermediate_values = 0; | |||
*intermediate_values = NULL; | |||
if (!number_of_arguments) | |||
return 0; | |||
/* Parse the first value. */ | |||
value = (int)strtol(arguments[0], &end_of_integer, 10); | |||
if (end_of_integer == arguments[0]) { | |||
/* If an error occurred while parsing the integer. */ | |||
fprintf(stderr, "Unable to parse integer from argument %s\n", | |||
arguments[0]); | |||
*error_occurred = 1; | |||
return 0; | |||
} | |||
/* Allocate an array for the output values. */ | |||
*intermediate_values = calloc(((number_of_arguments - 1) / 2), | |||
sizeof(**intermediate_values)); | |||
i = 1; | |||
while (i < number_of_arguments) { | |||
int other_value; | |||
const char* const operator_string = arguments[i]; | |||
const BinaryOperator function = find_operator_function_by_string( | |||
number_of_operator_functions, operator_functions, operator_string); | |||
int * const intermediate_value = | |||
&((*intermediate_values)[*number_of_intermediate_values]); | |||
(*number_of_intermediate_values) ++; | |||
if (!function) { | |||
fprintf(stderr, "Unknown operator %s, argument %d\n", | |||
operator_string, i); | |||
*error_occurred = 1; | |||
break; | |||
} | |||
i ++; | |||
if (i == number_of_arguments) { | |||
fprintf(stderr, "Binary operator %s missing argument\n", | |||
operator_string); | |||
*error_occurred = 1; | |||
break; | |||
} | |||
other_value = (int)strtol(arguments[i], &end_of_integer, 10); | |||
if (end_of_integer == arguments[i]) { | |||
/* If an error occurred while parsing the integer. */ | |||
fprintf(stderr, "Unable to parse integer %s of argument %d\n", | |||
arguments[i], i); | |||
*error_occurred = 1; | |||
break; | |||
} | |||
i ++; | |||
/* Perform the operation and store the intermediate value. */ | |||
*intermediate_value = function(value, other_value); | |||
value = *intermediate_value; | |||
} | |||
if (*error_occurred) { | |||
free(*intermediate_values); | |||
*intermediate_values = NULL; | |||
*number_of_intermediate_values = 0; | |||
return 0; | |||
} | |||
return value; | |||
} | |||
int main(int argc, char *argv[]) { | |||
int return_value; | |||
int number_of_intermediate_values; | |||
int *intermediate_values; | |||
/* Peform the operation. */ | |||
const int result = perform_operation( | |||
argc - 1, &argv[1], | |||
sizeof(operator_function_map) / sizeof(operator_function_map[0]), | |||
operator_function_map, &number_of_intermediate_values, | |||
&intermediate_values, &return_value); | |||
/* If no errors occurred display the result. */ | |||
if (!return_value && argc > 1) { | |||
int i; | |||
int intermediate_value_index = 0; | |||
printf("%s\n", argv[1]); | |||
for (i = 2; i < argc; i += 2) { | |||
assert(intermediate_value_index < number_of_intermediate_values); | |||
printf(" %s %s = %d\n", argv[i], argv[i + 1], | |||
intermediate_values[intermediate_value_index++]); | |||
} | |||
printf("= %d\n", result); | |||
} | |||
if (intermediate_values) { | |||
free(intermediate_values); | |||
} | |||
return return_value; | |||
} |
@@ -0,0 +1,482 @@ | |||
/* | |||
* Copyright 2008 Google Inc. | |||
* | |||
* 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 <stddef.h> | |||
#include <setjmp.h> | |||
#include "cmocka.h" | |||
#include <stdio.h> | |||
#ifdef _WIN32 | |||
/* Compatibility with the Windows standard C library. */ | |||
#define vsnprintf _vsnprintf | |||
#endif /* _WIN32 */ | |||
#define array_length(x) (sizeof(x) / sizeof((x)[0])) | |||
/* To simplify this code, these functions and data structures could have been | |||
* separated out from the application example.c into a header shared with | |||
* test application. However, this example illustrates how it's possible to | |||
* test existing code with little modification. */ | |||
typedef int (*BinaryOperator)(int a, int b); | |||
typedef struct OperatorFunction { | |||
const char* operator; | |||
BinaryOperator function; | |||
} OperatorFunction; | |||
extern int add(int a, int b); | |||
extern int subtract(int a, int b); | |||
extern int multiply(int a, int b); | |||
extern int divide(int a, int b); | |||
extern BinaryOperator find_operator_function_by_string( | |||
const size_t number_of_operator_functions, | |||
const OperatorFunction * const operator_functions, | |||
const char* const operator_string); | |||
extern int perform_operation( | |||
int number_of_arguments, char *arguments[], | |||
const size_t number_of_operator_functions, | |||
const OperatorFunction * const operator_functions, | |||
int * const number_of_intermediate_values, | |||
int ** const intermediate_values, int * const error_occurred); | |||
extern int example_main(int argc, char *argv[]); | |||
int example_test_fprintf(FILE* const file, const char *format, ...) CMOCKA_PRINTF_ATTRIBUTE(2, 3); | |||
int example_test_printf(const char *format, ...) CMOCKA_PRINTF_ATTRIBUTE(1, 2); | |||
static char temporary_buffer[256]; | |||
/* A mock fprintf function that checks the value of strings printed to the | |||
* standard error stream. */ | |||
int example_test_fprintf(FILE* const file, const char *format, ...) { | |||
int return_value; | |||
va_list args; | |||
assert_true(file == stderr); | |||
va_start(args, format); | |||
return_value = vsnprintf(temporary_buffer, sizeof(temporary_buffer), | |||
format, args); | |||
check_expected_ptr(temporary_buffer); | |||
va_end(args); | |||
return return_value; | |||
} | |||
/* A mock printf function that checks the value of strings printed to the | |||
* standard output stream. */ | |||
int example_test_printf(const char *format, ...) { | |||
int return_value; | |||
va_list args; | |||
va_start(args, format); | |||
return_value = vsnprintf(temporary_buffer, sizeof(temporary_buffer), | |||
format, args); | |||
check_expected_ptr(temporary_buffer); | |||
va_end(args); | |||
return return_value; | |||
} | |||
/* A mock binary operator function. */ | |||
static int binary_operator(int a, int b) { | |||
check_expected(a); | |||
check_expected(b); | |||
return (int)mock(); | |||
} | |||
/* Ensure add() adds two integers correctly. */ | |||
static void test_add(void **state) { | |||
(void) state; /* unused */ | |||
assert_int_equal(add(3, 3), 6); | |||
assert_int_equal(add(3, -3), 0); | |||
} | |||
/* Ensure subtract() subtracts two integers correctly. */ | |||
static void test_subtract(void **state) { | |||
(void) state; /* unused */ | |||
assert_int_equal(subtract(3, 3), 0); | |||
assert_int_equal(subtract(3, -3), 6); | |||
} | |||
/* Ensure multiple() mulitplies two integers correctly. */ | |||
static void test_multiply(void **state) { | |||
(void) state; /* unused */ | |||
assert_int_equal(multiply(3, 3), 9); | |||
assert_int_equal(multiply(3, 0), 0); | |||
} | |||
/* Ensure divide() divides one integer by another correctly. */ | |||
static void test_divide(void **state) { | |||
(void) state; /* unused */ | |||
assert_int_equal(divide(10, 2), 5); | |||
assert_int_equal(divide(2, 10), 0); | |||
} | |||
/* Ensure divide() asserts when trying to divide by zero. */ | |||
static void test_divide_by_zero(void **state) { | |||
(void) state; /* unused */ | |||
expect_assert_failure(divide(100, 0)); | |||
} | |||
/* Ensure find_operator_function_by_string() asserts when a NULL pointer is | |||
* specified as the table to search. */ | |||
static void test_find_operator_function_by_string_null_functions(void **state) { | |||
(void) state; /* unused */ | |||
expect_assert_failure(find_operator_function_by_string(1, NULL, "test")); | |||
} | |||
/* Ensure find_operator_function_by_string() asserts when a NULL pointer is | |||
* specified as the string to search for. */ | |||
static void test_find_operator_function_by_string_null_string(void **state) { | |||
const OperatorFunction operator_functions[] = { | |||
{"+", binary_operator}, | |||
}; | |||
(void) state; /* unused */ | |||
expect_assert_failure(find_operator_function_by_string( | |||
array_length(operator_functions), operator_functions, NULL)); | |||
} | |||
/* Ensure find_operator_function_by_string() returns NULL when a NULL pointer | |||
* is specified as the table to search when the table size is 0. */ | |||
static void test_find_operator_function_by_string_valid_null_functions(void **state) { | |||
(void) state; /* unused */ | |||
assert_null(find_operator_function_by_string(0, NULL, "test")); | |||
} | |||
/* Ensure find_operator_function_by_string() returns NULL when searching for | |||
* an operator string that isn't in the specified table. */ | |||
static void test_find_operator_function_by_string_not_found(void **state) { | |||
const OperatorFunction operator_functions[] = { | |||
{"+", binary_operator}, | |||
{"-", binary_operator}, | |||
{"/", binary_operator}, | |||
}; | |||
(void) state; /* unused */ | |||
assert_null(find_operator_function_by_string( | |||
array_length(operator_functions), operator_functions, "test")); | |||
} | |||
/* Ensure find_operator_function_by_string() returns the correct function when | |||
* searching for an operator string that is in the specified table. */ | |||
static void test_find_operator_function_by_string_found(void **state) { | |||
const OperatorFunction operator_functions[] = { | |||
{"+", (BinaryOperator)0x12345678}, | |||
{"-", (BinaryOperator)0xDEADBEEF}, | |||
{"/", (BinaryOperator)0xABADCAFE}, | |||
}; | |||
(void) state; /* unused */ | |||
assert_int_equal( | |||
cast_ptr_to_largest_integral_type( | |||
find_operator_function_by_string(array_length(operator_functions), | |||
operator_functions, | |||
"-")), | |||
0xDEADBEEF); | |||
} | |||
/* Ensure perform_operation() asserts when a NULL arguments array is specified. */ | |||
static void test_perform_operation_null_args(void **state) { | |||
const OperatorFunction operator_functions[] = { | |||
{"+", binary_operator}, | |||
}; | |||
int number_of_intermediate_values; | |||
int *intermediate_values; | |||
int error_occurred; | |||
(void) state; /* unused */ | |||
expect_assert_failure(perform_operation( | |||
1, NULL, array_length(operator_functions), operator_functions, | |||
&number_of_intermediate_values, &intermediate_values, | |||
&error_occurred)); | |||
} | |||
/* Ensure perform_operation() asserts when a NULL operator_functions array is | |||
* specified. */ | |||
static void test_perform_operation_null_operator_functions(void **state) { | |||
const char *args[] = { | |||
"1", "+", "2", "*", "4" | |||
}; | |||
int number_of_intermediate_values; | |||
int *intermediate_values; | |||
int error_occurred; | |||
(void) state; /* unused */ | |||
expect_assert_failure(perform_operation( | |||
array_length(args), (char **) args, 1, NULL, &number_of_intermediate_values, | |||
&intermediate_values, &error_occurred)); | |||
} | |||
/* Ensure perform_operation() asserts when a NULL pointer is specified for | |||
* number_of_intermediate_values. */ | |||
static void test_perform_operation_null_number_of_intermediate_values(void **state) { | |||
const OperatorFunction operator_functions[] = { | |||
{"+", binary_operator}, | |||
}; | |||
const char *args[] = { | |||
"1", "+", "2", "*", "4" | |||
}; | |||
int *intermediate_values; | |||
int error_occurred; | |||
(void) state; /* unused */ | |||
expect_assert_failure(perform_operation( | |||
array_length(args), (char **) args, 1, operator_functions, NULL, | |||
&intermediate_values, &error_occurred)); | |||
} | |||
/* Ensure perform_operation() asserts when a NULL pointer is specified for | |||
* intermediate_values. */ | |||
static void test_perform_operation_null_intermediate_values(void **state) { | |||
const OperatorFunction operator_functions[] = { | |||
{"+", binary_operator}, | |||
}; | |||
const char *args[] = { | |||
"1", "+", "2", "*", "4" | |||
}; | |||
int number_of_intermediate_values; | |||
int error_occurred; | |||
(void) state; /* unused */ | |||
expect_assert_failure(perform_operation( | |||
array_length(args), (char **) args, array_length(operator_functions), | |||
operator_functions, &number_of_intermediate_values, NULL, | |||
&error_occurred)); | |||
} | |||
/* Ensure perform_operation() returns 0 when no arguments are specified. */ | |||
static void test_perform_operation_no_arguments(void **state) { | |||
int number_of_intermediate_values; | |||
int *intermediate_values; | |||
int error_occurred; | |||
(void) state; /* unused */ | |||
assert_int_equal(perform_operation( | |||
0, NULL, 0, NULL, &number_of_intermediate_values, &intermediate_values, | |||
&error_occurred), 0); | |||
assert_int_equal(error_occurred, 0); | |||
} | |||
/* Ensure perform_operation() returns an error if the first argument isn't | |||
* an integer string. */ | |||
static void test_perform_operation_first_arg_not_integer(void **state) { | |||
const OperatorFunction operator_functions[] = { | |||
{"+", binary_operator}, | |||
}; | |||
const char *args[] = { | |||
"test", "+", "2", "*", "4" | |||
}; | |||
int number_of_intermediate_values; | |||
int *intermediate_values; | |||
int error_occurred; | |||
(void) state; /* unused */ | |||
expect_string(example_test_fprintf, temporary_buffer, | |||
"Unable to parse integer from argument test\n"); | |||
assert_int_equal(perform_operation( | |||
array_length(args), (char **) args, array_length(operator_functions), | |||
operator_functions, &number_of_intermediate_values, | |||
&intermediate_values, &error_occurred), 0); | |||
assert_int_equal(error_occurred, 1); | |||
} | |||
/* Ensure perform_operation() returns an error when parsing an unknown | |||
* operator. */ | |||
static void test_perform_operation_unknown_operator(void **state) { | |||
const OperatorFunction operator_functions[] = { | |||
{"+", binary_operator}, | |||
}; | |||
const char *args[] = { | |||
"1", "*", "2", "*", "4" | |||
}; | |||
int number_of_intermediate_values; | |||
int *intermediate_values; | |||
int error_occurred; | |||
(void) state; /* unused */ | |||
expect_string(example_test_fprintf, temporary_buffer, | |||
"Unknown operator *, argument 1\n"); | |||
assert_int_equal(perform_operation( | |||
array_length(args), (char **) args, array_length(operator_functions), | |||
operator_functions, &number_of_intermediate_values, | |||
&intermediate_values, &error_occurred), 0); | |||
assert_int_equal(error_occurred, 1); | |||
} | |||
/* Ensure perform_operation() returns an error when nothing follows an | |||
* operator. */ | |||
static void test_perform_operation_missing_argument(void **state) { | |||
const OperatorFunction operator_functions[] = { | |||
{"+", binary_operator}, | |||
}; | |||
const char *args[] = { | |||
"1", "+", | |||
}; | |||
int number_of_intermediate_values; | |||
int *intermediate_values; | |||
int error_occurred; | |||
(void) state; /* unused */ | |||
expect_string(example_test_fprintf, temporary_buffer, | |||
"Binary operator + missing argument\n"); | |||
assert_int_equal(perform_operation( | |||
array_length(args), (char **) args, array_length(operator_functions), | |||
operator_functions, &number_of_intermediate_values, | |||
&intermediate_values, &error_occurred), 0); | |||
assert_int_equal(error_occurred, 1); | |||
} | |||
/* Ensure perform_operation() returns an error when an integer doesn't follow | |||
* an operator. */ | |||
static void test_perform_operation_no_integer_after_operator(void **state) { | |||
const OperatorFunction operator_functions[] = { | |||
{"+", binary_operator}, | |||
}; | |||
const char *args[] = { | |||
"1", "+", "test", | |||
}; | |||
int number_of_intermediate_values; | |||
int *intermediate_values; | |||
int error_occurred; | |||
(void) state; /* unused */ | |||
expect_string(example_test_fprintf, temporary_buffer, | |||
"Unable to parse integer test of argument 2\n"); | |||
assert_int_equal(perform_operation( | |||
array_length(args), (char **) args, array_length(operator_functions), | |||
operator_functions, &number_of_intermediate_values, | |||
&intermediate_values, &error_occurred), 0); | |||
assert_int_equal(error_occurred, 1); | |||
} | |||
/* Ensure perform_operation() succeeds given valid input parameters. */ | |||
static void test_perform_operation(void **state) { | |||
const OperatorFunction operator_functions[] = { | |||
{"+", binary_operator}, | |||
{"*", binary_operator}, | |||
}; | |||
const char *args[] = { | |||
"1", "+", "3", "*", "10", | |||
}; | |||
int number_of_intermediate_values; | |||
int *intermediate_values = NULL; | |||
int error_occurred; | |||
(void) state; /* unused */ | |||
/* Setup return values of mock operator functions. */ | |||
/* Addition. */ | |||
expect_value(binary_operator, a, 1); | |||
expect_value(binary_operator, b, 3); | |||
will_return(binary_operator, 4); | |||
/* Multiplication. */ | |||
expect_value(binary_operator, a, 4); | |||
expect_value(binary_operator, b, 10); | |||
will_return(binary_operator, 40); | |||
assert_int_equal(perform_operation( | |||
array_length(args), (char **) args, array_length(operator_functions), | |||
operator_functions, &number_of_intermediate_values, | |||
&intermediate_values, &error_occurred), 40); | |||
assert_int_equal(error_occurred, 0); | |||
assert_non_null(intermediate_values); | |||
assert_int_equal(intermediate_values[0], 4); | |||
assert_int_equal(intermediate_values[1], 40); | |||
test_free(intermediate_values); | |||
} | |||
/* Ensure main() in example.c succeeds given no arguments. */ | |||
static void test_example_main_no_args(void **state) { | |||
const char *args[] = { | |||
"example", | |||
}; | |||
(void) state; /* unused */ | |||
assert_int_equal(example_main(array_length(args), (char **) args), 0); | |||
} | |||
/* Ensure main() in example.c succeeds given valid input arguments. */ | |||
static void test_example_main(void **state) { | |||
const char *args[] = { | |||
"example", "1", "+", "3", "*", "10", | |||
}; | |||
(void) state; /* unused */ | |||
expect_string(example_test_printf, temporary_buffer, "1\n"); | |||
expect_string(example_test_printf, temporary_buffer, " + 3 = 4\n"); | |||
expect_string(example_test_printf, temporary_buffer, " * 10 = 40\n"); | |||
expect_string(example_test_printf, temporary_buffer, "= 40\n"); | |||
assert_int_equal(example_main(array_length(args), (char **) args), 0); | |||
} | |||
int main(void) { | |||
const struct CMUnitTest tests[] = { | |||
cmocka_unit_test(test_add), | |||
cmocka_unit_test(test_subtract), | |||
cmocka_unit_test(test_multiply), | |||
cmocka_unit_test(test_divide), | |||
cmocka_unit_test(test_divide_by_zero), | |||
cmocka_unit_test(test_find_operator_function_by_string_null_functions), | |||
cmocka_unit_test(test_find_operator_function_by_string_null_string), | |||
cmocka_unit_test(test_find_operator_function_by_string_valid_null_functions), | |||
cmocka_unit_test(test_find_operator_function_by_string_not_found), | |||
cmocka_unit_test(test_find_operator_function_by_string_found), | |||
cmocka_unit_test(test_perform_operation_null_args), | |||
cmocka_unit_test(test_perform_operation_null_operator_functions), | |||
cmocka_unit_test(test_perform_operation_null_number_of_intermediate_values), | |||
cmocka_unit_test(test_perform_operation_null_intermediate_values), | |||
cmocka_unit_test(test_perform_operation_no_arguments), | |||
cmocka_unit_test(test_perform_operation_first_arg_not_integer), | |||
cmocka_unit_test(test_perform_operation_unknown_operator), | |||
cmocka_unit_test(test_perform_operation_missing_argument), | |||
cmocka_unit_test(test_perform_operation_no_integer_after_operator), | |||
cmocka_unit_test(test_perform_operation), | |||
cmocka_unit_test(test_example_main_no_args), | |||
cmocka_unit_test(test_example_main), | |||
}; | |||
return cmocka_run_group_tests(tests, NULL, NULL); | |||
} |
@@ -0,0 +1,20 @@ | |||
project(cmocka-wrap-examples C) | |||
include_directories( | |||
${CMAKE_BINARY_DIR} | |||
${CMAKE_CURRENT_SOURCE_DIR} | |||
${CMOCKA_PUBLIC_INCLUDE_DIRS} | |||
) | |||
add_executable(waiter_test_wrap waiter_test_wrap.c chef.c) | |||
target_link_libraries(waiter_test_wrap ${CMOCKA_SHARED_LIBRARY}) | |||
add_test(waiter_test_wrap ${CMAKE_CURRENT_BINARY_DIR}/waiter_test_wrap) | |||
set_target_properties(waiter_test_wrap | |||
PROPERTIES | |||
LINK_FLAGS "-Wl,--wrap=chef_cook" | |||
) | |||
if (WIN32 OR MINGW OR CYGWIN) | |||
set_tests_properties(waiter_test_wrap PROPERTIES ENVIRONMENT "PATH=${DLL_PATH_ENV}") | |||
endif (WIN32 OR MINGW OR CYGWIN) |
@@ -0,0 +1,54 @@ | |||
/* | |||
* Copyright 2013 (c) Andreas Schneider <asn@cynapses.org> | |||
* Jakub Hrozek <jakub.hrozek@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 <stdarg.h> | |||
#include <stddef.h> | |||
#include <setjmp.h> | |||
#include <cmocka.h> | |||
#include <stdio.h> | |||
#include <errno.h> | |||
#include <stdbool.h> | |||
#include <string.h> | |||
#include "chef.h" | |||
/* This is the real chef, just not implemented yet, currently it always | |||
* returns ENOSYS | |||
*/ | |||
int chef_cook(const char *order, char **dish_out) | |||
{ | |||
if (order == NULL || dish_out == NULL) return EINVAL; | |||
return -ENOSYS; | |||
} | |||
/* Print chef return codes as string */ | |||
const char *chef_strerror(int error) | |||
{ | |||
switch (error) { | |||
case 0: | |||
return "Success"; | |||
case -1: | |||
return "Unknown dish"; | |||
case -2: | |||
return "Not enough ingredients for the dish"; | |||
} | |||
return "Unknown error!"; | |||
} | |||
@@ -0,0 +1,19 @@ | |||
/* | |||
* Copyright 2013 (c) Andreas Schneider <asn@cynapses.org> | |||
* Jakub Hrozek <jakub.hrozek@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. | |||
*/ | |||
int chef_cook(const char *order, char **dish_out); | |||
const char *chef_strerror(int error); |
@@ -0,0 +1,176 @@ | |||
/* | |||
* Copyright 2013 (c) Andreas Schneider <asn@cynapses.org> | |||
* Jakub Hrozek <jakub.hrozek@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 <errno.h> | |||
#include <stdbool.h> | |||
#include <stdio.h> | |||
#include <stdlib.h> | |||
#include <string.h> | |||
#include <stdarg.h> | |||
#include <stddef.h> | |||
#include <setjmp.h> | |||
#include <cmocka.h> | |||
#include "waiter_test_wrap.h" | |||
#include "chef.h" | |||
/* | |||
* This is a mocked Chef object. A real Chef would look if he knows | |||
* the dish in some kind of internal database and check his storage for | |||
* ingredients. This chef simply retrieves this information from the test | |||
* that is calling him. | |||
* | |||
* This object is also wrapped - if any code links with this file and is | |||
* compiled with linker option --wrap chef_cook, any calls of that code to | |||
* chef_cook will end up calling __wrap_chef_cook. | |||
* | |||
* If for any reason the wrapped function wanted to call the real chef_cook() | |||
* function, it could do so by calling the special symbol __real_chef_cook(). | |||
* | |||
* Please note that when setting return codes for the chef_cook function, we | |||
* use this wrapper as a parameter for the will_return() macro, not the | |||
* real function. | |||
* | |||
* A chef object would return: | |||
* 0 - cooking dish went fine | |||
* -1 - unknown dish | |||
* -2 - ran out of ingredients for the dish | |||
* any other error code -- unexpected error while cooking | |||
* | |||
* The return codes should be consistent between the real and mocked objects. | |||
*/ | |||
int __wrap_chef_cook(const char *order, char **dish_out) | |||
{ | |||
bool has_ingredients; | |||
bool knows_dish; | |||
char *dish; | |||
check_expected_ptr(order); | |||
knows_dish = mock_type(bool); | |||
if (knows_dish == false) { | |||
return -1; | |||
} | |||
has_ingredients = mock_type(bool); | |||
if (has_ingredients == false) { | |||
return -2; | |||
} | |||
dish = mock_ptr_type(char *); | |||
*dish_out = strdup(dish); | |||
if (*dish_out == NULL) return ENOMEM; | |||
return mock_type(int); | |||
} | |||
/* Waiter return codes: | |||
* 0 - success | |||
* -1 - kitchen failed | |||
* -2 - kitchen succeeded, but cooked a different food | |||
*/ | |||
static int waiter_process(const char *order, char **dish) | |||
{ | |||
int rv; | |||
rv = chef_cook(order, dish); | |||
if (rv != 0) { | |||
fprintf(stderr, "Chef couldn't cook %s: %s\n", | |||
order, chef_strerror(rv)); | |||
return -1; | |||
} | |||
/* Check if we received the dish we wanted from the kitchen */ | |||
if (strcmp(order, *dish) != 0) { | |||
free(*dish); | |||
*dish = NULL; | |||
return -2; | |||
} | |||
return 0; | |||
} | |||
static void test_order_hotdog(void **state) | |||
{ | |||
int rv; | |||
char *dish; | |||
(void) state; /* unused */ | |||
/* We expect the chef to receive an order for a hotdog */ | |||
expect_string(__wrap_chef_cook, order, "hotdog"); | |||
/* And we tell the test chef that ke knows how to cook a hotdog | |||
* and has the ingredients | |||
*/ | |||
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(__wrap_chef_cook, 0); | |||
/* Test the waiter */ | |||
rv = waiter_process("hotdog", &dish); | |||
/* We expect the cook to succeed cooking the hotdog */ | |||
assert_int_equal(rv, 0); | |||
/* And actually receive one */ | |||
assert_string_equal(dish, "hotdog"); | |||
if (dish != NULL) { | |||
free(dish); | |||
} | |||
} | |||
static void test_bad_dish(void **state) | |||
{ | |||
int rv; | |||
char *dish; | |||
(void) state; /* unused */ | |||
/* We expect the chef to receive an order for a hotdog */ | |||
expect_string(__wrap_chef_cook, order, "hotdog"); | |||
/* And we tell the test chef that ke knows how to cook a hotdog | |||
* and has the ingredients | |||
*/ | |||
will_return(__wrap_chef_cook, true); | |||
will_return(__wrap_chef_cook, true); | |||
/* The result will be a burger and the cooking process will succeed. | |||
* 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(__wrap_chef_cook, 0); | |||
/* Test the waiter */ | |||
rv = waiter_process("hotdog", &dish); | |||
/* According to the documentation the waiter should return -2 now */ | |||
assert_int_equal(rv, -2); | |||
/* And do not give the bad dish to the customer */ | |||
assert_null(dish); | |||
} | |||
int main(void) | |||
{ | |||
const struct CMUnitTest tests[] = { | |||
cmocka_unit_test(test_order_hotdog), | |||
cmocka_unit_test(test_bad_dish), | |||
}; | |||
return cmocka_run_group_tests(tests, NULL, NULL); | |||
} |
@@ -0,0 +1,2 @@ | |||
int __wrap_chef_cook(const char *order, char **dish_out); |
@@ -0,0 +1,51 @@ | |||
/* | |||
* Copyright 2008 Google Inc. | |||
* | |||
* 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 <stddef.h> | |||
#include <stdio.h> | |||
#include <database.h> | |||
#ifdef _WIN32 | |||
#define snprintf _snprintf | |||
#endif /* _WIN32 */ | |||
DatabaseConnection* connect_to_customer_database(void); | |||
unsigned int get_customer_id_by_name( | |||
DatabaseConnection * const connection, | |||
const char * const customer_name); | |||
/* Connect to the database containing customer information. */ | |||
DatabaseConnection* connect_to_customer_database(void) { | |||
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)*((int *)results); | |||
} |
@@ -0,0 +1,89 @@ | |||
/* | |||
* Copyright 2008 Google Inc. | |||
* | |||
* 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 <stddef.h> | |||
#include <setjmp.h> | |||
#include <cmocka.h> | |||
#include <database.h> | |||
extern DatabaseConnection* connect_to_customer_database(void); | |||
extern unsigned int get_customer_id_by_name( | |||
DatabaseConnection * const connection, const char * const customer_name); | |||
/* Mock query database function. */ | |||
static unsigned int mock_query_database(DatabaseConnection* const connection, | |||
const char * const query_string, | |||
void *** const results) { | |||
(void) connection; /* unused */ | |||
(void) query_string; /* unused */ | |||
*results = (void **)mock_ptr_type(int *); | |||
return mock_ptr_type(int); | |||
} | |||
/* Mock of the connect to database function. */ | |||
DatabaseConnection* connect_to_database(const char * const database_url, | |||
const unsigned int port) { | |||
(void) database_url; /* unused */ | |||
(void) port; /* unused */ | |||
return (DatabaseConnection*)((size_t)mock()); | |||
} | |||
static void test_connect_to_customer_database(void **state) { | |||
(void) state; /* unused */ | |||
will_return(connect_to_database, 0x0DA7ABA53); | |||
assert_int_equal((size_t)connect_to_customer_database(), 0x0DA7ABA53); | |||
} | |||
/* This test fails as the mock function connect_to_database() will have no | |||
* value to return. */ | |||
#if 0 | |||
static void fail_connect_to_customer_database(void **state) { | |||
(void) state; /* unused */ | |||
assert_true(connect_to_customer_database() == | |||
(DatabaseConnection*)0x0DA7ABA53); | |||
} | |||
#endif | |||
static 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; | |||
int rc; | |||
(void) state; /* unused */ | |||
will_return(mock_query_database, | |||
cast_ptr_to_largest_integral_type(&customer_ids)); | |||
will_return(mock_query_database, 1); | |||
rc = get_customer_id_by_name(&connection, "john doe"); | |||
assert_int_equal(rc, 543); | |||
} | |||
int main(void) { | |||
const struct CMUnitTest tests[] = { | |||
cmocka_unit_test(test_connect_to_customer_database), | |||
cmocka_unit_test(test_get_customer_id_by_name), | |||
}; | |||
return cmocka_run_group_tests(tests, NULL, NULL); | |||
} |
@@ -0,0 +1,37 @@ | |||
/* | |||
* Copyright 2008 Google Inc. | |||
* | |||
* 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. | |||
*/ | |||
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); | |||
@@ -0,0 +1,51 @@ | |||
/* | |||
* Copyright 2008 Google Inc. | |||
* | |||
* 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 <stddef.h> | |||
#include <stdlib.h> | |||
#include <string.h> | |||
#include "key_value.h" | |||
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. */ | |||
static 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(void) { | |||
qsort(key_values, number_of_key_values, sizeof(*key_values), | |||
key_value_compare_keys); | |||
} |
@@ -0,0 +1,27 @@ | |||
/* | |||
* Copyright 2008 Google Inc. | |||
* | |||
* 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. | |||
*/ | |||
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); | |||
KeyValue* find_item_by_value(const char * const value); | |||
void sort_items_by_key(void); |
@@ -0,0 +1,77 @@ | |||
/* | |||
* Copyright 2008 Google Inc. | |||
* | |||
* 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 <stddef.h> | |||
#include <setjmp.h> | |||
#include <string.h> | |||
#include <cmocka.h> | |||
#include "key_value.h" | |||
static KeyValue key_values[] = { | |||
{ 10, "this" }, | |||
{ 52, "test" }, | |||
{ 20, "a" }, | |||
{ 13, "is" }, | |||
}; | |||
static int 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])); | |||
return 0; | |||
} | |||
static int destroy_key_values(void **state) { | |||
test_free(*state); | |||
set_key_values(NULL, 0); | |||
return 0; | |||
} | |||
static void test_find_item_by_value(void **state) { | |||
unsigned int i; | |||
(void) state; /* unused */ | |||
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 != NULL); | |||
assert_int_equal(found->key, key_values[i].key); | |||
assert_string_equal(found->value, key_values[i].value); | |||
} | |||
} | |||
static 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(void) { | |||
const struct CMUnitTest tests[] = { | |||
cmocka_unit_test_setup_teardown(test_find_item_by_value, | |||
create_key_values, destroy_key_values), | |||
cmocka_unit_test_setup_teardown(test_sort_items_by_key, | |||
create_key_values, destroy_key_values), | |||
}; | |||
return cmocka_run_group_tests(tests, NULL, NULL); | |||
} |
@@ -0,0 +1,24 @@ | |||
/* | |||
* Copyright 2008 Google Inc. | |||
* | |||
* 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 <database.h> | |||
DatabaseConnection* connect_to_product_database(void); | |||
/* Connect to the database containing customer information. */ | |||
DatabaseConnection* connect_to_product_database(void) { | |||
return connect_to_database("products.abcd.org", 322); | |||
} | |||
@@ -0,0 +1,72 @@ | |||
/* | |||
* Copyright 2008 Google Inc. | |||
* | |||
* 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 <stddef.h> | |||
#include <setjmp.h> | |||
#include <cmocka.h> | |||
#include <database.h> | |||
extern DatabaseConnection* connect_to_product_database(void); | |||
/* 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_ptr(url); | |||
check_expected(port); | |||
return (DatabaseConnection*)((size_t)mock()); | |||
} | |||
static void test_connect_to_product_database(void **state) { | |||
(void) state; /* unused */ | |||
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((size_t)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(). */ | |||
static void test_connect_to_product_database_bad_url(void **state) { | |||
(void) state; /* unused */ | |||
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((size_t)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. */ | |||
static void test_connect_to_product_database_missing_parameter(void **state) { | |||
(void) state; /* unused */ | |||
expect_string(connect_to_database, url, "products.abcd.org"); | |||
will_return(connect_to_database, 0xDA7ABA53); | |||
assert_int_equal((size_t)connect_to_product_database(), 0xDA7ABA53); | |||
} | |||
int main(void) { | |||
const struct CMUnitTest tests[] = { | |||
cmocka_unit_test(test_connect_to_product_database), | |||
cmocka_unit_test(test_connect_to_product_database_bad_url), | |||
cmocka_unit_test(test_connect_to_product_database_missing_parameter), | |||
}; | |||
return cmocka_run_group_tests(tests, NULL, NULL); | |||
} |
@@ -0,0 +1,17 @@ | |||
#include <stdarg.h> | |||
#include <stddef.h> | |||
#include <setjmp.h> | |||
#include <cmocka.h> | |||
/* A test case that does nothing and succeeds. */ | |||
static void null_test_success(void **state) { | |||
(void) state; /* unused */ | |||
} | |||
int main(void) { | |||
const struct CMUnitTest tests[] = { | |||
cmocka_unit_test(null_test_success), | |||
}; | |||
return cmocka_run_group_tests(tests, NULL, NULL); | |||
} |
@@ -0,0 +1,10 @@ | |||
DEFS_TO_REMOVE=-DHAVE_SETJMP_H -DHAVE_STDIO_H | |||
all: | |||
gcc -I../../include $(DEFS_TO_REMOVE) -o cmocka.o -c ../../src/cmocka.c | |||
gcc -I../../include -o simple_test.o -c simple_test.c | |||
gcc -o a.out cmocka.o simple_test.o | |||
clean: | |||
rm -rf *.o | |||
rm -rf a.out |
@@ -0,0 +1,17 @@ | |||
#include <stdarg.h> | |||
#include <stddef.h> | |||
#include <setjmp.h> | |||
#include <cmocka.h> | |||
/* A test case that does nothing and succeeds. */ | |||
static void null_test_success(void **state) { | |||
(void) state; /* unused */ | |||
} | |||
int main(void) { | |||
const struct CMUnitTest tests[] = { | |||
cmocka_unit_test(null_test_success), | |||
}; | |||
return cmocka_run_group_tests(tests, NULL, NULL); | |||
} |
@@ -0,0 +1,27 @@ | |||
project(cmocka-headers C) | |||
set(cmocka_HDRS | |||
cmocka.h | |||
cmocka_pbc.h | |||
) | |||
install( | |||
FILES | |||
${cmocka_HDRS} | |||
DESTINATION | |||
${INCLUDE_INSTALL_DIR} | |||
COMPONENT | |||
headers | |||
) | |||
if (WITH_CMOCKERY_SUPPORT) | |||
install( | |||
FILES | |||
cmockery/cmockery.h | |||
cmockery/pbc.h | |||
DESTINATION | |||
${INCLUDE_INSTALL_DIR}/cmockery | |||
COMPONENT | |||
headers | |||
) | |||
endif() |
@@ -0,0 +1,62 @@ | |||
/* | |||
* Copyright 2014 Luis Pabon, Jr. | |||
* | |||
* 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. | |||
*/ | |||
/* | |||
* Programming by Contract is a programming methodology | |||
* which binds the caller and the function called to a | |||
* contract. The contract is represented using Hoare Triple: | |||
* {P} C {Q} | |||
* where {P} is the precondition before executing command C, | |||
* and {Q} is the postcondition. | |||
* | |||
* See also: | |||
* http://en.wikipedia.org/wiki/Design_by_contract | |||
* http://en.wikipedia.org/wiki/Hoare_logic | |||
* http://dlang.org/dbc.html | |||
*/ | |||
#ifndef CMOCKA_PBC_H_ | |||
#define CMOCKA_PBC_H_ | |||
#if defined(UNIT_TESTING) || defined (DEBUG) | |||
#include <assert.h> | |||
/* | |||
* Checks caller responsibility against contract | |||
*/ | |||
#define REQUIRE(cond) assert(cond) | |||
/* | |||
* Checks function reponsability against contract. | |||
*/ | |||
#define ENSURE(cond) assert(cond) | |||
/* | |||
* While REQUIRE and ENSURE apply to functions, INVARIANT | |||
* applies to classes/structs. It ensures that intances | |||
* of the class/struct are consistent. In other words, | |||
* that the instance has not been corrupted. | |||
*/ | |||
#define INVARIANT(invariant_fnc) do{ (invariant_fnc) } while (0); | |||
#else | |||
#define REQUIRE(cond) do { } while (0); | |||
#define ENSURE(cond) do { } while (0); | |||
#define INVARIANT(invariant_fnc) do{ } while (0); | |||
#endif /* defined(UNIT_TESTING) || defined (DEBUG) */ | |||
#endif /* CMOCKA_PBC_H_ */ | |||
@@ -0,0 +1,163 @@ | |||
/* | |||
* Copyright 2008 Google Inc. | |||
* | |||
* 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_PRIVATE_H_ | |||
#define CMOCKA_PRIVATE_H_ | |||
#ifdef HAVE_CONFIG_H | |||
#include "config.h" | |||
#endif | |||
#include <stdint.h> | |||
#ifdef _WIN32 | |||
#include <windows.h> | |||
# ifdef _MSC_VER | |||
# include <stdio.h> /* _snprintf */ | |||
# undef inline | |||
# define inline __inline | |||
# ifndef va_copy | |||
# define va_copy(dest, src) (dest = src) | |||
# endif | |||
# define strcasecmp _stricmp | |||
# define strncasecmp _strnicmp | |||
# if defined(HAVE__SNPRINTF_S) | |||
# undef snprintf | |||
# define snprintf(d, n, ...) _snprintf_s((d), (n), _TRUNCATE, __VA_ARGS__) | |||
# else /* HAVE__SNPRINTF_S */ | |||
# if defined(HAVE__SNPRINTF) | |||
# undef snprintf | |||
# define snprintf _snprintf | |||
# else /* HAVE__SNPRINTF */ | |||
# if !defined(HAVE_SNPRINTF) | |||
# error "no snprintf compatible function found" | |||
# endif /* HAVE_SNPRINTF */ | |||
# endif /* HAVE__SNPRINTF */ | |||
# endif /* HAVE__SNPRINTF_S */ | |||
# if defined(HAVE__VSNPRINTF_S) | |||
# undef vsnprintf | |||
# define vsnprintf(s, n, f, v) _vsnprintf_s((s), (n), _TRUNCATE, (f), (v)) | |||
# else /* HAVE__VSNPRINTF_S */ | |||
# if defined(HAVE__VSNPRINTF) | |||
# undef vsnprintf | |||
# define vsnprintf _vsnprintf | |||
# else | |||
# if !defined(HAVE_VSNPRINTF) | |||
# error "No vsnprintf compatible function found" | |||
# endif /* HAVE_VSNPRINTF */ | |||
# endif /* HAVE__VSNPRINTF */ | |||
# 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 | |||
#ifndef PRIu64 | |||
# define PRIu64 "I64u" | |||
#endif | |||
#ifndef PRIuMAX | |||
# define PRIuMAX PRIu64 | |||
#endif | |||
#ifndef PRIxMAX | |||
#define PRIxMAX "I64x" | |||
#endif | |||
#ifndef PRIXMAX | |||
#define PRIXMAX "I64X" | |||
#endif | |||
#else /* _WIN32 */ | |||
#ifndef __PRI64_PREFIX | |||
# if __WORDSIZE == 64 | |||
# define __PRI64_PREFIX "l" | |||
# else | |||
# define __PRI64_PREFIX "ll" | |||
# endif | |||
#endif | |||
#ifndef PRIdS | |||
# define PRIdS "zd" | |||
#endif | |||
#ifndef PRIu64 | |||
# define PRIu64 __PRI64_PREFIX "u" | |||
#endif | |||
#ifndef PRIuMAX | |||
# define PRIuMAX __PRI64_PREFIX "u" | |||
#endif | |||
#ifndef PRIxMAX | |||
#define PRIxMAX __PRI64_PREFIX "x" | |||
#endif | |||
#ifndef PRIXMAX | |||
#define PRIXMAX __PRI64_PREFIX "X" | |||
#endif | |||
#endif /* _WIN32 */ | |||
/** Free memory space */ | |||
#define SAFE_FREE(x) do { if ((x) != NULL) {free(x); x=NULL;} } while(0) | |||
/** Zero a structure */ | |||
#define ZERO_STRUCT(x) memset((char *)&(x), 0, sizeof(x)) | |||
/** Zero a structure given a pointer to the structure */ | |||
#define ZERO_STRUCTP(x) do { if ((x) != NULL) memset((char *)(x), 0, sizeof(*(x))); } while(0) | |||
/** Get the size of an array */ | |||
#define ARRAY_SIZE(a) (sizeof(a)/sizeof(a[0])) | |||
/** Overwrite the complete string with 'X' */ | |||
#define BURN_STRING(x) do { if ((x) != NULL) memset((x), 'X', strlen((x))); } while(0) | |||
/** | |||
* This is a hack to fix warnings. The idea is to use this everywhere that we | |||
* get the "discarding const" warning by the compiler. That doesn't actually | |||
* fix the real issue, but marks the place and you can search the code for | |||
* discard_const. | |||
* | |||
* Please use this macro only when there is no other way to fix the warning. | |||
* We should use this function in only in a very few places. | |||
* | |||
* Also, please call this via the discard_const_p() macro interface, as that | |||
* makes the return type safe. | |||
*/ | |||
#define discard_const(ptr) ((void *)((uintptr_t)(ptr))) | |||
/** | |||
* Type-safe version of discard_const | |||
*/ | |||
#define discard_const_p(type, ptr) ((type *)discard_const(ptr)) | |||
#endif /* CMOCKA_PRIVATE_H_ */ |
@@ -0,0 +1 @@ | |||
#include <cmocka.h> |
@@ -0,0 +1 @@ | |||
#include <cmocka_pbc.h> |
@@ -0,0 +1,118 @@ | |||
project(cmocka-library C) | |||
set(CMOCKA_PLATFORM_INCLUDE CACHE PATH "Path to include directory for cmocka_platform.h") | |||
set(CMOCKA_PUBLIC_INCLUDE_DIRS | |||
${cmocka_SOURCE_DIR}/include | |||
${CMOCKA_PLATFORM_INCLUDE} | |||
CACHE INTERNAL "cmocka public include directories" | |||
) | |||
set(CMOCKA_PRIVATE_INCLUDE_DIRS | |||
${cmocka_BINARY_DIR} | |||
) | |||
set(CMOCKA_SHARED_LIBRARY | |||
cmocka_shared | |||
CACHE INTERNAL "cmocka shared library" | |||
) | |||
if (WITH_STATIC_LIB) | |||
set(CMOCKA_STATIC_LIBRARY | |||
cmocka_static | |||
CACHE INTERNAL "cmocka static library" | |||
) | |||
endif (WITH_STATIC_LIB) | |||
set(CMOCKA_LINK_LIBRARIES | |||
${CMOCKA_REQUIRED_LIBRARIES} | |||
CACHE INTERNAL "cmocka link libraries" | |||
) | |||
set(cmocka_SRCS | |||
cmocka.c | |||
) | |||
if (WIN32) | |||
set(cmocka_SRCS | |||
${cmocka_SRCS} | |||
cmocka.def | |||
) | |||
endif (WIN32) | |||
include_directories( | |||
${CMOCKA_PUBLIC_INCLUDE_DIRS} | |||
${CMOCKA_PRIVATE_INCLUDE_DIRS} | |||
) | |||
add_definitions(-DHAVE_CONFIG_H=1) | |||
if (CMOCKA_PLATFORM_INCLUDE) | |||
add_definitions(-DCMOCKA_PLATFORM_INCLUDE=1) | |||
endif() | |||
add_library(${CMOCKA_SHARED_LIBRARY} SHARED ${cmocka_SRCS}) | |||
target_link_libraries(${CMOCKA_SHARED_LIBRARY} ${CMOCKA_LINK_LIBRARIES}) | |||
set_target_properties( | |||
${CMOCKA_SHARED_LIBRARY} | |||
PROPERTIES | |||
OUTPUT_NAME | |||
cmocka | |||
DEFINE_SYMBOL | |||
CMOCKA_EXPORTS | |||
) | |||
if (NOT WIN32) | |||
set_target_properties( | |||
${CMOCKA_SHARED_LIBRARY} | |||
PROPERTIES | |||
VERSION | |||
${LIBRARY_VERSION} | |||
SOVERSION | |||
${LIBRARY_SOVERSION} | |||
) | |||
endif (NOT WIN32) | |||
install( | |||
TARGETS ${CMOCKA_SHARED_LIBRARY} | |||
RUNTIME DESTINATION ${BIN_INSTALL_DIR} | |||
LIBRARY DESTINATION ${LIB_INSTALL_DIR} | |||
ARCHIVE DESTINATION ${LIB_INSTALL_DIR} | |||
COMPONENT libraries | |||
) | |||
if (WITH_STATIC_LIB) | |||
add_library(${CMOCKA_STATIC_LIBRARY} STATIC ${cmocka_SRCS}) | |||
set_target_properties( | |||
${CMOCKA_STATIC_LIBRARY} | |||
PROPERTIES | |||
VERSION | |||
${LIBRARY_VERSION} | |||
SOVERSION | |||
${LIBRARY_SOVERSION} | |||
OUTPUT_NAME | |||
cmocka | |||
) | |||
install( | |||
TARGETS ${CMOCKA_STATIC_LIBRARY} | |||
DESTINATION ${LIB_INSTALL_DIR} | |||
COMPONENT libraries | |||
) | |||
endif (WITH_STATIC_LIB) | |||
if (POLICY CMP0026) | |||
cmake_policy(SET CMP0026 OLD) | |||
endif() | |||
# | |||
# In order to run tests we will need to set the approriate environment | |||
# variable so that the test program can locate its dependent DLL's. First | |||
# we want to know what directory our dependent DLL was installed into: | |||
# | |||
get_target_property(_cmocka_dir cmocka_shared LOCATION_${CMOCKA_BUILD_TYPE}) | |||
get_filename_component(_cmocka_path "${_cmocka_dir}" PATH) | |||
file(TO_NATIVE_PATH "${_cmocka_path}" _cmocka_path_native) | |||
set(CMOCKA_DLL_PATH "${_cmocka_path_native}" PARENT_SCOPE) |
@@ -0,0 +1,49 @@ | |||
LIBRARY cmocka | |||
EXPORTS | |||
_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 | |||
cmocka_set_message_output | |||
global_expect_assert_env | |||
global_expecting_assert | |||
global_last_failed_assert | |||
mock_assert | |||
print_error | |||
print_message | |||
vprint_error | |||
vprint_message |
@@ -0,0 +1,243 @@ | |||
project(tests C) | |||
include_directories( | |||
${CMAKE_BINARY_DIR} | |||
${CMAKE_CURRENT_SOURCE_DIR} | |||
${CMAKE_SOURCE_DIR}/include | |||
) | |||
set(CMOCKA_TESTS | |||
test_alloc | |||
test_group_setup_assert | |||
test_group_setup_fail | |||
test_fixtures | |||
test_group_fixtures | |||
test_groups | |||
test_assert_macros | |||
test_assert_macros_fail | |||
test_exception_handler | |||
test_basics | |||
test_skip | |||
test_setup_fail | |||
test_ordering | |||
test_ordering_fail | |||
test_returns | |||
test_returns_fail) | |||
foreach(_CMOCKA_TEST ${CMOCKA_TESTS}) | |||
add_cmocka_test(${_CMOCKA_TEST} ${_CMOCKA_TEST}.c ${CMOCKA_STATIC_LIBRARY}) | |||
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() | |||
add_cmocka_test(test_cmockery test_cmockery.c ${CMOCKA_STATIC_LIBRARY}) | |||
### Exceptions | |||
# test_skip | |||
set_tests_properties( | |||
test_skip | |||
PROPERTIES | |||
PASS_REGULAR_EXPRESSION | |||
"\\[ SKIPPED \\] test_check_skip" | |||
) | |||
# test_assert_macros_fail | |||
set_tests_properties( | |||
test_assert_macros_fail | |||
PROPERTIES | |||
PASS_REGULAR_EXPRESSION | |||
"\\[ FAILED \\] 1 test" | |||
) | |||
# test_ordering ensure proper failures | |||
set_tests_properties( | |||
test_ordering_fail | |||
PROPERTIES | |||
PASS_REGULAR_EXPRESSION | |||
"\\[ FAILED \\] 7 test" | |||
) | |||
# test_returns_fail ensure proper failures | |||
set_tests_properties( | |||
test_returns_fail | |||
PROPERTIES | |||
PASS_REGULAR_EXPRESSION | |||
"\\[ FAILED \\] 3 test" | |||
) | |||
# 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)" | |||
) | |||
endif (WIN32) | |||
set_tests_properties( | |||
test_setup_fail | |||
PROPERTIES | |||
WILL_FAIL | |||
1 | |||
) | |||
set_tests_properties( | |||
test_group_setup_assert | |||
PROPERTIES | |||
WILL_FAIL | |||
1 | |||
) | |||
set_tests_properties( | |||
test_group_setup_fail | |||
PROPERTIES | |||
WILL_FAIL | |||
1 | |||
) | |||
add_test (test_setup_fail_1_failed test_setup_fail) | |||
set_tests_properties( | |||
test_setup_fail_1_failed | |||
PROPERTIES | |||
PASS_REGULAR_EXPRESSION | |||
"\\[ ERROR \\] int_test_ignored" | |||
) | |||
add_test (test_setup_fail_1_passed test_setup_fail) | |||
set_tests_properties( | |||
test_setup_fail_1_passed | |||
PROPERTIES | |||
PASS_REGULAR_EXPRESSION | |||
"\\[ PASSED \\] 1 test\\(s\\)." | |||
) | |||
add_test (test_setup_fail_match_failed test_setup_fail) | |||
set_tests_properties( | |||
test_setup_fail_match_failed | |||
PROPERTIES | |||
PASS_REGULAR_EXPRESSION | |||
"\\[ ERROR \\] int_test_ignored" | |||
) | |||
add_test (test_setup_fail_match_passed test_setup_fail) | |||
set_tests_properties( | |||
test_setup_fail_match_passed | |||
PROPERTIES | |||
PASS_REGULAR_EXPRESSION | |||
"\\[ OK \\] int_test_success" | |||
) | |||
### Output formats | |||
# test output of success, failure, skip, fixture failure | |||
set(OUTPUT_TESTS | |||
test_basics | |||
test_assert_macros_fail | |||
test_groups | |||
test_skip | |||
test_setup_fail) | |||
set(TEST_OUTPUT_FMTS | |||
tap | |||
subunit | |||
xml) | |||
set(test_basics_tap_out | |||
"^1\\.\\.2" | |||
"ok 1 - null_test_success" | |||
"ok 2 - int_test_success" | |||
"# ok - tests") | |||
set(test_assert_macros_fail_tap_out | |||
"^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" | |||
"ok 1 - null_test_success" | |||
"# ok - test_group1" | |||
"1\\.\\.1" | |||
"ok 1 - int_test_success" | |||
"# ok - test_group2") | |||
set(test_skip_tap_out | |||
"not ok 1 # SKIP") | |||
set(test_setup_fail_tap_out | |||
"not ok 1 - int_test_ignored Could not run test: Test setup failed") | |||
set(test_basics_subunit_out | |||
"^test: null_test_success" | |||
"success: null_test_success") | |||
set(test_assert_macros_fail_subunit_out | |||
"failure: test_assert_return_code_fail \\[") | |||
set(test_groups_subunit_out | |||
"^test: null_test_success" | |||
"success: null_test_success") | |||
set(test_skip_subunit_out | |||
"^test: test_check_skip" | |||
"skip: test_check_skip") | |||
set(test_setup_fail_subunit_out | |||
"error: int_test_ignored \\[ Could not run test: Test setup failed \\]") | |||
set(test_basics_xml_out | |||
"<testsuite name=\"tests\" time=\"[0-9.]+\" tests=\"2\" failures=\"0\" errors=\"0\" skipped=\"0\" >" | |||
"<testcase name=\"null_test_success\" time=\"[0-9.]+\" >.*</testcase>") | |||
set(test_assert_macros_fail_xml_out | |||
"<testcase name=\"test_assert_return_code_fail\" time=\"[0-9.]+\" >" | |||
"<failure>") | |||
set(test_groups_xml_out | |||
"^<\\?xml version=\"1.0\" encoding=\"UTF-8\" \\?>" | |||
"<testsuites>" | |||
"<testsuite name=\"test_group1\" time=\"[0-9.]+\" tests=\"1\" failures=\"0\" errors=\"0\" skipped=\"0\" >" | |||
"<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\" >" | |||
"<testcase name=\"int_test_success\" time=\"[0-9.]+\" >" | |||
"</testcase>" | |||
"</testsuite>" | |||
"</testsuites>") | |||
set(test_skip_xml_out | |||
"<testcase name=\"test_check_skip\" time=\"[0-9.]+\" >" | |||
"<skipped/>") | |||
set(test_setup_fail_xml_out | |||
"<testcase name=\"int_test_ignored\" time=\"[0-9.]+\" >" | |||
"<failure><!\\[CDATA\\[Test setup failed\\]\\]></failure>") | |||
foreach(_TEST_OUTPUT_FMT ${TEST_OUTPUT_FMTS}) | |||
foreach(_OUTPUT_TEST ${OUTPUT_TESTS}) | |||
set(TEST_NAME ${_OUTPUT_TEST}_${_TEST_OUTPUT_FMT}) | |||
add_test(${TEST_NAME} ${_OUTPUT_TEST}) | |||
set_property( | |||
TEST | |||
${TEST_NAME} | |||
PROPERTY | |||
ENVIRONMENT CMOCKA_MESSAGE_OUTPUT=${_TEST_OUTPUT_FMT} | |||
) | |||
list(LENGTH ${TEST_NAME}_out len) | |||
list(GET ${TEST_NAME}_out 0 output) | |||
if(len GREATER 1) | |||
list(REMOVE_AT ${TEST_NAME}_out 0) | |||
foreach(line ${${TEST_NAME}_out}) | |||
set(output "${output}[ \n\r]+${line}") | |||
endforeach() | |||
endif() | |||
set_tests_properties( | |||
${TEST_NAME} | |||
PROPERTIES | |||
PASS_REGULAR_EXPRESSION | |||
${output} | |||
) | |||
endforeach() | |||
endforeach() |
@@ -0,0 +1,74 @@ | |||
## The directory to run ctest in. | |||
set(CTEST_DIRECTORY "$ENV{HOME}/workspace/tmp/dashboards/cmocka") | |||
## The hostname of the machine | |||
set(CTEST_SITE "host.cmocka.org") | |||
## The buildname | |||
set(CTEST_BUILD_NAME "Linux_GCC_x86_64_default") | |||
## The Makefile generator to use | |||
set(CTEST_CMAKE_GENERATOR "Unix Makefiles") | |||
## The Build configuration to use. | |||
set(CTEST_BUILD_CONFIGURATION "Debug") | |||
## The build options for the project | |||
set(CTEST_BUILD_OPTIONS "-DUNIT_TESTING=ON -DWITH_CMOCKERY_SUPPORT=ON") | |||
#set(CTEST_CUSTOM_MEMCHECK_IGNORE torture_rand) | |||
## The Model to set: Nightly, Continous, Experimental | |||
set(CTEST_MODEL "Experimental") | |||
## The URL to the git repository | |||
set(CTEST_GIT_REPOSITORY "git://git.cryptomilk.org/projects/cmocka.git") | |||
## The branch | |||
#set(CTEST_GIT_BRANCH "--branch v0-5") | |||
## Wether to enable memory checking. | |||
set(WITH_MEMCHECK FALSE) | |||
## Wether to enable code coverage. | |||
set(WITH_COVERAGE FALSE) | |||
####################################################################### | |||
if (WITH_COVERAGE AND NOT WIN32) | |||
set(CTEST_BUILD_CONFIGURATION "Profiling") | |||
endif (WITH_COVERAGE AND NOT WIN32) | |||
set(CTEST_SOURCE_DIRECTORY "${CTEST_DIRECTORY}/${CTEST_BUILD_NAME}/source") | |||
set(CTEST_BINARY_DIRECTORY "${CTEST_DIRECTORY}/${CTEST_BUILD_NAME}/build") | |||
set(CTEST_MEMORYCHECK_SUPPRESSIONS_FILE ${CMAKE_SOURCE_DIR}/tests/valgrind.supp) | |||
find_program(CTEST_GIT_COMMAND NAMES git) | |||
find_program(CTEST_COVERAGE_COMMAND NAMES gcov) | |||
find_program(CTEST_MEMORYCHECK_COMMAND NAMES valgrind) | |||
if(NOT EXISTS "${CTEST_SOURCE_DIRECTORY}") | |||
set(CTEST_CHECKOUT_COMMAND "${CTEST_GIT_COMMAND} clone ${CTEST_GIT_BRANCH} ${CTEST_GIT_REPOSITORY} ${CTEST_SOURCE_DIRECTORY}") | |||
endif() | |||
set(CTEST_UPDATE_COMMAND "${CTEST_GIT_COMMAND}") | |||
set(CTEST_CONFIGURE_COMMAND "${CMAKE_COMMAND} -DCMAKE_BUILD_TYPE:STRING=${CTEST_BUILD_CONFIGURATION}") | |||
set(CTEST_CONFIGURE_COMMAND "${CTEST_CONFIGURE_COMMAND} ${CTEST_BUILD_OPTIONS}") | |||
set(CTEST_CONFIGURE_COMMAND "${CTEST_CONFIGURE_COMMAND} \"-G${CTEST_CMAKE_GENERATOR}\"") | |||
set(CTEST_CONFIGURE_COMMAND "${CTEST_CONFIGURE_COMMAND} \"${CTEST_SOURCE_DIRECTORY}\"") | |||
ctest_empty_binary_directory(${CTEST_BINARY_DIRECTORY}) | |||
ctest_start(${CTEST_MODEL} TRACK ${CTEST_MODEL}) | |||
ctest_update(SOURCE ${CTEST_SOURCE_DIRECTORY}) | |||
ctest_configure(BUILD ${CTEST_BINARY_DIRECTORY}) | |||
ctest_build(BUILD ${CTEST_BINARY_DIRECTORY}) | |||
ctest_test(BUILD ${CTEST_BINARY_DIRECTORY}) | |||
if (WITH_MEMCHECK AND CTEST_COVERAGE_COMMAND) | |||
ctest_coverage(BUILD ${CTEST_BINARY_DIRECTORY}) | |||
endif (WITH_MEMCHECK AND CTEST_COVERAGE_COMMAND) | |||
if (WITH_MEMCHECK AND CTEST_MEMORYCHECK_COMMAND) | |||
ctest_memcheck(BUILD ${CTEST_BINARY_DIRECTORY}) | |||
endif (WITH_MEMCHECK AND CTEST_MEMORYCHECK_COMMAND) | |||
ctest_submit() |
@@ -0,0 +1,6 @@ | |||
DEFS=-I../../include -DHAVE_STDIO_H -DHAVE_SETJMP_H | |||
all: | |||
gcc $(DEFS) -o cmocka.o -c ../../src/cmocka.c | |||
gcc $(DEFS) -o test_basics.o -c ../test_basics.c | |||
gcc $(DEFS) -o a.out test_basics.o cmocka.o |
@@ -0,0 +1,91 @@ | |||
#include "config.h" | |||
#include <stdarg.h> | |||
#include <stddef.h> | |||
#include <setjmp.h> | |||
#include <cmocka.h> | |||
#include <cmocka_private.h> | |||
#include <stdlib.h> | |||
#include <stdio.h> | |||
#include <string.h> | |||
static void torture_test_malloc(void **state) | |||
{ | |||
char *str; | |||
size_t str_len; | |||
size_t len; | |||
(void)state; /* unsused */ | |||
str_len = 12; | |||
str = (char *)test_malloc(str_len); | |||
assert_non_null(str); | |||
len = snprintf(str, str_len, "test string"); | |||
assert_int_equal(len, 11); | |||
len = strlen(str); | |||
assert_int_equal(len, 11); | |||
test_free(str); | |||
} | |||
static void torture_test_realloc(void **state) | |||
{ | |||
char *str; | |||
char *tmp; | |||
size_t str_len; | |||
size_t len; | |||
(void)state; /* unsused */ | |||
str_len = 16; | |||
str = (char *)test_malloc(str_len); | |||
assert_non_null(str); | |||
len = snprintf(str, str_len, "test string 123"); | |||
assert_int_equal(len, 15); | |||
len = strlen(str); | |||
assert_int_equal(len, 15); | |||
str_len = 20; | |||
tmp = test_realloc(str, str_len); | |||
assert_non_null(tmp); | |||
str = tmp; | |||
len = strlen(str); | |||
assert_string_equal(tmp, "test string 123"); | |||
snprintf(str + len, str_len - len, "4567"); | |||
assert_string_equal(tmp, "test string 1234567"); | |||
test_free(str); | |||
} | |||
static void torture_test_realloc_set0(void **state) | |||
{ | |||
char *str; | |||
size_t str_len; | |||
(void)state; /* unsused */ | |||
str_len = 16; | |||
str = (char *)test_malloc(str_len); | |||
assert_non_null(str); | |||
/* realloc(ptr, 0) is like a free() */ | |||
str = (char *)test_realloc(str, 0); | |||
assert_null(str); | |||
} | |||
int main(void) { | |||
const struct CMUnitTest alloc_tests[] = { | |||
cmocka_unit_test(torture_test_malloc), | |||
cmocka_unit_test(torture_test_realloc), | |||
cmocka_unit_test(torture_test_realloc_set0), | |||
}; | |||
return cmocka_run_group_tests(alloc_tests, NULL, NULL); | |||
} |
@@ -0,0 +1,41 @@ | |||
#include "config.h" | |||
#include <stdarg.h> | |||
#include <stddef.h> | |||
#include <setjmp.h> | |||
#include <cmocka.h> | |||
#include <cmocka_private.h> | |||
#include <errno.h> | |||
#include <sys/types.h> | |||
#include <sys/stat.h> | |||
#ifdef HAVE_UNISTD_H | |||
#include <unistd.h> | |||
#endif | |||
#include <fcntl.h> | |||
/************************************** | |||
*** assert_return_code | |||
**************************************/ | |||
static void test_assert_return_code(void **state) | |||
{ | |||
struct stat sb; | |||
int rc; | |||
(void)state; /* unused */ | |||
rc = stat(".", &sb); | |||
assert_return_code(rc, 0); | |||
#ifndef _MSC_VER | |||
assert_true(S_ISDIR(sb.st_mode)); | |||
#endif | |||
} | |||
int main(void) { | |||
const struct CMUnitTest tests[] = { | |||
cmocka_unit_test(test_assert_return_code), | |||
}; | |||
return cmocka_run_group_tests(tests, NULL, NULL); | |||
} |
@@ -0,0 +1,43 @@ | |||
#include "config.h" | |||
#include <stdarg.h> | |||
#include <stddef.h> | |||
#include <setjmp.h> | |||
#include <cmocka.h> | |||
#include <cmocka_private.h> | |||
#include <errno.h> | |||
#include <sys/types.h> | |||
#include <sys/stat.h> | |||
#ifdef HAVE_UNISTD_H | |||
#include <unistd.h> | |||
#endif | |||
#ifdef HAVE_IO_H | |||
#include <io.h> | |||
#endif | |||
#include <fcntl.h> | |||
/************************************** | |||
*** assert_return_code | |||
**************************************/ | |||
static void test_assert_return_code_fail(void **state) | |||
{ | |||
int fd; | |||
(void)state; /* unused */ | |||
fd = open("this_file_doesnt_exist.cmocka", 0); | |||
assert_return_code(fd, errno); | |||
if (fd >= 0) { | |||
close(fd); | |||
} | |||
} | |||
int main(void) { | |||
const struct CMUnitTest tests[] = { | |||
cmocka_unit_test(test_assert_return_code_fail), | |||
}; | |||
return cmocka_run_group_tests(tests, NULL, NULL); | |||
} |
@@ -0,0 +1,62 @@ | |||
/* | |||
* Copyright 2008 Google Inc. | |||
* | |||
* Licensed under the Apache License, Version 2.0 (the "License"); | |||
* you may not use this file except in compliance with the License. | |||
* You may obtain a copy of the License at | |||
* | |||
* http://www.apache.org/licenses/LICENSE-2.0 | |||
* | |||
* Unless required by applicable law or agreed to in writing, software | |||
* distributed under the License is distributed on an "AS IS" BASIS, | |||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
* See the License for the specific language governing permissions and | |||
* limitations under the License. | |||
*/ | |||
/* Use the unit test allocators */ | |||
#define UNIT_TESTING 1 | |||
#include <stdarg.h> | |||
#include <stddef.h> | |||
#include <setjmp.h> | |||
#include <cmocka.h> | |||
static int setup(void **state) { | |||
int *answer = malloc(sizeof(int)); | |||
assert_non_null(answer); | |||
*answer = 42; | |||
*state = answer; | |||
return 0; | |||
} | |||
static int teardown(void **state) { | |||
free(*state); | |||
return 0; | |||
} | |||
/* A test case that does nothing and succeeds. */ | |||
static void null_test_success(void **state) { | |||
(void) state; | |||
} | |||
/* A test case that does check if an int is equal. */ | |||
static void int_test_success(void **state) { | |||
int *answer = *state; | |||
assert_int_equal(*answer, 42); | |||
} | |||
int main(void) { | |||
const struct CMUnitTest tests[] = { | |||
cmocka_unit_test(null_test_success), | |||
cmocka_unit_test_setup_teardown(int_test_success, setup, teardown), | |||
}; | |||
return cmocka_run_group_tests(tests, NULL, NULL); | |||
} |
@@ -0,0 +1,32 @@ | |||
/* | |||
* Copyright 2008 Google Inc. | |||
* | |||
* 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 <stddef.h> | |||
#include <setjmp.h> | |||
#include <cmockery/cmockery.h> | |||
/* A test case that does nothing and succeeds. */ | |||
static void null_test_success(void **state) { | |||
(void) state; /* unused */ | |||
} | |||
int main(void) { | |||
const UnitTest tests[] = { | |||
unit_test(null_test_success), | |||
}; | |||
return run_tests(tests); | |||
} |
@@ -0,0 +1,30 @@ | |||
#include <stdarg.h> | |||
#include <stddef.h> | |||
#include <setjmp.h> | |||
#include <cmocka.h> | |||
#include <stdlib.h> | |||
struct test_segv { | |||
int x; | |||
int y; | |||
}; | |||
static void test_segfault_recovery(void **state) | |||
{ | |||
struct test_segv *s = NULL; | |||
(void) state; /* unused */ | |||
s->x = 1; | |||
} | |||
int main(void) { | |||
const struct CMUnitTest tests[] = { | |||
cmocka_unit_test(test_segfault_recovery), | |||
cmocka_unit_test(test_segfault_recovery), | |||
cmocka_unit_test(test_segfault_recovery), | |||
}; | |||
return cmocka_run_group_tests(tests, NULL, NULL); | |||
} |
@@ -0,0 +1,82 @@ | |||
#include <stdarg.h> | |||
#include <stddef.h> | |||
#include <setjmp.h> | |||
#include <cmocka.h> | |||
#include <stdlib.h> | |||
static int setup_only(void **state) | |||
{ | |||
*state = malloc(1); | |||
return 0; | |||
} | |||
static int teardown_only(void **state) | |||
{ | |||
free(*state); | |||
return 0; | |||
} | |||
static void malloc_setup_test(void **state) | |||
{ | |||
assert_non_null(*state); | |||
free(*state); | |||
} | |||
static void malloc_teardown_test(void **state) | |||
{ | |||
*state = malloc(1); | |||
assert_non_null(*state); | |||
} | |||
static int prestate_setup(void **state) | |||
{ | |||
int *val = (int *)*state, *a; | |||
a = malloc(sizeof(int)); | |||
*a = *val + 1; | |||
*state = a; | |||
return 0; | |||
} | |||
static int prestate_teardown(void **state) | |||
{ | |||
free(*state); | |||
return 0; | |||
} | |||
static void prestate_setup_test(void **state) | |||
{ | |||
int *a = (int *)*state; | |||
assert_non_null(a); | |||
assert_int_equal(*a, 43); | |||
} | |||
static void prestate_test(void **state) | |||
{ | |||
int *a = (int *)*state; | |||
assert_non_null(a); | |||
assert_int_equal(*a, 42); | |||
} | |||
int main(void) { | |||
int prestate = 42; | |||
const struct CMUnitTest tests[] = { | |||
cmocka_unit_test_setup(malloc_setup_test, setup_only), | |||
cmocka_unit_test_setup(malloc_setup_test, setup_only), | |||
cmocka_unit_test_teardown(malloc_teardown_test, teardown_only), | |||
cmocka_unit_test_teardown(malloc_teardown_test, teardown_only), | |||
cmocka_unit_test_teardown(malloc_teardown_test, teardown_only), | |||
cmocka_unit_test_teardown(malloc_teardown_test, teardown_only), | |||
cmocka_unit_test_prestate(prestate_test, &prestate), | |||
cmocka_unit_test_prestate_setup_teardown(prestate_setup_test, prestate_setup, prestate_teardown, &prestate), | |||
}; | |||
return cmocka_run_group_tests(tests, NULL, NULL); | |||
} |
@@ -0,0 +1,50 @@ | |||
/* Use the unit test allocators */ | |||
#define UNIT_TESTING 1 | |||
#include <stdarg.h> | |||
#include <stddef.h> | |||
#include <setjmp.h> | |||
#include <cmocka.h> | |||
static int group_setup(void **state) | |||
{ | |||
int *answer = malloc(sizeof(int)); | |||
assert_non_null(answer); | |||
*answer = 42; | |||
*state = answer; | |||
return 0; | |||
} | |||
static int group_teardown(void **state) | |||
{ | |||
int *answer = (int *)*state; | |||
free(answer); | |||
return 0; | |||
} | |||
static void test_value_equal(void **state) | |||
{ | |||
int a = *((int *)*state); | |||
assert_int_equal(a, 42); | |||
} | |||
static void test_value_range(void **state) | |||
{ | |||
int a = *((int *)*state); | |||
assert_in_range(a, 0, 100); | |||
} | |||
int main(void) { | |||
int prestate = 1337; | |||
const struct CMUnitTest tests[] = { | |||
cmocka_unit_test(test_value_equal), | |||
cmocka_unit_test(test_value_range), | |||
cmocka_unit_test_prestate(test_value_equal, &prestate), | |||
}; | |||
return cmocka_run_group_tests(tests, group_setup, group_teardown); | |||
} |
@@ -0,0 +1,37 @@ | |||
/* Use the unit test allocators */ | |||
#define UNIT_TESTING 1 | |||
#include <stdarg.h> | |||
#include <stddef.h> | |||
#include <setjmp.h> | |||
#include <cmocka.h> | |||
static int group_setup_failing(void **state) | |||
{ | |||
(void) state; /* unused */ | |||
assert_int_equal(0, 1); | |||
return 0; | |||
} | |||
static void test_true(void **state) | |||
{ | |||
(void) state; /* unused */ | |||
assert_true(1); | |||
} | |||
static void test_false(void **state) | |||
{ | |||
(void) state; /* unused */ | |||
assert_false(0); | |||
} | |||
int main(void) { | |||
const struct CMUnitTest tests[] = { | |||
cmocka_unit_test(test_true), | |||
cmocka_unit_test(test_false), | |||
}; | |||
return cmocka_run_group_tests(tests, group_setup_failing, NULL); | |||
} |
@@ -0,0 +1,34 @@ | |||
/* Use the unit test allocators */ | |||
#define UNIT_TESTING 1 | |||
#include <stdarg.h> | |||
#include <stddef.h> | |||
#include <setjmp.h> | |||
#include <cmocka.h> | |||
static int group_setup_failing(void **state) | |||
{ | |||
(void) state; /* unused */ | |||
return 1; /* To indicate the failure */ | |||
} | |||
static void test_true(void **state) | |||
{ | |||
(void) state; /* unused */ | |||
assert_true(1); | |||
} | |||
static void test_false(void **state) | |||
{ | |||
(void) state; /* unused */ | |||
assert_false(0); | |||
} | |||
int main(void) { | |||
const struct CMUnitTest tests[] = { | |||
cmocka_unit_test(test_true), | |||
cmocka_unit_test(test_false), | |||
}; | |||
return cmocka_run_group_tests(tests, group_setup_failing, NULL); | |||
} |
@@ -0,0 +1,69 @@ | |||
/* | |||
* Copyright 2016 David Schneider <schneidav81@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. | |||
*/ | |||
/* Use the unit test allocators */ | |||
#define UNIT_TESTING 1 | |||
#include <stdarg.h> | |||
#include <stddef.h> | |||
#include <setjmp.h> | |||
#include <cmocka.h> | |||
static int setup(void **state) { | |||
int *answer = malloc(sizeof(int)); | |||
assert_non_null(answer); | |||
*answer = 42; | |||
*state = answer; | |||
return 0; | |||
} | |||
static int teardown(void **state) { | |||
free(*state); | |||
return 0; | |||
} | |||
/* A test case that does nothing and succeeds. */ | |||
static void null_test_success(void **state) { | |||
(void) state; | |||
} | |||
/* A test case that does check if an int is equal. */ | |||
static void int_test_success(void **state) { | |||
int *answer = *state; | |||
assert_int_equal(*answer, 42); | |||
} | |||
int main(void) { | |||
const struct CMUnitTest test_group1[] = { | |||
cmocka_unit_test(null_test_success), | |||
}; | |||
const struct CMUnitTest test_group2[] = { | |||
cmocka_unit_test_setup_teardown(int_test_success, setup, teardown), | |||
}; | |||
int result = 0; | |||
result += cmocka_run_group_tests(test_group1, NULL, NULL); | |||
result += cmocka_run_group_tests(test_group2, NULL, NULL); | |||
return result; | |||
} |
@@ -0,0 +1,112 @@ | |||
#include "config.h" | |||
#include <stdarg.h> | |||
#include <stddef.h> | |||
#include <setjmp.h> | |||
#include <cmocka.h> | |||
#include <cmocka_private.h> | |||
static void mock_test_a_called(void) | |||
{ | |||
function_called(); | |||
} | |||
static void mock_test_b_called(void) | |||
{ | |||
function_called(); | |||
} | |||
static void mock_test_c_called(void) | |||
{ | |||
function_called(); | |||
} | |||
static void test_does_succeed_for_expected(void **state) | |||
{ | |||
(void)state; | |||
expect_function_call(mock_test_a_called); | |||
expect_function_call(mock_test_a_called); | |||
mock_test_a_called(); | |||
mock_test_a_called(); | |||
} | |||
static void test_does_succeed_for_multiple_calls(void **state) | |||
{ | |||
(void)state; | |||
expect_function_call(mock_test_a_called); | |||
expect_function_calls(mock_test_a_called, 2); | |||
expect_function_call(mock_test_a_called); | |||
mock_test_a_called(); | |||
mock_test_a_called(); | |||
mock_test_a_called(); | |||
mock_test_a_called(); | |||
} | |||
static void test_ordering_does_ignore_calls(void **state) | |||
{ | |||
(void)state; | |||
ignore_function_calls(mock_test_a_called); | |||
mock_test_a_called(); | |||
mock_test_a_called(); | |||
mock_test_a_called(); | |||
} | |||
static void test_ordering_does_ignore_no_calls(void **state) | |||
{ | |||
(void)state; | |||
ignore_function_calls(mock_test_a_called); | |||
} | |||
static void test_ordering_does_expect_at_least_one_call(void **state) | |||
{ | |||
(void)state; | |||
expect_function_call_any(mock_test_a_called); | |||
mock_test_a_called(); | |||
mock_test_a_called(); | |||
mock_test_a_called(); | |||
} | |||
static void test_ordering_does_work_across_different_functions(void **state) | |||
{ | |||
(void)state; | |||
expect_function_call(mock_test_a_called); | |||
expect_function_call(mock_test_b_called); | |||
expect_function_call(mock_test_a_called); | |||
mock_test_a_called(); | |||
mock_test_b_called(); | |||
mock_test_a_called(); | |||
} | |||
static void test_ordering_ignores_out_of_order_properly(void **state) | |||
{ | |||
(void)state; | |||
ignore_function_calls(mock_test_a_called); | |||
ignore_function_calls(mock_test_b_called); | |||
expect_function_calls(mock_test_c_called, 2); | |||
mock_test_c_called(); | |||
mock_test_b_called(); | |||
mock_test_c_called(); | |||
} | |||
int main(void) { | |||
const struct CMUnitTest tests[] = { | |||
cmocka_unit_test(test_does_succeed_for_expected) | |||
,cmocka_unit_test(test_does_succeed_for_multiple_calls) | |||
,cmocka_unit_test(test_ordering_does_ignore_no_calls) | |||
,cmocka_unit_test(test_ordering_does_ignore_calls) | |||
,cmocka_unit_test(test_ordering_does_expect_at_least_one_call) | |||
,cmocka_unit_test(test_ordering_does_work_across_different_functions) | |||
,cmocka_unit_test(test_ordering_ignores_out_of_order_properly) | |||
}; | |||
return cmocka_run_group_tests(tests, NULL, NULL); | |||
} |
@@ -0,0 +1,95 @@ | |||
#include "config.h" | |||
#include <stdarg.h> | |||
#include <stddef.h> | |||
#include <setjmp.h> | |||
#include <cmocka.h> | |||
#include <cmocka_private.h> | |||
static void mock_test_a_called(void) | |||
{ | |||
function_called(); | |||
} | |||
static void mock_test_b_called(void) | |||
{ | |||
function_called(); | |||
} | |||
static void mock_test_c_called(void) | |||
{ | |||
function_called(); | |||
} | |||
static void test_does_fail_for_unexpected_call(void **state) | |||
{ | |||
(void)state; | |||
expect_function_call(mock_test_a_called); | |||
expect_function_call(mock_test_a_called); | |||
mock_test_a_called(); | |||
mock_test_a_called(); | |||
mock_test_a_called(); | |||
} | |||
static void test_does_fail_for_unmade_expected_call(void **state) | |||
{ | |||
(void)state; | |||
expect_function_call(mock_test_a_called); | |||
expect_function_call(mock_test_a_called); | |||
mock_test_a_called(); | |||
} | |||
static void test_ordering_fails_out_of_order(void **state) | |||
{ | |||
(void)state; | |||
expect_function_call(mock_test_a_called); | |||
expect_function_call(mock_test_b_called); | |||
expect_function_call(mock_test_a_called); | |||
mock_test_b_called(); | |||
} | |||
static void test_ordering_fails_out_of_order_for_at_least_once_calls(void **state) | |||
{ | |||
(void)state; | |||
expect_function_call_any(mock_test_a_called); | |||
ignore_function_calls(mock_test_b_called); | |||
mock_test_b_called(); | |||
mock_test_c_called(); | |||
} | |||
/* Primarily used to test error message */ | |||
static void test_fails_out_of_order_if_no_calls_found_on_any(void **state) | |||
{ | |||
(void)state; | |||
expect_function_call_any(mock_test_a_called); | |||
ignore_function_calls(mock_test_b_called); | |||
mock_test_a_called(); | |||
mock_test_c_called(); | |||
} | |||
static void test_fails_if_zero_count_used(void **state) | |||
{ | |||
(void)state; | |||
expect_function_calls(mock_test_a_called, 0); | |||
mock_test_a_called(); | |||
} | |||
int main(void) { | |||
const struct CMUnitTest tests[] = { | |||
cmocka_unit_test(test_does_fail_for_unexpected_call) | |||
,cmocka_unit_test(test_does_fail_for_unmade_expected_call) | |||
,cmocka_unit_test(test_does_fail_for_unmade_expected_call) | |||
,cmocka_unit_test(test_ordering_fails_out_of_order) | |||
,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) | |||
}; | |||
return cmocka_run_group_tests(tests, NULL, NULL); | |||
} |
@@ -0,0 +1,69 @@ | |||
#include "config.h" | |||
#include <stdarg.h> | |||
#include <stddef.h> | |||
#include <setjmp.h> | |||
#include <cmocka.h> | |||
#include <cmocka_private.h> | |||
#include <stdlib.h> | |||
int mock_function(void); | |||
void mock_function_call_times(size_t times, int expectedValue); | |||
int mock_function(void) | |||
{ | |||
return (int) mock(); | |||
} | |||
void mock_function_call_times(size_t times, int expectedValue) | |||
{ | |||
size_t i; | |||
for (i = 0u; i < times; ++i) | |||
{ | |||
assert_int_equal(expectedValue, mock_function()); | |||
} | |||
} | |||
static void test_will_return_maybe_for_no_calls(void **state) | |||
{ | |||
(void) state; | |||
will_return_maybe(mock_function, 32); | |||
} | |||
static void test_will_return_maybe_for_one_mock_call(void **state) | |||
{ | |||
int value; | |||
(void) state; | |||
value = rand(); | |||
will_return_maybe(mock_function, value); | |||
mock_function_call_times(1u, value); | |||
} | |||
static void test_will_return_maybe_for_more_than_one_call(void **state) | |||
{ | |||
int value; | |||
size_t numberOfCalls; | |||
(void)state; | |||
value = rand(); | |||
numberOfCalls = (size_t) ((rand()) % 20 + 2); | |||
will_return_maybe(mock_function, value); | |||
mock_function_call_times(numberOfCalls, value); | |||
} | |||
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) | |||
}; | |||
(void)argc; | |||
(void)argv; | |||
return cmocka_run_group_tests(alloc_tests, NULL, NULL); | |||
} |
@@ -0,0 +1,77 @@ | |||
#include "config.h" | |||
#include <stdarg.h> | |||
#include <stddef.h> | |||
#include <setjmp.h> | |||
#include <cmocka.h> | |||
#include <cmocka_private.h> | |||
#include <stdlib.h> | |||
int mock_function(void); | |||
void mock_function_call_times(size_t times, int expectedValue); | |||
int mock_function(void) | |||
{ | |||
return (int) mock(); | |||
} | |||
void mock_function_call_times(size_t times, int expectedValue) | |||
{ | |||
size_t i; | |||
for (i = 0u; i < times; ++i) | |||
{ | |||
assert_int_equal(expectedValue, mock_function()); | |||
} | |||
} | |||
static void test_will_return_fails_for_no_calls(void **state) | |||
{ | |||
(void) state; | |||
will_return(mock_function, 32); | |||
} | |||
static void test_will_return_count_fails_for_unreturned_items(void **state) | |||
{ | |||
int value; | |||
size_t numberOfCalls; | |||
(void) state; | |||
value = rand(); | |||
numberOfCalls = (size_t) ((rand()) % 20 + 2); | |||
will_return_count(mock_function, value, numberOfCalls); | |||
mock_function_call_times(numberOfCalls - 1u, value); | |||
} | |||
static void test_will_return_always_fails_for_no_calls(void **state) | |||
{ | |||
int value; | |||
(void) state; | |||
value = rand(); | |||
will_return_always(mock_function, value); | |||
} | |||
static int teardown(void **state) { | |||
free(*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) | |||
}; | |||
(void)argc; | |||
(void)argv; | |||
return cmocka_run_group_tests(alloc_tests, NULL, NULL); | |||
} |
@@ -0,0 +1,54 @@ | |||
#define UNIT_TESTING 1 | |||
#include <stdarg.h> | |||
#include <stddef.h> | |||
#include <setjmp.h> | |||
#include <cmocka.h> | |||
static int setup_fail(void **state) { | |||
*state = NULL; | |||
/* We need to fail in setup */ | |||
return -1; | |||
} | |||
static void int_test_ignored(void **state) { | |||
/* should not be called */ | |||
assert_non_null(*state); | |||
} | |||
static int setup_ok(void **state) { | |||
int *answer; | |||
answer = malloc(sizeof(int)); | |||
if (answer == NULL) { | |||
return -1; | |||
} | |||
*answer = 42; | |||
*state = answer; | |||
return 0; | |||
} | |||
/* A test case that does check if an int is equal. */ | |||
static void int_test_success(void **state) { | |||
int *answer = *state; | |||
assert_int_equal(*answer, 42); | |||
} | |||
static int teardown(void **state) { | |||
free(*state); | |||
return 0; | |||
} | |||
int main(void) { | |||
const struct CMUnitTest tests[] = { | |||
cmocka_unit_test_setup_teardown(int_test_ignored, setup_fail, teardown), | |||
cmocka_unit_test_setup_teardown(int_test_success, setup_ok, teardown), | |||
}; | |||
return cmocka_run_group_tests(tests, NULL, NULL); | |||
} |
@@ -0,0 +1,39 @@ | |||
/* | |||
* Copyright 2008 Google Inc. | |||
* | |||
* 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 <stddef.h> | |||
#include <setjmp.h> | |||
#include <cmocka.h> | |||
/* A test case that does check if an int is equal. */ | |||
static void test_check_skip(void **state) { | |||
(void)state; /* unused */ | |||
skip(); | |||
assert_true(0); | |||
} | |||
int main(void) { | |||
const struct CMUnitTest tests[] = { | |||
cmocka_unit_test(test_check_skip), | |||
}; | |||
return cmocka_run_group_tests(tests, NULL, NULL); | |||
} | |||
@@ -0,0 +1,6 @@ | |||
[submodule "bssl/src"] | |||
path = bssl/src | |||
url = https://github.com/google/boringssl.git | |||
[submodule "mbedtls/src"] | |||
path = mbedtls/src | |||
url = https://github.com/ARMmbed/mbedtls.git |
@@ -0,0 +1,278 @@ | |||
# Additional information | |||
A lot of, mostly useless, details | |||
## Appendix A | |||
Default NDK flags | |||
* CC: | |||
``` | |||
--target=aarch64-none-linux-android | |||
-DBORINGSSL_IMPLEMENTATION | |||
-g | |||
-DANDROID | |||
-ffunction-sections | |||
-funwind-tables | |||
-fstack-protector-strong | |||
-no-canonical-prefixes | |||
-Wa,--noexecstack | |||
-Wformat | |||
-Werror=format-security | |||
-Werror | |||
-Wformat=2 | |||
-Wsign-compare | |||
-Wmissing-field-initializers | |||
-Wwrite-strings | |||
-Wall | |||
-ggdb | |||
-fvisibility=hidden | |||
-fno-common | |||
-Wnewline-eof | |||
-fcolor-diagnostics | |||
-Wimplicit-fallthrough | |||
-Wmissing-prototypes | |||
-Wold-style-definition | |||
-Wstrict-prototypes | |||
-Wshadow | |||
-D_XOPEN_SOURCE=700 | |||
-O2 | |||
-DNDEBUG | |||
-fPIC | |||
``` | |||
* CPP: | |||
``` | |||
-cc1 | |||
-triple aarch64-none-linux-android | |||
-emit-obj | |||
-mnoexecstack | |||
-disable-free | |||
-disable-llvm-verifier | |||
-discard-value-names | |||
-mrelocation-model pic | |||
-pic-level 2 | |||
-pic-is-pie | |||
-mthread-model posix | |||
-mdisable-fp-elim | |||
-fmath-errno | |||
-masm-verbose | |||
-mconstructor-aliases | |||
-munwind-tables | |||
-fuse-init-array | |||
-target-cpu generic | |||
-target-feature +neon | |||
-target-abi aapcs | |||
-dwarf-column-info | |||
-debug-info-kind=limited | |||
-dwarf-version=4 | |||
-debugger-tuning=gdb | |||
-ffunction-sections | |||
-D BORINGSSL_IMPLEMENTATION | |||
-D ANDROID | |||
-D NDEBUG | |||
-O2 | |||
-Wformat | |||
-Werror=format-security | |||
-Werror | |||
-Wformat=2 | |||
-Wsign-compare | |||
-Wmissing-field-initializers | |||
-Wwrite-strings | |||
-Wall | |||
-Wnewline-eof | |||
-Wimplicit-fallthrough | |||
-Wmissing-declarations | |||
-Wmissing-prototypes | |||
-Wshadow | |||
-std=c++11 | |||
-fdeprecated-macro | |||
-fdebug-compilation-dir /home/hdc/repos/mbedtls_vs_boringssl/bssl/src/build/crypto | |||
-ferror-limit 19 | |||
-fmessage-length 238 | |||
-fvisibility hidden | |||
-femulated-tls | |||
-stack-protector 2 | |||
-fallow-half-arguments-and-returns | |||
-fno-rtti | |||
-fno-signed-char | |||
-fobjc-runtime=gcc | |||
-fno-common | |||
-fdiagnostics-show-option | |||
-fcolor-diagnostics | |||
-vectorize-loops | |||
-vectorize-slp | |||
``` | |||
## Appendix B | |||
Test platform settings | |||
``` | |||
[ro.build.id]: [OPR6.170623.013] | |||
[ro.bootimage.build.date]: [Wed Oct 11 15:46:15 BST 2017] | |||
[ro.bootimage.build.fingerprint]: [Android/hikey/hikey:8.0.0/OPR6.170623.013/110:userdebug/test-keys] | |||
[ro.product.cpu.abi]: [arm64-v8a] | |||
[ro.product.cpu.abilist]: [arm64-v8a,armeabi-v7a,armeabi] | |||
[ro.product.cpu.abilist32]: [armeabi-v7a,armeabi] | |||
[ro.product.cpu.abilist64]: [arm64-v8a] | |||
[ro.build.version.sdk]: [26] | |||
[ro.build.version.security_patch]: [2017-08-05] | |||
``` | |||
## Appendix C | |||
Performance measures provied by ``bssl speed``: | |||
| Operation | Small | Default | | |||
|-----------|------|---------| | |||
|RSA 2048 signing | (59.5 ops/sec) | (108.1 ops/sec) | | |||
|RSA 2048 verify | (2377.5 ops/sec) | (4078.3 ops/sec) | | |||
|RSA 4096 signing | (8.3 ops/sec) | (14.9 ops/sec) | | |||
|RSA 4096 verify | (668.0 ops/sec) | (1088.4 ops/sec) | | |||
|AES-128-GCM (16 bytes) | (497832.2 ops/sec): 8.0 MB/s | (1690241.1 ops/sec): 27.0 MB/s | | |||
|AES-128-GCM (1350 bytes) | (17675.4 ops/sec): 23.9 MB/s | (291430.3 ops/sec): 393.4 MB/s | | |||
|AES-128-GCM (8192 bytes) | (2991.6 ops/sec): 24.5 MB/s | (57088.8 ops/sec): 467.7 MB/s | | |||
|AES-256-GCM (16 bytes) | (444847.4 ops/sec): 7.1 MB/s | (1615148.8 ops/sec): 25.8 MB/s | | |||
|AES-256-GCM (1350 bytes) | (14792.6 ops/sec): 20.0 MB/s | (254718.5 ops/sec): 343.9 MB/s | | |||
|AES-256-GCM (8192 bytes) | (2525.7 ops/sec): 20.7 MB/s | (49056.6 ops/sec): 401.9 MB/s | | |||
|ChaCha20-Poly1305 (16 bytes) | (385043.6 ops/sec): 6.2 MB/s | (460788.5 ops/sec): 7.4 MB/s | | |||
|ChaCha20-Poly1305 (1350 bytes) | (33108.8 ops/sec): 44.7 MB/s | (67622.8 ops/sec): 91.3 MB/s | | |||
|ChaCha20-Poly1305 (8192 bytes) | (5905.1 ops/sec): 48.4 MB/s | (13219.5 ops/sec): 108.3 MB/s | | |||
|DES-EDE3-CBC-SHA1 (16 bytes) | (100311.5 ops/sec): 1.6 MB/s | (110073.3 ops/sec): 1.8 MB/s | | |||
|DES-EDE3-CBC-SHA1 (1350 bytes) | (3787.2 ops/sec): 5.1 MB/s | (3926.7 ops/sec): 5.3 MB/s | | |||
|DES-EDE3-CBC-SHA1 (8192 bytes) | (638.4 ops/sec): 5.2 MB/s | (661.2 ops/sec): 5.4 MB/s | | |||
|AES-128-CBC-SHA1 (16 bytes) | (268159.9 ops/sec): 4.3 MB/s | (540844.8 ops/sec): 8.7 MB/s | | |||
|AES-128-CBC-SHA1 (1350 bytes) | (22535.6 ops/sec): 30.4 MB/s | (162597.6 ops/sec): 219.5 MB/s | | |||
|AES-128-CBC-SHA1 (8192 bytes) | (3959.9 ops/sec): 32.4 MB/s | (37787.3 ops/sec): 309.6 MB/s | | |||
|AES-256-CBC-SHA1 (16 bytes) | (244904.2 ops/sec): 3.9 MB/s | (524976.9 ops/sec): 8.4 MB/s | | |||
|AES-256-CBC-SHA1 (1350 bytes) | (18272.3 ops/sec): 24.7 MB/s | (141626.7 ops/sec): 191.2 MB/s | | |||
|AES-256-CBC-SHA1 (8192 bytes) | (3181.3 ops/sec): 26.1 MB/s | (31195.9 ops/sec): 255.6 MB/s | | |||
|AES-128-GCM-SIV (16 bytes) | (244929.5 ops/sec): 3.9 MB/s | (776750.7 ops/sec): 12.4 MB/s | | |||
|AES-128-GCM-SIV (1350 bytes) | (14640.5 ops/sec): 19.8 MB/s | (66627.7 ops/sec): 89.9 MB/s | | |||
|AES-128-GCM-SIV (8192 bytes) | (2531.6 ops/sec): 20.7 MB/s | (11850.0 ops/sec): 97.1 MB/s | | |||
|AES-256-GCM-SIV (16 bytes) | (171899.3 ops/sec): 2.8 MB/s | (660748.9 ops/sec): 10.6 MB/s | | |||
|AES-256-GCM-SIV (1350 bytes) | (12489.6 ops/sec): 16.9 MB/s | (61124.5 ops/sec): 82.5 MB/s | | |||
|AES-256-GCM-SIV (8192 bytes) | (2182.7 ops/sec): 17.9 MB/s | (10936.1 ops/sec): 89.6 MB/s | | |||
|AES-128-GCM-SIV (16 bytes) | (239698.0 ops/sec): 3.8 MB/s | (733661.0 ops/sec): 11.7 MB/s | | |||
|AES-128-GCM-SIV (1350 bytes) | (14616.0 ops/sec): 19.7 MB/s | (65984.0 ops/sec): 89.1 MB/s | | |||
|AES-128-GCM-SIV (8192 bytes) | (2529.8 ops/sec): 20.7 MB/s | (11745.7 ops/sec): 96.2 MB/s | | |||
|AES-256-GCM-SIV (16 bytes) | (170826.1 ops/sec): 2.7 MB/s | (626465.6 ops/sec): 10.0 MB/s | | |||
|AES-256-GCM-SIV (1350 bytes) | (12474.8 ops/sec): 16.8 MB/s | (60595.5 ops/sec): 81.8 MB/s | | |||
|AES-256-GCM-SIV (8192 bytes) | (2182.1 ops/sec): 17.9 MB/s | (10841.9 ops/sec): 88.8 MB/s | | |||
|AES-128-CCM-Bluetooth (16 bytes) | (438558.8 ops/sec): 7.0 MB/s | (1405567.1 ops/sec): 22.5 MB/s | | |||
|AES-128-CCM-Bluetooth (1350 bytes) | (14776.5 ops/sec): 19.9 MB/s | (140168.4 ops/sec): 189.2 MB/s | | |||
|AES-128-CCM-Bluetooth (8192 bytes) | (2498.7 ops/sec): 20.5 MB/s | (25890.2 ops/sec): 212.1 MB/s | | |||
|SHA-1 (16 bytes) | (1244563.2 ops/sec): 19.9 MB/s | (2567122.0 ops/sec): 41.1 MB/s | | |||
|SHA-1 (256 bytes) | (341934.0 ops/sec): 87.5 MB/s | (1162590.8 ops/sec): 297.6 MB/s | | |||
|SHA-1 (8192 bytes) | (14574.3 ops/sec): 119.4 MB/s | (66844.3 ops/sec): 547.6 MB/s | | |||
|SHA-256 (16 bytes) | (691326.6 ops/sec): 11.1 MB/s | (2431927.0 ops/sec): 38.9 MB/s | | |||
|SHA-256 (256 bytes) | (166138.9 ops/sec): 42.5 MB/s | (1120621.2 ops/sec): 286.9 MB/s | | |||
|SHA-256 (8192 bytes) | (6824.7 ops/sec): 55.9 MB/s | (63214.7 ops/sec): 517.9 MB/s | | |||
|SHA-512 (16 bytes) | (688007.9 ops/sec): 11.0 MB/s | (729988.3 ops/sec): 11.7 MB/s | | |||
|SHA-512 (256 bytes) | (272146.5 ops/sec): 69.7 MB/s | (289178.7 ops/sec): 74.0 MB/s | | |||
|SHA-512 (8192 bytes) | (14014.7 ops/sec): 114.8 MB/s | (14759.6 ops/sec): 120.9 MB/s | | |||
|RNG (16 bytes) | (137217.4 ops/sec): 2.2 MB/s | (249239.3 ops/sec): 4.0 MB/s | | |||
|RNG (256 bytes) | (69898.9 ops/sec): 17.9 MB/s | (224698.5 ops/sec): 57.5 MB/s | | |||
|RNG (8192 bytes) | (4058.7 ops/sec): 33.2 MB/s | (55705.4 ops/sec): 456.3 MB/s | | |||
|ECDH P-224 operations | (151.0 ops/sec) | (1602.4 ops/sec) | | |||
|ECDH P-256 operations | (594.7 ops/sec) | (642.8 ops/sec) | | |||
|ECDH P-384 operations | (59.0 ops/sec) | (97.4 ops/sec) | | |||
|ECDH P-521 operations | (27.1 ops/sec) | (43.4 ops/sec) | | |||
|ECDSA P-224 signing | (277.8 ops/sec) | (3312.7 ops/sec) | | |||
|ECDSA P-224 verify | (241.2 ops/sec) | (1451.7 ops/sec) | | |||
|ECDSA P-256 signing | (1396.6 ops/sec) | (1738.5 ops/sec) | | |||
|ECDSA P-256 verify | (672.1 ops/sec) | (704.2 ops/sec) | | |||
|ECDSA P-384 signing | (107.0 ops/sec) | (177.6 ops/sec) | | |||
|ECDSA P-384 verify | (94.4 ops/sec) | (156.9 ops/sec) | | |||
|ECDSA P-521 signing | (49.0 ops/sec) | (78.2 ops/sec) | | |||
|ECDSA P-521 verify | (43.8 ops/sec) | (70.8 ops/sec) | | |||
Performance measures provided by ``benchmark``: | |||
| Algo | Small | Normal | | |||
|-------------------------------|----------------------|----------------------| | |||
|MD5 | 131223 KiB/s | 131761 KiB/s | | |||
|RIPEMD160 | 81451 KiB/s | 89899 KiB/s | | |||
|SHA-1 | 104117 KiB/s | 104375 KiB/s | | |||
|SHA-256 | 46809 KiB/s | 52044 KiB/s | | |||
|SHA-512 | 56760 KiB/s | 57648 KiB/s | | |||
|ARC4 | 65014 KiB/s | 65023 KiB/s | | |||
|3DES | 7785 KiB/s | 7885 KiB/s | | |||
|DES | 19071 KiB/s | 19512 KiB/s | | |||
|AES-CBC-128 | 32460 KiB/s | 35995 KiB/s | | |||
|AES-CBC-192 | 28392 KiB/s | 31044 KiB/s | | |||
|AES-CBC-256 | 25213 KiB/s | 27296 KiB/s | | |||
|AES-GCM-128 | 16399 KiB/s | 16398 KiB/s | | |||
|AES-GCM-192 | 15272 KiB/s | 15271 KiB/s | | |||
|AES-GCM-256 | 14287 KiB/s | 14286 KiB/s | | |||
|AES-CCM-128 | 15824 KiB/s | 15887 KiB/s | | |||
|AES-CCM-192 | 13853 KiB/s | 13899 KiB/s | | |||
|AES-CCM-256 | 12315 KiB/s | 12356 KiB/s | | |||
|CAMELLIA-CBC-128 | 19735 KiB/s | 26762 KiB/s | | |||
|CAMELLIA-CBC-192 | 15458 KiB/s | 20839 KiB/s | | |||
|CAMELLIA-CBC-256 | 15459 KiB/s | 20839 KiB/s | | |||
|BLOWFISH-CBC-128 | 25188 KiB/s | 28955 KiB/s | | |||
|BLOWFISH-CBC-192 | 25189 KiB/s | 28954 KiB/s | | |||
|BLOWFISH-CBC-256 | 25183 KiB/s | 28955 KiB/s | | |||
|CTR_DRBG (NOPR) | 27122 KiB/s | 27050 KiB/s | | |||
|CTR_DRBG (PR) | 18397 KiB/s | 19111 KiB/s | | |||
|HMAC_DRBG SHA-1 (NOPR) | 6746 KiB/s | 6968 KiB/s | | |||
|HMAC_DRBG SHA-1 (PR) | 6208 KiB/s | 6426 KiB/s | | |||
|HMAC_DRBG SHA-256 (NOPR) | 5321 KiB/s | 5795 KiB/s | | |||
|HMAC_DRBG SHA-256 (PR) | 4657 KiB/s | 5083 KiB/s | | |||
|RSA-2048 | 652 public/s | 653 public/s | | |||
|RSA-2048 | 17 private/s | 17 private/s | | |||
|RSA-4096 | 168 public/s | 168 public/s | | |||
|RSA-4096 | 3 private/s | 3 private/s | | |||
|DHE-2048 | 3 handshake/s | 3 handshake/s | | |||
|DH-2048 | 5 handshake/s | 6 handshake/s | | |||
|DHE-3072 | 1 handshake/s | 1 handshake/s | | |||
|DH-3072 | 2 handshake/s | 2 handshake/s | | |||
|ECDSA-secp521r1 | 70 sign/s | 74 sign/s | | |||
|ECDSA-brainpoolP512r1 | 8 sign/s | 9 sign/s | | |||
|ECDSA-secp384r1 | 126 sign/s | 133 sign/s | | |||
|ECDSA-brainpoolP384r1 | 16 sign/s | 18 sign/s | | |||
|ECDSA-secp256r1 | 189 sign/s | 195 sign/s | | |||
|ECDSA-secp256k1 | 176 sign/s | 189 sign/s | | |||
|ECDSA-brainpoolP256r1 | 27 sign/s | 31 sign/s | | |||
|ECDSA-secp224r1 | 277 sign/s | 291 sign/s | | |||
|ECDSA-secp224k1 | 216 sign/s | 230 sign/s | | |||
|ECDSA-secp192r1 | 329 sign/s | 352 sign/s | | |||
|ECDSA-secp192k1 | 264 sign/s | 277 sign/s | | |||
|ECDSA-secp521r1 | 19 verify/s | 21 verify/s | | |||
|ECDSA-brainpoolP512r1 | 2 verify/s | 2 verify/s | | |||
|ECDSA-secp384r1 | 35 verify/s | 36 verify/s | | |||
|ECDSA-brainpoolP384r1 | 4 verify/s | 4 verify/s | | |||
|ECDSA-secp256r1 | 54 verify/s | 57 verify/s | | |||
|ECDSA-secp256k1 | 53 verify/s | 57 verify/s | | |||
|ECDSA-brainpoolP256r1 | 7 verify/s | 8 verify/s | | |||
|ECDSA-secp224r1 | 82 verify/s | 86 verify/s | | |||
|ECDSA-secp224k1 | 63 verify/s | 67 verify/s | | |||
|ECDSA-secp192r1 | 102 verify/s | 110 verify/s | | |||
|ECDSA-secp192k1 | 77 verify/s | 82 verify/s | | |||
|ECDHE-secp521r1 | 20 handshake/s | 21 handshake/s | | |||
|ECDHE-brainpoolP512r1 | 2 handshake/s | 2 handshake/s | | |||
|ECDHE-secp384r1 | 37 handshake/s | 39 handshake/s | | |||
|ECDHE-brainpoolP384r1 | 4 handshake/s | 4 handshake/s | | |||
|ECDHE-secp256r1 | 57 handshake/s | 60 handshake/s | | |||
|ECDHE-secp256k1 | 56 handshake/s | 60 handshake/s | | |||
|ECDHE-brainpoolP256r1 | 7 handshake/s | 8 handshake/s | | |||
|ECDHE-secp224r1 | 89 handshake/s | 92 handshake/s | | |||
|ECDHE-secp224k1 | 67 handshake/s | 71 handshake/s | | |||
|ECDHE-secp192r1 | 111 handshake/s | 118 handshake/s | | |||
|ECDHE-secp192k1 | 83 handshake/s | 87 handshake/s | | |||
|ECDHE-Curve25519 | 41 handshake/s | 41 handshake/s | | |||
|ECDH-secp521r1 | 27 handshake/s | 28 handshake/s | | |||
|ECDH-brainpoolP512r1 | 3 handshake/s | 3 handshake/s | | |||
|ECDH-secp384r1 | 49 handshake/s | 51 handshake/s | | |||
|ECDH-brainpoolP384r1 | 5 handshake/s | 5 handshake/s | | |||
|ECDH-secp256r1 | 77 handshake/s | 81 handshake/s | | |||
|ECDH-secp256k1 | 78 handshake/s | 82 handshake/s | | |||
|ECDH-brainpoolP256r1 | 9 handshake/s | 11 handshake/s | | |||
|ECDH-secp224r1 | 121 handshake/s | 126 handshake/s | | |||
|ECDH-secp224k1 | 91 handshake/s | 97 handshake/s | | |||
|ECDH-secp192r1 | 150 handshake/s | 159 handshake/s | | |||
|ECDH-secp192k1 | 113 handshake/s | 120 handshake/s | | |||
|ECDH-Curve25519 | 80 handshake/s | 82 handshake/s | | |||
@@ -0,0 +1,3 @@ | |||
# BoringSSL and mbedTLS comparison | |||
See here: http://hdc.amongbytes.com/post/201804-comparing-mbedtls-to-boringssl/ |
@@ -0,0 +1,29 @@ | |||
include ../common.mk | |||
BUILD_DIR = src/build | |||
MAKE = cmake --build . | |||
all: prepare build | |||
clean: | |||
rm -rf $(BUILD_DIR) | |||
prepare: clean | |||
rm -rf $(BUILD_DIR) | |||
mkdir -p $(BUILD_DIR) | |||
cd $(BUILD_DIR); \ | |||
cmake \ | |||
-DANDROID_TOOLCHAIN_NAME=aarch64-linux-android-clang5.0 \ | |||
-DCMAKE_TOOLCHAIN_FILE=${ANDROID_NDK}/build/cmake/android.toolchain.cmake \ | |||
-DANDROID_NATIVE_API_LEVEL=$(NDK_TARGETVER) \ | |||
-DCMAKE_BUILD_TYPE=Release \ | |||
-DANDROID_ABI=arm64-v8a \ | |||
-DOPENSSL_SMALL=1 \ | |||
-DCMAKE_C_FLAGS_RELEASE="-Os -fdata-sections -Wno-error=unused-command-line-argument" \ | |||
-DCMAKE_CXX_FLAGS_RELEASE="-Os -fdata-sections -Wno-error=unused-command-line-argument" \ | |||
-DCMAKE_EXE_LINKER_FLAGS="-Wl,--gc-sections -Wno-error=unused-command-line-argument" \ | |||
.. | |||
build: | |||
cd $(BUILD_DIR); \ | |||
$(MAKE) | |||
python ../print_bssl_size.py " -fdata-sections (+)" |
@@ -0,0 +1,22 @@ | |||
include ../common.mk | |||
BUILD_DIR = src/build | |||
MAKE = cmake --build . | |||
all: prepare build | |||
prepare: | |||
rm -rf $(BUILD_DIR) | |||
mkdir -p $(BUILD_DIR) | |||
cd $(BUILD_DIR); \ | |||
cmake -DCMAKE_BUILD_TYPE=Release \ | |||
-DCMAKE_BUILD_TYPE=Release \ | |||
-DOPENSSL_SMALL=1 \ | |||
-DCMAKE_C_FLAGS_RELEASE="-Os -fdata-sections" \ | |||
-DCMAKE_CXX_FLAGS_RELEASE="-Os -fdata-sections" \ | |||
-DCMAKE_EXE_LINKER_FLAGS="-Wl,--gc-sections" \ | |||
.. | |||
build: | |||
cd $(BUILD_DIR); \ | |||
$(MAKE) |
@@ -0,0 +1,5 @@ | |||
# Constants and makefile shit used in build | |||
mkfile_path = $(abspath $(lastword $(MAKEFILE_LIST))) | |||
current_dir = $(notdir $(patsubst %/,%,$(dir $(mkfile_path)))) | |||
ANDROID_NDK = /opt/android-ndk | |||
NDK_TARGETVER = 27 |
@@ -0,0 +1,48 @@ | |||
include ../common.mk | |||
## NDK configuration. | |||
NDK = $(ANDROID_NDK) | |||
NDK_TARGETARCH = aarch64-linux-android | |||
NDK_TARGETSHORTARCH = arm64 | |||
NDK_TOOLVER = 4.9 | |||
NDK_HOSTARCH = linux-x86_64 | |||
NDK_TOOLS = $(NDK)/toolchains/llvm/prebuilt/$(NDK_HOSTARCH)/bin | |||
NDK_SYSROOT = $(NDK)/sysroot | |||
NDK_TOOL = $(NDK_TOOLS)/clang | |||
NDK_LIBS = $(NDK)/toolchains/$(NDK_TARGETARCH)-$(NDK_TOOLVER)/prebuilt/linux-x86_64/lib/gcc/$(NDK_TARGETARCH)/4.9.x | |||
NDK_INCLUDES = -I$(NDK)/sysroot/usr/include -I$(NDK)/sysroot/usr/include/$(NDK_TARGETARCH) | |||
NDK_SYSROOT = $(NDK)/platforms/android-$(NDK_TARGETVER)/arch-$(NDK_TARGETSHORTARCH) | |||
OPT = -std=c99 -Os \ | |||
-fdata-sections \ | |||
-ffunction-sections \ | |||
-fPIE \ | |||
-Wall \ | |||
-target $(NDK_TARGETARCH) | |||
CFLAGS = $(OPT) \ | |||
$(NDK_INCLUDES) \ | |||
-D__ANDROID_API__=$(NDK_TARGETVER) \ | |||
-D_SOCKLEN_T_DECLARED | |||
LDFLAGS = $(OPT) \ | |||
-pie \ | |||
-Wl,--gc-sections \ | |||
--sysroot=$(NDK_SYSROOT) \ | |||
-B $(ANDROID_NDK)/toolchains/$(NDK_TARGETARCH)-$(NDK_TOOLVER)/prebuilt/linux-x86_64/$(NDK_TARGETARCH)/bin \ | |||
-L$(NDK_LIBS) | |||
all: | |||
CC=$(NDK_TOOL) CFLAGS="$(CFLAGS)" LDFLAGS="$(LDFLAGS)" make -C src | |||
clean: | |||
make -C src clean | |||
push: | |||
adb root | |||
adb remount | |||
adb shell "rm -rf /data/app/mbedtls/*" | |||
adb shell "mkdir -p /data/app/mbedtls" | |||
adb push src/programs/ssl/ssl_client1 /data/app/mbedtls/ | |||
adb push src/programs/ssl/ssl_server /data/app/mbedtls/ | |||
adb push src/programs/test/benchmark /data/app/mbedtls/ |
@@ -0,0 +1,13 @@ | |||
include ../common.mk | |||
OPT = -D_SOCKLEN_T_DECLARED -Os -fdata-sections | |||
CFLAGS = $(OPT) | |||
LDFLAGS = | |||
all: | |||
CC=gcc CFLAGS="$(CFLAGS)" LDFLAGS="$(LDFLAGS)" make -C src | |||
clean: | |||
make -C src clean | |||