[v2.2.0] Merge branch 'bleeding' (Version release)

This commit is contained in:
Snaipe 2015-12-08 13:54:56 +01:00
commit 65aa79dd52
150 changed files with 13155 additions and 1949 deletions

View file

@ -1,5 +1,5 @@
[bumpversion]
current_version = 2.1.0
current_version = 2.2.0
commit = False
[bumpversion:file:CMakeLists.txt]

View file

@ -0,0 +1,12 @@
# Copyright (C) 2015 Franklin "Snaipe" Mathieu.
# Redistribution and use of this file is allowed according to the terms of the MIT license.
# For details see the LICENSE file distributed with Criterion.
include(CheckPrototypeDefinition)
check_prototype_definition(
strtok_s
"char *strtok_s(char *strToken, const char *strDelimit, char **context)"
NULL
"string.h"
HAVE_STRTOK_S)

View file

@ -0,0 +1,42 @@
# build a Debian package for Launchpad
set(CPACK_DEBIAN_PACKAGE_NAME "criterion")
set(CPACK_DEBIAN_PACKAGE_PRIORITY "optional")
set(CPACK_DEBIAN_PACKAGE_SECTION "libs")
set(CPACK_DEBIAN_PACKAGE_HOMEPAGE "https://github.com/Snaipe/Criterion")
set(CPACK_DEBIAN_BUILD_DEPENDS
debhelper
cmake
gettext
libpcre3-dev
)
set(CPACK_DEBIAN_PACKAGE_DEPENDS
libpcre3
)
set(CPACK_DEBIAN_CMAKE_OPTIONS)
set(CPACK_PACKAGE_DESCRIPTION_FILE "${CMAKE_SOURCE_DIR}/description.txt")
set(CPACK_DEBIAN_PACKAGE_SOURCE_COPY "${CMAKE_SOURCE_DIR}/.cmake/copy-source.sh")
set(CPACK_DEBIAN_DISTRIBUTION_NAME ubuntu)
set(CPACK_DEBIAN_DISTRIBUTION_RELEASES precise trusty vivid wily xenial)
set(DPUT_HOST "snaipewastaken-ppa")
set(DPUT_SNAPSHOT_HOST "snaipewastaken-ppa")
set(CPACK_DEBIAN_PACKAGE_DOCS "")
set(CPACK_DEBIAN_PACKAGE_INSTALL
"/usr/lib/*.so"
"/usr/lib/*.so.*"
"/usr/share/locale/*"
)
set(CPACK_COMPONENTS_ALL "dev")
set(CPACK_COMPONENT_DEV_DISPLAY_NAME "Criterion library development files")
set(CPACK_COMPONENT_DEV_DESCRIPTION "These are the development files.")
set(CPACK_COMPONENT_DEV_SECTION "devel")
set(CPACK_COMPONENT_DEV_DOCS "")
set(CPACK_COMPONENT_DEV_INSTALL "/usr/include")
include (DebSourcePPA)

View file

@ -0,0 +1,347 @@
## Debian Source Package Generator
#
# Copyright (c) 2010 Daniel Pfeifer <daniel@pfeifer-mail.de>
# Many modifications by Rosen Diankov <rosen.diankov@gmail.com>
#
# Creates source debian files and manages library dependencies
#
# Features:
#
# - Automatically generates symbols and run-time dependencies from the build dependencies
# - Custom copy of source directory via CPACK_DEBIAN_PACKAGE_SOURCE_COPY
# - Simultaneous output of multiple debian source packages for each distribution
# - Can specificy distribution-specific dependencies by suffixing DEPENDS with _${DISTRO_NAME}, for example: CPACK_DEBIAN_PACKAGE_DEPENDS_LUCID, CPACK_COMPONENT_MYCOMP0_DEPENDS_LUCID
#
# Usage:
#
# set(CPACK_DEBIAN_BUILD_DEPENDS debhelper cmake)
# set(CPACK_DEBIAN_PACKAGE_PRIORITY optional)
# set(CPACK_DEBIAN_PACKAGE_SECTION devel)
# set(CPACK_DEBIAN_CMAKE_OPTIONS "-DMYOPTION=myvalue")
# set(CPACK_DEBIAN_PACKAGE_DEPENDS mycomp0 mycomp1 some_ubuntu_package)
# set(CPACK_DEBIAN_PACKAGE_DEPENDS_UBUNTU_LUCID mycomp0 mycomp1 lucid_specific_package)
# set(CPACK_DEBIAN_PACKAGE_NAME mypackage)
# set(CPACK_DEBIAN_PACKAGE_REMOVE_SOURCE_FILES unnecessary_file unnecessary_dir/file0)
# set(CPACK_DEBIAN_PACKAGE_SOURCE_COPY svn export --force) # if using subversion
# set(CPACK_DEBIAN_DISTRIBUTION_NAME ubuntu)
# set(CPACK_DEBIAN_DISTRIBUTION_RELEASES karmic lucid maverick natty)
# set(CPACK_DEBIAN_CHANGELOG " * Extra change log lines")
# set(CPACK_DEBIAN_PACKAGE_SUGGESTS "ipython")
# set(CPACK_COMPONENT_X_RECOMMENDS "recommended-package")
##
find_program(DEBUILD_EXECUTABLE debuild)
find_program(DPUT_EXECUTABLE dput)
if(NOT DEBUILD_EXECUTABLE OR NOT DPUT_EXECUTABLE)
return()
endif(NOT DEBUILD_EXECUTABLE OR NOT DPUT_EXECUTABLE)
# DEBIAN/control
# debian policy enforce lower case for package name
# Package: (mandatory)
IF(NOT CPACK_DEBIAN_PACKAGE_NAME)
STRING(TOLOWER "${CPACK_PACKAGE_NAME}" CPACK_DEBIAN_PACKAGE_NAME)
ENDIF(NOT CPACK_DEBIAN_PACKAGE_NAME)
# Section: (recommended)
IF(NOT CPACK_DEBIAN_PACKAGE_SECTION)
SET(CPACK_DEBIAN_PACKAGE_SECTION "devel")
ENDIF(NOT CPACK_DEBIAN_PACKAGE_SECTION)
# Priority: (recommended)
IF(NOT CPACK_DEBIAN_PACKAGE_PRIORITY)
SET(CPACK_DEBIAN_PACKAGE_PRIORITY "optional")
ENDIF(NOT CPACK_DEBIAN_PACKAGE_PRIORITY)
file(STRINGS ${CPACK_PACKAGE_DESCRIPTION_FILE} DESC_LINES)
foreach(LINE ${DESC_LINES})
set(DEB_LONG_DESCRIPTION "${DEB_LONG_DESCRIPTION} ${LINE}\n")
endforeach(LINE ${DESC_LINES})
file(REMOVE_RECURSE "${CMAKE_BINARY_DIR}/Debian")
file(MAKE_DIRECTORY "${CMAKE_BINARY_DIR}/Debian")
set(DEBIAN_SOURCE_ORIG_DIR "${CMAKE_BINARY_DIR}/Debian/${CPACK_DEBIAN_PACKAGE_NAME}-${CPACK_PACKAGE_VERSION}")
if( CPACK_DEBIAN_PACKAGE_SOURCE_COPY )
execute_process(COMMAND ${CPACK_DEBIAN_PACKAGE_SOURCE_COPY} "${CMAKE_SOURCE_DIR}" "${DEBIAN_SOURCE_ORIG_DIR}.orig")
else()
execute_process(COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_SOURCE_DIR} "${DEBIAN_SOURCE_ORIG_DIR}.orig")
execute_process(COMMAND ${CMAKE_COMMAND} -E remove_directory "${DEBIAN_SOURCE_ORIG_DIR}.orig/.git")
execute_process(COMMAND ${CMAKE_COMMAND} -E remove_directory "${DEBIAN_SOURCE_ORIG_DIR}.orig/.svn")
endif()
# remove unnecessary folders
foreach(REMOVE_DIR ${CPACK_DEBIAN_PACKAGE_REMOVE_SOURCE_FILES})
file(REMOVE_RECURSE ${DEBIAN_SOURCE_ORIG_DIR}.orig/${REMOVE_DIR})
endforeach()
# create the original source tar
execute_process(COMMAND ${CMAKE_COMMAND} -E tar czf "${CPACK_DEBIAN_PACKAGE_NAME}_${CPACK_PACKAGE_VERSION}.orig.tar.gz" "${CPACK_DEBIAN_PACKAGE_NAME}-${CPACK_PACKAGE_VERSION}.orig" WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/Debian)
set(DEB_SOURCE_CHANGES)
foreach(RELEASE ${CPACK_DEBIAN_DISTRIBUTION_RELEASES})
set(DEBIAN_SOURCE_DIR "${DEBIAN_SOURCE_ORIG_DIR}-${CPACK_DEBIAN_DISTRIBUTION_NAME}1~${RELEASE}1")
set(RELEASE_PACKAGE_VERSION "${CPACK_PACKAGE_VERSION}-${CPACK_DEBIAN_DISTRIBUTION_NAME}1~${RELEASE}1")
string(TOUPPER ${RELEASE} RELEASE_UPPER)
string(TOUPPER ${CPACK_DEBIAN_DISTRIBUTION_NAME} DISTRIBUTION_NAME_UPPER)
file(MAKE_DIRECTORY ${DEBIAN_SOURCE_DIR}/debian)
##############################################################################
# debian/control
set(DEBIAN_CONTROL ${DEBIAN_SOURCE_DIR}/debian/control)
file(WRITE ${DEBIAN_CONTROL}
"Source: ${CPACK_DEBIAN_PACKAGE_NAME}\n"
"Section: ${CPACK_DEBIAN_PACKAGE_SECTION}\n"
"Priority: ${CPACK_DEBIAN_PACKAGE_PRIORITY}\n"
"DM-Upload-Allowed: yes\n"
"Maintainer: ${CPACK_PACKAGE_CONTACT}\n"
"Build-Depends: "
)
if( CPACK_DEBIAN_BUILD_DEPENDS_${DISTRIBUTION_NAME_UPPER}_${RELEASE_UPPER} )
foreach(DEP ${CPACK_DEBIAN_BUILD_DEPENDS_${DISTRIBUTION_NAME_UPPER}_${RELEASE_UPPER}})
file(APPEND ${DEBIAN_CONTROL} "${DEP}, ")
endforeach(DEP ${CPACK_DEBIAN_BUILD_DEPENDS_${DISTRIBUTION_NAME_UPPER}_${RELEASE_UPPER}})
else( CPACK_DEBIAN_BUILD_DEPENDS_${DISTRIBUTION_NAME_UPPER}_${RELEASE_UPPER} )
if( CPACK_DEBIAN_BUILD_DEPENDS_${DISTRIBUTION_NAME_UPPER} )
foreach(DEP ${CPACK_DEBIAN_BUILD_DEPENDS_${DISTRIBUTION_NAME_UPPER}})
file(APPEND ${DEBIAN_CONTROL} "${DEP}, ")
endforeach(DEP ${CPACK_DEBIAN_BUILD_DEPENDS_${DISTRIBUTION_NAME_UPPER}})
else( CPACK_DEBIAN_BUILD_DEPENDS_${DISTRIBUTION_NAME_UPPER} )
foreach(DEP ${CPACK_DEBIAN_BUILD_DEPENDS})
file(APPEND ${DEBIAN_CONTROL} "${DEP}, ")
endforeach(DEP ${CPACK_DEBIAN_BUILD_DEPENDS})
endif( CPACK_DEBIAN_BUILD_DEPENDS_${DISTRIBUTION_NAME_UPPER} )
endif( CPACK_DEBIAN_BUILD_DEPENDS_${DISTRIBUTION_NAME_UPPER}_${RELEASE_UPPER} )
file(APPEND ${DEBIAN_CONTROL} "\n"
"Standards-Version: 3.8.4\n"
"Homepage: ${CPACK_PACKAGE_VENDOR}\n"
"\n"
"Package: ${CPACK_DEBIAN_PACKAGE_NAME}\n"
"Architecture: any\n"
"Depends: "
)
if( CPACK_DEBIAN_PACKAGE_DEPENDS_${DISTRIBUTION_NAME_UPPER}_${RELEASE_UPPER} )
foreach(DEP ${CPACK_DEBIAN_PACKAGE_DEPENDS_${DISTRIBUTION_NAME_UPPER}_${RELEASE_UPPER}})
file(APPEND ${DEBIAN_CONTROL} "${DEP}, ")
endforeach(DEP ${CPACK_DEBIAN_PACKAGE_DEPENDS_${DISTRIBUTION_NAME_UPPER}_${RELEASE_UPPER}})
else( CPACK_DEBIAN_PACKAGE_DEPENDS_${DISTRIBUTION_NAME_UPPER}_${RELEASE_UPPER} )
if( CPACK_DEBIAN_PACKAGE_DEPENDS_${DISTRIBUTION_NAME_UPPER} )
foreach(DEP ${CPACK_DEBIAN_PACKAGE_DEPENDS_${DISTRIBUTION_NAME_UPPER}})
file(APPEND ${DEBIAN_CONTROL} "${DEP}, ")
endforeach(DEP ${CPACK_DEBIAN_PACKAGE_DEPENDS_${DISTRIBUTION_NAME_UPPER}})
else( CPACK_DEBIAN_PACKAGE_DEPENDS_${DISTRIBUTION_NAME_UPPER} )
foreach(DEP ${CPACK_DEBIAN_PACKAGE_DEPENDS})
file(APPEND ${DEBIAN_CONTROL} "${DEP}, ")
endforeach(DEP ${CPACK_DEBIAN_PACKAGE_DEPENDS})
endif( CPACK_DEBIAN_PACKAGE_DEPENDS_${DISTRIBUTION_NAME_UPPER} )
endif( CPACK_DEBIAN_PACKAGE_DEPENDS_${DISTRIBUTION_NAME_UPPER}_${RELEASE_UPPER} )
file(APPEND ${DEBIAN_CONTROL} "\nRecommends: ")
if( CPACK_DEBIAN_PACKAGE_RECOMMENDS_${DISTRIBUTION_NAME_UPPER}_${RELEASE_UPPER} )
foreach(DEP ${CPACK_DEBIAN_PACKAGE_RECOMMENDS_${DISTRIBUTION_NAME_UPPER}_${RELEASE_UPPER}})
file(APPEND ${DEBIAN_CONTROL} "${DEP}, ")
endforeach(DEP ${CPACK_DEBIAN_PACKAGE_RECOMMENDS_${DISTRIBUTION_NAME_UPPER}_${RELEASE_UPPER}})
else( CPACK_DEBIAN_PACKAGE_RECOMMENDS_${DISTRIBUTION_NAME_UPPER}_${RELEASE_UPPER} )
if( CPACK_DEBIAN_PACKAGE_RECOMMENDS_${DISTRIBUTION_NAME_UPPER} )
foreach(DEP ${CPACK_DEBIAN_PACKAGE_RECOMMENDS_${DISTRIBUTION_NAME_UPPER}})
file(APPEND ${DEBIAN_CONTROL} "${DEP}, ")
endforeach(DEP ${CPACK_DEBIAN_PACKAGE_RECOMMENDS_${DISTRIBUTION_NAME_UPPER}})
else( CPACK_DEBIAN_PACKAGE_RECOMMENDS_${DISTRIBUTION_NAME_UPPER} )
foreach(DEP ${CPACK_DEBIAN_PACKAGE_RECOMMENDS})
file(APPEND ${DEBIAN_CONTROL} "${DEP}, ")
endforeach(DEP ${CPACK_DEBIAN_PACKAGE_RECOMMENDS})
endif( CPACK_DEBIAN_PACKAGE_RECOMMENDS_${DISTRIBUTION_NAME_UPPER} )
endif( CPACK_DEBIAN_PACKAGE_RECOMMENDS_${DISTRIBUTION_NAME_UPPER}_${RELEASE_UPPER} )
file(APPEND ${DEBIAN_CONTROL} "\nSuggests: ")
if( CPACK_DEBIAN_PACKAGE_SUGGESTS_${DISTRIBUTION_NAME_UPPER}_${RELEASE_UPPER} )
foreach(DEP ${CPACK_DEBIAN_PACKAGE_SUGGESTS_${DISTRIBUTION_NAME_UPPER}_${RELEASE_UPPER}})
file(APPEND ${DEBIAN_CONTROL} "${DEP}, ")
endforeach(DEP ${CPACK_DEBIAN_PACKAGE_SUGGESTS_${DISTRIBUTION_NAME_UPPER}_${RELEASE_UPPER}})
else( CPACK_DEBIAN_PACKAGE_SUGGESTS_${DISTRIBUTION_NAME_UPPER}_${RELEASE_UPPER} )
if( CPACK_DEBIAN_PACKAGE_SUGGESTS_${DISTRIBUTION_NAME_UPPER} )
foreach(DEP ${CPACK_DEBIAN_PACKAGE_SUGGESTS_${DISTRIBUTION_NAME_UPPER}})
file(APPEND ${DEBIAN_CONTROL} "${DEP}, ")
endforeach(DEP ${CPACK_DEBIAN_PACKAGE_SUGGESTS_${DISTRIBUTION_NAME_UPPER}})
else( CPACK_DEBIAN_PACKAGE_SUGGESTS_${DISTRIBUTION_NAME_UPPER} )
foreach(DEP ${CPACK_DEBIAN_PACKAGE_SUGGESTS})
file(APPEND ${DEBIAN_CONTROL} "${DEP}, ")
endforeach(DEP ${CPACK_DEBIAN_PACKAGE_SUGGESTS})
endif( CPACK_DEBIAN_PACKAGE_SUGGESTS_${DISTRIBUTION_NAME_UPPER} )
endif( CPACK_DEBIAN_PACKAGE_SUGGESTS_${DISTRIBUTION_NAME_UPPER}_${RELEASE_UPPER} )
file(APPEND ${DEBIAN_CONTROL} "\n"
"Description: ${CPACK_PACKAGE_DISPLAY_NAME} ${CPACK_PACKAGE_DESCRIPTION_SUMMARY}\n"
"${DEB_LONG_DESCRIPTION}"
)
foreach(COMPONENT ${CPACK_COMPONENTS_ALL})
string(TOUPPER ${COMPONENT} UPPER_COMPONENT)
set(DEPENDS "\${shlibs:Depends}")
if( CPACK_COMPONENT_${UPPER_COMPONENT}_DEPENDS_${DISTRIBUTION_NAME_UPPER}_${RELEASE_UPPER} )
foreach(DEP ${CPACK_COMPONENT_${UPPER_COMPONENT}_DEPENDS_${DISTRIBUTION_NAME_UPPER}_${RELEASE_UPPER}})
set(DEPENDS "${DEPENDS}, ${DEP}")
endforeach(DEP ${CPACK_COMPONENT_${UPPER_COMPONENT}_DEPENDS_${DISTRIBUTION_NAME_UPPER}_${RELEASE_UPPER}})
else( CPACK_COMPONENT_${UPPER_COMPONENT}_DEPENDS_${DISTRIBUTION_NAME_UPPER}_${RELEASE_UPPER} )
if( CPACK_COMPONENT_${UPPER_COMPONENT}_DEPENDS_${DISTRIBUTION_NAME_UPPER} )
foreach(DEP ${CPACK_COMPONENT_${UPPER_COMPONENT}_DEPENDS_${DISTRIBUTION_NAME_UPPER}})
set(DEPENDS "${DEPENDS}, ${DEP}")
endforeach(DEP ${CPACK_COMPONENT_${UPPER_COMPONENT}_DEPENDS_${DISTRIBUTION_NAME_UPPER}})
else( CPACK_COMPONENT_${UPPER_COMPONENT}_DEPENDS_${DISTRIBUTION_NAME_UPPER} )
foreach(DEP ${CPACK_COMPONENT_${UPPER_COMPONENT}_DEPENDS})
set(DEPENDS "${DEPENDS}, ${DEP}")
endforeach(DEP ${CPACK_COMPONENT_${UPPER_COMPONENT}_DEPENDS})
endif( CPACK_COMPONENT_${UPPER_COMPONENT}_DEPENDS_${DISTRIBUTION_NAME_UPPER} )
endif( CPACK_COMPONENT_${UPPER_COMPONENT}_DEPENDS_${DISTRIBUTION_NAME_UPPER}_${RELEASE_UPPER} )
set(RECOMMENDS)
if( CPACK_COMPONENT_${UPPER_COMPONENT}_RECOMMENDS_${DISTRIBUTION_NAME_UPPER}_${RELEASE_UPPER} )
foreach(DEP ${CPACK_COMPONENT_${UPPER_COMPONENT}_RECOMMENDS_${DISTRIBUTION_NAME_UPPER}_${RELEASE_UPPER}})
set(RECOMMENDS "${RECOMMENDS} ${DEP}, ")
endforeach(DEP ${CPACK_COMPONENT_${UPPER_COMPONENT}_RECOMMENDS_${DISTRIBUTION_NAME_UPPER}_${RELEASE_UPPER}})
else( CPACK_COMPONENT_${UPPER_COMPONENT}_RECOMMENDS_${DISTRIBUTION_NAME_UPPER}_${RELEASE_UPPER} )
if( CPACK_COMPONENT_${UPPER_COMPONENT}_RECOMMENDS_${DISTRIBUTION_NAME_UPPER} )
foreach(DEP ${CPACK_COMPONENT_${UPPER_COMPONENT}_RECOMMENDS_${DISTRIBUTION_NAME_UPPER}})
set(RECOMMENDS "${RECOMMENDS} ${DEP}, ")
endforeach(DEP ${CPACK_COMPONENT_${UPPER_COMPONENT}_RECOMMENDS_${DISTRIBUTION_NAME_UPPER}})
else( CPACK_COMPONENT_${UPPER_COMPONENT}_RECOMMENDS_${DISTRIBUTION_NAME_UPPER} )
foreach(DEP ${CPACK_COMPONENT_${UPPER_COMPONENT}_RECOMMENDS})
set(RECOMMENDS "${RECOMMENDS} ${DEP}, ")
endforeach(DEP ${CPACK_COMPONENT_${UPPER_COMPONENT}_RECOMMENDS})
endif( CPACK_COMPONENT_${UPPER_COMPONENT}_RECOMMENDS_${DISTRIBUTION_NAME_UPPER} )
endif( CPACK_COMPONENT_${UPPER_COMPONENT}_RECOMMENDS_${DISTRIBUTION_NAME_UPPER}_${RELEASE_UPPER} )
set(SUGGESTS)
if( CPACK_COMPONENT_${UPPER_COMPONENT}_SUGGESTS_${DISTRIBUTION_NAME_UPPER}_${RELEASE_UPPER} )
foreach(DEP ${CPACK_COMPONENT_${UPPER_COMPONENT}_SUGGESTS_${DISTRIBUTION_NAME_UPPER}_${RELEASE_UPPER}})
set(SUGGESTS "${SUGGESTS} ${DEP}, ")
endforeach(DEP ${CPACK_COMPONENT_${UPPER_COMPONENT}_SUGGESTS_${DISTRIBUTION_NAME_UPPER}_${RELEASE_UPPER}})
else( CPACK_COMPONENT_${UPPER_COMPONENT}_SUGGESTS_${DISTRIBUTION_NAME_UPPER}_${RELEASE_UPPER} )
if( CPACK_COMPONENT_${UPPER_COMPONENT}_SUGGESTS_${DISTRIBUTION_NAME_UPPER} )
foreach(DEP ${CPACK_COMPONENT_${UPPER_COMPONENT}_SUGGESTS_${DISTRIBUTION_NAME_UPPER}})
set(SUGGESTS "${SUGGESTS} ${DEP}, ")
endforeach(DEP ${CPACK_COMPONENT_${UPPER_COMPONENT}_SUGGESTS_${DISTRIBUTION_NAME_UPPER}})
else( CPACK_COMPONENT_${UPPER_COMPONENT}_SUGGESTS_${DISTRIBUTION_NAME_UPPER} )
foreach(DEP ${CPACK_COMPONENT_${UPPER_COMPONENT}_SUGGESTS})
set(SUGGESTS "${SUGGESTS} ${DEP}, ")
endforeach(DEP ${CPACK_COMPONENT_${UPPER_COMPONENT}_SUGGESTS})
endif( CPACK_COMPONENT_${UPPER_COMPONENT}_SUGGESTS_${DISTRIBUTION_NAME_UPPER} )
endif( CPACK_COMPONENT_${UPPER_COMPONENT}_SUGGESTS_${DISTRIBUTION_NAME_UPPER}_${RELEASE_UPPER} )
file(APPEND ${DEBIAN_CONTROL} "\n"
"Package: ${CPACK_DEBIAN_PACKAGE_NAME}-${COMPONENT}\n"
"Architecture: any\n"
"Depends: ${DEPENDS}\n"
"Recommends: ${RECOMMENDS}\n"
"Suggests: ${SUGGESTS}\n"
"Description: ${CPACK_PACKAGE_DISPLAY_NAME} ${CPACK_COMPONENT_${UPPER_COMPONENT}_DISPLAY_NAME}\n"
"${DEB_LONG_DESCRIPTION}"
" .\n"
" ${CPACK_COMPONENT_${UPPER_COMPONENT}_DESCRIPTION}\n"
)
endforeach(COMPONENT ${CPACK_COMPONENTS_ALL})
##############################################################################
# debian/copyright
set(DEBIAN_COPYRIGHT ${DEBIAN_SOURCE_DIR}/debian/copyright)
execute_process(COMMAND ${CMAKE_COMMAND} -E
copy ${CPACK_RESOURCE_FILE_LICENSE} ${DEBIAN_COPYRIGHT}
)
##############################################################################
# debian/rules
set(DEBIAN_RULES ${DEBIAN_SOURCE_DIR}/debian/rules)
file(WRITE ${DEBIAN_RULES}
"#!/usr/bin/make -f\n"
"\n"
"BUILDDIR = build_dir\n"
"\n"
"build:\n"
" mkdir $(BUILDDIR)\n"
" cd $(BUILDDIR); cmake -DCMAKE_BUILD_TYPE=Release ${CPACK_DEBIAN_CMAKE_OPTIONS} -DCMAKE_INSTALL_PREFIX=/usr ..\n"
" $(MAKE) -C $(BUILDDIR) preinstall\n"
" touch build\n"
"\n"
"binary: binary-indep binary-arch\n"
"\n"
"binary-indep: build\n"
"\n"
"binary-arch: build\n"
" cd $(BUILDDIR); cmake -DCOMPONENT=Unspecified -DCMAKE_INSTALL_PREFIX=../debian/tmp/usr -P cmake_install.cmake\n"
" mkdir -p debian/tmp/DEBIAN\n"
" dpkg-gensymbols -p${CPACK_DEBIAN_PACKAGE_NAME}\n"
)
foreach(COMPONENT ${CPACK_COMPONENTS_ALL})
set(PATH debian/${COMPONENT})
file(APPEND ${DEBIAN_RULES}
" cd $(BUILDDIR); cmake -DCOMPONENT=${COMPONENT} -DCMAKE_INSTALL_PREFIX=../${PATH}/usr -P cmake_install.cmake\n"
" mkdir -p ${PATH}/DEBIAN\n"
" dpkg-gensymbols -p${CPACK_DEBIAN_PACKAGE_NAME}-${COMPONENT} -P${PATH}\n"
)
endforeach(COMPONENT ${CPACK_COMPONENTS_ALL})
file(APPEND ${DEBIAN_RULES}
" dh_shlibdeps\n"
" dh_strip\n" # for reducing size
" dpkg-gencontrol -p${CPACK_DEBIAN_PACKAGE_NAME}\n"
" dpkg --build debian/tmp ..\n"
)
foreach(COMPONENT ${CPACK_COMPONENTS_ALL})
set(PATH debian/${COMPONENT})
file(APPEND ${DEBIAN_RULES}
" dpkg-gencontrol -p${CPACK_DEBIAN_PACKAGE_NAME}-${COMPONENT} -P${PATH} -Tdebian/${COMPONENT}.substvars\n"
" dpkg --build ${PATH} ..\n"
)
endforeach(COMPONENT ${CPACK_COMPONENTS_ALL})
file(APPEND ${DEBIAN_RULES}
"\n"
"clean:\n"
" rm -f build\n"
" rm -rf $(BUILDDIR)\n"
"\n"
".PHONY: binary binary-arch binary-indep clean\n"
)
execute_process(COMMAND chmod +x ${DEBIAN_RULES})
##############################################################################
# debian/compat
file(WRITE ${DEBIAN_SOURCE_DIR}/debian/compat "7")
##############################################################################
# debian/source/format
file(WRITE ${DEBIAN_SOURCE_DIR}/debian/source/format "3.0 (quilt)")
##############################################################################
# debian/changelog
set(DEBIAN_CHANGELOG ${DEBIAN_SOURCE_DIR}/debian/changelog)
execute_process(COMMAND date -R OUTPUT_VARIABLE DATE_TIME)
file(WRITE ${DEBIAN_CHANGELOG}
"${CPACK_DEBIAN_PACKAGE_NAME} (${RELEASE_PACKAGE_VERSION}) ${RELEASE}; urgency=medium\n\n"
" * Package built with CMake\n\n"
"${CPACK_DEBIAN_CHANGELOG}"
" -- ${CPACK_PACKAGE_CONTACT} ${DATE_TIME}"
)
##############################################################################
# debuild -S
if( DEB_SOURCE_CHANGES )
set(DEBUILD_OPTIONS "-sd")
else()
set(DEBUILD_OPTIONS "-sa")
endif()
set(SOURCE_CHANGES_FILE "${CPACK_DEBIAN_PACKAGE_NAME}_${RELEASE_PACKAGE_VERSION}_source.changes")
set(DEB_SOURCE_CHANGES ${DEB_SOURCE_CHANGES} "${SOURCE_CHANGES_FILE}")
add_custom_command(OUTPUT "${SOURCE_CHANGES_FILE}" COMMAND ${DEBUILD_EXECUTABLE} -S ${DEBUILD_OPTIONS} WORKING_DIRECTORY ${DEBIAN_SOURCE_DIR})
endforeach(RELEASE ${CPACK_DEBIAN_DISTRIBUTION_RELEASES})
##############################################################################
# dput ppa:your-lp-id/ppa <source.changes>
add_custom_target(dput ${DPUT_EXECUTABLE} ${DPUT_HOST} ${DEB_SOURCE_CHANGES} DEPENDS ${DEB_SOURCE_CHANGES} WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/Debian)

View file

@ -252,13 +252,29 @@ macro(GettextTranslate)
else()
add_custom_target(${PO_TARGET}
COMMAND ${GettextTranslate_MSGMERGE_EXECUTABLE} --lang=${lang}
${PO_FILE_NAME} ${TEMPLATE_FILE_ABS}
-o ${PO_FILE_NAME}.new
COMMAND mv ${PO_FILE_NAME}.new ${PO_FILE_NAME}
DEPENDS ${TEMPLATE_FILE_ABS}
execute_process(
COMMAND ${GettextTranslate_MSGMERGE_EXECUTABLE} --version
OUTPUT_VARIABLE MSGMERGE_VERSION_MSG
)
string(REGEX MATCH "[0-9]+\\.[0-9]+(\\.[0-9]+)?" MSGMERGE_VERSION "${MSGMERGE_VERSION_MSG}")
if ("${MSGMERGE_VERSION}" VERSION_GREATER "0.17")
add_custom_target(${PO_TARGET}
COMMAND ${GettextTranslate_MSGMERGE_EXECUTABLE} --lang=${lang}
${PO_FILE_NAME} ${TEMPLATE_FILE_ABS}
-o ${PO_FILE_NAME}.new
COMMAND mv ${PO_FILE_NAME}.new ${PO_FILE_NAME}
DEPENDS ${TEMPLATE_FILE_ABS}
)
else ()
add_custom_target(${PO_TARGET}
COMMAND ${GettextTranslate_MSGMERGE_EXECUTABLE}
${PO_FILE_NAME} ${TEMPLATE_FILE_ABS}
-o ${PO_FILE_NAME}.new
COMMAND mv ${PO_FILE_NAME}.new ${PO_FILE_NAME}
DEPENDS ${TEMPLATE_FILE_ABS}
)
endif ()
endif()
@ -271,7 +287,7 @@ macro(GettextTranslate)
add_dependencies(${PO_TARGET} ${MAKEVAR_DOMAIN}.pot-update)
install(FILES ${GMO_FILE_NAME} DESTINATION
${LOCALEDIR}/${lang}/LC_MESSAGES
${LOCALEDIR_REL}/${lang}/LC_MESSAGES
RENAME ${MAKEVAR_DOMAIN}.mo
)

View file

@ -0,0 +1,79 @@
function(extract_version version major minor patch extra)
string(REGEX MATCH "([0-9]+)\\.([0-9]+)\\.([0-9]+)(.*)?" version_valid ${version})
if(version_valid)
string(REGEX REPLACE "([0-9]+)\\.([0-9]+)\\.([0-9]+)(.*)?" "\\1;\\2;\\3;\\4" VERSION_MATCHES ${version})
list(GET VERSION_MATCHES 0 version_major)
set(${major} ${version_major} PARENT_SCOPE)
list(GET VERSION_MATCHES 1 version_minor)
set(${minor} ${version_minor} PARENT_SCOPE)
list(GET VERSION_MATCHES 2 version_patch)
set(${patch} ${version_patch} PARENT_SCOPE)
list(GET VERSION_MATCHES 3 version_extra)
set(${extra} ${version_extra} PARENT_SCOPE)
else(version_valid)
message(AUTHOR_WARNING "Bad version ${version}; falling back to 0 (have you made an initial release?)")
set(${major} "0" PARENT_SCOPE)
set(${minor} "" PARENT_SCOPE)
set(${patch} "" PARENT_SCOPE)
set(${extra} "" PARENT_SCOPE)
endif(version_valid)
endfunction(extract_version)
if (WIN32)
set(CPACK_GENERATOR "ZIP")
set(CPACK_SOURCE_GENERATOR "ZIP")
else ()
set(CPACK_GENERATOR "TGZ")
set(CPACK_SOURCE_GENERATOR "TGZ")
endif ()
set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "A KISS, modern unit testing framework for C and C++.")
set(CPACK_PACKAGE_FILE_NAME "${CMAKE_PROJECT_NAME}-binary-${PROJECT_VERSION}")
set(CPACK_SOURCE_PACKAGE_FILE_NAME "${CMAKE_PROJECT_NAME}-${PROJECT_VERSION}")
set(CPACK_PACKAGE_INSTALL_DIRECTORY "${CMAKE_PROJECT_NAME}-${PROJECT_VERSION}")
set(CPACK_PACKAGE_VENDOR "Franklin \"Snaipe\" Mathieu")
set(CPACK_PACKAGE_CONTACT "Franklin \"Snaipe\" Mathieu <franklinmathieu@gmail.com>")
set(CPACK_PACKAGE_VERSION "${PROJECT_VERSION}")
if (WIN32)
# add snapshot specific versioning information
if (CPACK_DEBIAN_PACKAGE_TYPE STREQUAL "snapshot")
execute_process(COMMAND date +%Y%m%d%0k%0M%0S%z OUTPUT_VARIABLE SNAPSHOT_DATE_TIME)
set(CPACK_PACKAGE_VERSION "${PROJECT_VERSION}-snapshot-${SNAPSHOT_DATE_TIME}")
STRING(REPLACE "\n" "" CPACK_PACKAGE_VERSION ${CPACK_PACKAGE_VERSION})
endif ()
endif ()
set(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_SOURCE_DIR}/debian.copyright")
extract_version(${PROJECT_VERSION}
CPACK_PACKAGE_VERSION_MAJOR
CPACK_PACKAGE_VERSION_MINOR
CPACK_PACKAGE_VERSION_PATCH
VERSION_EXTRA
)
set(CPACK_PACKAGE_VERSION ${PROJECT_VERSION})
file(GLOB TRASH_FILES "${CMAKE_SOURCE_DIR}/*")
set(KEEP_FILES
"${CMAKE_SOURCE_DIR}/.cmake"
"${CMAKE_SOURCE_DIR}/src"
"${CMAKE_SOURCE_DIR}/include"
"${CMAKE_SOURCE_DIR}/doc"
"${CMAKE_SOURCE_DIR}/dev"
"${CMAKE_SOURCE_DIR}/po"
"${CMAKE_SOURCE_DIR}/dependencies"
"${CMAKE_SOURCE_DIR}/CMakeLists.txt"
"${CMAKE_SOURCE_DIR}/README.md"
"${CMAKE_SOURCE_DIR}/CONTRIBUTING.md"
"${CMAKE_SOURCE_DIR}/LICENSE"
"${CMAKE_SOURCE_DIR}/ChangeLog"
"${CMAKE_SOURCE_DIR}/description.txt"
)
list(REMOVE_ITEM TRASH_FILES ${KEEP_FILES})
# Escape any '.' characters
string(REPLACE "." "\\\\." TRASH_FILES "${TRASH_FILES}")
set(CPACK_SOURCE_IGNORE_FILES "${TRASH_FILES}")
include(CPack)

11
.cmake/copy-source.sh Executable file
View file

@ -0,0 +1,11 @@
#!/bin/sh
CURDIR=$(dirname $0)
SOURCE_DIR=$1; shift
DEST_DIR=$1; shift
(
cd "$SOURCE_DIR"
mkdir -p "$DEST_DIR"
"$CURDIR/git-archive-all.sh" --format tar -- - | tar -x -C "$DEST_DIR"
)

302
.cmake/git-archive-all.sh Executable file
View file

@ -0,0 +1,302 @@
#!/bin/bash -
#
# File: git-archive-all.sh
#
# Description: A utility script that builds an archive file(s) of all
# git repositories and submodules in the current path.
# Useful for creating a single tarfile of a git super-
# project that contains other submodules.
#
# Examples: Use git-archive-all.sh to create archive distributions
# from git repositories. To use, simply do:
#
# cd $GIT_DIR; git-archive-all.sh
#
# where $GIT_DIR is the root of your git superproject.
#
# License: GPL3+
#
###############################################################################
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#
###############################################################################
# DEBUGGING
set -e
set -C # noclobber
# TRAP SIGNALS
trap 'cleanup' QUIT EXIT
# For security reasons, explicitly set the internal field separator
# to newline, space, tab
OLD_IFS=$IFS
IFS='
'
function cleanup () {
rm -f $TMPFILE
rm -f $TOARCHIVE
IFS="$OLD_IFS"
}
function usage () {
echo "Usage is as follows:"
echo
echo "$PROGRAM <--version>"
echo " Prints the program version number on a line by itself and exits."
echo
echo "$PROGRAM <--usage|--help|-?>"
echo " Prints this usage output and exits."
echo
echo "$PROGRAM [--format <fmt>] [--prefix <path>] [--verbose|-v] [--separate|-s]"
echo " [--tree-ish|-t <tree-ish>] [output_file]"
echo " Creates an archive for the entire git superproject, and its submodules"
echo " using the passed parameters, described below."
echo
echo " If '--format' is specified, the archive is created with the named"
echo " git archiver backend. Obviously, this must be a backend that git archive"
echo " understands. The format defaults to 'tar' if not specified."
echo
echo " If '--prefix' is specified, the archive's superproject and all submodules"
echo " are created with the <path> prefix named. The default is to not use one."
echo
echo " If '--separate' or '-s' is specified, individual archives will be created"
echo " for each of the superproject itself and its submodules. The default is to"
echo " concatenate individual archives into one larger archive."
echo
echo " If '--tree-ish' is specified, the archive will be created based on whatever"
echo " you define the tree-ish to be. Branch names, commit hash, etc. are acceptable."
echo " Defaults to HEAD if not specified. See git archive's documentation for more"
echo " information on what a tree-ish is."
echo
echo " If 'output_file' is specified, the resulting archive is created as the"
echo " file named. This parameter is essentially a path that must be writeable."
echo " When combined with '--separate' ('-s') this path must refer to a directory."
echo " Without this parameter or when combined with '--separate' the resulting"
echo " archive(s) are named with a dot-separated path of the archived directory and"
echo " a file extension equal to their format (e.g., 'superdir.submodule1dir.tar')."
echo
echo " The special value '-' (single dash) is treated as STDOUT and, when used, the"
echo " --separate option is ignored. Use a double-dash to separate the outfile from"
echo " the value of previous options. For example, to write a .zip file to STDOUT:"
echo
echo " ./$PROGRAM --format zip -- -"
echo
echo " If '--verbose' or '-v' is specified, progress will be printed."
}
function version () {
echo "$PROGRAM version $VERSION"
}
# Internal variables and initializations.
readonly PROGRAM=`basename "$0"`
readonly VERSION=0.3
SEPARATE=0
VERBOSE=0
TARCMD=`command -v gnutar || command -v tar`
FORMAT=tar
PREFIX=
TREEISH=HEAD
# RETURN VALUES/EXIT STATUS CODES
readonly E_BAD_OPTION=254
readonly E_UNKNOWN=255
# Process command-line arguments.
while test $# -gt 0; do
if [ x"$1" == x"--" ]; then
# detect argument termination
shift
break
fi
case $1 in
--format )
shift
FORMAT="$1"
shift
;;
--prefix )
shift
PREFIX="$1"
shift
;;
--separate | -s )
shift
SEPARATE=1
;;
--tree-ish | -t )
shift
TREEISH="$1"
shift
;;
--version )
version
exit
;;
--verbose | -v )
shift
VERBOSE=1
;;
-? | --usage | --help )
usage
exit
;;
-* )
echo "Unrecognized option: $1" >&2
usage
exit $E_BAD_OPTION
;;
* )
break
;;
esac
done
OLD_PWD="`pwd`"
TMPDIR=${TMPDIR:-/tmp}
TMPFILE=`mktemp "$TMPDIR/$PROGRAM.XXXXXX"` # Create a place to store our work's progress
TOARCHIVE=`mktemp "$TMPDIR/$PROGRAM.toarchive.XXXXXX"`
OUT_FILE=$OLD_PWD # assume "this directory" without a name change by default
if [ ! -z "$1" ]; then
OUT_FILE="$1"
if [ "-" == $OUT_FILE ]; then
SEPARATE=0
fi
shift
fi
# Validate parameters; error early, error often.
if [ "-" == $OUT_FILE -o $SEPARATE -ne 1 ] && [ "$FORMAT" == "tar" -a `$TARCMD --help | grep -q -- "--concatenate"; echo $?` -ne 0 ]; then
echo "Your 'tar' does not support the '--concatenate' option, which we need"
echo "to produce a single tarfile. Either install a compatible tar (such as"
echo "gnutar), or invoke $PROGRAM with the '--separate' option."
exit
elif [ $SEPARATE -eq 1 -a ! -d $OUT_FILE ]; then
echo "When creating multiple archives, your destination must be a directory."
echo "If it's not, you risk being surprised when your files are overwritten."
exit
elif [ `git config -l | grep -q '^core\.bare=false'; echo $?` -ne 0 ]; then
echo "$PROGRAM must be run from a git working copy (i.e., not a bare repository)."
exit
fi
# Create the superproject's git-archive
if [ $VERBOSE -eq 1 ]; then
echo -n "creating superproject archive..."
fi
git archive --format=$FORMAT --prefix="$PREFIX" $TREEISH > $TMPDIR/$(basename "$(pwd)").$FORMAT
if [ $VERBOSE -eq 1 ]; then
echo "done"
fi
echo $TMPDIR/$(basename "$(pwd)").$FORMAT >| $TMPFILE # clobber on purpose
superfile=`head -n 1 $TMPFILE`
if [ $VERBOSE -eq 1 ]; then
echo -n "looking for subprojects..."
fi
# find all '.git' dirs, these show us the remaining to-be-archived dirs
# we only want directories that are below the current directory
find . -mindepth 2 -name '.git' -type d -print | sed -e 's/^\.\///' -e 's/\.git$//' >> $TOARCHIVE
# as of version 1.7.8, git places the submodule .git directories under the superprojects .git dir
# the submodules get a .git file that points to their .git dir. we need to find all of these too
find . -mindepth 2 -name '.git' -type f -print | xargs grep -l "gitdir" | sed -e 's/^\.\///' -e 's/\.git$//' >> $TOARCHIVE
if [ $VERBOSE -eq 1 ]; then
echo "done"
echo " found:"
cat $TOARCHIVE | while read arch
do
echo " $arch"
done
fi
if [ $VERBOSE -eq 1 ]; then
echo -n "archiving submodules..."
fi
while read path; do
TREEISH=$(git submodule | grep "^ .*${path%/} " | cut -d ' ' -f 2) # git submodule does not list trailing slashes in $path
cd "$path"
git archive --format=$FORMAT --prefix="${PREFIX}$path" ${TREEISH:-HEAD} > "$TMPDIR"/"$(echo "$path" | sed -e 's/\//./g')"$FORMAT
if [ $FORMAT == 'zip' ]; then
# delete the empty directory entry; zipped submodules won't unzip if we don't do this
zip -d "$(tail -n 1 $TMPFILE)" "${PREFIX}${path%/}" >/dev/null # remove trailing '/'
fi
echo "$TMPDIR"/"$(echo "$path" | sed -e 's/\//./g')"$FORMAT >> $TMPFILE
cd "$OLD_PWD"
done < $TOARCHIVE
if [ $VERBOSE -eq 1 ]; then
echo "done"
fi
if [ $VERBOSE -eq 1 ]; then
echo -n "concatenating archives into single archive..."
fi
# Concatenate archives into a super-archive.
if [ $SEPARATE -eq 0 -o "-" == $OUT_FILE ]; then
if [ $FORMAT == 'tar.gz' ]; then
gunzip $superfile
superfile=${superfile:0: -3} # Remove '.gz'
sed -e '1d' $TMPFILE | while read file; do
gunzip $file
file=${file:0: -3}
$TARCMD --concatenate -f "$superfile" "$file" && rm -f "$file"
done
gzip $superfile
superfile=$superfile.gz
elif [ $FORMAT == 'tar' ]; then
sed -e '1d' $TMPFILE | while read file; do
$TARCMD --concatenate -f "$superfile" "$file" && rm -f "$file"
done
elif [ $FORMAT == 'zip' ]; then
sed -e '1d' $TMPFILE | while read file; do
# zip incorrectly stores the full path, so cd and then grow
cd `dirname "$file"`
zip -g "$superfile" `basename "$file"` && rm -f "$file"
done
cd "$OLD_PWD"
fi
echo "$superfile" >| $TMPFILE # clobber on purpose
fi
if [ $VERBOSE -eq 1 ]; then
echo "done"
fi
if [ $VERBOSE -eq 1 ]; then
echo -n "moving archive to $OUT_FILE..."
fi
while read file; do
if [ "-" == $OUT_FILE ]; then
cat "$file" && rm -f "$file"
else
mv "$file" "$OUT_FILE"
fi
done < $TMPFILE
if [ $VERBOSE -eq 1 ]; then
echo "done"
fi

5
.gitignore vendored
View file

@ -10,13 +10,16 @@
!doc/*
!*.c
!*.m
!*.cc
!*.h
!*.hxx
!*.rst
!*.po
!*.in
!.cmake/Modules/*.cmake
!samples/tests/*.sh
!samples/*.expected
!samples/**/*.expected
!LICENSE
!HEADER

3
.gitmodules vendored
View file

@ -7,3 +7,6 @@
[submodule "dependencies/wingetopt"]
path = dependencies/wingetopt
url = https://github.com/alex85k/wingetopt.git
[submodule "dependencies/klib"]
path = dependencies/klib
url = https://github.com/attractivechaos/klib.git

View file

@ -1,49 +1,130 @@
language: c
os:
- linux
- osx
compiler:
- gcc-4.9
sudo: false
addons:
apt:
sources:
- ubuntu-toolchain-r-test
packages:
- gcc-4.9
- g++-4.9
env:
global:
GCOV: gcov-4.9
CXX: g++-4.9
matrix:
- CONFIGURATION=Debug COVERAGE=ON
- CONFIGURATION=Release COVERAGE=OFF
- CONFIGURATION=RelWithDebInfo COVERAGE=OFF
_anchors:
- &gcc49-packages
apt:
sources:
- ubuntu-toolchain-r-test
packages:
- gcc-4.9
- g++-4.9
- gobjc-4.9
- gnustep-devel
matrix:
include:
# Linux Debug, GCC 4.9
- compiler: gcc-4.9
addons: *gcc49-packages
env:
CONFIGURATION: Debug
GCOV: gcov-4.9
CMAKE_OPTS: -DLANG_OBJC=ON
COVERAGE: "ON"
# Linux Release, GCC 4.9
- compiler: gcc-4.9
addons: *gcc49-packages
env:
CONFIGURATION: Release
CMAKE_OPTS: -DLANG_OBJC=ON
# Linux RelWithDebInfo, GCC 4.9
- compiler: gcc-4.9
addons: *gcc49-packages
env:
CONFIGURATION: RelWithDebInfo
CMAKE_OPTS: -DLANG_OBJC=ON
DEPLOY: true
# Linux Debug, GCC 4.6
- compiler: gcc
env: CONFIGURATION=Debug TESTS=OFF
# Linux Release, GCC 4.6
- compiler: gcc
env: CONFIGURATION=Release TESTS=OFF
# Linux RelWithDebInfo, GCC 4.6
- compiler: gcc
env: CONFIGURATION=RelWithDebInfo TESTS=OFF
# OSX Debug, GCC 4.9
- os: osx
compiler: gcc-4.9
env:
CONFIGURATION: Debug
GCOV: gcov-4.9
COVERAGE: "ON"
# OSX Release, GCC 4.9
- os: osx
compiler: gcc-4.9
env: CONFIGURATION=Release
# OSX RelWithDebInfo, GCC 4.9
- os: osx
compiler: gcc-4.9
env: CONFIGURATION=RelWithDebInfo
# OSX Debug, Clang
- os: osx
compiler: clang
env:
CONFIGURATION: Debug
CMAKE_OPTS: -DLANG_OBJC=ON
# OSX Release, Clang
- os: osx
compiler: clang
env:
CONFIGURATION: Release
CMAKE_OPTS: -DLANG_OBJC=ON
# OSX RelWithDebInfo, Clang
- os: osx
compiler: clang
env:
CONFIGURATION: RelWithDebInfo
CMAKE_OPTS: -DLANG_OBJC=ON
DEPLOY: true
allow_failures:
- compiler: gcc
before_install:
- |
if [ "$TRAVIS_OS_NAME" = "osx" ] && [ "$CC" = "clang" ]; then
brew update
brew unlink cmake
brew install llvm cmake
fi
- export CXX=${CC/gcc/g++}; export CXX=${CXX/clang/clang++}
- $CC --version
- $CXX --version
script:
- mkdir -p build
- cd build
- mkdir -p build && cd $_
- >
cmake
-Wno-dev
-DCOVERALLS=${COVERAGE}
-DCTESTS=${TESTS:-ON}
-DCOVERALLS=${COVERAGE:-OFF}
-DCMAKE_BUILD_TYPE=${CONFIGURATION}
-DCMAKE_INSTALL_PREFIX=criterion-${TRAVIS_TAG}
${CMAKE_OPTS}
..
- make
- make criterion_tests
- make test
- |
if [ "${TESTS:-ON}" = "ON" ]; then
TERM=dumb cmake --build . --target criterion_tests -- -j4
ctest -j4
else
TERM=dumb cmake --build . -- -j4
fi
after_success:
- make gcov
- bash <(curl -s https://codecov.io/bash)
- |
if [ "$COVERAGE" = "ON" ]; then
make gcov
bash <(curl -s https://codecov.io/bash)
fi
after_failure:
- cat Testing/Temporary/LastTest.log samples/*.{out,err} ../samples/tests/*.{out,err}
- |
if [ "$TESTS" = "ON" ]; then
cat Testing/Temporary/LastTest.log samples/*.{out,err} ../samples/tests/*.{out,err}
fi
before_deploy:
- make install
@ -58,4 +139,4 @@ deploy:
on:
repo: Snaipe/Criterion
tags: true
condition: $CONFIGURATION = RelWithDebInfo
condition: $DEPLOY = true

View file

@ -1,25 +1,41 @@
cmake_minimum_required(VERSION 2.8)
project(Criterion C CXX)
project(Criterion C)
set(MODULE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/.cmake/Modules")
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${MODULE_DIR})
set(LIBCSPTR_DISABLE_TESTS ON)
set(LIBCSPTR_DISABLE_COVERALLS ON)
# Content options
option(THEORIES "Activate the support for theories" ON)
# Initialization
include(Submodules)
include(Capabilities)
if (MSVC)
add_definitions(-D_CRT_SECURE_NO_WARNINGS=1)
endif ()
add_subdirectory(dependencies/libcsptr/ EXCLUDE_FROM_ALL)
add_subdirectory(dependencies/dyncall/ EXCLUDE_FROM_ALL)
if (THEORIES)
add_subdirectory(dependencies/dyncall/ EXCLUDE_FROM_ALL)
include_directories(dependencies/dyncall/dyncall/)
endif ()
include_directories(SYSTEM
/usr/local/include
/usr/include/GNUstep
)
include_directories(
/usr/local/include/
dependencies/libcsptr/include/
dependencies/dyncall/dyncall/
dependencies/valgrind/include/
dependencies/klib/
)
if (MSVC)
@ -27,17 +43,45 @@ if (MSVC)
include_directories(dependencies/wingetopt/src/)
endif ()
# Check for C++11
option(LANG_CXX "Turn on C++ support" ON)
if (LANG_CXX)
enable_language(CXX)
endif ()
if (NOT MSVC AND CMAKE_CXX_COMPILER_WORKS)
include(CheckCXXCompilerFlag)
CHECK_CXX_COMPILER_FLAG("-std=c++11" COMPILER_SUPPORTS_CXX11)
CHECK_CXX_COMPILER_FLAG("-std=c++0x" COMPILER_SUPPORTS_CXX0X)
if(COMPILER_SUPPORTS_CXX11)
set(CXX11_FLAG "-std=c++11")
elseif(COMPILER_SUPPORTS_CXX0X)
set(CXX11_FLAG "-std=c++0x")
else()
message(FATAL_ERROR "Compiler ${CMAKE_CXX_COMPILER} has no C++11 support.")
endif()
endif()
# Project setup & environment variables
set(PROJECT_VERSION "2.1.0")
set(LOCALEDIR ${CMAKE_INSTALL_PREFIX}/share/locale)
set(PROJECT_VERSION "2.2.0")
set(LOCALEDIR_REL "share/locale")
set(LOCALEDIR "${CMAKE_INSTALL_PREFIX}/${LOCALEDIR_REL}")
set(GettextTranslate_ALL 1)
set(GettextTranslate_GMO_BINARY 1)
add_definitions(-DCRITERION_BUILDING_DLL=1)
set(CMAKE_C_FLAGS_DEFAULT "${CMAKE_C_FLAGS}")
set(CMAKE_CXX_FLAGS_DEFAULT "${CMAKE_CXX_FLAGS}")
if (NOT MSVC)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wextra -Werror -g -std=gnu99")
if (CMAKE_CXX_COMPILER_WORKS)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra -Werror -g ${CXX11_FLAG}")
endif ()
endif ()
if (MSVC)
@ -48,10 +92,20 @@ if (WIN32 AND NOT MSVC)
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Wl,-no-undefined")
endif()
# Compilation options
option(MINGW_DEFINE_OFF_T "Define off_t and off64_t ourselves before including io.h" OFF)
# Setup coveralls
option(COVERALLS "Turn on coveralls support" OFF)
option(COVERALLS_UPLOAD "Upload the generated coveralls json" ON)
option(DEV_BUILD "Compile in developer mode" OFF)
option(CTESTS "Turn on the samples and test" ${DEV_BUILD})
if (DEV_BUILD)
set(ENABLE_VALGRIND_ERRORS 1)
endif ()
if (COVERALLS)
include(Coveralls)
@ -60,12 +114,16 @@ endif()
# Find dependencies
find_package(Gettext)
find_package(Libintl)
if (GETTEXT_FOUND AND LIBINTL_LIB_FOUND)
include(GettextTranslate)
add_subdirectory(po)
set(ENABLE_NLS 1)
option(I18N "Turn on internationalization" ON)
if (I18N)
find_package(Gettext)
find_package(Libintl)
if (GETTEXT_FOUND AND LIBINTL_LIB_FOUND)
include(GettextTranslate)
add_subdirectory(po)
set(ENABLE_NLS 1)
endif ()
endif ()
include(CheckLibraryExists)
@ -82,15 +140,19 @@ set(SOURCE_FILES
src/core/report.h
src/core/runner.c
src/core/runner.h
src/core/runner_coroutine.c
src/core/runner_coroutine.h
src/core/coroutine.h
src/core/worker.c
src/core/worker.h
src/core/stats.c
src/core/stats.h
src/core/ordered-set.c
src/core/theories.c
src/core/test.c
src/compat/internal.h
src/compat/pipe.c
src/compat/pipe.h
src/compat/pipe-internal.h
src/compat/section.c
src/compat/section.h
src/compat/process.c
@ -103,21 +165,35 @@ set(SOURCE_FILES
src/compat/posix.h
src/compat/alloc.c
src/compat/alloc.h
src/compat/processor.c
src/compat/processor.h
src/io/redirect.c
src/io/event.c
src/io/event.h
src/io/asprintf.c
src/io/file.c
src/io/output.c
src/io/output.h
src/io/tap.c
src/io/xml.c
src/io/json.c
src/log/logging.c
src/log/tap.c
src/log/normal.c
src/string/i18n.c
src/string/i18n.h
src/entry/options.c
src/entry/main.c
src/entry/params.c
src/entry/entry.c
src/common.h
src/config.h
)
if (THEORIES)
set (SOURCE_FILES ${SOURCE_FILES}
src/core/theories.c
)
endif ()
if (PCRE_FOUND)
set (SOURCE_FILES ${SOURCE_FILES}
src/string/extmatch.c
@ -129,22 +205,39 @@ endif ()
set(INTERFACE_FILES
include/criterion/assert.h
include/criterion/abort.h
include/criterion/common.h
include/criterion/criterion.h
include/criterion/event.h
include/criterion/hooks.h
include/criterion/logging.h
include/criterion/types.h
include/criterion/options.h
include/criterion/ordered-set.h
include/criterion/stats.h
include/criterion/theories.h
include/criterion/asprintf-compat.h
include/criterion/designated-initializer-compat.h
include/criterion/preprocess.h
include/criterion/alloc.h
include/criterion/parameterized.h
include/criterion/redirect.h
include/criterion/output.h
include/criterion/internal/assert.h
include/criterion/internal/test.h
include/criterion/internal/common.h
include/criterion/internal/ordered-set.h
include/criterion/internal/asprintf-compat.h
include/criterion/internal/designated-initializer-compat.h
include/criterion/internal/preprocess.h
include/criterion/internal/parameterized.h
include/criterion/internal/stdio_filebuf.hxx
include/criterion/internal/stream.hxx
include/criterion/internal/hooks.h
include/criterion/internal/redirect.h
include/criterion/internal/stdio_filebuf.hxx
)
if (THEORIES)
set(INTERFACE_FILES ${INTERFACE_FILES}
include/criterion/theories.h
include/criterion/internal/theories.h
)
endif()
# Generate the configure file
configure_file(
@ -154,7 +247,11 @@ configure_file(
include_directories(include src)
add_library(criterion SHARED ${SOURCE_FILES} ${INTERFACE_FILES})
target_link_libraries(criterion csptr dyncall_s)
target_link_libraries(criterion csptr)
if (THEORIES)
target_link_libraries(criterion dyncall_s)
endif ()
if (MSVC)
target_link_libraries(criterion wingetopt)
@ -170,17 +267,22 @@ endif()
if (LIBINTL_LIB_FOUND)
target_link_libraries(criterion ${LIBINTL_LIBRARIES})
include_directories(${LIBINTL_INCLUDE_DIR})
endif()
if (COVERALLS)
coveralls_setup("${SOURCE_FILES}" ${COVERALLS_UPLOAD})
endif()
install(FILES ${INTERFACE_FILES} DESTINATION include/criterion)
foreach (F ${INTERFACE_FILES})
get_filename_component(DEST "${F}" PATH)
install(FILES "${F}" DESTINATION "${DEST}" COMPONENT dev)
endforeach ()
install(TARGETS criterion
RUNTIME DESTINATION bin
LIBRARY DESTINATION lib
ARCHIVE DESTINATION lib
ARCHIVE DESTINATION lib COMPONENT dev
)
add_custom_target(criterion_tests)
@ -192,6 +294,19 @@ add_custom_target(gcov
-P "${CMAKE_MODULE_PATH}/Gcov.cmake"
)
if (CTESTS)
enable_testing()
add_subdirectory(samples)
add_subdirectory(test)
endif ()
# Add toolchain patch number for incremental deb builds
set(PROJECT_VERSION "${PROJECT_VERSION}-6")
include (PackageConfig)
option(UPLOAD_DEB "Upload package to launchpad" OFF)
if (UNIX AND UPLOAD_DEB)
include (DebConfig)
endif ()

View file

@ -1,3 +1,38 @@
2015-12-08 Franklin "Snaipe" Mathieu <franklinmathieu@gmail.com>
* criterion: version 2.2.0
* Breaking: Renamed all unprefixed internal macros and functions that were
exposed in the API, and moved them to criterion/internal.
This shouldn't break your code if you did not use these in the first
place.
* Change: Added language-specific wrapping logic to decouple the language
the tests are written in from the test runner.
* Change: Rewrote the reporting logic to allow multiple test reports to be
written using any format.
* Addition: Added parallel jobs for the test runner.
* Addition: Added C++ allocator for STL collections based on
cr_malloc/cr_free.
* Addition: Added criterion::parameters in C++ for simpler parameter list
generation.
* Addition: Added saner defaults when the tests detect they run under
valgrind.
* Addition: Added basic Objective-C language support.
* Addition: Added JUnit XML reporting.
* Addition: Added JSON reporting.
* Addition: Added dynamic reporter registration.
* Addition: Added back support for GCC 4.6 when compiling C tests.
* Addition: Added single test execution mode.
* Removal: Removed all deprecated 1.x unprefixed assertion macros.
* Fix: Fixed some memory corruption happening on rare occasions on assert
messages.
* Fix: Fixed deadlocks happening at random when a large quantity of assert
is present.
* Fix: Fixed the library not compiling with the intel compiler collection.
* Deprecation: All cr_assume_strings_* macros are deprecated in favor of
cr_assume_str_*.
* Deprecation: All cr_assume_arrays_* macros are deprecated in favor of
cr_assume_arr_*.
2015-11-25 Franklin "Snaipe" Mathieu <franklinmathieu@gmail.com>
* criterion: version 2.1.1

View file

@ -8,6 +8,8 @@
[![License](https://img.shields.io/badge/license-MIT-blue.svg?style=flat)](https://github.com/Snaipe/Criterion/blob/master/LICENSE)
[![Version](https://img.shields.io/github/tag/Snaipe/Criterion.svg?label=version&style=flat)](https://github.com/Snaipe/Criterion/releases)
![Analytics](https://ga-beacon.appspot.com/UA-68371536-1/Criterion/README.md?pixel)
A dead-simple, yet extensible, C and C++ unit testing framework.
![Screencast](./doc/screencast.gif)
@ -39,10 +41,19 @@ the user would have with other frameworks:
## Downloads
* [Linux (x86_64)](https://github.com/Snaipe/Criterion/releases/download/v2.1.0/criterion-v2.1.0-linux-x86_64.tar.bz2)
* [OS X (x86_64)](https://github.com/Snaipe/Criterion/releases/download/v2.1.0/criterion-v2.1.0-osx-x86_64.tar.bz2)
* [Windows (MSVC - x86_64)](https://github.com/Snaipe/Criterion/releases/download/v2.1.0/criterion-v2.1.0-windows-msvc-x86_64.tar.bz2)
* [Windows (MinGW - x86_64)](https://github.com/Snaipe/Criterion/releases/download/v2.1.0/criterion-v2.1.0-windows-mingw-x86_64.tar.bz2)
### Packages
* Mac OS X: `brew install snaipe/soft/criterion`
* [AUR](https://aur.archlinux.org/packages/criterion/): `yaourt -S criterion`
### Binary archives
* [Linux (x86_64)](https://github.com/Snaipe/Criterion/releases/download/v2.2.0/criterion-v2.2.0-linux-x86_64.tar.bz2)
* [OS X (x86_64)](https://github.com/Snaipe/Criterion/releases/download/v2.2.0/criterion-v2.2.0-osx-x86_64.tar.bz2)
* [Windows (MSVC - x86_64)](https://github.com/Snaipe/Criterion/releases/download/v2.2.0/criterion-v2.2.0-windows-msvc-x86_64.tar.bz2)
* [Windows (MinGW - x86_64)](https://github.com/Snaipe/Criterion/releases/download/v2.2.0/criterion-v2.2.0-windows-mingw-x86_64.tar.bz2)
[comment]: # (Don't forget to change x86_64 to x64 on windows links on the next release)
If you have a different platform, you can still [build the library from source](http://criterion.readthedocs.org/en/latest/setup.html#installation)
@ -66,27 +77,13 @@ Sample tests can be found in the [sample directory][samples].
### Getting help
Gitter.im chat room: [![Join the chat at https://gitter.im/Snaipe/Criterion](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/Snaipe/Criterion?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
Gitter.im chat room: [![Join the chat at https://gitter.im/Snaipe/Criterion](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/Snaipe/Criterion?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
IRC channel: [#criterion][irc-chan] on irc.freenode.net
### Misc
* [CMake find module for Criterion][find-module]
## F.A.Q.
**Q. What's wrong with other C test frameworks?**
A. I worked with CUnit and Check, and I must say that they do their job
very well -- the only thing that bugs me is that setting up a test
suite from scratch is a pain, it should really be simpler. Most
(if not all) high-level languages have test frameworks with automatic
test registration, but all the ones for C require you to set up a
main, manually register suites, then tests. Criterion tries to
fix these shortcomings.
**Q. Where has this been tested?**
A. Currently, on Linux 2.6.32 and Linux 3.15.7, although it should work on
most \*nix systems; Mac OS X Yosemite 10.10, FreeBSD 10.0, Windows 7 and 2K.
## Credits
Logo done by [Greehm](http://www.cargocollective.com/pbouigue)
@ -105,3 +102,5 @@ Logo done by [Greehm](http://www.cargocollective.com/pbouigue)
[sample-report]: ./samples/report.c
[find-module]: ./dev/FindCriterion.cmake
[irc-chan]: http://webchat.freenode.net/?channels=%23criterion&uio=MTY9dHJ1ZSYyPXRydWUmOT10cnVlJjExPTE5NQ4e

View file

@ -1,4 +1,4 @@
version: 2.1.0_b{build}-{branch}
version: 2.2.0_b{build}-{branch}
os: Visual Studio 2015
@ -15,14 +15,17 @@ environment:
matrix:
- COMPILER: mingw
GENERATOR: "MSYS Makefiles"
CXXFLAGS: -D__NO_INLINE__
- COMPILER: msvc
GENERATOR: "Visual Studio 14 2015"
CFLAGS: /MP
CXXFLAGS: /MP
clone_depth: 5
platform:
- x86
- x86_64
- x64
configuration:
- Debug
@ -38,8 +41,11 @@ install:
- >
cmake
-Wno-dev
-DCTESTS=ON
-DI18N=OFF
-DCMAKE_INSTALL_PREFIX="criterion-%RELEASE_NAME%"
-DCMAKE_BUILD_TYPE="%CONFIGURATION%"
%CMAKE_OPTS%
-G "%GENERATOR%"
..
@ -56,7 +62,11 @@ before_deploy:
test_script:
- cmake --build . --target criterion_tests
- ps: try { ctest } catch { type Testing/Temporary/LastTest.log }
- ps: |
ctest -j2
if (-not $lastexitcode -eq 0) {
type Testing/Temporary/LastTest.log
}
#after_test:
# - 'make coveralls'

25
debian.copyright Normal file
View file

@ -0,0 +1,25 @@
Format: http://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
Upstream-Name: Criterion
Upstream-Contact: Franklin "Snaipe" Mathieu <franklinmathieu@gmail.com>
Source: http://github.com/Snaipe/Criterion
Files: *
Copyright: 2015, Franklin "Snaipe" Mathieu <franklinmathieu@gmail.com>
License: MIT
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
.
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

@ -1 +1 @@
Subproject commit 68c57f664d4fabbc5b80327fbf5661a3a5a51e06
Subproject commit 180a5b77ff95a17991afdc6e9be3501eca99ad36

1
dependencies/klib vendored Submodule

@ -0,0 +1 @@
Subproject commit cdb7e9236dc47abf8da7ebd702cc6f7f21f0c502

@ -1 +1 @@
Subproject commit 2762164acfaa712fea7dec6ed760ff88f7d2e026
Subproject commit 0d52904da5d7bd0a3eac3c47e9f9bb10cd78a26e

File diff suppressed because it is too large Load diff

23
description.txt Normal file
View file

@ -0,0 +1,23 @@
Criterion is a dead-simple, yet extensible, C and C++ unit testing framework.
Most test frameworks for C require a lot of boilerplate code to
set up tests and test suites -- you need to create a main,
then register new test suites, then register the tests within
these suits, and finally call the right functions.
This gives the user great control, at the unfortunate cost of simplicity.
Criterion follows the KISS principle, while keeping the control
the user would have with other frameworks:
* C99 and C++11 compatible.
* Tests are automatically registered when declared.
* Implements a xUnit framework structure.
* A default entry point is provided, no need to declare a main
unless you want to do special handling.
* Test are isolated in their own process, crashes and signals can be
reported and tested.
* Unified interface between C and C++: include the criterion header and it *just* works.
* Supports parameterized tests and theories.
* Progress and statistics can be followed in real time with report hooks.
* TAP output format can be enabled with an option.

View file

@ -9,36 +9,39 @@ As each ``assert`` macros have an ``expect`` counterpart with the exact same
number of parameters and name suffix, there is no benefit in adding ``expect``
macros to this list. Hence only ``assert`` macros are represented here.
All ``assert`` macros may take an optional ``printf`` format string and
parameters.
Common Assertions
-----------------
======================================================================= =========================================================================== ===========================================
Macro Passes if and only if Notes
======================================================================= =========================================================================== ===========================================
cr_assert(Condition, [Message, [Args...]]) ``Condition`` is true.
----------------------------------------------------------------------- --------------------------------------------------------------------------- -------------------------------------------
cr_assert_not(Condition, [Message, [Args...]]) ``Condition`` is false.
----------------------------------------------------------------------- --------------------------------------------------------------------------- -------------------------------------------
cr_assert_null(Value, [Message, [Args...]]) ``Value`` is ``NULL``.
----------------------------------------------------------------------- --------------------------------------------------------------------------- -------------------------------------------
cr_assert_not_null(Value, [Message, [Args...]]) ``Value`` is not ``NULL``.
----------------------------------------------------------------------- --------------------------------------------------------------------------- -------------------------------------------
cr_assert_eq(Actual, Expected, [Message, [Args...]]) ``Actual`` is equal to ``Expected``. Compatible with C++ operator overloading
----------------------------------------------------------------------- --------------------------------------------------------------------------- -------------------------------------------
cr_assert_neq(Actual, Unexpected, [Message, [Args...]]) ``Actual`` is not equal to ``Unexpected``. Compatible with C++ operator overloading
----------------------------------------------------------------------- --------------------------------------------------------------------------- -------------------------------------------
cr_assert_lt(Actual, Reference, [Message, [Args...]]) ``Actual`` is less than ``Reference``. Compatible with C++ operator overloading
----------------------------------------------------------------------- --------------------------------------------------------------------------- -------------------------------------------
cr_assert_leq(Actual, Reference, [Message, [Args...]]) ``Actual`` is less or equal to ``Reference``. Compatible with C++ operator overloading
----------------------------------------------------------------------- --------------------------------------------------------------------------- -------------------------------------------
cr_assert_gt(Actual, Reference, [Message, [Args...]]) ``Actual`` is greater than ``Reference``. Compatible with C++ operator overloading
----------------------------------------------------------------------- --------------------------------------------------------------------------- -------------------------------------------
cr_assert_geq(Actual, Reference, [Message, [Args...]]) ``Actual`` is greater or equal to ``Reference``. Compatible with C++ operator overloading
----------------------------------------------------------------------- --------------------------------------------------------------------------- -------------------------------------------
cr_assert_float_eq(Actual, Expected, Epsilon, [Message, [Args...]]) ``Actual`` is equal to ``Expected`` with a tolerance of ``Epsilon``. Use this to test equality between floats
----------------------------------------------------------------------- --------------------------------------------------------------------------- -------------------------------------------
cr_assert_float_neq(Actual, Unexpected, Epsilon, [Message, [Args...]]) ``Actual`` is not equal to ``Unexpected`` with a tolerance of ``Epsilon``. Use this to test inequality between floats
======================================================================= =========================================================================== ===========================================
=========================================================================== =========================================================================== ===========================================
Macro Passes if and only if Notes
=========================================================================== =========================================================================== ===========================================
cr_assert(Condition, [FormatString, [Args...]]) ``Condition`` is true.
--------------------------------------------------------------------------- --------------------------------------------------------------------------- -------------------------------------------
cr_assert_not(Condition, [FormatString, [Args...]]) ``Condition`` is false.
--------------------------------------------------------------------------- --------------------------------------------------------------------------- -------------------------------------------
cr_assert_null(Value, [FormatString, [Args...]]) ``Value`` is ``NULL``.
--------------------------------------------------------------------------- --------------------------------------------------------------------------- -------------------------------------------
cr_assert_not_null(Value, [FormatString, [Args...]]) ``Value`` is not ``NULL``.
--------------------------------------------------------------------------- --------------------------------------------------------------------------- -------------------------------------------
cr_assert_eq(Actual, Expected, [FormatString, [Args...]]) ``Actual`` is equal to ``Expected``. Compatible with C++ operator overloading
--------------------------------------------------------------------------- --------------------------------------------------------------------------- -------------------------------------------
cr_assert_neq(Actual, Unexpected, [FormatString, [Args...]]) ``Actual`` is not equal to ``Unexpected``. Compatible with C++ operator overloading
--------------------------------------------------------------------------- --------------------------------------------------------------------------- -------------------------------------------
cr_assert_lt(Actual, Reference, [FormatString, [Args...]]) ``Actual`` is less than ``Reference``. Compatible with C++ operator overloading
--------------------------------------------------------------------------- --------------------------------------------------------------------------- -------------------------------------------
cr_assert_leq(Actual, Reference, [FormatString, [Args...]]) ``Actual`` is less or equal to ``Reference``. Compatible with C++ operator overloading
--------------------------------------------------------------------------- --------------------------------------------------------------------------- -------------------------------------------
cr_assert_gt(Actual, Reference, [FormatString, [Args...]]) ``Actual`` is greater than ``Reference``. Compatible with C++ operator overloading
--------------------------------------------------------------------------- --------------------------------------------------------------------------- -------------------------------------------
cr_assert_geq(Actual, Reference, [FormatString, [Args...]]) ``Actual`` is greater or equal to ``Reference``. Compatible with C++ operator overloading
--------------------------------------------------------------------------- --------------------------------------------------------------------------- -------------------------------------------
cr_assert_float_eq(Actual, Expected, Epsilon, [FormatString, [Args...]]) ``Actual`` is equal to ``Expected`` with a tolerance of ``Epsilon``. Use this to test equality between floats
--------------------------------------------------------------------------- --------------------------------------------------------------------------- -------------------------------------------
cr_assert_float_neq(Actual, Unexpected, Epsilon, [FormatString, [Args...]]) ``Actual`` is not equal to ``Unexpected`` with a tolerance of ``Epsilon``. Use this to test inequality between floats
=========================================================================== =========================================================================== ===========================================
String Assertions
-----------------
@ -47,98 +50,98 @@ Note: these macros are meant to deal with *native* strings, i.e. char arrays.
Most of them won't work on ``std::string`` in C++, with some exceptions -- for
``std::string``, you should use regular comparison assersions, as listed above.
=========================================================== =================================================================== ===========================================
Macro Passes if and only if Notes
=========================================================== =================================================================== ===========================================
cr_assert_str_empty(Value, [Message, [Args...]]) ``Value`` is an empty string. Also works on std::string
----------------------------------------------------------- ------------------------------------------------------------------- -------------------------------------------
cr_assert_str_not_empty(Value, [Message, [Args...]]) ``Value`` is not an empty string. Also works on std::string
----------------------------------------------------------- ------------------------------------------------------------------- -------------------------------------------
cr_assert_str_eq(Actual, Expected, [Message, [Args...]]) ``Actual`` is lexicographically equal to ``Expected``.
----------------------------------------------------------- ------------------------------------------------------------------- -------------------------------------------
cr_assert_str_neq(Actual, Unexpected, [Message, [Args...]]) ``Actual`` is not lexicographically equal to ``Unexpected``.
----------------------------------------------------------- ------------------------------------------------------------------- -------------------------------------------
cr_assert_str_lt(Actual, Reference, [Message, [Args...]]) ``Actual`` is lexicographically less than ``Reference``.
----------------------------------------------------------- ------------------------------------------------------------------- -------------------------------------------
cr_assert_str_leq(Actual, Reference, [Message, [Args...]]) ``Actual`` is lexicographically less or equal to ``Reference``.
----------------------------------------------------------- ------------------------------------------------------------------- -------------------------------------------
cr_assert_str_gt(Actual, Reference, [Message, [Args...]]) ``Actual`` is lexicographically greater than ``Reference``.
----------------------------------------------------------- ------------------------------------------------------------------- -------------------------------------------
cr_assert_str_geq(Actual, Reference, [Message, [Args...]]) ``Actual`` is lexicographically greater or equal to ``Reference``.
=========================================================== =================================================================== ===========================================
================================================================ =================================================================== ===========================================
Macro Passes if and only if Notes
================================================================ =================================================================== ===========================================
cr_assert_str_empty(Value, [FormatString, [Args...]]) ``Value`` is an empty string. Also works on std::string
---------------------------------------------------------------- ------------------------------------------------------------------- -------------------------------------------
cr_assert_str_not_empty(Value, [FormatString, [Args...]]) ``Value`` is not an empty string. Also works on std::string
---------------------------------------------------------------- ------------------------------------------------------------------- -------------------------------------------
cr_assert_str_eq(Actual, Expected, [FormatString, [Args...]]) ``Actual`` is lexicographically equal to ``Expected``.
---------------------------------------------------------------- ------------------------------------------------------------------- -------------------------------------------
cr_assert_str_neq(Actual, Unexpected, [FormatString, [Args...]]) ``Actual`` is not lexicographically equal to ``Unexpected``.
---------------------------------------------------------------- ------------------------------------------------------------------- -------------------------------------------
cr_assert_str_lt(Actual, Reference, [FormatString, [Args...]]) ``Actual`` is lexicographically less than ``Reference``.
---------------------------------------------------------------- ------------------------------------------------------------------- -------------------------------------------
cr_assert_str_leq(Actual, Reference, [FormatString, [Args...]]) ``Actual`` is lexicographically less or equal to ``Reference``.
---------------------------------------------------------------- ------------------------------------------------------------------- -------------------------------------------
cr_assert_str_gt(Actual, Reference, [FormatString, [Args...]]) ``Actual`` is lexicographically greater than ``Reference``.
---------------------------------------------------------------- ------------------------------------------------------------------- -------------------------------------------
cr_assert_str_geq(Actual, Reference, [FormatString, [Args...]]) ``Actual`` is lexicographically greater or equal to ``Reference``.
================================================================ =================================================================== ===========================================
Array Assertions
-----------------
=========================================================================== =========================================================================== ===========================================
Macro Passes if and only if Notes
=========================================================================== =========================================================================== ===========================================
cr_assert_arr_eq(Actual, Expected, [Message, [Args...]]) ``Actual`` is byte-to-byte equal to ``Expected``. This should not be used on struct arrays,
consider using ``cr_assert_arr_eq_cmp``
instead.
--------------------------------------------------------------------------- --------------------------------------------------------------------------- -------------------------------------------
cr_assert_arr_neq(Actual, Unexpected, [Message, [Args...]]) ``Actual`` is not byte-to-byte equal to ``Unexpected``. This should not be used on struct arrays,
consider using ``cr_assert_arr_neq_cmp``
instead.
--------------------------------------------------------------------------- --------------------------------------------------------------------------- -------------------------------------------
cr_assert_arr_eq_cmp(Actual, Expected, Size, Cmp, [Message, [Args...]]) ``Actual`` is comparatively equal to ``Expected`` Only available in C++ and GNU C99
--------------------------------------------------------------------------- --------------------------------------------------------------------------- -------------------------------------------
cr_assert_arr_neq_cmp(Actual, Unexpected, Size, Cmp, [Message, [Args...]]) ``Actual`` is not comparatively equal to ``Expected`` Only available in C++ and GNU C99
--------------------------------------------------------------------------- --------------------------------------------------------------------------- -------------------------------------------
cr_assert_arr_lt_cmp(Actual, Reference, Size, Cmp, [Message, [Args...]]) ``Actual`` is comparatively less than ``Reference`` Only available in C++ and GNU C99
--------------------------------------------------------------------------- --------------------------------------------------------------------------- -------------------------------------------
cr_assert_arr_leq_cmp(Actual, Reference, Size, Cmp, [Message, [Args...]]) ``Actual`` is comparatively less or equal to ``Reference`` Only available in C++ and GNU C99
--------------------------------------------------------------------------- --------------------------------------------------------------------------- -------------------------------------------
cr_assert_arr_gt_cmp(Actual, Reference, Size, Cmp, [Message, [Args...]]) ``Actual`` is comparatively greater than ``Reference`` Only available in C++ and GNU C99
--------------------------------------------------------------------------- --------------------------------------------------------------------------- -------------------------------------------
cr_assert_arr_geq_cmp(Actual, Reference, Size, Cmp, [Message, [Args...]]) ``Actual`` is comparatively greater or equal to ``Reference`` Only available in C++ and GNU C99
=========================================================================== =========================================================================== ===========================================
=============================================================================== =========================================================================== ===========================================
Macro Passes if and only if Notes
=============================================================================== =========================================================================== ===========================================
cr_assert_arr_eq(Actual, Expected, [FormatString, [Args...]]) ``Actual`` is byte-to-byte equal to ``Expected``. This should not be used on struct arrays,
consider using ``cr_assert_arr_eq_cmp``
instead.
------------------------------------------------------------------------------- --------------------------------------------------------------------------- -------------------------------------------
cr_assert_arr_neq(Actual, Unexpected, [FormatString, [Args...]]) ``Actual`` is not byte-to-byte equal to ``Unexpected``. This should not be used on struct arrays,
consider using ``cr_assert_arr_neq_cmp``
instead.
------------------------------------------------------------------------------- --------------------------------------------------------------------------- -------------------------------------------
cr_assert_arr_eq_cmp(Actual, Expected, Size, Cmp, [FormatString, [Args...]]) ``Actual`` is comparatively equal to ``Expected`` Only available in C++ and GNU C99
------------------------------------------------------------------------------- --------------------------------------------------------------------------- -------------------------------------------
cr_assert_arr_neq_cmp(Actual, Unexpected, Size, Cmp, [FormatString, [Args...]]) ``Actual`` is not comparatively equal to ``Expected`` Only available in C++ and GNU C99
------------------------------------------------------------------------------- --------------------------------------------------------------------------- -------------------------------------------
cr_assert_arr_lt_cmp(Actual, Reference, Size, Cmp, [FormatString, [Args...]]) ``Actual`` is comparatively less than ``Reference`` Only available in C++ and GNU C99
------------------------------------------------------------------------------- --------------------------------------------------------------------------- -------------------------------------------
cr_assert_arr_leq_cmp(Actual, Reference, Size, Cmp, [FormatString, [Args...]]) ``Actual`` is comparatively less or equal to ``Reference`` Only available in C++ and GNU C99
------------------------------------------------------------------------------- --------------------------------------------------------------------------- -------------------------------------------
cr_assert_arr_gt_cmp(Actual, Reference, Size, Cmp, [FormatString, [Args...]]) ``Actual`` is comparatively greater than ``Reference`` Only available in C++ and GNU C99
------------------------------------------------------------------------------- --------------------------------------------------------------------------- -------------------------------------------
cr_assert_arr_geq_cmp(Actual, Reference, Size, Cmp, [FormatString, [Args...]]) ``Actual`` is comparatively greater or equal to ``Reference`` Only available in C++ and GNU C99
=============================================================================== =========================================================================== ===========================================
Exception Assertions
--------------------
The following assertion macros are only defined for C++.
=========================================================================== =========================================================================== ===========================================
Macro Passes if and only if Notes
=========================================================================== =========================================================================== ===========================================
cr_assert_throw(Statement, Exception, [Message, [Args...]]) ``Statement`` throws an instance of ``Exception``.
--------------------------------------------------------------------------- --------------------------------------------------------------------------- -------------------------------------------
cr_assert_no_throw(Statement, Exception, [Message, [Args...]]) ``Statement`` does not throws an instance of ``Exception``.
--------------------------------------------------------------------------- --------------------------------------------------------------------------- -------------------------------------------
cr_assert_any_throw(Statement, [Message, [Args...]]) ``Statement`` throws any kind of exception.
--------------------------------------------------------------------------- --------------------------------------------------------------------------- -------------------------------------------
cr_assert_none_throw(Statement, [Message, [Args...]]) ``Statement`` does not throw any exception.
=========================================================================== =========================================================================== ===========================================
=============================================================================== =========================================================================== ===========================================
Macro Passes if and only if Notes
=============================================================================== =========================================================================== ===========================================
cr_assert_throw(Statement, Exception, [FormatString, [Args...]]) ``Statement`` throws an instance of ``Exception``.
------------------------------------------------------------------------------- --------------------------------------------------------------------------- -------------------------------------------
cr_assert_no_throw(Statement, Exception, [FormatString, [Args...]]) ``Statement`` does not throws an instance of ``Exception``.
------------------------------------------------------------------------------- --------------------------------------------------------------------------- -------------------------------------------
cr_assert_any_throw(Statement, [FormatString, [Args...]]) ``Statement`` throws any kind of exception.
------------------------------------------------------------------------------- --------------------------------------------------------------------------- -------------------------------------------
cr_assert_none_throw(Statement, [FormatString, [Args...]]) ``Statement`` does not throw any exception.
=============================================================================== =========================================================================== ===========================================
File Assertions
---------------
=============================================================================== ============================================================================ ===========================================
Macro Passes if and only if Notes
=============================================================================== ============================================================================ ===========================================
cr_assert_file_contents_eq_str(File, ExpectedContents, [Message, [Args...]]) The contents of ``File`` are equal to the string ``ExpectedContents``.
------------------------------------------------------------------------------- ---------------------------------------------------------------------------- -------------------------------------------
cr_assert_file_contents_neq_str(File, ExpectedContents, [Message, [Args...]]) The contents of ``File`` are not equal to the string ``ExpectedContents``.
------------------------------------------------------------------------------- ---------------------------------------------------------------------------- -------------------------------------------
cr_assert_stdout_eq_str(ExpectedContents, [Message, [Args...]]) The contents of ``stdout`` are equal to the string ``ExpectedContents``.
------------------------------------------------------------------------------- ---------------------------------------------------------------------------- -------------------------------------------
cr_assert_stdout_neq_str(ExpectedContents, [Message, [Args...]]) The contents of ``stdout`` are not equal to the string ``ExpectedContents``.
------------------------------------------------------------------------------- ---------------------------------------------------------------------------- -------------------------------------------
cr_assert_stderr_eq_str(ExpectedContents, [Message, [Args...]]) The contents of ``stderr`` are equal to the string ``ExpectedContents``.
------------------------------------------------------------------------------- ---------------------------------------------------------------------------- -------------------------------------------
cr_assert_stderr_neq_str(ExpectedContents, [Message, [Args...]]) The contents of ``stderr`` are not equal to the string ``ExpectedContents``.
------------------------------------------------------------------------------- ---------------------------------------------------------------------------- -------------------------------------------
cr_assert_file_contents_eq(File, RefFile, [Message, [Args...]]) The contents of ``File`` are equal to the contents of ``RefFile``.
------------------------------------------------------------------------------- ---------------------------------------------------------------------------- -------------------------------------------
cr_assert_file_contents_neq(File, RefFile, [Message, [Args...]]) The contents of ``File`` are not equal to the contents of ``RefFile``.
------------------------------------------------------------------------------- ---------------------------------------------------------------------------- -------------------------------------------
cr_assert_stdout_eq(RefFile, [Message, [Args...]]) The contents of ``stdout`` are equal to the contents of ``RefFile``.
------------------------------------------------------------------------------- ---------------------------------------------------------------------------- -------------------------------------------
cr_assert_stdout_neq(RefFile, [Message, [Args...]]) The contents of ``stdout`` are not equal to the contents of ``RefFile``.
------------------------------------------------------------------------------- ---------------------------------------------------------------------------- -------------------------------------------
cr_assert_stderr_eq(RefFile, [Message, [Args...]]) The contents of ``stderr`` are equal to the contents of ``RefFile``.
------------------------------------------------------------------------------- ---------------------------------------------------------------------------- -------------------------------------------
cr_assert_stderr_neq(RefFile, [Message, [Args...]]) The contents of ``stderr`` are not equal to the contents of ``RefFile``.
=============================================================================== ============================================================================ ===========================================
=================================================================================== ============================================================================ ===========================================
Macro Passes if and only if Notes
=================================================================================== ============================================================================ ===========================================
cr_assert_file_contents_eq_str(File, ExpectedContents, [FormatString, [Args...]]) The contents of ``File`` are equal to the string ``ExpectedContents``.
----------------------------------------------------------------------------------- ---------------------------------------------------------------------------- -------------------------------------------
cr_assert_file_contents_neq_str(File, ExpectedContents, [FormatString, [Args...]]) The contents of ``File`` are not equal to the string ``ExpectedContents``.
----------------------------------------------------------------------------------- ---------------------------------------------------------------------------- -------------------------------------------
cr_assert_stdout_eq_str(ExpectedContents, [FormatString, [Args...]]) The contents of ``stdout`` are equal to the string ``ExpectedContents``.
----------------------------------------------------------------------------------- ---------------------------------------------------------------------------- -------------------------------------------
cr_assert_stdout_neq_str(ExpectedContents, [FormatString, [Args...]]) The contents of ``stdout`` are not equal to the string ``ExpectedContents``.
----------------------------------------------------------------------------------- ---------------------------------------------------------------------------- -------------------------------------------
cr_assert_stderr_eq_str(ExpectedContents, [FormatString, [Args...]]) The contents of ``stderr`` are equal to the string ``ExpectedContents``.
----------------------------------------------------------------------------------- ---------------------------------------------------------------------------- -------------------------------------------
cr_assert_stderr_neq_str(ExpectedContents, [FormatString, [Args...]]) The contents of ``stderr`` are not equal to the string ``ExpectedContents``.
----------------------------------------------------------------------------------- ---------------------------------------------------------------------------- -------------------------------------------
cr_assert_file_contents_eq(File, RefFile, [FormatString, [Args...]]) The contents of ``File`` are equal to the contents of ``RefFile``.
----------------------------------------------------------------------------------- ---------------------------------------------------------------------------- -------------------------------------------
cr_assert_file_contents_neq(File, RefFile, [FormatString, [Args...]]) The contents of ``File`` are not equal to the contents of ``RefFile``.
----------------------------------------------------------------------------------- ---------------------------------------------------------------------------- -------------------------------------------
cr_assert_stdout_eq(RefFile, [FormatString, [Args...]]) The contents of ``stdout`` are equal to the contents of ``RefFile``.
----------------------------------------------------------------------------------- ---------------------------------------------------------------------------- -------------------------------------------
cr_assert_stdout_neq(RefFile, [FormatString, [Args...]]) The contents of ``stdout`` are not equal to the contents of ``RefFile``.
----------------------------------------------------------------------------------- ---------------------------------------------------------------------------- -------------------------------------------
cr_assert_stderr_eq(RefFile, [FormatString, [Args...]]) The contents of ``stderr`` are equal to the contents of ``RefFile``.
----------------------------------------------------------------------------------- ---------------------------------------------------------------------------- -------------------------------------------
cr_assert_stderr_neq(RefFile, [FormatString, [Args...]]) The contents of ``stderr`` are not equal to the contents of ``RefFile``.
=================================================================================== ============================================================================ ===========================================

View file

@ -39,7 +39,7 @@ copyright = u'2015, Franklin "Snaipe" Mathieu'
# built documents.
#
# The short X.Y version.
version = '2.1.0'
version = '2.2.0'
# The full version, including alpha/beta/rc tags.
release = version

View file

@ -8,11 +8,14 @@ Command line arguments
----------------------
* ``-h or --help``: Show a help message with the available switches.
* ``-q or --quiet``: Disables all logging.
* ``-v or --version``: Prints the version of criterion that has been
linked against.
* ``-l or --list``: Print all the tests in a list.
* ``-f or --fail-fast``: Exit after the first test failure.
* ``--ascii``: Don't use fancy unicode symbols or colors in the output.
* ``-jN or --jobs N``: Use ``N`` parallel jobs to run the tests. ``0`` picks
a number of jobs ideal for your hardware configuration.
* ``--pattern [PATTERN]``: Run tests whose string identifier matches
the given shell wildcard pattern (see dedicated section below). (\*nix only)
* ``--no-early-exit``: The test workers shall not prematurely exit when done and
@ -20,30 +23,53 @@ Command line arguments
This is useful when tracking memory leaks with ``valgrind --tool=memcheck``.
* ``-S or --short-filename``: The filenames are displayed in their short form.
* ``--always-succeed``: The process shall exit with a status of ``0``.
* ``--tap``: Enables the TAP (Test Anything Protocol) output format.
* ``--tap[=FILE]``: Writes a TAP (Test Anything Protocol) report to FILE.
No file or ``"-"`` means ``stderr`` and implies ``--quiet``. This option is
equivalent to ``--output=tap:FILE``.
* ``--xml[=FILE]``: Writes JUnit4 XML report to FILE.
No file or ``"-"`` means ``stderr`` and implies ``--quiet``. This option is
equivalent to ``--output=tap:FILE``.
* ``--json[=FILE]``: Writes a JSON report to FILE.
No file or ``"-"`` means ``stderr`` and implies ``--quiet``. This option is
equivalent to ``--output=tap:FILE``.
* ``--verbose[=level]``: Makes the output verbose. When provided with an integer,
sets the verbosity level to that integer.
* ``-OPROVIDER:FILE or --output=PROVIDER:FILE``: Write a test report to FILE
using the output provider named by PROVIDER.
If FILE is ``"-"``, it implies ``--quiet``, and the report shall be written
to ``stderr``.
Shell Wildcard Pattern
----------------------
Patterns in criterion are matched against a test's string identifier with
``fnmatch``. This feature is only available on \*nix systems where ``fnmatch``
is provided.
Extglob patterns in criterion are matched against a test's string identifier.
This feature is only available on \*nix systems where ``PCRE`` is provided.
Special characters used in shell-style wildcard patterns are:
In the table below, a ``pattern-list`` is a list of patterns separated by ``|``.
Any extglob pattern can be constructed by combining any of the following
sub-patterns:
=========== ===================================
Pattern Meaning
=========== ===================================
``*`` matches everything
----------- -----------------------------------
``?`` matches any character
----------- -----------------------------------
``[seq]`` matches any character in *seq*
----------- -----------------------------------
``[!seq]`` matches any character not in *seq*
=========== ===================================
==================== ======================================================
Pattern Meaning
==================== ======================================================
``*`` matches everything
-------------------- ------------------------------------------------------
``?`` matches any character
-------------------- ------------------------------------------------------
``[seq]`` matches any character in *seq*
-------------------- ------------------------------------------------------
``[!seq]`` matches any character not in *seq*
-------------------- ------------------------------------------------------
``?(pattern-list)`` Matches zero or one occurrence of the given patterns
-------------------- ------------------------------------------------------
``*(pattern-list)`` Matches zero or more occurrences of the given patterns
-------------------- ------------------------------------------------------
``+(pattern-list)`` Matches one or more occurrences of the given patterns
-------------------- ------------------------------------------------------
``@(pattern-list)`` Matches one of the given patterns
-------------------- ------------------------------------------------------
``!(pattern-list)`` Matches anything except one of the given patterns
==================== ======================================================
A test string identifier is of the form ``suite-name/test-name``, so a pattern
of ``simple/*`` matches every tests in the ``simple`` suite, ``*/passing``
@ -57,11 +83,19 @@ Environment variables are alternatives to command line switches when set to 1.
* ``CRITERION_ALWAYS_SUCCEED``: Same as ``--always-succeed``.
* ``CRITERION_NO_EARLY_EXIT``: Same as ``--no-early-exit``.
* ``CRITERION_ENABLE_TAP``: Same as ``--tap``.
* ``CRITERION_FAIL_FAST``: Same as ``--fail-fast``.
* ``CRITERION_USE_ASCII``: Same as ``--ascii``.
* ``CRITERION_JOBS``: Same as ``--jobs``. Sets the number of jobs to
its value.
* ``CRITERION_SHORT_FILENAME``: Same as ``--short-filename``.
* ``CRITERION_VERBOSITY_LEVEL``: Same as ``--verbose``. Sets the verbosity level
to its value.
* ``CRITERION_TEST_PATTERN``: Same as ``--pattern``. Sets the test pattern
to its value. (\*nix only)
* ``CRITERION_DISABLE_TIME_MEASUREMENTS``: Disables any time measurements on
the tests.
* ``CRITERION_OUTPUTS``: Can be set to a comma-separated list of
``PROVIDER:FILE`` entries. For instance, setting the variable to
``tap:foo.tap,xml:bar.xml`` has the same effect as specifying ``--tap=foo.tap``
and ``--xml=bar.xml`` at once.
* ``CRITERION_ENABLE_TAP``: (Deprecated, use CRITERION_OUTPUTS) Same as ``--tap``.

View file

@ -10,6 +10,7 @@ Criterion
assert
hooks
env
output
parameterized
theories
internal

View file

@ -28,7 +28,7 @@ Field Type Description
=================== ================================== ==============================================================
logging_threshold enum criterion_logging_level The logging level
------------------- ---------------------------------- --------------------------------------------------------------
output_provider struct criterion_output_provider * The output provider (see below)
logger struct criterion_logger * The logger (see below)
------------------- ---------------------------------- --------------------------------------------------------------
no_early_exit bool True iff the test worker should exit early
------------------- ---------------------------------- --------------------------------------------------------------
@ -66,24 +66,23 @@ Example main
int main(int argc, char *argv[]) {
struct criterion_test_set *tests = criterion_initialize();
if (!criterion_handle_args(argc, argv, true))
return 0;
int result = !criterion_run_all_tests(set);
int result = 0;
if (criterion_handle_args(argc, argv, true))
result = !criterion_run_all_tests(set);
criterion_finalize(set);
return result;
}
Implementing your own output provider
-------------------------------------
Implementing your own logger
----------------------------
In case you are not satisfied by the default output provider, you can implement
yours. To do so, simply set the ``output_provider`` option to your custom
output provider.
In case you are not satisfied by the default logger, you can implement
yours. To do so, simply set the ``logger`` option to your custom
logger.
Each function contained in the structure is called during one of the standard
phase of the criterion runner.
For more insight on how to implement this, see other existing output providers
For more insight on how to implement this, see other existing loggers
in ``src/log/``.

View file

@ -1,8 +1,7 @@
Introduction
============
Criterion is a dead-simple, non-intrusive testing framework for the C
programming language.
Criterion is a dead-simple, non-intrusive unit testing framework for C and C++.
Philosophy
----------
@ -20,12 +19,15 @@ the user would have with other frameworks.
Features
--------
* C99 and C++11 compatible.
* Tests are automatically registered when declared.
* Implements a xUnit framework structure.
* A default entry point is provided, no need to declare a main
unless you want to do special handling.
* Test are isolated in their own process, crashes and signals can be
reported and tested.
* Unified interface between C and C++: include the criterion header and it *just* works.
* Supports parameterized tests and theories.
* Progress and statistics can be followed in real time with report hooks.
* TAP output format can be enabled with an option.
* Runs on Linux, FreeBSD, Mac OS X, and Windows (Compiling with MinGW GCC).
* xUnit framework structure
* Runs on Linux, FreeBSD, Mac OS X, and Windows (Compiling with MinGW GCC and Visual Studio 2015+).

44
doc/output.rst Normal file
View file

@ -0,0 +1,44 @@
Writing tests reports in a custom format
========================================
Outputs providers are used to write tests reports in the format of your choice:
for instance, TAP and XML reporting are implemented with output providers.
Adding a custom output provider
-------------------------------
An output provider is a function with the following signature:
.. code-block:: c
void func(FILE *out, struct criterion_global_stats *stats);
Once implemented, you then need to register it as an output provider:
.. code-block:: c
criterion_register_output_provider("provider name", func);
This needs to be done before the test runner stops, so you may want to register
it either in a self-provided main, or in a PRE_ALL or POST_ALL report hook.
Writing to a file with an output provider
-----------------------------------------
To tell criterion to write a report to a specific file using the output provider
of your choice, you can either pass ``--output`` as a command-line
parameter:
.. code-block:: bash
./my_tests --output="provider name":/path/to/file
Or, you can do so directly by calling ``criterion_add_output`` before the
runner stops:
.. code-block:: c
criterion_add_output("provider name", "/path/to/file");
The path may be relative. If ``"-"`` is passed as a filename, the report will
be written to ``stderr``.

View file

@ -18,7 +18,7 @@ and the parameter generator function:
#include <criterion/parameterized.h>
ParameterizedTestParameter(suite_name, test_name) = {
ParameterizedTestParameters(suite_name, test_name) {
void *params;
size_t nb_params;
@ -54,17 +54,12 @@ easily use a struct to hold the context as a workaround:
...
};
ParameterizedTestParameter(suite_name, test_name) = {
size_t nb_params = 32;
struct my_params *params = cr_malloc(sizeof (struct my_params) * nb_params);
// generate parameter set
params[0] = ...
params[1] = ...
...
ParameterizedTestParameters(suite_name, test_name) {
struct my_params params[] = {
// parameter set
};
size_t nb_params = sizeof (params) / sizeof (struct my_params);
return cr_make_param_array(struct my_params, params, nb_params);
}
@ -72,8 +67,20 @@ easily use a struct to hold the context as a workaround:
// access param.param0, param.param1, ...
}
Dynamically allocating fields
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
C++ users can also use a simpler syntax before returning an array of parameters:
.. code-block:: c++
ParameterizedTestParameters(suite_name, test_name) {
struct my_params params[] = {
// parameter set
};
return criterion_test_params(params);
}
Dynamically allocating parameters
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Any dynamic memory allocation done from a ParameterizedTestParameter function
**must** be done with ``cr_malloc``, ``cr_calloc``, or ``cr_realloc``.
@ -100,6 +107,9 @@ use:
``criterion::new_arr``.
The function possess the exact same semantics as ``delete[] array``.
Furthermore, the ``criterion::allocator<T>`` allocator can be used with STL
containers to allocate memory with the functions above.
Freeing dynamically allocated parameter fields
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@ -118,15 +128,36 @@ the cleanup function that should be called on the generated parameter context:
cr_free(((struct my_params *) ctp->params)->some_int_ptr);
}
ParameterizedTestParameter(suite_name, test_name) = {
static my_params param = {
ParameterizedTestParameters(suite_name, test_name) {
static my_params params[] = {{
.some_int_ptr = cr_malloc(sizeof (int));
};
*param.some_int_ptr = 42;
}};
param[0].some_int_ptr = 42;
return cr_make_param_array(struct my_params, &param, 1, cleanup_params);
return cr_make_param_array(struct my_params, params, 1, cleanup_params);
}
C++ users can use a more convenient approach:
.. code-block:: c++
#include <criterion/parameterized.h>
struct my_params {
std::unique_ptr<int, decltype(criterion::free)> some_int_ptr;
my_params(int *ptr) : some_int_ptr(ptr, criterion::free) {}
};
ParameterizedTestParameters(suite_name, test_name) {
static criterion::parameters<my_params> params;
params.push_back(my_params(criterion::new_obj<int>(42)));
return params;
}
``criterion::parameters<T>`` is typedef'd as ``std::vector<T, criterion::allocator<T>>``.
Configuring parameterized tests
-------------------------------

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 MiB

After

Width:  |  Height:  |  Size: 1.3 MiB

View file

@ -7,7 +7,8 @@ Prerequisites
The library is supported on Linux, OS X, FreeBSD, and Windows.
The following compilers are supported to compile both the library and the tests:
* GCC 4.9+
* GCC 4.9+ (Can be relaxed to GCC 4.6+ when not using C++)
* Clang 3.4+
* MSVC 14+ (Included in Visual Studio 2015 or later)

View file

@ -78,26 +78,26 @@ Macro Description
------------------------------------------------------- ----------------------------------------------------
``cr_assume_float_neq(Actual, Unexpected, Epsilon)`` Assumes Actual != Expected with an error of Epsilon.
------------------------------------------------------- ----------------------------------------------------
``cr_assume_strings_eq(Actual, Expected)`` Assumes Actual and Expected are the same string.
``cr_assume_str_eq(Actual, Expected)`` Assumes Actual and Expected are the same string.
------------------------------------------------------- ----------------------------------------------------
``cr_assume_strings_neq(Actual, Unexpected)`` Assumes Actual and Expected are not the same string.
``cr_assume_str_neq(Actual, Unexpected)`` Assumes Actual and Expected are not the same string.
------------------------------------------------------- ----------------------------------------------------
``cr_assume_strings_lt(Actual, Expected)`` Assumes Actual is less than Expected
``cr_assume_str_lt(Actual, Expected)`` Assumes Actual is less than Expected
lexicographically.
------------------------------------------------------- ----------------------------------------------------
``cr_assume_strings_leq(Actual, Expected)`` Assumes Actual is less or equal to Expected
``cr_assume_str_leq(Actual, Expected)`` Assumes Actual is less or equal to Expected
lexicographically.
------------------------------------------------------- ----------------------------------------------------
``cr_assume_strings_gt(Actual, Expected)`` Assumes Actual is greater than Expected
``cr_assume_str_gt(Actual, Expected)`` Assumes Actual is greater than Expected
lexicographically.
------------------------------------------------------- ----------------------------------------------------
``cr_assume_strings_geq(Actual, Expected)`` Assumes Actual is greater or equal to Expected
``cr_assume_str_geq(Actual, Expected)`` Assumes Actual is greater or equal to Expected
lexicographically.
------------------------------------------------------- ----------------------------------------------------
``cr_assume_arrays_eq(Actual, Expected, Size)`` Assumes all elements of Actual (from 0 to Size - 1)
``cr_assume_arr_eq(Actual, Expected, Size)`` Assumes all elements of Actual (from 0 to Size - 1)
are equals to those of Expected.
------------------------------------------------------- ----------------------------------------------------
``cr_assume_arrays_neq(Actual, Unexpected, Size)`` Assumes one or more elements of Actual (from 0 to
``cr_assume_arr_neq(Actual, Unexpected, Size)`` Assumes one or more elements of Actual (from 0 to
Size - 1) differs from their counterpart in Expected.
======================================================= ====================================================

View file

@ -24,13 +24,26 @@
#ifndef CRITERION_ABORT_H_
# define CRITERION_ABORT_H_
# include "common.h"
# include "internal/common.h"
CR_BEGIN_C_API
CR_API NORETURN void criterion_abort_test(void);
/**
* Aborts the current test, marking it as failed.
*
* This function does not return.
*/
CR_API CR_NORETURN void criterion_abort_test(void);
/**
* Continues the current test.
*
* Used as a counterpart to criterion_abort_test.
*/
CR_INLINE static void criterion_continue_test(void) {}
CR_API void criterion_test_die(const char *msg, ...);
CR_END_C_API
#endif /* !CRITERION_ABORT_H_ */

View file

@ -24,14 +24,66 @@
#ifndef CRITERION_ALLOC_H_
# define CRITERION_ALLOC_H_
# include <stddef.h>
# include "common.h"
# ifdef __cplusplus
# include <memory>
# include <cstddef>
using std::size_t;
# else
# include <stddef.h>
# endif
# include "internal/common.h"
CR_BEGIN_C_API
/**
* Allocates a block of memory usable by the test.
*
* It is undefined behaviour to access a pointer returned by malloc(3)
* inside a test or its setup and teardown functions; cr_malloc must
* be use in its place for this purpose.
*
* This function is semantically identical to malloc(3).
*
* @param[in] size The minimal size in bytes of the newly allocated memory.
* @returns The pointer to the start of the allocated memory.
*/
CR_API void *cr_malloc(size_t size);
/**
* Allocates and zero-initialize a block of memory usable by the test.
*
* It is undefined behaviour to access a pointer returned by calloc(3)
* inside a test or its setup and teardown functions; cr_calloc must
* be use in its place for this purpose.
*
* This function is semantically identical to calloc(3).
*
* @param[in] nmemb The number of elements to allocate
* @param[in] size The minimal size of each element.
* @returns The pointer to the start of the allocated memory.
*/
CR_API void *cr_calloc(size_t nmemb, size_t size);
/**
* Reallocates a block of memory usable by the test.
*
* It is undefined behaviour to access a pointer returned by realloc(3)
* inside a test or its setup and teardown functions; cr_realloc must
* be used in its place for this purpose.
*
* This function is semantically identical to realloc(3).
*
* @param[in] ptr A pointer to the memory that needs to be resized.
* @param[in] size The minimal size of the reallocated memory.
* @returns The pointer to the start of the reallocated memory.
*/
CR_API void *cr_realloc(void *ptr, size_t size);
/**
* Free a block of memory allocated by cr_malloc, cr_free or cr_realloc.
*
* @param[in] ptr A pointer to the memory that needs to be freed.
*/
CR_API void cr_free(void *ptr);
CR_END_C_API
@ -46,6 +98,19 @@ namespace criterion {
void *(*const calloc)(size_t, size_t) = cr_calloc;
void *(*const realloc)(void *, size_t) = cr_realloc;
/**
* Allocates and construct a new object.
*
* It is undefined behaviour to access a pointer returned by the new
* operator inside a test or its setup and teardown functions;
* new_obj must be used in its place for this purpose.
*
* This function is semantically identical to the new operator.
*
* @tparam T The type of the object to construct
* @param[in] params The constructor parameters of T.
* @returns The pointer to the newly constructed object.
*/
template<typename T, typename... Params>
T* new_obj(Params... params) {
T* obj = static_cast<T*>(cr_malloc(sizeof (T)));
@ -53,6 +118,19 @@ namespace criterion {
return obj;
}
/**
* Allocates and construct a new array of primitive types
*
* It is undefined behaviour to access a pointer returned by the new[]
* operator inside a test or its setup and teardown functions;
* new_arr must be used in its place for this purpose.
*
* This function is semantically identical to the new[] operator.
*
* @tparam T The compound type of the array to construct
* @param[in] len The length of the array.
* @returns The pointer to the newly constructed array.
*/
template<typename T>
typename std::enable_if<std::is_fundamental<T>::value>::type*
new_arr(size_t len) {
@ -62,6 +140,19 @@ namespace criterion {
return arr;
}
/**
* Allocates and construct a new array of object types
*
* It is undefined behaviour to access a pointer returned by the new[]
* operator inside a test or its setup and teardown functions;
* new_arr must be used in its place for this purpose.
*
* This function is semantically identical to the new[] operator.
*
* @tparam T The compound type of the array to construct
* @param[in] len The length of the array.
* @returns The pointer to the newly constructed array.
*/
template<typename T>
T* new_arr(size_t len) {
void *ptr = cr_malloc(sizeof (size_t) + sizeof (T) * len);
@ -73,27 +164,100 @@ namespace criterion {
return arr;
}
/**
* Destroys and frees an object allocated by new_obj.
*
* This function is semantically identical to the delete operator.
*
* @tparam T The type of the object to construct
* @param[in] ptr The object to destroy.
*/
template<typename T>
void delete_obj(T* ptr) {
ptr->~T();
cr_free(ptr);
}
/**
* Destroys and frees an array allocated by delete_arr.
*
* This function is semantically identical to the delete[] operator.
*
* @tparam T The type of the object to construct
* @param[in] ptr The object to destroy.
*/
template<typename T>
void delete_arr(typename std::enable_if<std::is_fundamental<T>::value>::type* ptr) {
cr_free(ptr);
}
/**
* Destroys and frees an array allocated by delete_arr.
*
* This function is semantically identical to the delete[] operator.
*
* @tparam T The type of the object to construct
* @param[in] ptr The object to destroy.
*/
template<typename T>
void delete_arr(T* ptr) {
size_t len = *(reinterpret_cast<size_t*>(ptr));
T* arr = reinterpret_cast<T*>(reinterpret_cast<size_t*>(ptr) + 1);
for (int i = 0; i < len; ++i) {
size_t *ptr_ = reinterpret_cast<size_t*>(ptr);
size_t len = *(ptr_ - 1);
T* arr = reinterpret_cast<T*>(ptr_);
for (size_t i = 0; i < len; ++i)
arr[i].~T();
}
cr_free(ptr);
cr_free(ptr_ - 1);
}
/**
* Allocator for use in the STL.
*
* This internally uses calls to the cr_malloc function family, which
* means that STL collections can be safely used inside tests or
* setup/teardown functions if this allocator is used.
*/
template<typename T>
struct allocator {
typedef T value_type;
typedef value_type* pointer;
typedef const value_type* const_pointer;
typedef value_type& reference;
typedef const value_type& const_reference;
typedef std::size_t size_type;
typedef std::ptrdiff_t difference_type;
template<typename U>
struct rebind {
typedef allocator<U> other;
};
inline explicit allocator() {}
inline ~allocator() {}
inline explicit allocator(allocator const&) {}
template<typename U>
inline explicit allocator(allocator<U> const&) {}
inline pointer address(reference r) { return &r; }
inline const_pointer address(const_reference r) { return &r; }
inline pointer allocate(size_type cnt, typename std::allocator<void>::const_pointer = 0) {
return reinterpret_cast<pointer>(cr_malloc(cnt * sizeof (T)));
}
inline void deallocate(pointer p, size_type) { cr_free(p); }
inline size_type max_size() const {
return size_type(-1) / sizeof(T);
}
inline void construct(pointer p, const T& t) { new(p) T(t); }
inline void construct(pointer p, T&& t) { new (p) T(std::move(t)); }
inline void destroy(pointer p) { p->~T(); }
inline bool operator==(allocator const&) { return true; }
inline bool operator!=(allocator const& a) { return !operator==(a); }
};
}
# endif

View file

@ -24,210 +24,25 @@
#ifndef CRITERION_ASSERT_H_
# define CRITERION_ASSERT_H_
# include "preprocess.h"
# include "asprintf-compat.h"
# ifdef __cplusplus
# include <cstring>
# include <cstdlib>
# include <algorithm>
# else
# include <string.h>
# include <stdlib.h>
# include <stdbool.h>
# endif
# include "designated-initializer-compat.h"
# include "types.h"
# include "stats.h"
# include "hooks.h"
# include "event.h"
# include "abort.h"
struct criterion_assert_args {
const char *msg;
int sentinel_;
#ifdef __cplusplus
constexpr criterion_assert_args(const char *msg) : msg(msg), sentinel_(0) {}
constexpr criterion_assert_args(const char *msg, int sentinel_) : msg(msg), sentinel_(sentinel_) {}
#endif
};
// Do NOT reorder unless you want to break the ABI
enum criterion_assert_messages {
CRITERION_ASSERT_MSG_FAIL,
CRITERION_ASSERT_MSG_EXPR_FALSE,
CRITERION_ASSERT_MSG_EXPR_AS_STRINGS_FALSE,
CRITERION_ASSERT_MSG_IS_NULL,
CRITERION_ASSERT_MSG_IS_NOT_NULL,
CRITERION_ASSERT_MSG_IS_EMPTY,
CRITERION_ASSERT_MSG_IS_NOT_EMPTY,
CRITERION_ASSERT_MSG_FILE_STR_MATCH,
CRITERION_ASSERT_MSG_FILE_MATCH,
CRITERION_ASSERT_MSG_THROW,
CRITERION_ASSERT_MSG_NO_THROW,
CRITERION_ASSERT_MSG_ANY_THROW,
CRITERION_ASSERT_MSG_NONE_THROW,
};
CR_BEGIN_C_API
CR_API char *translate_assert_msg(int msg_index, ...);
CR_END_C_API
# define CR_GET_CONDITION(Condition, ...) Condition
# define CR_GET_CONDITION_STR(Condition, ...) #Condition
# define CR_VA_SKIP(_, ...) __VA_ARGS__
# ifdef __cplusplus
# define CR_STDN std::
# else
# define CR_STDN
# endif
# define CR_TRANSLATE_DEF_MSG__(Arg) \
CR_IDENTITY Arg
# define CR_TRANSLATE_DEF_MSG_(...) \
CR_EXPAND(translate_assert_msg( \
CR_VA_HEAD(__VA_ARGS__), \
"" CR_TRANSLATE_DEF_MSG__(CR_VA_HEAD(CR_VA_TAIL(__VA_ARGS__))) \
))
# define CR_INIT_STATS_(BufSize, MsgVar, ...) CR_EXPAND( \
do { \
char *def_msg = CR_EXPAND(CR_TRANSLATE_DEF_MSG_(__VA_ARGS__)); \
char *formatted_msg = NULL; \
int msglen = cr_asprintf(&formatted_msg, \
"" CR_VA_TAIL(CR_VA_TAIL(__VA_ARGS__))); \
if (formatted_msg && *formatted_msg) { \
MsgVar = formatted_msg; \
CR_STDN free(def_msg); \
} else { \
MsgVar = def_msg; \
msglen = strlen(def_msg); \
CR_STDN free(formatted_msg); \
} \
\
BufSize = sizeof(struct criterion_assert_stats) \
+ sizeof (size_t) + msglen + 1; \
\
char *buf = (char*) CR_STDN malloc(BufSize); \
stat = (struct criterion_assert_stats*) buf; \
CR_STDN memset(buf, 0, sizeof (struct criterion_assert_stats)); \
buf += sizeof (struct criterion_assert_stats); \
*((size_t*) buf) = msglen + 1; \
buf += sizeof (size_t); \
CR_STDN strcpy(buf, MsgVar); \
CR_STDN free(MsgVar); \
} while (0))
# define CR_FAIL_ABORT_ criterion_abort_test
# define CR_FAIL_CONTINUES_ criterion_continue_test
# ifdef __GNUC__
// We disable the format-zero-length warning because we use the validity of
// asprintf(out, "") for empty assertion messages
# pragma GCC diagnostic ignored "-Wformat-zero-length"
# endif
# define cr_assert_impl(Fail, Condition, ...) \
do { \
bool passed = !!(Condition); \
\
char *msg = NULL; \
size_t bufsize; \
\
struct criterion_assert_stats *stat; \
CR_EXPAND(CR_INIT_STATS_(bufsize, msg, CR_VA_TAIL(__VA_ARGS__))); \
stat->passed = passed; \
stat->file = __FILE__; \
stat->line = __LINE__; \
\
send_event(ASSERT, stat, bufsize); \
CR_STDN free(stat); \
\
if (!passed) \
Fail(); \
} while (0)
# include "internal/assert.h"
// Base assertions
# define cr_fail(Fail, ...) \
CR_EXPAND(cr_assert_impl( \
Fail, \
0, \
dummy, \
CRITERION_ASSERT_MSG_FAIL, \
(), \
__VA_ARGS__ \
))
# define cr_assert_fail(...) CR_EXPAND(cr_fail(CR_FAIL_ABORT_, __VA_ARGS__))
# define cr_expect_fail(...) CR_EXPAND(cr_fail(CR_FAIL_CONTINUES_, __VA_ARGS__))
# define cr_assert(...) \
CR_EXPAND(cr_assert_impl( \
CR_FAIL_ABORT_, \
CR_VA_HEAD(__VA_ARGS__), \
dummy, \
CRITERION_ASSERT_MSG_EXPR_FALSE, \
(CR_STR(CR_VA_HEAD(__VA_ARGS__))), \
CR_VA_TAIL(__VA_ARGS__) \
))
# define cr_assert(...) CR_EXPAND(cr_assert_(__VA_ARGS__))
# define cr_expect(...) CR_EXPAND(cr_expect_(__VA_ARGS__))
# define cr_expect(...) \
CR_EXPAND(cr_assert_impl( \
CR_FAIL_CONTINUES_, \
CR_VA_HEAD(__VA_ARGS__), \
dummy, \
CRITERION_ASSERT_MSG_EXPR_FALSE, \
(CR_STR(CR_VA_HEAD(__VA_ARGS__))), \
CR_VA_TAIL(__VA_ARGS__) \
))
# define cr_assert_not(...) \
CR_EXPAND(cr_assert_impl( \
CR_FAIL_ABORT_, \
!(CR_VA_HEAD(__VA_ARGS__)), \
dummy, \
CRITERION_ASSERT_MSG_EXPR_FALSE, \
(CR_STR(!(CR_VA_HEAD(__VA_ARGS__)))), \
CR_VA_TAIL(__VA_ARGS__) \
))
# define cr_expect_not(...) \
CR_EXPAND(cr_assert_impl( \
CR_FAIL_CONTINUES_, \
!(CR_VA_HEAD(__VA_ARGS__)), \
dummy, \
CRITERION_ASSERT_MSG_EXPR_FALSE, \
(CR_STR(!(CR_VA_HEAD(__VA_ARGS__)))), \
CR_VA_TAIL(__VA_ARGS__) \
))
# define cr_assert_not(...) CR_EXPAND(cr_assert_not_(__VA_ARGS__))
# define cr_expect_not(...) CR_EXPAND(cr_expect_not_(__VA_ARGS__))
// Common binary assertions
# define cr_assert_op_(Fail, Op, Actual, Expected, ...) \
CR_EXPAND(cr_assert_impl( \
Fail, \
(Actual) Op (Expected), \
dummy, \
CRITERION_ASSERT_MSG_EXPR_FALSE, \
(CR_STR((Actual) Op (Expected))), \
__VA_ARGS__ \
))
# define cr_assert_op_va_(Fail, Op, ...) \
CR_EXPAND(cr_assert_op_( \
Fail, \
Op, \
CR_VA_HEAD(__VA_ARGS__), \
CR_VA_HEAD(CR_VA_TAIL(__VA_ARGS__)), \
CR_VA_TAIL(CR_VA_TAIL(__VA_ARGS__)) \
))
# define cr_assert_eq(...) CR_EXPAND(cr_assert_op_va_(CR_FAIL_ABORT_, ==, __VA_ARGS__))
# define cr_expect_eq(...) CR_EXPAND(cr_assert_op_va_(CR_FAIL_CONTINUES_, ==, __VA_ARGS__))
@ -248,25 +63,6 @@ CR_END_C_API
// Common unary assertions
# define cr_assert_null_op_(Fail, Op, Msg, Value, ...) \
CR_EXPAND(cr_assert_impl( \
Fail, \
(Value) Op NULL, \
dummy, \
Msg, \
(CR_STR(Value)), \
__VA_ARGS__ \
))
# define cr_assert_null_op_va_(Fail, Op, Msg, ...) \
CR_EXPAND(cr_assert_null_op_( \
Fail, \
Op, \
Msg, \
CR_VA_HEAD(__VA_ARGS__), \
CR_VA_TAIL(__VA_ARGS__) \
))
# define cr_assert_null(...) CR_EXPAND(cr_assert_null_op_va_(CR_FAIL_ABORT_, ==, CRITERION_ASSERT_MSG_IS_NOT_NULL, __VA_ARGS__))
# define cr_expect_null(...) CR_EXPAND(cr_assert_null_op_va_(CR_FAIL_CONTINUES_, ==, CRITERION_ASSERT_MSG_IS_NOT_NULL, __VA_ARGS__))
@ -275,32 +71,6 @@ CR_END_C_API
// Floating-point assertions
# define cr_assert_float_eq_op_(Actual, Expected, Epsilon) \
(Expected) - (Actual) <= (Epsilon) && (Actual) - (Expected) <= (Epsilon)
# define cr_assert_float_neq_op_(Actual, Expected, Epsilon) \
(Expected) - (Actual) > (Epsilon) || (Actual) - (Expected) > (Epsilon)
# define cr_assert_float_op_(Fail, Op, Actual, Expected, Epsilon, ...) \
CR_EXPAND(cr_assert_impl( \
Fail, \
Op(Actual, Expected, Epsilon), \
dummy, \
CRITERION_ASSERT_MSG_EXPR_FALSE, \
(CR_STR(Op(Actual, Expected, Epsilon))), \
__VA_ARGS__ \
))
# define cr_assert_float_op_va_(Fail, Op, ...) \
CR_EXPAND(cr_assert_float_op_( \
Fail, \
Op, \
CR_VA_HEAD(__VA_ARGS__), \
CR_VA_HEAD(CR_VA_TAIL(__VA_ARGS__)), \
CR_VA_HEAD(CR_VA_TAIL(CR_VA_TAIL(__VA_ARGS__))), \
CR_VA_TAIL(CR_VA_TAIL(CR_VA_TAIL(__VA_ARGS__))) \
))
# define cr_assert_float_eq(...) CR_EXPAND(cr_assert_float_op_va_(CR_FAIL_ABORT_, cr_assert_float_eq_op_, __VA_ARGS__))
# define cr_expect_float_eq(...) CR_EXPAND(cr_assert_float_op_va_(CR_FAIL_CONTINUES_, cr_assert_float_eq_op_, __VA_ARGS__))
@ -309,50 +79,12 @@ CR_END_C_API
// String assertions
# define cr_assert_str_op_empty_(Fail, Op, Msg, Value, ...) \
CR_EXPAND(cr_assert_impl( \
Fail, \
(Value)[0] Op '\0', \
dummy, \
Msg, \
(CR_STR(Value)), \
__VA_ARGS__ \
))
# define cr_assert_str_op_empty_va_(Fail, Op, Msg, ...) \
CR_EXPAND(cr_assert_str_op_empty_( \
Fail, \
Op, \
Msg, \
CR_VA_HEAD(__VA_ARGS__), \
CR_VA_TAIL(__VA_ARGS__) \
))
# define cr_assert_str_empty(...) CR_EXPAND(cr_assert_str_op_empty_va_(CR_FAIL_ABORT_, ==, CRITERION_ASSERT_MSG_IS_NOT_EMPTY, __VA_ARGS__))
# define cr_expect_str_empty(...) CR_EXPAND(cr_assert_str_op_empty_va_(CR_FAIL_CONTINUES_, ==, CRITERION_ASSERT_MSG_IS_NOT_EMPTY, __VA_ARGS__))
# define cr_assert_str_not_empty(...) CR_EXPAND(cr_assert_str_op_empty_va_(CR_FAIL_ABORT_, !=, CRITERION_ASSERT_MSG_IS_EMPTY, __VA_ARGS__))
# define cr_expect_str_not_empty(...) CR_EXPAND(cr_assert_str_op_empty_va_(CR_FAIL_CONTINUES_, !=, CRITERION_ASSERT_MSG_IS_EMPTY, __VA_ARGS__))
# define cr_assert_str_op_(Fail, Op, Actual, Expected, ...) \
CR_EXPAND(cr_assert_impl( \
Fail, \
CR_STDN strcmp((Actual), (Expected)) Op 0, \
dummy, \
CRITERION_ASSERT_MSG_EXPR_AS_STRINGS_FALSE, \
(CR_STR((Actual) Op (Expected))), \
__VA_ARGS__ \
))
# define cr_assert_str_op_va_(Fail, Op, ...) \
CR_EXPAND(cr_assert_str_op_( \
Fail, \
Op, \
CR_VA_HEAD(__VA_ARGS__), \
CR_VA_HEAD(CR_VA_TAIL(__VA_ARGS__)), \
CR_VA_TAIL(CR_VA_TAIL(__VA_ARGS__)) \
))
# define cr_assert_str_eq(...) CR_EXPAND(cr_assert_str_op_va_(CR_FAIL_ABORT_, ==, __VA_ARGS__))
# define cr_expect_str_eq(...) CR_EXPAND(cr_assert_str_op_va_(CR_FAIL_CONTINUES_, ==, __VA_ARGS__))
@ -373,26 +105,6 @@ CR_END_C_API
// Array assertions
# define cr_assert_mem_op_(Fail, Op, Actual, Expected, Size, ...) \
CR_EXPAND(cr_assert_impl( \
Fail, \
CR_STDN memcmp((Actual), (Expected), (Size)) Op 0, \
dummy, \
CRITERION_ASSERT_MSG_EXPR_FALSE, \
(CR_STR((Actual)[0 .. Size] Op (Expected)[0 .. Size])), \
__VA_ARGS__ \
))
# define cr_assert_mem_op_va_(Fail, Op, ...) \
CR_EXPAND(cr_assert_mem_op_( \
Fail, \
Op, \
CR_VA_HEAD(__VA_ARGS__), \
CR_VA_HEAD(CR_VA_TAIL(__VA_ARGS__)), \
CR_VA_HEAD(CR_VA_TAIL(CR_VA_TAIL(__VA_ARGS__))), \
CR_VA_TAIL(CR_VA_TAIL(CR_VA_TAIL(__VA_ARGS__))) \
))
# define cr_assert_arr_eq(...) CR_EXPAND(cr_assert_mem_op_va_(CR_FAIL_ABORT_, ==, __VA_ARGS__))
# define cr_expect_arr_eq(...) CR_EXPAND(cr_assert_mem_op_va_(CR_FAIL_CONTINUES_, ==, __VA_ARGS__))
@ -401,44 +113,7 @@ CR_END_C_API
// Safe array comparison assertions
# if defined(__GNUC__) || defined(__cplusplus)
# ifdef __cplusplus
# define CR_ARR_COMPARE_(A, B, Size, Cmp, Result) \
int Result = std::lexicographical_compare((A), (A) + Size, (B), (B) + Size, Cmp)
# else
# define CR_ARR_COMPARE_(A, B, Size, Cmp, Result) \
__typeof__(&(A)[0]) first = (A); \
__typeof__(&(B)[0]) second = (B); \
int Result = 0; \
size_t i, size; \
for (i = 0, size = (Size); !Result && i < size; ++i) \
Result = Cmp(first + i, second + i)
# endif
# define cr_assert_arr_op_cmp_(Fail, Op, Actual, Expected, Size, Cmp, ...) \
do { \
CR_ARR_COMPARE_(Actual, Expected, Size, Cmp, order); \
CR_EXPAND(cr_assert_impl( \
Fail, \
order Op 0, \
dummy, \
CRITERION_ASSERT_MSG_EXPR_FALSE, \
(CR_STR((Actual)[0 .. Size] Op (Expected)[0 .. Size])), \
__VA_ARGS__ \
)); \
} while (0)
# define cr_assert_arr_op_cmp_va_(Fail, Op, ...) \
CR_EXPAND(cr_assert_arr_op_cmp_( \
Fail, \
Op, \
CR_VA_HEAD(__VA_ARGS__), \
CR_VA_HEAD(CR_VA_TAIL(__VA_ARGS__)), \
CR_VA_HEAD(CR_VA_TAIL(CR_VA_TAIL(__VA_ARGS__))), \
CR_VA_HEAD(CR_VA_TAIL(CR_VA_TAIL(CR_VA_TAIL(__VA_ARGS__)))), \
CR_VA_TAIL(CR_VA_TAIL(CR_VA_TAIL(CR_VA_TAIL(__VA_ARGS__)))) \
))
# if defined(__GNUC__) || defined(__clang__) || defined(__cplusplus)
# define cr_assert_arr_eq_cmp(...) CR_EXPAND(cr_assert_arr_op_cmp_va_(CR_FAIL_ABORT_, ==, __VA_ARGS__))
# define cr_expect_arr_eq_cmp(...) CR_EXPAND(cr_assert_arr_op_cmp_va_(CR_FAIL_CONTINUES_, ==, __VA_ARGS__))
@ -460,14 +135,6 @@ CR_END_C_API
# else
# define CRITERION_GNUC_WARN__(Msg) \
_Pragma(#Msg)
# define CRITERION_GNUC_WARN_(Name) CRITERION_GNUC_WARN__( \
message \
"The `" #Name "` macro is only available on GNU C compilers." \
)
# define cr_assert_arr_eq_cmp(...) CRITERION_GNUC_WARN_(cr_assert_arr_eq_cmp) CR_NOOP
# define cr_expect_arr_eq_cmp(...) CRITERION_GNUC_WARN_(cr_expect_arr_eq_cmp) CR_NOOP
@ -490,103 +157,15 @@ CR_END_C_API
# ifdef __cplusplus
# define cr_assert_throw_abort_(Fail, Msg, MsgArgs, ...) \
CR_EXPAND(cr_assert_impl( \
Fail, \
0, \
dummy, \
Msg, \
MsgArgs, \
CR_VA_TAIL(__VA_ARGS__) \
))
# define cr_assert_throw_(Fail, Statement, Exception, ...) \
try { \
Statement; \
} catch (Exception const &) { \
} catch (...) { \
CR_EXPAND(cr_assert_throw_abort_( \
Fail, \
CRITERION_ASSERT_MSG_NO_THROW, \
(CR_STR(Statement), CR_STR(Exception)), \
__VA_ARGS__)); \
}
# define cr_assert_throw_va_(...) \
CR_EXPAND(cr_assert_throw_( \
CR_VA_HEAD(__VA_ARGS__), \
CR_VA_HEAD(CR_VA_TAIL(__VA_ARGS__)), \
CR_VA_HEAD(CR_VA_TAIL(CR_VA_TAIL(__VA_ARGS__))), \
dummy, \
CR_VA_TAIL(CR_VA_TAIL(CR_VA_TAIL(__VA_ARGS__))) \
))
# define cr_assert_throw(...) CR_EXPAND(cr_assert_throw_va_(CR_FAIL_ABORT_, __VA_ARGS__))
# define cr_expect_throw(...) CR_EXPAND(cr_assert_throw_va_(CR_FAIL_CONTINUES_, __VA_ARGS__))
# define cr_assert_no_throw_(Fail, Statement, Exception, ...) \
try { \
Statement; \
} catch (Exception const &) { \
CR_EXPAND(cr_assert_throw_abort_( \
Fail, \
CRITERION_ASSERT_MSG_THROW, \
(CR_STR(Statement), CR_STR(Exception)), \
__VA_ARGS__)); \
}
# define cr_assert_no_throw_va_(...) \
CR_EXPAND(cr_assert_no_throw_( \
CR_VA_HEAD(__VA_ARGS__), \
CR_VA_HEAD(CR_VA_TAIL(__VA_ARGS__)), \
CR_VA_HEAD(CR_VA_TAIL(CR_VA_TAIL(__VA_ARGS__))), \
dummy, \
CR_VA_TAIL(CR_VA_TAIL(CR_VA_TAIL(__VA_ARGS__))) \
))
# define cr_assert_no_throw(...) CR_EXPAND(cr_assert_no_throw_va_(CR_FAIL_ABORT_, __VA_ARGS__))
# define cr_expect_no_throw(...) CR_EXPAND(cr_assert_no_throw_va_(CR_FAIL_CONTINUES_, __VA_ARGS__))
# define cr_assert_any_throw_(Fail, Statement, ...) \
try { \
Statement; \
CR_EXPAND(cr_assert_throw_abort_( \
Fail, \
CRITERION_ASSERT_MSG_ANY_THROW, \
(CR_STR(Statement)), \
__VA_ARGS__)); \
} catch (...) {}
# define cr_assert_any_throw_va_(...) \
CR_EXPAND(cr_assert_any_throw_( \
CR_VA_HEAD(__VA_ARGS__), \
CR_VA_HEAD(CR_VA_TAIL(__VA_ARGS__)), \
dummy, \
CR_VA_TAIL(CR_VA_TAIL(__VA_ARGS__)) \
))
# define cr_assert_any_throw(...) CR_EXPAND(cr_assert_any_throw_va_(CR_FAIL_ABORT_, __VA_ARGS__))
# define cr_expect_any_throw(...) CR_EXPAND(cr_assert_any_throw_va_(CR_FAIL_CONTINUES_, __VA_ARGS__))
# define cr_assert_none_throw_(Fail, Statement, ...) \
try { \
Statement; \
} catch (...) { \
CR_EXPAND(cr_assert_throw_abort_( \
Fail, \
CRITERION_ASSERT_MSG_NONE_THROW, \
(CR_STR(Statement)), \
__VA_ARGS__)); \
}
# define cr_assert_none_throw_va_(...) \
CR_EXPAND(cr_assert_none_throw_( \
CR_VA_HEAD(__VA_ARGS__), \
CR_VA_HEAD(CR_VA_TAIL(__VA_ARGS__)), \
dummy, \
CR_VA_TAIL(CR_VA_TAIL(__VA_ARGS__)) \
))
# define cr_assert_none_throw(...) CR_EXPAND(cr_assert_none_throw_va_(CR_FAIL_ABORT_, __VA_ARGS__))
# define cr_expect_none_throw(...) CR_EXPAND(cr_assert_none_throw_va_(CR_FAIL_CONTINUES_, __VA_ARGS__))
@ -596,12 +175,6 @@ CR_END_C_API
// It shall be removed in the next major version of Criterion
# ifndef CRITERION_NO_COMPAT
# define CRITERION_ASSERT_DEPRECATED_(Name) CRITERION_ASSERT_DEPRECATED__( \
message \
("The `" #Name "` macro is deprecated, " \
"please use `cr_" #Name "` instead.") \
)
# define CRITERION_ASSERT_DEPRECATED_B(Name, Newname) \
CRITERION_ASSERT_DEPRECATED__( \
message \
@ -617,16 +190,6 @@ CR_END_C_API
_Pragma(#Msg)
# endif
# ifndef assert
# define assert(...) CRITERION_ASSERT_DEPRECATED_(assert) cr_assert(__VA_ARGS__)
// this is needed to make the POSIX assert.h redefine assert if
// subsequently included
# ifndef _ASSERT_H
# define _ASSERT_H 1
# endif /* !_ASSERT_H */
# endif /* !assert */
// scheduled for removal after 2.0
# define cr_abort_test(Message) CRITERION_ASSERT_DEPRECATED_B(cr_abort_test, cr_assert_fail) cr_assert_fail(Message)
# define cr_assert_strings_eq(...) CRITERION_ASSERT_DEPRECATED_B(cr_assert_strings_eq, cr_assert_str_eq) cr_assert_str_eq(__VA_ARGS__)
@ -642,52 +205,6 @@ CR_END_C_API
# define cr_assert_arrays_eq_cmp(...) CRITERION_ASSERT_DEPRECATED_B(cr_assert_arrays_eq_cmp, cr_assert_arr_eq_cmp) cr_assert_arr_eq_cmp(__VA_ARGS__)
# define cr_assert_arrays_neq_cmp(...) CRITERION_ASSERT_DEPRECATED_B(cr_assert_arrays_neq_cmp, cr_assert_arr_neq_cmp) cr_assert_arr_neq_cmp(__VA_ARGS__)
// scheduled for removal at 2.0
# define abort_test(Message) CRITERION_ASSERT_DEPRECATED_(abort_test) cr_abort_test(Message)
# define expect(...) CRITERION_ASSERT_DEPRECATED_(expect) cr_expect(__VA_ARGS__)
# define assert_not(...) CRITERION_ASSERT_DEPRECATED_(assert_not) cr_assert_not(__VA_ARGS__)
# define expect_not(...) CRITERION_ASSERT_DEPRECATED_(expect_not) cr_expect_not(__VA_ARGS__)
# define assert_eq(...) CRITERION_ASSERT_DEPRECATED_(assert_eq) cr_assert_eq(__VA_ARGS__)
# define expect_eq(...) CRITERION_ASSERT_DEPRECATED_(expect_eq) cr_expect_eq(__VA_ARGS__)
# define assert_neq(...) CRITERION_ASSERT_DEPRECATED_(assert_neq) cr_assert_neq(__VA_ARGS__)
# define expect_neq(...) CRITERION_ASSERT_DEPRECATED_(expect_neq) cr_expect_neq(__VA_ARGS__)
# define assert_lt(...) CRITERION_ASSERT_DEPRECATED_(assert_lt) cr_assert_lt(__VA_ARGS__)
# define expect_lt(...) CRITERION_ASSERT_DEPRECATED_(expect_lt) cr_expect_lt(__VA_ARGS__)
# define assert_gt(...) CRITERION_ASSERT_DEPRECATED_(assert_gt) cr_assert_gt(__VA_ARGS__)
# define expect_gt(...) CRITERION_ASSERT_DEPRECATED_(expect_gt) cr_expect_gt(__VA_ARGS__)
# define assert_leq(...) CRITERION_ASSERT_DEPRECATED_(assert_leq) cr_assert_leq(__VA_ARGS__)
# define expect_leq(...) CRITERION_ASSERT_DEPRECATED_(expect_leq) cr_expect_leq(__VA_ARGS__)
# define assert_geq(...) CRITERION_ASSERT_DEPRECATED_(assert_geq) cr_assert_geq(__VA_ARGS__)
# define expect_geq(...) CRITERION_ASSERT_DEPRECATED_(expect_geq) cr_expect_geq(__VA_ARGS__)
# define assert_null(...) CRITERION_ASSERT_DEPRECATED_(assert_null) cr_assert_null(__VA_ARGS__)
# define expect_null(...) CRITERION_ASSERT_DEPRECATED_(expect_null) cr_expect_null(__VA_ARGS__)
# define assert_not_null(...) CRITERION_ASSERT_DEPRECATED_(assert_not_null) cr_assert_not_null(__VA_ARGS__)
# define expect_not_null(...) CRITERION_ASSERT_DEPRECATED_(expect_not_null) cr_expect_not_null(__VA_ARGS__)
# define assert_float_eq(...) CRITERION_ASSERT_DEPRECATED_(assert_float_eq) cr_assert_float_eq(__VA_ARGS__)
# define expect_float_eq(...) CRITERION_ASSERT_DEPRECATED_(expect_float_eq) cr_expect_float_eq(__VA_ARGS__)
# define assert_float_neq(...) CRITERION_ASSERT_DEPRECATED_(assert_float_neq) cr_assert_float_neq(__VA_ARGS__)
# define expect_float_neq(...) CRITERION_ASSERT_DEPRECATED_(expect_float_neq) cr_expect_float_neq(__VA_ARGS__)
# define assert_strings_eq(...) CRITERION_ASSERT_DEPRECATED_(assert_strings_eq) cr_assert_strings_eq(__VA_ARGS__)
# define expect_strings_eq(...) CRITERION_ASSERT_DEPRECATED_(expect_strings_eq) cr_expect_strings_eq(__VA_ARGS__)
# define assert_strings_neq(...) CRITERION_ASSERT_DEPRECATED_(assert_strings_neq) cr_assert_strings_neq(__VA_ARGS__)
# define expect_strings_neq(...) CRITERION_ASSERT_DEPRECATED_(expect_strings_neq) cr_expect_strings_neq(__VA_ARGS__)
# define assert_strings_gt(...) CRITERION_ASSERT_DEPRECATED_(assert_strings_gt) cr_assert_strings_gt(__VA_ARGS__)
# define expect_strings_gt(...) CRITERION_ASSERT_DEPRECATED_(expect_strings_gt) cr_expect_strings_gt(__VA_ARGS__)
# define assert_strings_lt(...) CRITERION_ASSERT_DEPRECATED_(assert_strings_lt) cr_assert_strings_lt(__VA_ARGS__)
# define expect_strings_lt(...) CRITERION_ASSERT_DEPRECATED_(expect_strings_lt) cr_expect_strings_lt(__VA_ARGS__)
# define assert_strings_leq(...) CRITERION_ASSERT_DEPRECATED_(assert_strings_leq) cr_assert_strings_leq(__VA_ARGS__)
# define expect_strings_leq(...) CRITERION_ASSERT_DEPRECATED_(expect_strings_leq) cr_expect_strings_leq(__VA_ARGS__)
# define assert_strings_geq(...) CRITERION_ASSERT_DEPRECATED_(assert_strings_geq) cr_assert_strings_geq(__VA_ARGS__)
# define expect_strings_geq(...) CRITERION_ASSERT_DEPRECATED_(expect_strings_geq) cr_expect_strings_geq(__VA_ARGS__)
# define assert_arrays_eq(...) CRITERION_ASSERT_DEPRECATED_(assert_arrays_eq) cr_assert_arrays_eq(__VA_ARGS__)
# define expect_arrays_eq(...) CRITERION_ASSERT_DEPRECATED_(expect_arrays_eq) cr_expect_arrays_eq(__VA_ARGS__)
# define assert_arrays_neq(...) CRITERION_ASSERT_DEPRECATED_(assert_arrays_neq) cr_assert_arrays_neq(__VA_ARGS__)
# define expect_arrays_neq(...) CRITERION_ASSERT_DEPRECATED_(expect_arrays_neq) cr_expect_arrays_neq(__VA_ARGS__)
# define assert_arrays_eq_cmp(...) CRITERION_ASSERT_DEPRECATED_(assert_arrays_eq_cmp) cr_assert_arrays_eq_cmp(__VA_ARGS__)
# define expect_arrays_eq_cmp(...) CRITERION_ASSERT_DEPRECATED_(expect_arrays_eq_cmp) cr_expect_arrays_eq_cmp(__VA_ARGS__)
# define assert_arrays_neq_cmp(...) CRITERION_ASSERT_DEPRECATED_(assert_arrays_neq_cmp) cr_assert_arrays_neq_cmp(__VA_ARGS__)
# define expect_arrays_neq_cmp(...) CRITERION_ASSERT_DEPRECATED_(expect_arrays_neq_cmp) cr_expect_arrays_neq_cmp(__VA_ARGS__)
# endif
#endif /* !CRITERION_ASSERT_H_ */

View file

@ -24,74 +24,98 @@
#ifndef CRITERION_H_
# define CRITERION_H_
# include "designated-initializer-compat.h"
# include "common.h"
# include "types.h"
# include "assert.h"
# include "alloc.h"
# define IDENTIFIER_(Category, Name, Suffix) \
Category ## _ ## Name ## _ ## Suffix
# include "internal/test.h"
# ifdef __cplusplus
# define TEST_PROTOTYPE_(Category, Name) \
extern "C" void IDENTIFIER_(Category, Name, impl)(void)
# else
# define TEST_PROTOTYPE_(Category, Name) \
void IDENTIFIER_(Category, Name, impl)(void)
# endif
/**
* Test(Suite, Name, [Options...]) { Function body }
*
* Defines a new test.
*
* @param Suite The name of the test suite containing this test.
* @param Name The name of the test.
* @param Options An optional sequence of designated initializer key/value
* pairs as described in the `criterion_test_extra_data` structure
* (see criterion/types.h).
* Example: .exit_code = 1
*/
# define Test(...) CR_EXPAND(CR_TEST_BASE(__VA_ARGS__, .sentinel_ = 0))
# define SUITE_IDENTIFIER_(Name, Suffix) \
suite_ ## Name ## _ ## Suffix
# define Test(...) CR_EXPAND(Test_(__VA_ARGS__, .sentinel_ = 0))
# define Test_(Category, Name, ...) \
TEST_PROTOTYPE_(Category, Name); \
struct criterion_test_extra_data IDENTIFIER_(Category, Name, extra) = \
CR_EXPAND(CRITERION_MAKE_STRUCT(struct criterion_test_extra_data, \
.kind_ = CR_TEST_NORMAL, \
.param_ = (struct criterion_test_params(*)(void)) NULL, \
.identifier_ = #Category "/" #Name, \
.file_ = __FILE__, \
.line_ = __LINE__, \
__VA_ARGS__ \
)); \
struct criterion_test IDENTIFIER_(Category, Name, meta) = { \
#Name, \
#Category, \
IDENTIFIER_(Category, Name, impl), \
&IDENTIFIER_(Category, Name, extra) \
}; \
SECTION_("cr_tst") \
struct criterion_test *IDENTIFIER_(Category, Name, ptr) \
= &IDENTIFIER_(Category, Name, meta) SECTION_SUFFIX_; \
TEST_PROTOTYPE_(Category, Name)
# define TestSuite(...) CR_EXPAND(TestSuite_(__VA_ARGS__, .sentinel_ = 0))
# define TestSuite_(Name, ...) \
struct criterion_test_extra_data SUITE_IDENTIFIER_(Name, extra) = \
CR_EXPAND(CRITERION_MAKE_STRUCT(struct criterion_test_extra_data, \
.file_ = __FILE__, \
.line_ = 0, \
__VA_ARGS__ \
)); \
struct criterion_suite SUITE_IDENTIFIER_(Name, meta) = { \
#Name, \
&SUITE_IDENTIFIER_(Name, extra), \
}; \
SECTION_("cr_sts") \
struct criterion_suite *SUITE_IDENTIFIER_(Name, ptr) \
= &SUITE_IDENTIFIER_(Name, meta) SECTION_SUFFIX_
/**
* TestSuite(Name, [Options...]);
*
* Explicitely defines a test suite and its options.
*
* @param Name The name of the test suite.
* @param Options An optional sequence of designated initializer key/value
* pairs as described in the `criterion_test_extra_data` structure
* (see criterion/types.h).
* These options will provide the defaults for each test.
*/
# define TestSuite(...) CR_EXPAND(CR_SUITE_BASE(__VA_ARGS__, .sentinel_ = 0))
CR_BEGIN_C_API
/**
* Initializes criterion and builds a set of all discovered tests.
*
* Using any of the functions and macros provided by criterion before calling
* this results in undefined behaviour.
*
* @returns the set of tests
*/
CR_API struct criterion_test_set *criterion_initialize(void);
/**
* Release all resources allocated by criterion.
*
* Using any of the functions and macros provided by criterion except
* criterion_initialize after this function is called results in undefined
* behaviour.
*/
CR_API void criterion_finalize(struct criterion_test_set *tests);
/**
* Run all the tests in the test set.
*
* @param[in] tests The set of tests that are to be executed.
*
* @returns 1 if all tests succeeded or criterion_options.always_succeed
* is true, 0 otherwise.
*/
CR_API int criterion_run_all_tests(struct criterion_test_set *tests);
/**
* Handles all default command-line parameters, as documented in:
* <http://criterion.readthedocs.org/en/latest/env.html>, and appropriately
* sets criterion_options.
*
* @param[in] argc The number of arguments in argv.
* @param[in] argv A null-terminated array of strings representing the arguments.
* @param[in] handle_unknown_arg Whether the function should print a message
* and exit when an unknown parameter is encountered. Use false if you want
* to handle additional parameters yourself.
*
* @returns 0 if the process should exit immediately after, for instance after
* printing the help message.
*/
CR_API int criterion_handle_args(int argc, char *argv[], bool handle_unknown_arg);
/**
* Manually registers a new test within the specified test set.
*
* @param[in] tests The set of tests you want to insert the test in.
* @param[in] test The newly created test.
*/
CR_API void criterion_register_test(struct criterion_test_set *tests,
struct criterion_test *test);
extern const struct criterion_test *const criterion_current_test;
extern const struct criterion_suite *const criterion_current_suite;
CR_END_C_API
#endif /* !CRITERION_H_ */

View file

@ -29,11 +29,11 @@
# else
# include <stddef.h>
# endif
# include "common.h"
# include "internal/common.h"
CR_BEGIN_C_API
CR_API void send_event(int kind, void *data, size_t size);
CR_API void criterion_send_event(int kind, void *data, size_t size);
CR_END_C_API

View file

@ -24,9 +24,11 @@
#ifndef CRITERION_HOOKS_H_
# define CRITERION_HOOKS_H_
# include "common.h"
# include "types.h"
# include "internal/hooks.h"
/**
* This enum lists all the phases of the runner lifecycle.
*/
typedef enum {
PRE_ALL,
PRE_SUITE,
@ -43,57 +45,24 @@ typedef enum {
typedef void (*f_report_hook)();
# define HOOK_IDENTIFIER_(Suffix) HOOK_IDENTIFIER__(__LINE__, Suffix)
# define HOOK_IDENTIFIER__(Line, Suffix) HOOK_IDENTIFIER___(Line, Suffix)
# define HOOK_IDENTIFIER___(Line, Suffix) hook_l ## Line ## _ ## Suffix
# ifdef __cplusplus
# define HOOK_PROTOTYPE_ \
extern "C" void HOOK_IDENTIFIER_(impl)
# else
# define HOOK_PROTOTYPE_ \
void HOOK_IDENTIFIER_(impl)
# endif
// Section abbreviations
# define HOOK_SECTION_PRE_ALL cr_pra
# define HOOK_SECTION_PRE_SUITE cr_prs
# define HOOK_SECTION_PRE_INIT cr_pri
# define HOOK_SECTION_PRE_TEST cr_prt
# define HOOK_SECTION_ASSERT cr_ast
# define HOOK_SECTION_THEORY_FAIL cr_thf
# define HOOK_SECTION_TEST_CRASH cr_tsc
# define HOOK_SECTION_POST_TEST cr_pot
# define HOOK_SECTION_POST_FINI cr_pof
# define HOOK_SECTION_POST_SUITE cr_pos
# define HOOK_SECTION_POST_ALL cr_poa
# define HOOK_SECTION(Kind) HOOK_SECTION_ ## Kind
# define HOOK_SECTION_STRINGIFY__(Sec) #Sec
# define HOOK_SECTION_STRINGIFY_(Sec) HOOK_SECTION_STRINGIFY__(Sec)
# define HOOK_SECTION_STRINGIFY(Kind) HOOK_SECTION_STRINGIFY_(HOOK_SECTION(Kind))
# define HOOK_PARAM_TYPE_PRE_ALL struct criterion_test_set *
# define HOOK_PARAM_TYPE_PRE_SUITE struct criterion_suite_set *
# define HOOK_PARAM_TYPE_PRE_INIT struct criterion_test *
# define HOOK_PARAM_TYPE_PRE_TEST struct criterion_test *
# define HOOK_PARAM_TYPE_ASSERT struct criterion_assert_stats *
# define HOOK_PARAM_TYPE_THEORY_FAIL struct criterion_theory_stats *
# define HOOK_PARAM_TYPE_TEST_CRASH struct criterion_test_stats *
# define HOOK_PARAM_TYPE_POST_TEST struct criterion_test_stats *
# define HOOK_PARAM_TYPE_POST_FINI struct criterion_test_stats *
# define HOOK_PARAM_TYPE_POST_SUITE struct criterion_suite_stats *
# define HOOK_PARAM_TYPE_POST_ALL struct criterion_global_stats *
# define HOOK_PARAM_TYPE(Kind) HOOK_PARAM_TYPE_ ## Kind
# define ReportHook(Kind) \
HOOK_PROTOTYPE_(HOOK_PARAM_TYPE(Kind)); \
SECTION_(HOOK_SECTION_STRINGIFY(Kind)) \
f_report_hook HOOK_IDENTIFIER_(func) = \
(f_report_hook) HOOK_IDENTIFIER_(impl) \
SECTION_SUFFIX_; \
HOOK_PROTOTYPE_
/**
* ReportHook(Kind)(Type *param) { Function Body }
*
* Defines a report hook for the phase defined by Kind.
*
* The type of the parameter depends on the phase:
*
* - struct criterion_test_set for PRE_ALL.
* - struct criterion_suite_set for PRE_SUITE.
* - struct criterion_test for PRE_INIT and PRE_TEST.
* - struct criterion_assert_stats for ASSERT.
* - struct criterion_theory_stats for THEORY_FAIL.
* - struct criterion_test_stats for POST_TEST, POST_FINI, and TEST_CRASH.
* - struct criterion_suite_stats for POST_SUITE.
* - struct criterion_global_stats for POST_ALL.
*
* @param Kind The report phase to hook the function onto.
*/
# define ReportHook(Kind) CR_REPORT_HOOK_IMPL(Kind)
#endif /* !CRITERION_HOOKS_H_ */

View file

@ -34,7 +34,7 @@
CR_BEGIN_C_API
FORMAT(printf, 2, 3)
CR_FORMAT(printf, 2, 3)
CR_API int cr_asprintf(char **strp, const char *fmt, ...);
CR_API int cr_vasprintf(char **strp, const char *fmt, va_list ap);

View file

@ -0,0 +1,477 @@
/*
* The MIT License (MIT)
*
* Copyright © 2015 Franklin "Snaipe" Mathieu <http://snai.pe/>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#ifndef CRITERION_INTERNAL_ASSERT_H_
# define CRITERION_INTERNAL_ASSERT_H_
# include "common.h"
# include "preprocess.h"
# include "asprintf-compat.h"
# include "designated-initializer-compat.h"
# ifdef __cplusplus
# include <cstring>
# include <cstdlib>
# else
# include <string.h>
# include <stdlib.h>
# include <stdbool.h>
# endif
# include "../types.h"
# include "../stats.h"
# include "../hooks.h"
# include "../event.h"
# include "../abort.h"
struct criterion_assert_args {
const char *msg;
int sentinel_;
#ifdef __cplusplus
constexpr criterion_assert_args(const char *msg) : msg(msg), sentinel_(0) {}
constexpr criterion_assert_args(const char *msg, int sentinel_) : msg(msg), sentinel_(sentinel_) {}
#endif
};
// Do NOT reorder unless you want to break the ABI
enum criterion_assert_messages {
CRITERION_ASSERT_MSG_FAIL,
CRITERION_ASSERT_MSG_EXPR_FALSE,
CRITERION_ASSERT_MSG_EXPR_AS_STRINGS_FALSE,
CRITERION_ASSERT_MSG_IS_NULL,
CRITERION_ASSERT_MSG_IS_NOT_NULL,
CRITERION_ASSERT_MSG_IS_EMPTY,
CRITERION_ASSERT_MSG_IS_NOT_EMPTY,
CRITERION_ASSERT_MSG_FILE_STR_MATCH,
CRITERION_ASSERT_MSG_FILE_MATCH,
CRITERION_ASSERT_MSG_THROW,
CRITERION_ASSERT_MSG_NO_THROW,
CRITERION_ASSERT_MSG_ANY_THROW,
CRITERION_ASSERT_MSG_NONE_THROW,
};
CR_BEGIN_C_API
CR_API char *cr_translate_assert_msg(int msg_index, ...);
CR_END_C_API
# define CR_GET_CONDITION(Condition, ...) Condition
# define CR_GET_CONDITION_STR(Condition, ...) #Condition
# define CR_VA_SKIP(_, ...) __VA_ARGS__
# ifdef __cplusplus
# define CR_STDN std::
# else
# define CR_STDN
# endif
# define CR_TRANSLATE_DEF_MSG__(Arg) \
CR_IDENTITY Arg
# define CR_TRANSLATE_DEF_MSG_(...) \
CR_EXPAND(cr_translate_assert_msg( \
CR_VA_HEAD(__VA_ARGS__), \
"" CR_TRANSLATE_DEF_MSG__(CR_VA_HEAD(CR_VA_TAIL(__VA_ARGS__))) \
))
# define CR_INIT_STATS_(BufSize, MsgVar, ...) CR_EXPAND( \
do { \
char *def_msg = CR_EXPAND(CR_TRANSLATE_DEF_MSG_(__VA_ARGS__)); \
char *formatted_msg = NULL; \
int msglen = cr_asprintf(&formatted_msg, \
"" CR_VA_TAIL(CR_VA_TAIL(__VA_ARGS__))); \
if (formatted_msg && *formatted_msg) { \
MsgVar = formatted_msg; \
CR_STDN free(def_msg); \
} else { \
MsgVar = def_msg; \
msglen = strlen(def_msg); \
CR_STDN free(formatted_msg); \
} \
\
BufSize = sizeof(struct criterion_assert_stats) \
+ sizeof (size_t) + msglen + 1; \
\
char *buf = (char*) CR_STDN malloc(BufSize); \
stat = (struct criterion_assert_stats*) buf; \
CR_STDN memset(buf, 0, sizeof (struct criterion_assert_stats)); \
buf += sizeof (struct criterion_assert_stats); \
*((size_t*) buf) = msglen + 1; \
buf += sizeof (size_t); \
CR_STDN strcpy(buf, MsgVar); \
CR_STDN free(MsgVar); \
} while (0))
# define CR_FAIL_ABORT_ criterion_abort_test
# define CR_FAIL_CONTINUES_ criterion_continue_test
# if defined(__GNUC__) || defined(__clang__)
// We disable the format-zero-length warning because we use the validity of
// asprintf(out, "") for empty assertion messages
# pragma GCC diagnostic ignored "-Wformat-zero-length"
# endif
# define cr_assert_impl(Fail, Condition, ...) \
do { \
bool passed = !!(Condition); \
\
char *msg = NULL; \
size_t bufsize; \
\
struct criterion_assert_stats *stat; \
CR_EXPAND(CR_INIT_STATS_(bufsize, msg, CR_VA_TAIL(__VA_ARGS__))); \
stat->passed = passed; \
stat->file = __FILE__; \
stat->line = __LINE__; \
\
criterion_send_event(ASSERT, stat, bufsize); \
CR_STDN free(stat); \
\
if (!passed) \
Fail(); \
} while (0)
# define cr_fail(Fail, ...) \
CR_EXPAND(cr_assert_impl( \
Fail, \
0, \
dummy, \
CRITERION_ASSERT_MSG_FAIL, \
(), \
__VA_ARGS__ \
))
# define cr_assert_(...) \
CR_EXPAND(cr_assert_impl( \
CR_FAIL_ABORT_, \
CR_VA_HEAD(__VA_ARGS__), \
dummy, \
CRITERION_ASSERT_MSG_EXPR_FALSE, \
(CR_STR(CR_VA_HEAD(__VA_ARGS__))), \
CR_VA_TAIL(__VA_ARGS__) \
))
# define cr_expect_(...) \
CR_EXPAND(cr_assert_impl( \
CR_FAIL_CONTINUES_, \
CR_VA_HEAD(__VA_ARGS__), \
dummy, \
CRITERION_ASSERT_MSG_EXPR_FALSE, \
(CR_STR(CR_VA_HEAD(__VA_ARGS__))), \
CR_VA_TAIL(__VA_ARGS__) \
))
# define cr_assert_not_(...) \
CR_EXPAND(cr_assert_impl( \
CR_FAIL_ABORT_, \
!(CR_VA_HEAD(__VA_ARGS__)), \
dummy, \
CRITERION_ASSERT_MSG_EXPR_FALSE, \
(CR_STR(!(CR_VA_HEAD(__VA_ARGS__)))), \
CR_VA_TAIL(__VA_ARGS__) \
))
# define cr_expect_not_(...) \
CR_EXPAND(cr_assert_impl( \
CR_FAIL_CONTINUES_, \
!(CR_VA_HEAD(__VA_ARGS__)), \
dummy, \
CRITERION_ASSERT_MSG_EXPR_FALSE, \
(CR_STR(!(CR_VA_HEAD(__VA_ARGS__)))), \
CR_VA_TAIL(__VA_ARGS__) \
))
// Binary
# define cr_assert_op_(Fail, Op, Actual, Expected, ...) \
CR_EXPAND(cr_assert_impl( \
Fail, \
(Actual) Op (Expected), \
dummy, \
CRITERION_ASSERT_MSG_EXPR_FALSE, \
(CR_STR((Actual) Op (Expected))), \
__VA_ARGS__ \
))
# define cr_assert_op_va_(Fail, Op, ...) \
CR_EXPAND(cr_assert_op_( \
Fail, \
Op, \
CR_VA_HEAD(__VA_ARGS__), \
CR_VA_HEAD(CR_VA_TAIL(__VA_ARGS__)), \
CR_VA_TAIL(CR_VA_TAIL(__VA_ARGS__)) \
))
// Unary
# define cr_assert_null_op_(Fail, Op, Msg, Value, ...) \
CR_EXPAND(cr_assert_impl( \
Fail, \
(Value) Op NULL, \
dummy, \
Msg, \
(CR_STR(Value)), \
__VA_ARGS__ \
))
# define cr_assert_null_op_va_(Fail, Op, Msg, ...) \
CR_EXPAND(cr_assert_null_op_( \
Fail, \
Op, \
Msg, \
CR_VA_HEAD(__VA_ARGS__), \
CR_VA_TAIL(__VA_ARGS__) \
))
// Floating point
# define cr_assert_float_eq_op_(Actual, Expected, Epsilon) \
(Expected) - (Actual) <= (Epsilon) && (Actual) - (Expected) <= (Epsilon)
# define cr_assert_float_neq_op_(Actual, Expected, Epsilon) \
(Expected) - (Actual) > (Epsilon) || (Actual) - (Expected) > (Epsilon)
# define cr_assert_float_op_(Fail, Op, Actual, Expected, Epsilon, ...) \
CR_EXPAND(cr_assert_impl( \
Fail, \
Op(Actual, Expected, Epsilon), \
dummy, \
CRITERION_ASSERT_MSG_EXPR_FALSE, \
(CR_STR(Op(Actual, Expected, Epsilon))), \
__VA_ARGS__ \
))
# define cr_assert_float_op_va_(Fail, Op, ...) \
CR_EXPAND(cr_assert_float_op_( \
Fail, \
Op, \
CR_VA_HEAD(__VA_ARGS__), \
CR_VA_HEAD(CR_VA_TAIL(__VA_ARGS__)), \
CR_VA_HEAD(CR_VA_TAIL(CR_VA_TAIL(__VA_ARGS__))), \
CR_VA_TAIL(CR_VA_TAIL(CR_VA_TAIL(__VA_ARGS__))) \
))
// String
# define cr_assert_str_op_empty_(Fail, Op, Msg, Value, ...) \
CR_EXPAND(cr_assert_impl( \
Fail, \
(Value)[0] Op '\0', \
dummy, \
Msg, \
(CR_STR(Value)), \
__VA_ARGS__ \
))
# define cr_assert_str_op_empty_va_(Fail, Op, Msg, ...) \
CR_EXPAND(cr_assert_str_op_empty_( \
Fail, \
Op, \
Msg, \
CR_VA_HEAD(__VA_ARGS__), \
CR_VA_TAIL(__VA_ARGS__) \
))
# define cr_assert_str_op_(Fail, Op, Actual, Expected, ...) \
CR_EXPAND(cr_assert_impl( \
Fail, \
CR_STDN strcmp((Actual), (Expected)) Op 0, \
dummy, \
CRITERION_ASSERT_MSG_EXPR_AS_STRINGS_FALSE, \
(CR_STR((Actual) Op (Expected))), \
__VA_ARGS__ \
))
# define cr_assert_str_op_va_(Fail, Op, ...) \
CR_EXPAND(cr_assert_str_op_( \
Fail, \
Op, \
CR_VA_HEAD(__VA_ARGS__), \
CR_VA_HEAD(CR_VA_TAIL(__VA_ARGS__)), \
CR_VA_TAIL(CR_VA_TAIL(__VA_ARGS__)) \
))
// Array
# define cr_assert_mem_op_(Fail, Op, Actual, Expected, Size, ...) \
CR_EXPAND(cr_assert_impl( \
Fail, \
CR_STDN memcmp((Actual), (Expected), (Size)) Op 0, \
dummy, \
CRITERION_ASSERT_MSG_EXPR_FALSE, \
(CR_STR((Actual)[0 .. Size] Op (Expected)[0 .. Size])), \
__VA_ARGS__ \
))
# define cr_assert_mem_op_va_(Fail, Op, ...) \
CR_EXPAND(cr_assert_mem_op_( \
Fail, \
Op, \
CR_VA_HEAD(__VA_ARGS__), \
CR_VA_HEAD(CR_VA_TAIL(__VA_ARGS__)), \
CR_VA_HEAD(CR_VA_TAIL(CR_VA_TAIL(__VA_ARGS__))), \
CR_VA_TAIL(CR_VA_TAIL(CR_VA_TAIL(__VA_ARGS__))) \
))
// Array comparisons
# ifdef __cplusplus
# define CR_ARR_COMPARE_(A, B, Size, Cmp, Result) \
int Result = std::lexicographical_compare((A), (A) + Size, (B), (B) + Size, Cmp)
# else
# define CR_ARR_COMPARE_(A, B, Size, Cmp, Result) \
__typeof__(&(A)[0]) first = (A); \
__typeof__(&(B)[0]) second = (B); \
int Result = 0; \
size_t i, size; \
for (i = 0, size = (Size); !Result && i < size; ++i) \
Result = Cmp(first + i, second + i)
# endif
# define cr_assert_arr_op_cmp_(Fail, Op, Actual, Expected, Size, Cmp, ...) \
do { \
CR_ARR_COMPARE_(Actual, Expected, Size, Cmp, order); \
CR_EXPAND(cr_assert_impl( \
Fail, \
order Op 0, \
dummy, \
CRITERION_ASSERT_MSG_EXPR_FALSE, \
(CR_STR((Actual)[0 .. Size] Op (Expected)[0 .. Size])), \
__VA_ARGS__ \
)); \
} while (0)
# define cr_assert_arr_op_cmp_va_(Fail, Op, ...) \
CR_EXPAND(cr_assert_arr_op_cmp_( \
Fail, \
Op, \
CR_VA_HEAD(__VA_ARGS__), \
CR_VA_HEAD(CR_VA_TAIL(__VA_ARGS__)), \
CR_VA_HEAD(CR_VA_TAIL(CR_VA_TAIL(__VA_ARGS__))), \
CR_VA_HEAD(CR_VA_TAIL(CR_VA_TAIL(CR_VA_TAIL(__VA_ARGS__)))), \
CR_VA_TAIL(CR_VA_TAIL(CR_VA_TAIL(CR_VA_TAIL(__VA_ARGS__)))) \
))
// Exceptions
# define cr_assert_throw_abort_(Fail, Msg, MsgArgs, ...) \
CR_EXPAND(cr_assert_impl( \
Fail, \
0, \
dummy, \
Msg, \
MsgArgs, \
CR_VA_TAIL(__VA_ARGS__) \
))
# define cr_assert_throw_(Fail, Statement, Exception, ...) \
try { \
Statement; \
} catch (Exception const &) { \
} catch (...) { \
CR_EXPAND(cr_assert_throw_abort_( \
Fail, \
CRITERION_ASSERT_MSG_NO_THROW, \
(CR_STR(Statement), CR_STR(Exception)), \
__VA_ARGS__)); \
}
# define cr_assert_throw_va_(...) \
CR_EXPAND(cr_assert_throw_( \
CR_VA_HEAD(__VA_ARGS__), \
CR_VA_HEAD(CR_VA_TAIL(__VA_ARGS__)), \
CR_VA_HEAD(CR_VA_TAIL(CR_VA_TAIL(__VA_ARGS__))), \
dummy, \
CR_VA_TAIL(CR_VA_TAIL(CR_VA_TAIL(__VA_ARGS__))) \
))
# define cr_assert_no_throw_(Fail, Statement, Exception, ...) \
try { \
Statement; \
} catch (Exception const &) { \
CR_EXPAND(cr_assert_throw_abort_( \
Fail, \
CRITERION_ASSERT_MSG_THROW, \
(CR_STR(Statement), CR_STR(Exception)), \
__VA_ARGS__)); \
}
# define cr_assert_no_throw_va_(...) \
CR_EXPAND(cr_assert_no_throw_( \
CR_VA_HEAD(__VA_ARGS__), \
CR_VA_HEAD(CR_VA_TAIL(__VA_ARGS__)), \
CR_VA_HEAD(CR_VA_TAIL(CR_VA_TAIL(__VA_ARGS__))), \
dummy, \
CR_VA_TAIL(CR_VA_TAIL(CR_VA_TAIL(__VA_ARGS__))) \
))
# define cr_assert_any_throw_(Fail, Statement, ...) \
try { \
Statement; \
CR_EXPAND(cr_assert_throw_abort_( \
Fail, \
CRITERION_ASSERT_MSG_ANY_THROW, \
(CR_STR(Statement)), \
__VA_ARGS__)); \
} catch (...) {}
# define cr_assert_any_throw_va_(...) \
CR_EXPAND(cr_assert_any_throw_( \
CR_VA_HEAD(__VA_ARGS__), \
CR_VA_HEAD(CR_VA_TAIL(__VA_ARGS__)), \
dummy, \
CR_VA_TAIL(CR_VA_TAIL(__VA_ARGS__)) \
))
# define cr_assert_none_throw_(Fail, Statement, ...) \
try { \
Statement; \
} catch (...) { \
CR_EXPAND(cr_assert_throw_abort_( \
Fail, \
CRITERION_ASSERT_MSG_NONE_THROW, \
(CR_STR(Statement)), \
__VA_ARGS__)); \
}
# define cr_assert_none_throw_va_(...) \
CR_EXPAND(cr_assert_none_throw_( \
CR_VA_HEAD(__VA_ARGS__), \
CR_VA_HEAD(CR_VA_TAIL(__VA_ARGS__)), \
dummy, \
CR_VA_TAIL(CR_VA_TAIL(__VA_ARGS__)) \
))
// Messages
# define CRITERION_GNUC_WARN__(Msg) \
_Pragma(#Msg)
# define CRITERION_GNUC_WARN_(Name) CRITERION_GNUC_WARN__( \
message \
"The `" #Name "` macro is only available on GNU C compilers." \
)
#endif /* !CRITERION_INTERNAL_ASSERT_H_ */

View file

@ -42,7 +42,11 @@
# endif
# ifdef __cplusplus
# define CR_ATTRIBUTE(Arg) [[gnu::Arg]]
# ifdef __GNUC__
# define CR_ATTRIBUTE(Arg) __attribute__((Arg))
# else
# define CR_ATTRIBUTE(Arg) [[gnu::Arg]]
# endif
# define CR_BEGIN_C_API extern "C" {
# define CR_END_C_API }
# else
@ -52,74 +56,74 @@
# endif
# ifdef __APPLE__
# define SECTION_START_PREFIX __first
# define SECTION_END_PREFIX __last
# define SECTION_START_SUFFIX(Name) __asm("section$start$__DATA$" Name)
# define SECTION_END_SUFFIX(Name) __asm("section$end$__DATA$" Name)
# define SECTION_(Name) CR_ATTRIBUTE(section("__DATA," Name))
# define SECTION_SUFFIX_
# define CR_SECTION_START_PREFIX __first
# define CR_SECTION_END_PREFIX __last
# define CR_SECTION_START_SUFFIX(Name) __asm("section$start$__DATA$" Name)
# define CR_SECTION_END_SUFFIX(Name) __asm("section$end$__DATA$" Name)
# define CR_SECTION_(Name) CR_ATTRIBUTE(section("__DATA," Name))
# define CR_SECTION_SUFFIX_
# elif CR_IS_MSVC
# define SECTION_START_PREFIX __start
# define SECTION_END_PREFIX __stop
# define SECTION_START_SUFFIX(Name)
# define SECTION_END_SUFFIX(Name)
# define SECTION_(Name) \
# define CR_SECTION_START_PREFIX __start
# define CR_SECTION_END_PREFIX __stop
# define CR_SECTION_START_SUFFIX(Name)
# define CR_SECTION_END_SUFFIX(Name)
# define CR_SECTION_(Name) \
__pragma(data_seg(push)) \
__pragma(section(Name, read)) \
__declspec(allocate(Name))
# define SECTION_SUFFIX_ \
# define CR_SECTION_SUFFIX_ \
__pragma(data_seg(pop))
# else
# define SECTION_START_PREFIX __start
# define SECTION_END_PREFIX __stop
# define SECTION_START_SUFFIX(Name)
# define SECTION_END_SUFFIX(Name)
# define SECTION_(Name) CR_ATTRIBUTE(section(Name))
# define SECTION_SUFFIX_
# define CR_SECTION_START_PREFIX __start
# define CR_SECTION_END_PREFIX __stop
# define CR_SECTION_START_SUFFIX(Name)
# define CR_SECTION_END_SUFFIX(Name)
# define CR_SECTION_(Name) CR_ATTRIBUTE(section(Name))
# define CR_SECTION_SUFFIX_
# endif
# define MAKE_IDENTIFIER_(Prefix, Id) MAKE_IDENTIFIER__(Prefix, Id)
# define MAKE_IDENTIFIER__(Prefix, Id) Prefix ## _ ## Id
# define CR_MAKE_IDENTIFIER_(Prefix, Id) CR_MAKE_IDENTIFIER__(Prefix, Id)
# define CR_MAKE_IDENTIFIER__(Prefix, Id) Prefix ## _ ## Id
# define SECTION_START_(Name) MAKE_IDENTIFIER_(SECTION_START_PREFIX, Name)
# define SECTION_END_(Name) MAKE_IDENTIFIER_(SECTION_END_PREFIX, Name)
# define CR_SECTION_START_(Name) CR_MAKE_IDENTIFIER_(CR_SECTION_START_PREFIX, Name)
# define CR_SECTION_END_(Name) CR_MAKE_IDENTIFIER_(CR_SECTION_END_PREFIX, Name)
# define SECTION_START(Name) g_ ## Name ## _section_start
# define SECTION_END(Name) g_ ## Name ## _section_end
# define CR_SECTION_START(Name) g_ ## Name ## _section_start
# define CR_SECTION_END(Name) g_ ## Name ## _section_end
# define DECL_SECTION_LIMITS(Type, Name) DECL_SECTION_LIMITS_(Type, Name)
# define DECL_SECTION_LIMITS_(Type, Name) \
extern Type SECTION_START_(Name) SECTION_START_SUFFIX(#Name); \
extern Type SECTION_END_(Name) SECTION_END_SUFFIX(#Name)
# define CR_DECL_SECTION_LIMITS(Type, Name) CR_DECL_SECTION_LIMITS_(Type, Name)
# define CR_DECL_SECTION_LIMITS_(Type, Name) \
extern Type CR_SECTION_START_(Name) CR_SECTION_START_SUFFIX(#Name); \
extern Type CR_SECTION_END_(Name) CR_SECTION_END_SUFFIX(#Name)
# define IMPL_SECTION_LIMITS(Type, Name) \
Type *const SECTION_START(Name) = &SECTION_START_(Name); \
Type *const SECTION_END(Name) = &SECTION_END_(Name)
# define CR_IMPL_SECTION_LIMITS(Type, Name) \
Type *const CR_SECTION_START(Name) = &CR_SECTION_START_(Name); \
Type *const CR_SECTION_END(Name) = &CR_SECTION_END_(Name)
# ifdef __GNUC__
# define UNUSED CR_ATTRIBUTE(unused)
# define NORETURN CR_ATTRIBUTE(noreturn)
# define CR_UNUSED CR_ATTRIBUTE(unused)
# define CR_NORETURN CR_ATTRIBUTE(noreturn)
# define CR_INLINE CR_ATTRIBUTE(always_inline) inline
# elif CR_IS_MSVC
# define UNUSED
# define NORETURN __declspec(noreturn)
# define CR_UNUSED __pragma(warning(suppress:4100))
# define CR_NORETURN __declspec(noreturn)
# define CR_INLINE __forceinline
# else
# define UNUSED
# define NORETURN
# define CR_UNUSED
# define CR_NORETURN
# define CR_INLINE inline
# endif
# ifdef _WIN32
# define SIZE_T_FORMAT "%Iu"
# define CR_SIZE_T_FORMAT "%Iu"
# else
# define SIZE_T_FORMAT "%zu"
# define CR_SIZE_T_FORMAT "%zu"
# endif
# ifdef __GNUC__
# define FORMAT(Archetype, Index, Ftc) CR_ATTRIBUTE(format(Archetype, Index, Ftc))
# define CR_FORMAT(Archetype, Index, Ftc) CR_ATTRIBUTE(format(Archetype, Index, Ftc))
# else
# define FORMAT(Archetype, Index, Ftc)
# define CR_FORMAT(Archetype, Index, Ftc)
# endif
# if defined _WIN32 || defined __CYGWIN__

View file

@ -112,11 +112,11 @@
CR_EXPAND(CRITERION_APPLY(CRITERION_ADD_PREFIX_ONCE, __VA_ARGS__))
# ifdef __cplusplus
# define CRITERION_MAKE_STRUCT(Type, ...) []() { \
Type t; \
std::memset(&t, 0, sizeof (t)); \
CR_EXPAND(CRITERION_ADD_PREFIX(t, __VA_ARGS__)) \
return t; \
# define CRITERION_MAKE_STRUCT(Type, ...) []() -> Type { \
Type t; \
std::memset(&t, 0, sizeof (t)); \
CR_EXPAND(CRITERION_ADD_PREFIX(t, __VA_ARGS__)) \
return t; \
}()
# else
# define CRITERION_MAKE_STRUCT(Type, ...) { __VA_ARGS__ }

View file

@ -0,0 +1,84 @@
/*
* The MIT License (MIT)
*
* Copyright © 2015 Franklin "Snaipe" Mathieu <http://snai.pe/>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#ifndef CRITERION_INTERNAL_HOOKS_H_
# define CRITERION_INTERNAL_HOOKS_H_
# include "common.h"
# include "../types.h"
# define CR_HOOK_IDENTIFIER_(Suffix) CR_HOOK_IDENTIFIER__(__LINE__, Suffix)
# define CR_HOOK_IDENTIFIER__(Line, Suffix) CR_HOOK_IDENTIFIER___(Line, Suffix)
# define CR_HOOK_IDENTIFIER___(Line, Suffix) hook_l ## Line ## _ ## Suffix
# ifdef __cplusplus
# define CR_HOOK_PROTOTYPE_ \
extern "C" void CR_HOOK_IDENTIFIER_(impl)
# else
# define CR_HOOK_PROTOTYPE_ \
void CR_HOOK_IDENTIFIER_(impl)
# endif
// Section abbreviations
# define CR_HOOK_SECTION_PRE_ALL cr_pra
# define CR_HOOK_SECTION_PRE_SUITE cr_prs
# define CR_HOOK_SECTION_PRE_INIT cr_pri
# define CR_HOOK_SECTION_PRE_TEST cr_prt
# define CR_HOOK_SECTION_ASSERT cr_ast
# define CR_HOOK_SECTION_THEORY_FAIL cr_thf
# define CR_HOOK_SECTION_TEST_CRASH cr_tsc
# define CR_HOOK_SECTION_POST_TEST cr_pot
# define CR_HOOK_SECTION_POST_FINI cr_pof
# define CR_HOOK_SECTION_POST_SUITE cr_pos
# define CR_HOOK_SECTION_POST_ALL cr_poa
# define CR_HOOK_SECTION(Kind) CR_HOOK_SECTION_ ## Kind
# define CR_HOOK_SECTION_STRINGIFY__(Sec) #Sec
# define CR_HOOK_SECTION_STRINGIFY_(Sec) CR_HOOK_SECTION_STRINGIFY__(Sec)
# define CR_HOOK_SECTION_STRINGIFY(Kind) CR_HOOK_SECTION_STRINGIFY_(CR_HOOK_SECTION(Kind))
# define CR_HOOK_PARAM_TYPE_PRE_ALL struct criterion_test_set *
# define CR_HOOK_PARAM_TYPE_PRE_SUITE struct criterion_suite_set *
# define CR_HOOK_PARAM_TYPE_PRE_INIT struct criterion_test *
# define CR_HOOK_PARAM_TYPE_PRE_TEST struct criterion_test *
# define CR_HOOK_PARAM_TYPE_ASSERT struct criterion_assert_stats *
# define CR_HOOK_PARAM_TYPE_THEORY_FAIL struct criterion_theory_stats *
# define CR_HOOK_PARAM_TYPE_TEST_CRASH struct criterion_test_stats *
# define CR_HOOK_PARAM_TYPE_POST_TEST struct criterion_test_stats *
# define CR_HOOK_PARAM_TYPE_POST_FINI struct criterion_test_stats *
# define CR_HOOK_PARAM_TYPE_POST_SUITE struct criterion_suite_stats *
# define CR_HOOK_PARAM_TYPE_POST_ALL struct criterion_global_stats *
# define CR_HOOK_PARAM_TYPE(Kind) CR_HOOK_PARAM_TYPE_ ## Kind
# define CR_REPORT_HOOK_IMPL(Kind) \
CR_HOOK_PROTOTYPE_(CR_HOOK_PARAM_TYPE(Kind)); \
CR_SECTION_(CR_HOOK_SECTION_STRINGIFY(Kind)) \
f_report_hook CR_HOOK_IDENTIFIER_(func) = \
(f_report_hook) CR_HOOK_IDENTIFIER_(impl) \
CR_SECTION_SUFFIX_; \
CR_HOOK_PROTOTYPE_
#endif /* !CRITERION_INTERNAL_HOOKS_H_ */

View file

@ -24,7 +24,7 @@
#ifndef CRITERION_ORDERED_SET_H_
# define CRITERION_ORDERED_SET_H_
# include "types.h"
# include "../types.h"
typedef int (*f_criterion_cmp)(void *, void *);
@ -37,7 +37,6 @@ struct criterion_ordered_set {
struct criterion_ordered_set_node {
struct criterion_ordered_set_node *next;
char data[0];
};
CR_BEGIN_C_API
@ -54,6 +53,6 @@ CR_END_C_API
# define FOREACH_SET(Elt, Set) \
for (struct criterion_ordered_set_node *n = Set->first; n; n = n->next) \
for (int cond = 1; cond;) \
for (Elt = (void*) n->data; cond && (cond = 0, 1);)
for (Elt = (void*) (n + 1); cond && (cond = 0, 1);)
#endif /* !CRITERION_ORDERED_SET_H_ */

View file

@ -0,0 +1,115 @@
/*
* The MIT License (MIT)
*
* Copyright © 2015 Franklin "Snaipe" Mathieu <http://snai.pe/>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#ifndef CRITERION_INTERNAL_PARAMETERIZED_H_
# define CRITERION_INTERNAL_PARAMETERIZED_H_
# include "test.h"
# include "../types.h"
struct criterion_test_params {
size_t size;
void *params;
size_t length;
void (*cleanup)(struct criterion_test_params *);
# ifdef __cplusplus
constexpr criterion_test_params(size_t size, void *params, size_t length)
: size(size)
, params(params)
, length(length)
, cleanup(nullptr)
{}
constexpr criterion_test_params(size_t size, void *params, size_t length,
void (*cleanup)(struct criterion_test_params *))
: size(size)
, params(params)
, length(length)
, cleanup(cleanup)
{}
template <typename T>
constexpr criterion_test_params(std::vector<T, criterion::allocator<T>>& vec,
void (*cleanup)(criterion_test_params *) = nullptr)
: size(sizeof (T))
, params(&vec[0])
, length(vec.size())
, cleanup(cleanup)
{}
template <typename T, unsigned int N>
constexpr criterion_test_params(T (&arr)[N],
void (*cleanup)(criterion_test_params *) = nullptr)
: size(sizeof (arr[0]))
, params(static_cast<void*>(&arr))
, length(N)
, cleanup(cleanup)
{}
# endif
};
# ifdef __cplusplus
# define CR_PARAM_TEST_PROTOTYPE_(Param, Category, Name) \
extern "C" void CR_IDENTIFIER_(Category, Name, impl)(Param)
# else
# define CR_PARAM_TEST_PROTOTYPE_(Param, Category, Name) \
void CR_IDENTIFIER_(Category, Name, impl)(Param)
# endif
# define CR_PARAM_TEST_BASE(Param, Category, Name, ...) \
CR_PARAM_TEST_PROTOTYPE_(Param, Category, Name); \
CR_TEST_TRAMPOLINE_(Category, Name) \
struct criterion_test_extra_data CR_IDENTIFIER_(Category, Name, extra) = \
CR_EXPAND(CRITERION_MAKE_STRUCT(criterion_test_extra_data, \
.lang_ = CR_LANG, \
.kind_ = CR_TEST_PARAMETERIZED, \
.param_ = CR_IDENTIFIER_(Category, Name, param), \
.identifier_ = #Category "/" #Name, \
.file_ = __FILE__, \
.line_ = __LINE__, \
__VA_ARGS__ \
)); \
struct criterion_test CR_IDENTIFIER_(Category, Name, meta) = { \
#Name, \
#Category, \
CR_IDENTIFIER_(Category, Name, jmp), \
&CR_IDENTIFIER_(Category, Name, extra) \
}; \
CR_SECTION_("cr_tst") \
struct criterion_test *CR_IDENTIFIER_(Category, Name, ptr) \
= &CR_IDENTIFIER_(Category, Name, meta) CR_SECTION_SUFFIX_; \
CR_PARAM_TEST_PROTOTYPE_(Param, Category, Name)
# define CR_PARAM_TEST_PARAMS(Category, Name) \
static struct criterion_test_params CR_IDENTIFIER_(Category, Name, param)(void)
# ifdef __cplusplus
# define cr_make_param_array_(Type, Array, ...) \
criterion_test_params(sizeof (Type), (Array), __VA_ARGS__)
# else
# define cr_make_param_array_(Type, Array, ...) \
(struct criterion_test_params) { .size = sizeof (Type), (void*)(Array), __VA_ARGS__ }
# endif
#endif /* !CRITERION_INTERNAL_PARAMETERIZED_H_ */

View file

@ -0,0 +1,71 @@
/*
* The MIT License (MIT)
*
* Copyright © 2015 Franklin "Snaipe" Mathieu <http://snai.pe/>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#ifndef CRITERION_INTERNAL_REDIRECT_H_
# define CRITERION_INTERNAL_REDIRECT_H_
# include "common.h"
# include "assert.h"
# define cr_assert_redir_op_(Fail, Fun, Op, File, Str, ...) \
CR_EXPAND(cr_assert_impl( \
Fail, \
!(Fun((File), (Str)) Op 0), \
dummy, \
CRITERION_ASSERT_MSG_FILE_STR_MATCH, \
(CR_STR(File), Str), \
__VA_ARGS__ \
))
# define cr_assert_redir_op_va_(Fail, Fun, Op, ...) \
CR_EXPAND(cr_assert_redir_op_( \
Fail, \
Fun, \
Op, \
CR_VA_HEAD(__VA_ARGS__), \
CR_VA_HEAD(CR_VA_TAIL(__VA_ARGS__)), \
CR_VA_TAIL(CR_VA_TAIL(__VA_ARGS__)) \
))
# define cr_assert_redir_f_op_(Fail, Fun, Op, File, Ref, ...) \
CR_EXPAND(cr_assert_impl( \
Fail, \
!(Fun((File), (Ref)) Op 0), \
dummy, \
CRITERION_ASSERT_MSG_FILE_MATCH, \
(CR_STR(File), CR_STR(Ref)), \
__VA_ARGS__ \
))
# define cr_assert_redir_f_op_va_(Fail, Fun, Op, ...) \
CR_EXPAND(cr_assert_redir_op_( \
Fail, \
Fun, \
Op, \
CR_VA_HEAD(__VA_ARGS__), \
CR_VA_HEAD(CR_VA_TAIL(__VA_ARGS__)), \
CR_VA_TAIL(CR_VA_TAIL(__VA_ARGS__)) \
))
#endif /* !CRITERION_INTERNAL_REDIRECT_H_ */

View file

@ -0,0 +1,138 @@
#ifndef CRITERION_INTERNAL_STDIO_FILEBUF_HXX_
# define CRITERION_INTERNAL_STDIO_FILEBUF_HXX_
# include <fstream>
namespace criterion { namespace internal {
template <typename CharT, typename Traits = std::char_traits<CharT>>
class stdio_sync_filebuf : public std::basic_streambuf<CharT, Traits> {
public:
typedef Traits traits;
typedef std::basic_filebuf<CharT, Traits> super;
typedef typename Traits::int_type int_type;
typedef typename Traits::pos_type pos_type;
typedef typename Traits::off_type off_type;
stdio_sync_filebuf(std::FILE *file)
: file(file)
, lastchar(Traits::eof())
{}
stdio_sync_filebuf(stdio_sync_filebuf&& other) = default;
stdio_sync_filebuf& operator=(stdio_sync_filebuf&& other) = default;
void swap(stdio_sync_filebuf& other) {
super::swap(other);
std::swap(file, other.file);
std::swap(lastchar, other.lastchar);
}
protected:
int_type syncgetc();
int_type syncungetc(int_type);
int_type syncputc(int_type);
virtual std::streampos seekoff(std::streamoff off,
std::ios_base::seekdir dir,
std::ios_base::openmode = std::ios_base::in | std::ios_base::out) {
int whence;
if (dir == std::ios_base::beg)
whence = SEEK_SET;
else if (dir == std::ios_base::cur)
whence = SEEK_CUR;
else
whence = SEEK_END;
if (!fseek(file, off, whence))
return std::streampos(std::ftell(file));
return std::streamoff(-1);
}
virtual std::streampos seekpos(std::streampos pos,
std::ios_base::openmode mode = std::ios_base::in | std::ios_base::out) {
return seekoff(std::streamoff(pos), std::ios_base::beg, mode);
}
virtual std::streamsize xsgetn(CharT* s, std::streamsize n);
virtual std::streamsize xsputn(const CharT* s, std::streamsize n);
virtual int sync() {
return std::fflush(file);
}
virtual int_type underflow() {
int_type c = syncgetc();
return syncungetc(c);
}
virtual int_type uflow() {
return lastchar = syncgetc();
}
static inline bool is_eof(int_type c) {
static const int_type eof = Traits::eof();
return Traits::eq_int_type(c, eof);
}
virtual int_type overflow(int_type c = Traits::eof()) {
int_type ret;
if (is_eof(c)) {
if (std::fflush(file))
ret = Traits::eof();
else
ret = Traits::not_eof(c);
} else {
ret = syncputc(c);
}
return ret;
}
virtual int_type pbackfail(int_type c = Traits::eof()) {
int_type ret = syncungetc(is_eof(c) && !is_eof(lastchar) ? lastchar : c);
lastchar = Traits::eof();
return ret;
}
private:
std::FILE *file;
bool file_open;
int_type lastchar;
};
template <>
inline stdio_sync_filebuf<char>::int_type
stdio_sync_filebuf<char>::syncgetc() {
return std::getc(file);
}
template <>
inline stdio_sync_filebuf<char>::int_type
stdio_sync_filebuf<char>::syncungetc(stdio_sync_filebuf<char>::int_type c) {
return std::ungetc(c, file);
}
template <>
inline stdio_sync_filebuf<char>::int_type
stdio_sync_filebuf<char>::syncputc(stdio_sync_filebuf<char>::int_type c) {
return std::putc(c, file);
}
template <>
inline std::streamsize
stdio_sync_filebuf<char>::xsgetn(char *s, std::streamsize n) {
std::streamsize res = std::fread(s, 1, n, file);
lastchar = res > 0 ? traits::to_int_type(s[res - 1]) : traits::eof();
return res;
}
template <>
inline std::streamsize
stdio_sync_filebuf<char>::xsputn(const char *s, std::streamsize n) {
return std::fwrite(s, 1, n, file);
}
}}
#endif /* !CRITERION_INTERNAL_STDIO_FILEBUF_HXX_ */

View file

@ -0,0 +1,110 @@
#ifndef CRITERION_INTERNAL_STREAM_HXX_
# define CRITERION_INTERNAL_STREAM_HXX_
# include <fstream>
# include <cstdio>
# include <memory>
# include "stdio_filebuf.hxx"
namespace criterion { namespace internal {
template <typename CharT, typename Super>
class stream_mixin : public Super {
public:
stream_mixin(FILE* f)
: Super()
, fbuf(new stdio_sync_filebuf<CharT>(f))
, file(f)
{
std::ios::rdbuf(&*fbuf);
}
# if __cplusplus > 199711L
stream_mixin(const stream_mixin& other) = delete;
stream_mixin& operator=(const stream_mixin& other) = delete;
# endif
stream_mixin(stream_mixin&& other) :
fbuf(std::move(other.fbuf)),
file(std::move(other.file))
{}
stream_mixin& operator=(stream_mixin&& other) {
fbuf = std::move(other.fbuf);
file = std::move(other.file);
}
void close(void) {
Super::flush();
Super::close();
std::fclose(file);
}
private:
std::shared_ptr<stdio_sync_filebuf<CharT>> fbuf;
std::FILE* file;
};
template <typename CharT>
class basic_ofstream : public stream_mixin<CharT, std::basic_ofstream<CharT>> {
typedef stream_mixin<CharT, std::basic_ofstream<CharT>> super;
public:
basic_ofstream(FILE* f)
: super(f)
{}
basic_ofstream(basic_ofstream&& other)
: super(std::move(other))
{}
};
template <typename CharT>
class basic_ifstream : public stream_mixin<CharT, std::basic_ifstream<CharT>> {
typedef stream_mixin<CharT, std::basic_ifstream<CharT>> super;
public:
basic_ifstream(FILE* f)
: super(f)
{}
basic_ifstream(basic_ifstream&& other)
: super(std::move(other))
{}
};
template <typename CharT>
class basic_fstream : public stream_mixin<CharT, std::basic_fstream<CharT>> {
typedef stream_mixin<CharT, std::basic_fstream<CharT>> super;
public:
basic_fstream(FILE* f)
: super(f)
{}
basic_fstream(basic_fstream&& other)
: super(std::move(other))
{}
};
struct get_redirected_out_stream_ {
static inline basic_ofstream<char>& call(std::FILE* f) {
static std::unique_ptr<basic_ofstream<char>> stream;
if (!stream)
stream.reset(new basic_ofstream<char>(f));
return *stream;
}
};
struct get_redirected_in_stream_ {
static inline basic_ifstream<char>& call(std::FILE* f) {
static std::unique_ptr<basic_ifstream<char>> stream;
if (!stream)
stream.reset(new basic_ifstream<char>(f));
return *stream;
}
};
}}
#endif /* !CRITERION_INTERNAL_STREAM_HXX_ */

View file

@ -0,0 +1,185 @@
/*
* The MIT License (MIT)
*
* Copyright © 2015 Franklin "Snaipe" Mathieu <http://snai.pe/>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#ifndef CRITERION_INTERNAL_TEST_H_
# define CRITERION_INTERNAL_TEST_H_
# include "designated-initializer-compat.h"
# include "common.h"
# ifdef __OBJC__
#import <Foundation/Foundation.h>
# endif
# ifdef __cplusplus
# include <exception>
# endif
# define CR_IDENTIFIER_(Category, Name, Suffix) \
Category ## _ ## Name ## _ ## Suffix
# ifdef __cplusplus
# ifdef __OBJC__
# define CR_LANG CR_LANG_OBJCXX
# else
# define CR_LANG CR_LANG_CXX
# endif
# else
# ifdef __OBJC__
# define CR_LANG CR_LANG_OBJC
# else
# define CR_LANG CR_LANG_C
# endif
# endif
# ifdef __cplusplus
# define CR_TEST_PROTOTYPE_(Category, Name) \
extern "C" void CR_IDENTIFIER_(Category, Name, impl)(void)
# else
# define CR_TEST_PROTOTYPE_(Category, Name) \
void CR_IDENTIFIER_(Category, Name, impl)(void)
# endif
# define CR_SUITE_IDENTIFIER_(Name, Suffix) \
suite_ ## Name ## _ ## Suffix
CR_BEGIN_C_API
CR_API void criterion_internal_test_setup(void);
CR_API void criterion_internal_test_main(void (*fn)(void));
CR_API void criterion_internal_test_teardown(void);
CR_END_C_API
static const char *const cr_msg_test_init_std_exception = "Caught an unexpected exception during the test initialization: %s.";
static const char *const cr_msg_test_init_other_exception = "Caught some unexpected exception during the test initialization.";
static const char *const cr_msg_test_main_std_exception = "Caught an unexpected exception during the test execution: %s.";
static const char *const cr_msg_test_main_other_exception = "Caught some unexpected exception during the test execution.";
static const char *const cr_msg_test_fini_std_exception = "Caught an unexpected exception during the test finalization: %s.";
static const char *const cr_msg_test_fini_other_exception = "Caught some unexpected exception during the test finalization.";
# ifdef __cplusplus
# define CR_TEST_TRAMPOLINE_(Category, Name) \
static inline void CR_IDENTIFIER_(Category, Name, jmp)(void) { \
try { \
criterion_internal_test_setup(); \
} catch (const std::exception &e) { \
criterion_test_die(cr_msg_test_init_std_exception, e.what()); \
} catch (...) { \
criterion_test_die(cr_msg_test_init_other_exception); \
} \
try { \
criterion_internal_test_main((void(*)(void)) CR_IDENTIFIER_(Category, Name, impl)); \
} catch (const std::exception &e) { \
criterion_test_die(cr_msg_test_main_std_exception, e.what()); \
} catch (...) { \
criterion_test_die(cr_msg_test_main_other_exception); \
} \
try { \
criterion_internal_test_teardown(); \
} catch (const std::exception &e) { \
criterion_test_die(cr_msg_test_fini_std_exception, e.what()); \
} catch (...) { \
criterion_test_die(cr_msg_test_fini_other_exception); \
} \
}
# else
# if defined(__OBJC__) && defined(__EXCEPTIONS)
# define CR_TEST_TRAMPOLINE_(Category, Name) \
static inline void CR_IDENTIFIER_(Category, Name, jmp)(void) { \
@try { \
criterion_internal_test_setup(); \
} @catch (NSException *e) { \
NSString *reason = [e reason]; \
criterion_test_die(cr_msg_test_init_std_exception, [reason UTF8String]); \
} @catch (...) { \
criterion_test_die(cr_msg_test_init_other_exception); \
} \
@try { \
criterion_internal_test_main((void(*)(void)) CR_IDENTIFIER_(Category, Name, impl)); \
} @catch (NSException *e) { \
NSString *reason = [e reason]; \
criterion_test_die(cr_msg_test_main_std_exception, [reason UTF8String]); \
} @catch (...) { \
criterion_test_die(cr_msg_test_main_other_exception); \
} \
@try { \
criterion_internal_test_teardown(); \
} @catch (NSException *e) { \
NSString *reason = [e reason]; \
criterion_test_die(cr_msg_test_fini_std_exception, [reason UTF8String]); \
} @catch (...) { \
criterion_test_die(cr_msg_test_fini_other_exception); \
} \
}
# else
# define CR_TEST_TRAMPOLINE_(Category, Name) \
static inline void CR_IDENTIFIER_(Category, Name, jmp)(void) { \
criterion_internal_test_setup(); \
criterion_internal_test_main((void(*)(void)) CR_IDENTIFIER_(Category, Name, impl)); \
criterion_internal_test_teardown(); \
}
# endif
# endif
# define CR_TEST_BASE(Category, Name, ...) \
CR_TEST_PROTOTYPE_(Category, Name); \
CR_TEST_TRAMPOLINE_(Category, Name) \
struct criterion_test_extra_data CR_IDENTIFIER_(Category, Name, extra) = \
CR_EXPAND(CRITERION_MAKE_STRUCT(criterion_test_extra_data, \
.lang_ = CR_LANG, \
.kind_ = CR_TEST_NORMAL, \
.param_ = (struct criterion_test_params(*)(void)) NULL, \
.identifier_ = #Category "/" #Name, \
.file_ = __FILE__, \
.line_ = __LINE__, \
__VA_ARGS__ \
)); \
struct criterion_test CR_IDENTIFIER_(Category, Name, meta) = { \
#Name, \
#Category, \
CR_IDENTIFIER_(Category, Name, jmp), \
&CR_IDENTIFIER_(Category, Name, extra) \
}; \
CR_SECTION_("cr_tst") \
struct criterion_test *CR_IDENTIFIER_(Category, Name, ptr) \
= &CR_IDENTIFIER_(Category, Name, meta) CR_SECTION_SUFFIX_; \
CR_TEST_PROTOTYPE_(Category, Name)
# define CR_SUITE_BASE(Name, ...) \
struct criterion_test_extra_data CR_SUITE_IDENTIFIER_(Name, extra) = \
CR_EXPAND(CRITERION_MAKE_STRUCT(criterion_test_extra_data, \
.file_ = __FILE__, \
.line_ = 0, \
__VA_ARGS__ \
)); \
struct criterion_suite CR_SUITE_IDENTIFIER_(Name, meta) = { \
#Name, \
&CR_SUITE_IDENTIFIER_(Name, extra), \
}; \
CR_SECTION_("cr_sts") \
struct criterion_suite *CR_SUITE_IDENTIFIER_(Name, ptr) \
= &CR_SUITE_IDENTIFIER_(Name, meta) CR_SECTION_SUFFIX_
#endif /* !CRITERION_INTERNAL_TEST_H_ */

View file

@ -0,0 +1,94 @@
/*
* The MIT License (MIT)
*
* Copyright © 2015 Franklin "Snaipe" Mathieu <http://snai.pe/>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#ifndef CRITERION_INTERNAL_THEORIES_H_
# define CRITERION_INTERNAL_THEORIES_H_
# include "test.h"
# ifdef __cplusplus
# include <cstddef>
using std::size_t;
# else
# include <stddef.h>
# endif
# ifdef __cplusplus
template <typename... T>
constexpr size_t criterion_va_num__(const T &...) {
return sizeof...(T);
}
# endif
struct criterion_datapoints {
size_t size;
size_t len;
const char *name;
void *arr;
};
CR_BEGIN_C_API
CR_API void cr_theory_main(struct criterion_datapoints *dps, size_t datapoints, void (*fnptr)(void));
CR_END_C_API
# ifdef __cplusplus
# define CR_TH_VA_NUM(Type, ...) criterion_va_num__(__VA_ARGS__)
# define CR_TH_TEMP_ARRAY(Type, ...) []() -> Type* { static Type arr[] = { __VA_ARGS__ }; return reinterpret_cast<Type*>(&arr); }()
# else
# define CR_TH_VA_NUM(Type, ...) sizeof ((Type[]) { __VA_ARGS__ }) / sizeof (Type)
# define CR_TH_TEMP_ARRAY(Type, ...) &(Type[]) { __VA_ARGS__ }
# endif
# define CR_TH_INTERNAL_TDPS(Category, Name) \
static struct criterion_datapoints CR_IDENTIFIER_(Category, Name, dps)[]
# define CR_TH_INTERNAL_TDP(Category, Name) \
(CR_IDENTIFIER_(Category, Name, dps))
# define CR_TH_INTERNAL_DP(Type, ...) { \
sizeof (Type), \
CR_EXPAND(CR_TH_VA_NUM(Type, __VA_ARGS__)), \
#Type, \
CR_EXPAND(CR_TH_TEMP_ARRAY(Type, __VA_ARGS__)), \
}
# define CR_NB_DATAPOINTS(Var) \
(sizeof (Var) / sizeof (struct criterion_datapoints))
# define CR_VAARG_ID(Suffix, Category, Name, ...) \
CR_IDENTIFIER_(Category, Name, Suffix)
# define CR_THEORY_BASE(Args, ...) \
void CR_EXPAND(CR_VAARG_ID(theory, __VA_ARGS__,))Args; \
CR_EXPAND(CR_TEST_BASE(__VA_ARGS__, .sentinel_ = 0)) { \
cr_theory_main( \
CR_EXPAND(CR_VAARG_ID(dps, __VA_ARGS__,)), \
CR_NB_DATAPOINTS(CR_EXPAND(CR_VAARG_ID(dps, __VA_ARGS__,))), \
(void(*)(void)) CR_EXPAND(CR_VAARG_ID(theory, __VA_ARGS__,)) \
); \
} \
void CR_EXPAND(CR_VAARG_ID(theory, __VA_ARGS__,))Args
#endif /* !CRITERION_INTERNAL_THEORIES_H_ */

View file

@ -31,13 +31,15 @@ using std::va_list;
# include <stdbool.h>
# include <stdarg.h>
# endif
# include "common.h"
# include "ordered-set.h"
# include "internal/common.h"
# include "internal/ordered-set.h"
# include "stats.h"
enum criterion_logging_level {
CRITERION_INFO = 1,
CRITERION_IMPORTANT,
CRITERION_LOG_LEVEL_QUIET = 1 << 30,
};
enum criterion_logging_prefix {
@ -47,6 +49,7 @@ enum criterion_logging_prefix {
CRITERION_LOGGING_PREFIX_SKIP,
CRITERION_LOGGING_PREFIX_PASS,
CRITERION_LOGGING_PREFIX_FAIL,
CRITERION_LOGGING_PREFIX_ERR,
};
struct criterion_prefix_data {
@ -64,12 +67,12 @@ struct criterion_prefix_data {
# define CRIT_FG_BLUE "\33[0;34m"
# define CRIT_RESET "\33[0m"
# define FG_BOLD CRIT_COLOR_NORMALIZE(CRIT_FG_BOLD)
# define FG_RED CRIT_COLOR_NORMALIZE(CRIT_FG_RED)
# define FG_GREEN CRIT_COLOR_NORMALIZE(CRIT_FG_GREEN)
# define FG_GOLD CRIT_COLOR_NORMALIZE(CRIT_FG_GOLD)
# define FG_BLUE CRIT_COLOR_NORMALIZE(CRIT_FG_BLUE)
# define RESET CRIT_COLOR_NORMALIZE(CRIT_RESET)
# define CR_FG_BOLD CRIT_COLOR_NORMALIZE(CRIT_FG_BOLD)
# define CR_FG_RED CRIT_COLOR_NORMALIZE(CRIT_FG_RED)
# define CR_FG_GREEN CRIT_COLOR_NORMALIZE(CRIT_FG_GREEN)
# define CR_FG_GOLD CRIT_COLOR_NORMALIZE(CRIT_FG_GOLD)
# define CR_FG_BLUE CRIT_COLOR_NORMALIZE(CRIT_FG_BLUE)
# define CR_RESET CRIT_COLOR_NORMALIZE(CRIT_RESET)
# endif
CR_BEGIN_C_API
@ -82,13 +85,14 @@ extern const struct criterion_prefix_data g_criterion_logging_prefixes[];
# define CRITERION_PREFIX_SKIP (&g_criterion_logging_prefixes[CRITERION_LOGGING_PREFIX_SKIP ])
# define CRITERION_PREFIX_PASS (&g_criterion_logging_prefixes[CRITERION_LOGGING_PREFIX_PASS ])
# define CRITERION_PREFIX_FAIL (&g_criterion_logging_prefixes[CRITERION_LOGGING_PREFIX_FAIL ])
# define CRITERION_PREFIX_ERR (&g_criterion_logging_prefixes[CRITERION_LOGGING_PREFIX_ERR ])
CR_API void criterion_vlog(enum criterion_logging_level level, const char *msg, va_list args);
FORMAT(printf, 3, 4)
CR_FORMAT(printf, 3, 4)
CR_API void criterion_plog(enum criterion_logging_level level, const struct criterion_prefix_data *prefix, const char *msg, ...);
FORMAT(printf, 2, 3)
CR_FORMAT(printf, 2, 3)
CR_API void criterion_log(enum criterion_logging_level level, const char *msg, ...);
# define criterion_info(...) criterion_log(CRITERION_INFO, __VA_ARGS__)
@ -97,7 +101,9 @@ CR_API void criterion_log(enum criterion_logging_level level, const char *msg, .
# define criterion_pinfo(...) criterion_plog(CRITERION_INFO, __VA_ARGS__)
# define criterion_pimportant(...) criterion_plog(CRITERION_IMPORTANT, __VA_ARGS__)
struct criterion_output_provider {
# define criterion_perror(...) criterion_plog(CRITERION_IMPORTANT, CRITERION_PREFIX_ERR, __VA_ARGS__)
struct criterion_logger {
void (*log_pre_all )(struct criterion_test_set *set);
void (*log_pre_suite )(struct criterion_suite_set *set);
void (*log_pre_init )(struct criterion_test *test);
@ -106,6 +112,7 @@ struct criterion_output_provider {
void (*log_theory_fail )(struct criterion_theory_stats *stats);
void (*log_test_timeout )(struct criterion_test_stats *stats);
void (*log_test_crash )(struct criterion_test_stats *stats);
void (*log_test_abort )(struct criterion_test_stats *stats, const char *msg);
void (*log_other_crash )(struct criterion_test_stats *stats);
void (*log_abnormal_exit)(struct criterion_test_stats *stats);
void (*log_post_test )(struct criterion_test_stats *stats);
@ -114,12 +121,10 @@ struct criterion_output_provider {
void (*log_post_all )(struct criterion_global_stats *stats);
};
extern struct criterion_output_provider normal_logging;
extern struct criterion_output_provider tap_logging;
extern struct criterion_logger normal_logging;
CR_END_C_API
#define NORMAL_LOGGING (&normal_logging)
#define TAP_LOGGING (&tap_logging)
#define CR_NORMAL_LOGGING (&normal_logging)
#endif /* !CRITERION_LOGGING_H_ */

View file

@ -28,18 +28,90 @@
# include "logging.h"
struct criterion_options {
/**
* The current logging threshold.
*
* default: 1
*/
enum criterion_logging_level logging_threshold;
struct criterion_output_provider *output_provider;
/**
* The logger that will be used during the execution of the runner.
*
* default: normal logger
*/
struct criterion_logger *logger;
/**
* Don't exit the child immediately after finishing to run the test
* function, and perform a full cleanup.
*
* Useful when tracking memory leaks, and is immediately implied when
* running the process under valgrind.
*
* default: false
*/
bool no_early_exit;
/**
* Always return a success from criterion_run_all_tests.
*
* default: false
*/
bool always_succeed;
/**
* Disable unicode and ansi coloring from the logging system.
*
* default: false
*/
bool use_ascii;
/**
* Exit immediately after the first test failure.
*
* default: false
*/
bool fail_fast;
/**
* Disable all tests not matching this extglob pattern.
* if NULL, don't filter tests.
*
* default: NULL
*/
const char *pattern;
/**
* Only print the base file name compound of the source file containing
* the tests during reporting.
*
* default: false
*/
bool short_filename;
/**
* The maximum number of parallel jobs that the test runner will spawn.
* 0 means that this number shall be the number of cores on your system.
*
* default: 0
*/
size_t jobs;
/**
* Measure and report times.
*
* default: true
*/
bool measure_time;
};
CR_BEGIN_C_API
/**
* The runtime options for the test runner.
*/
extern struct criterion_options criterion_options;
CR_END_C_API

View file

@ -0,0 +1,50 @@
/*
* The MIT License (MIT)
*
* Copyright © 2015 Franklin "Snaipe" Mathieu <http://snai.pe/>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#ifndef CRITERION_OUTPUT_H_
# define CRITERION_OUTPUT_H_
# include "stats.h"
typedef void criterion_reporter(FILE *stream, struct criterion_global_stats *);
/**
* Register an output provider.
*
* @param[in] name The name the output provider shall be registered as.
* @param[in] reporter The output reporting function.
* @returns 1 if no output provider is registered at that name, 0 otherwise,
* and -1 on error.
*/
int criterion_register_output_provider(const char *name, criterion_reporter *reporter);
/**
* Use an output provider to write a report in a specific path.
*
* @param[in] provider The name of a registered output provider.
* @param[in] path The path to the file to write the report to.
* @returns -1 on error.
*/
int criterion_add_output(const char *provider, const char *path);
#endif /* !CRITERION_OUTPUT_H_ */

View file

@ -1,50 +1,83 @@
/*
* The MIT License (MIT)
*
* Copyright © 2015 Franklin "Snaipe" Mathieu <http://snai.pe/>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#ifndef CRITERION_PARAMETERIZED_H_
# define CRITERION_PARAMETERIZED_H_
# include "criterion.h"
# include "alloc.h"
# include "assert.h"
# include "internal/parameterized.h"
/**
* ParameterizedTest(Type *param, Suite, Name, [Options...]) { Function Body }
*
* Defines a new parameterized test.
*
* A parameterized test only takes one parameter -- to pass multiple parameters,
* use a structure type.
*
* @param Type The type of the parameter.
* @param Suite The name of the test suite containing this test.
* @param Name The name of the test.
* @param Options An optional sequence of designated initializer key/value
* pairs as described in the `criterion_test_extra_data` structure
* (see criterion/types.h).
* Example: .exit_code = 1
*/
# define ParameterizedTest(...) CR_EXPAND(CR_PARAM_TEST_BASE(__VA_ARGS__, .sentinel_ = 0))
/**
* ParameterizedTestParameters(Suite, Test) { Function Body }
*
* Defines the parameter generator for the associated parameterized test.
*
* @param Suite The name of the test suite containing the test.
* @param Test The name of the test.
* @returns A constructed instance of criterion::parameters, or the result of
* the cr_make_param_array macro.
*/
# define ParameterizedTestParameters(Suite, Name) CR_PARAM_TEST_PARAMS(Suite, Name)
/**
* cr_make_param_array(Type, Array, Len, [Cleanup]);
*
* Constructs a parameter list used as a return value for a parameter generator.
*
* @param Type The type of the array subscript.
* @param Array The array of parameters.
* @param Len The length of the array.
* @param Cleanup The optional cleanup function for the array.
* @returns The parameter list.
*/
# define cr_make_param_array(...) CR_EXPAND(cr_make_param_array_(__VA_ARGS__))
# ifdef __cplusplus
# define CR_PARAM_TEST_PROTOTYPE_(Param, Category, Name) \
extern "C" void IDENTIFIER_(Category, Name, impl)(Param)
# else
# define CR_PARAM_TEST_PROTOTYPE_(Param, Category, Name) \
void IDENTIFIER_(Category, Name, impl)(Param)
# endif
# include <vector>
# define ParameterizedTest(...) \
CR_EXPAND(ParameterizedTest_(__VA_ARGS__, .sentinel_ = 0))
# define ParameterizedTest_(Param, Category, Name, ...) \
CR_PARAM_TEST_PROTOTYPE_(Param, Category, Name); \
struct criterion_test_extra_data IDENTIFIER_(Category, Name, extra) = \
CR_EXPAND(CRITERION_MAKE_STRUCT(struct criterion_test_extra_data, \
.kind_ = CR_TEST_PARAMETERIZED, \
.param_ = IDENTIFIER_(Category, Name, param), \
.identifier_ = #Category "/" #Name, \
.file_ = __FILE__, \
.line_ = __LINE__, \
__VA_ARGS__ \
)); \
struct criterion_test IDENTIFIER_(Category, Name, meta) = { \
#Name, \
#Category, \
(void(*)(void)) IDENTIFIER_(Category, Name, impl), \
&IDENTIFIER_(Category, Name, extra) \
}; \
SECTION_("cr_tst") \
struct criterion_test *IDENTIFIER_(Category, Name, ptr) \
= &IDENTIFIER_(Category, Name, meta) SECTION_SUFFIX_; \
CR_PARAM_TEST_PROTOTYPE_(Param, Category, Name)
# define ParameterizedTestParameters(Category, Name) \
static struct criterion_test_params IDENTIFIER_(Category, Name, param)(void)
# ifdef __cplusplus
# define cr_make_param_array(Type, Array, ...) \
criterion_test_params(sizeof (Type), (Array), __VA_ARGS__)
# else
# define cr_make_param_array(Type, Array, ...) \
(struct criterion_test_params) { .size = sizeof (Type), (void*)(Array), __VA_ARGS__ }
namespace criterion {
template <typename T>
using parameters = std::vector<T, criterion::allocator<T>>;
}
# endif
#endif /* !CRITERION_PARAMETERIZED_H_ */

View file

@ -24,86 +24,82 @@
#ifndef CRITERION_REDIRECT_H_
# define CRITERION_REDIRECT_H_
# include "common.h"
# include "assert.h"
# include "internal/common.h"
# include "internal/redirect.h"
# ifdef __cplusplus
# include <cstdio>
# include <memory>
# include <fstream>
# ifdef __GNUC__
# if defined(__MINGW32__) || defined(__MINGW64__)
# define off_t _off_t
# define off64_t _off64_t
# endif
# include <ext/stdio_sync_filebuf.h>
# if defined(__MINGW32__) || defined(__MINGW64__)
# undef off_t
# undef off64_t
# endif
# endif
# else
# include <stdio.h>
# endif
CR_BEGIN_C_API
/**
* Redirect stdout for testing.
*/
CR_API void cr_redirect_stdout(void);
/**
* Redirect stderr for testing.
*/
CR_API void cr_redirect_stderr(void);
/**
* Redirect stdin for testing.
* This is implicitely called before each test.
*/
CR_API void cr_redirect_stdin(void);
/**
* Get a file handle representing the read-end of the redirected stdout.
*
* @returns the file handle.
*/
CR_API CR_STDN FILE* cr_get_redirected_stdout(void);
/**
* Get a file handle representing the read-end of the redirected stderr.
*
* @returns the file handle.
*/
CR_API CR_STDN FILE* cr_get_redirected_stderr(void);
/**
* Get a file handle representing the write-end of the redirected stdin.
*
* @returns the file handle.
*/
CR_API CR_STDN FILE* cr_get_redirected_stdin(void);
/**
* Compare the contents of a file with a string.
*
* @param[in] f The file to compare the contents to.
* @param[in] str The string to compare the contents to.
* @returns 1 if the contents of the file is equal to the string, 0 otherwise.
*/
CR_API int cr_file_match_str(CR_STDN FILE* f, const char *str);
/**
* Compare the contents of a file with the contents of another file.
*
* @param[in] f The first file to compare the contents to.
* @param[in] ref The second file to compare the contents to.
* @returns 1 if the contents of the files are equal, 0 otherwise.
*/
CR_API int cr_file_match_file(CR_STDN FILE* f, CR_STDN FILE* ref);
/**
* Create a file mock.
*
* @param[in] max_size The maximum size in bytes of the file mock.
* @returns the file handle representing the mock.
*/
CR_API CR_STDN FILE *cr_mock_file_size(size_t max_size);
CR_END_C_API
# define cr_assert_redir_op_(Fail, Fun, Op, File, Str, ...) \
CR_EXPAND(cr_assert_impl( \
Fail, \
!(Fun((File), (Str)) Op 0), \
dummy, \
CRITERION_ASSERT_MSG_FILE_STR_MATCH, \
(CR_STR(File), Str), \
__VA_ARGS__ \
))
# define cr_assert_redir_op_va_(Fail, Fun, Op, ...) \
CR_EXPAND(cr_assert_redir_op_( \
Fail, \
Fun, \
Op, \
CR_VA_HEAD(__VA_ARGS__), \
CR_VA_HEAD(CR_VA_TAIL(__VA_ARGS__)), \
CR_VA_TAIL(CR_VA_TAIL(__VA_ARGS__)) \
))
# define cr_assert_redir_f_op_(Fail, Fun, Op, File, Ref, ...) \
CR_EXPAND(cr_assert_impl( \
Fail, \
!(Fun((File), (Ref)) Op 0), \
dummy, \
CRITERION_ASSERT_MSG_FILE_MATCH, \
(CR_STR(File), CR_STR(Ref)), \
__VA_ARGS__ \
))
# define cr_assert_redir_f_op_va_(Fail, Fun, Op, ...) \
CR_EXPAND(cr_assert_redir_op_( \
Fail, \
Fun, \
Op, \
CR_VA_HEAD(__VA_ARGS__), \
CR_VA_HEAD(CR_VA_TAIL(__VA_ARGS__)), \
CR_VA_TAIL(CR_VA_TAIL(__VA_ARGS__)) \
))
# define cr_assert_file_contents_eq_str(...) CR_EXPAND(cr_assert_redir_op_va_(CR_FAIL_ABORT_, cr_file_match_str, ==, __VA_ARGS__))
# define cr_expect_file_contents_eq_str(...) CR_EXPAND(cr_assert_redir_op_va_(CR_FAIL_CONTINUES_, cr_file_match_str, ==, __VA_ARGS__))
@ -141,134 +137,24 @@ CR_END_C_API
# define cr_expect_stderr_neq(...) CR_EXPAND(cr_assert_redir_f_op_va_(CR_FAIL_CONTINUES_, cr_file_match_file, !=, cr_get_redirected_stderr(), __VA_ARGS__))
# ifdef __cplusplus
# include "internal/stream.hxx"
namespace criterion {
template <typename CharT, typename Super>
class stream_mixin : public Super {
public:
stream_mixin(FILE* f)
# ifdef __GNUC__
: Super()
, fbuf(new ::__gnu_cxx::stdio_sync_filebuf<CharT>(f))
# else
: Super(f)
# endif
, file(f)
{
# ifdef __GNUC__
std::ios::rdbuf(&*fbuf);
# endif
}
stream_mixin(const stream_mixin& other) = delete;
stream_mixin& operator=(const stream_mixin& other) = delete;
stream_mixin(stream_mixin&& other) :
# ifdef __GNUC__
fbuf(std::move(other.fbuf)),
# endif
file(std::move(other.file))
{}
stream_mixin& operator=(stream_mixin&& other) {
# ifdef __GNUC__
fbuf = std::move(other.fbuf);
# endif
file = std::move(other.file);
}
void close(void) {
Super::flush();
Super::close();
std::fclose(file);
}
private:
# ifdef __GNUC__
std::shared_ptr<::__gnu_cxx::stdio_sync_filebuf<CharT>> fbuf;
# endif
std::FILE* file;
};
template <typename CharT>
using ofstream_mixin = stream_mixin<CharT, std::basic_ofstream<CharT>>;
template <typename CharT>
using ifstream_mixin = stream_mixin<CharT, std::basic_ifstream<CharT>>;
template <typename CharT>
using fstream_mixin = stream_mixin<CharT, std::basic_fstream<CharT>>;
template <typename CharT>
class basic_ofstream : public ofstream_mixin<CharT> {
public:
basic_ofstream(FILE* f)
: ofstream_mixin<CharT>(f)
{}
basic_ofstream(basic_ofstream&& other)
: ofstream_mixin<CharT>(std::move(other))
{}
};
template <typename CharT>
class basic_ifstream : public ifstream_mixin<CharT> {
public:
basic_ifstream(FILE* f)
: ifstream_mixin<CharT>(f)
{}
basic_ifstream(basic_ifstream&& other)
: ifstream_mixin<CharT>(std::move(other))
{}
};
template <typename CharT>
class basic_fstream : public fstream_mixin<CharT> {
public:
basic_fstream(FILE* f)
: fstream_mixin<CharT>(f)
{}
basic_fstream(basic_fstream&& other)
: fstream_mixin<CharT>(std::move(other))
{}
};
using ofstream = basic_ofstream<char>;
using ifstream = basic_ifstream<char>;
using fstream = basic_fstream<char>;
struct get_redirected_out_stream_ {
static inline ofstream& call(std::FILE* f) {
static std::unique_ptr<ofstream> stream;
if (!stream)
stream.reset(new ofstream(f));
return *stream;
}
};
struct get_redirected_in_stream_ {
static inline ifstream& call(std::FILE* f) {
static std::unique_ptr<ifstream> stream;
if (!stream)
stream.reset(new ifstream(f));
return *stream;
}
};
typedef internal::basic_ofstream<char> ofstream;
typedef internal::basic_ifstream<char> ifstream;
typedef internal::basic_fstream<char> fstream;
static inline ofstream& get_redirected_cin(void) {
return get_redirected_out_stream_::call(cr_get_redirected_stdin());
return internal::get_redirected_out_stream_::call(cr_get_redirected_stdin());
}
static inline ifstream& get_redirected_cout(void) {
return get_redirected_in_stream_::call(cr_get_redirected_stdout());
return internal::get_redirected_in_stream_::call(cr_get_redirected_stdout());
}
static inline ifstream& get_redirected_cerr(void) {
return get_redirected_in_stream_::call(cr_get_redirected_stderr());
return internal::get_redirected_in_stream_::call(cr_get_redirected_stderr());
}
# if __GNUC__ >= 5

View file

@ -45,6 +45,7 @@ struct criterion_test_stats {
int exit_code;
float elapsed_time;
bool timed_out;
bool crashed;
unsigned progress;
const char *file;

View file

@ -24,71 +24,71 @@
#ifndef CRITERION_THEORIES_H_
# define CRITERION_THEORIES_H_
# ifdef __cplusplus
# include <cstddef>
using std::size_t;
# else
# include <stddef.h>
# endif
# include "criterion.h"
# ifdef __cplusplus
template <typename... T>
constexpr size_t criterion_va_num__(const T &...) {
return sizeof...(T);
}
# endif
# include "internal/theories.h"
CR_BEGIN_C_API
struct criterion_theory_context;
CR_API struct criterion_theory_context* cr_theory_init(void);
CR_API void cr_theory_push_arg(struct criterion_theory_context *ctx, bool is_float, size_t size, void *ptr);
CR_API void cr_theory_free(struct criterion_theory_context *ctx);
/**
* Aborts the current theory iteration.
* This function does not return.
*/
CR_API void cr_theory_abort(void);
CR_API int cr_theory_mark(void);
CR_API void cr_theory_reset(struct criterion_theory_context *ctx);
CR_API void cr_theory_call(struct criterion_theory_context *ctx, void (*fnptr)(void));
CR_END_C_API
# define TheoryDataPoints(Category, Name) \
static struct criterion_datapoints IDENTIFIER_(Category, Name, dps)[]
// Theory and datapoint macros
# define TheoryDataPoint(Category, Name) \
(IDENTIFIER_(Category, Name, dps))
/**
* Theory((Params...), Suite, Name, [Options...]) { Function Body }
*
* Defines a new theory test.
*
* The parameters are selected from a cartesian product defined by a
* TheoryDataPoints macro.
*
* @param Params A list of function parameters.
* @param Suite The name of the test suite containing this test.
* @param Name The name of the test.
* @param Options An optional sequence of designated initializer key/value
* pairs as described in the `criterion_test_extra_data` structure
* (see criterion/types.h).
* Example: .exit_code = 1
*/
# define Theory(Args, ...) CR_EXPAND(CR_THEORY_BASE(Args, __VA_ARGS__))
# ifdef __cplusplus
# define CR_TH_VA_NUM(Type, ...) criterion_va_num__(__VA_ARGS__)
# define CR_TH_TEMP_ARRAY(Type, ...) []() { static Type arr[] = { __VA_ARGS__ }; return &arr; }()
# else
# define CR_TH_VA_NUM(Type, ...) sizeof ((Type[]) { __VA_ARGS__ }) / sizeof (Type)
# define CR_TH_TEMP_ARRAY(Type, ...) &(Type[]) { __VA_ARGS__ }
# endif
/**
* TheoryDataPoints(Suite, Name) = { Datapoints... };
*
* Defines an array of data points.
*
* The types of the specified data points *must* match the types of the
* associated theory.
*
* Each entry in the array must be the result of the DataPoints macro.
*
* @param Suite The name of the test suite containing this test.
* @param Name The name of the test.
*/
# define TheoryDataPoints(Category, Name) CR_TH_INTERNAL_TDPS(Category, Name)
# define DataPoints(Type, ...) { \
sizeof (Type), \
CR_EXPAND(CR_TH_VA_NUM(Type, __VA_ARGS__)), \
#Type, \
CR_EXPAND(CR_TH_TEMP_ARRAY(Type, __VA_ARGS__)), \
}
/**
* DataPoints(Type, Values...)
*
* Defines a new set of data points.
*
* @param Type The type of each data point in the set.
* @param Values The data points in the set.
*/
# define DataPoints(Type, ...) CR_EXPAND(CR_TH_INTERNAL_DP(Type, __VA_ARGS__))
struct criterion_datapoints {
size_t size;
size_t len;
const char *name;
void *arr;
};
# define CR_NB_DATAPOINTS(Var) \
(sizeof (Var) / sizeof (struct criterion_datapoints))
// Theory invariants
# define cr_assume(Condition) \
do { \
if (!(Condition)) \
cr_theory_abort(); \
} while (0);
} while (0)
# define cr_assume_not(Condition) cr_assume(!(Condition))
@ -111,35 +111,31 @@ struct criterion_datapoints {
cr_assume((Expected) - (Actual) > (Epsilon) \
|| (Actual) - (Expected) > (Epsilon))
# define cr_assume_strings_op_(Op, Actual, Expected) \
# define cr_assume_str_op_(Op, Actual, Expected) \
cr_assume(strcmp((Actual), (Expected)) Op 0)
# define cr_assume_strings_eq(Actual, Expected) cr_assume_strings_op_(==, Actual, Expected)
# define cr_assume_strings_neq(Actual, Expected) cr_assume_strings_op_(!=, Actual, Expected)
# define cr_assume_strings_lt(Actual, Expected) cr_assume_strings_op_(<, Actual, Expected)
# define cr_assume_strings_leq(Actual, Expected) cr_assume_strings_op_(<=, Actual, Expected)
# define cr_assume_strings_gt(Actual, Expected) cr_assume_strings_op_(>, Actual, Expected)
# define cr_assume_strings_geq(Actual, Expected) cr_assume_strings_op_(>=, Actual, Expected)
# define cr_assume_str_eq(Actual, Expected) cr_assume_str_op_(==, Actual, Expected)
# define cr_assume_str_neq(Actual, Expected) cr_assume_str_op_(!=, Actual, Expected)
# define cr_assume_str_lt(Actual, Expected) cr_assume_str_op_(<, Actual, Expected)
# define cr_assume_str_leq(Actual, Expected) cr_assume_str_op_(<=, Actual, Expected)
# define cr_assume_str_gt(Actual, Expected) cr_assume_str_op_(>, Actual, Expected)
# define cr_assume_str_geq(Actual, Expected) cr_assume_str_op_(>=, Actual, Expected)
# define cr_assume_arrays_eq(Actual, Expected, Size) cr_assume(!memcmp((A), (B), (Size)))
# define cr_assume_arrays_neq(Actual, Expected, Size) cr_assume(memcmp((A), (B), (Size)))
# define cr_assume_arr_eq(Actual, Expected, Size) cr_assume(!memcmp((A), (B), (Size)))
# define cr_assume_arr_neq(Actual, Expected, Size) cr_assume(memcmp((A), (B), (Size)))
CR_API void cr_theory_main(struct criterion_datapoints *dps, size_t datapoints, void (*fnptr)(void));
// Deprecated
# define CR_VAARG_ID(Suffix, Category, Name, ...) \
IDENTIFIER_(Category, Name, Suffix)
# ifndef CRITERION_NO_COMPAT
# define cr_assume_strings_eq(...) CRITERION_ASSERT_DEPRECATED_B(cr_assume_strings_eq, cr_assume_str_eq) cr_assume_str_eq(__VA_ARGS__)
# define cr_assume_strings_neq(...) CRITERION_ASSERT_DEPRECATED_B(cr_assume_strings_neq, cr_assume_str_neq) cr_assume_str_neq(__VA_ARGS__)
# define cr_assume_strings_lt(...) CRITERION_ASSERT_DEPRECATED_B(cr_assume_strings_lt, cr_assume_str_lt) cr_assume_str_lt(__VA_ARGS__)
# define cr_assume_strings_leq(...) CRITERION_ASSERT_DEPRECATED_B(cr_assume_strings_leq, cr_assume_str_leq) cr_assume_str_leq(__VA_ARGS__)
# define cr_assume_strings_gt(...) CRITERION_ASSERT_DEPRECATED_B(cr_assume_strings_gt, cr_assume_str_gt) cr_assume_str_gt(__VA_ARGS__)
# define cr_assume_strings_geq(...) CRITERION_ASSERT_DEPRECATED_B(cr_assume_strings_geq, cr_assume_str_geq) cr_assume_str_geq(__VA_ARGS__)
# define Theory(Args, ...) \
void CR_EXPAND(CR_VAARG_ID(theory, __VA_ARGS__,))Args; \
CR_EXPAND(Test_(__VA_ARGS__, .sentinel_ = 0)) { \
cr_theory_main( \
CR_EXPAND(CR_VAARG_ID(dps, __VA_ARGS__,)), \
CR_NB_DATAPOINTS(CR_EXPAND(CR_VAARG_ID(dps, __VA_ARGS__,))), \
(void(*)(void)) CR_EXPAND(CR_VAARG_ID(theory, __VA_ARGS__,)) \
); \
} \
void CR_EXPAND(CR_VAARG_ID(theory, __VA_ARGS__,))Args
CR_END_C_API
# define cr_assume_arrays_eq(...) CRITERION_ASSERT_DEPRECATED_B(cr_assume_arrays_eq, cr_assume_arr_eq) cr_assume_arr_eq(__VA_ARGS__)
# define cr_assume_arrays_neq(...) CRITERION_ASSERT_DEPRECATED_B(cr_assume_arrays_neq, cr_assume_arr_neq) cr_assume_arr_neq(__VA_ARGS__)
# endif
#endif /* !CRITERION_THEORIES_H_ */

View file

@ -24,61 +24,78 @@
#ifndef CRITERION_TYPES_H_
# define CRITERION_TYPES_H_
# include "alloc.h"
# ifdef __cplusplus
# include <cstddef>
# include <vector>
using std::size_t;
# else
# include <stdbool.h>
# include <stddef.h>
# endif
# include "common.h"
# include "internal/common.h"
/**
* Enumerates the supported languages for tests
*/
enum criterion_language {
CR_LANG_C, /// C
CR_LANG_CXX, /// C++
CR_LANG_OBJC, /// Objective-C
CR_LANG_OBJCXX, /// Objective-C++
CR_LANG_SIZE_ // leave this at the end
};
extern const char *const cr_language_names[CR_LANG_SIZE_];
/**
* Enumerates the supported kinds of tests
*/
enum criterion_test_kind {
CR_TEST_NORMAL,
CR_TEST_PARAMETERIZED,
};
struct criterion_test_params {
size_t size;
void *params;
size_t length;
void (*cleanup)(struct criterion_test_params *);
# ifdef __cplusplus
constexpr criterion_test_params(size_t size, void *params, size_t length)
: size(size)
, params(params)
, length(length)
, cleanup(nullptr)
{}
constexpr criterion_test_params(size_t size, void *params, size_t length,
void (*cleanup)(struct criterion_test_params *))
: size(size)
, params(params)
, length(length)
, cleanup(cleanup)
{}
# endif
};
/**
* Represents a set of parameters for a parameterized test.
*/
struct criterion_test_params;
/**
* Contains all the options that can be set for a test, through
* the Test and TestSuite macros, or other means.
*/
struct criterion_test_extra_data {
// Start of private API
/*
* Warning: the fields below are not meant to be set manually.
* Setting them improperly *will* wreck havock in your tests.
*
* You've been warned.
*/
int sentinel_;
enum criterion_language lang_;
enum criterion_test_kind kind_;
struct criterion_test_params (*param_)(void);
const char *identifier_;
const char *file_;
unsigned line_;
void (*init)(void);
void (*fini)(void);
int signal;
int exit_code;
bool disabled;
const char *description;
double timeout;
void *data;
// Enf of private API
void (*init)(void); /// The setup test fixture
void (*fini)(void); /// The setup test fixture
int signal; /// The expected signal raised by the test (or 0 if none)
int exit_code; /// The expected exit code returned by the test
bool disabled; /// Whether the test is disabled or not
const char *description; /// The description of a test
double timeout; /// A timeout for the test in seconds
void *data; /// Extra user data
};
/**
* Represents a test
*/
struct criterion_test {
const char *name;
const char *category;
@ -86,6 +103,9 @@ struct criterion_test {
struct criterion_test_extra_data *data;
};
/**
* Represents a test suite
*/
struct criterion_suite {
const char *name;
struct criterion_test_extra_data *data;
@ -103,6 +123,4 @@ struct criterion_test_set {
size_t tests;
};
typedef void (*f_worker_func)(struct criterion_test *, struct criterion_suite *);
#endif /* !CRITERION_TYPES_H_ */

View file

@ -1,3 +1,5 @@
# List of source files which contain translatable strings.
src/log/normal.c
src/string/i18n.c
src/core/runner.c
src/io/output.c

View file

@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: criterion 2.0.0\n"
"Report-Msgid-Bugs-To: franklinmathieu+criterion@gmail.com\n"
"POT-Creation-Date: 2015-09-16 21:18+0200\n"
"POT-Creation-Date: 2015-11-27 12:24+0100\n"
"PO-Revision-Date: 2015-04-03 17:58+0200\n"
"Last-Translator: <franklinmathieu@gmail.com>\n"
"Language-Team: French\n"
@ -18,65 +18,70 @@ msgstr ""
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n > 1);\n"
#: src/log/normal.c:50
#: src/log/normal.c:42
#, c-format
msgid "Criterion v%s\n"
msgstr "Criterion v%s\n"
#: src/log/normal.c:51
#: src/log/normal.c:43
#, c-format
msgid " %s\n"
msgstr " %s\n"
#: src/log/normal.c:54 src/log/normal.c:56
#: src/log/normal.c:46 src/log/normal.c:48
#, c-format
msgid "%1$s::%2$s\n"
msgstr "%1$s::%2$s\n"
#: src/log/normal.c:55
#: src/log/normal.c:47
#, fuzzy, c-format
msgid "%1$s::%2$s: (%3$3.2fs)\n"
msgstr "%1$s::%2$s: (%3$3.2fs)\n"
#: src/log/normal.c:57
#: src/log/normal.c:49
#, c-format
msgid "%1$s::%2$s: Test is disabled\n"
msgstr "%1$s::%2$s: Le test est désactivé\n"
#: src/log/normal.c:58
#: src/log/normal.c:50
#, c-format
msgid "%1$s::%2$s: Suite is disabled\n"
msgstr "%1$s::%2$s: La suite est désactivée\n"
#: src/log/normal.c:59
#: src/log/normal.c:51
#, c-format
msgid "%1$s%2$s%3$s:%4$s%5$d%6$s: Assertion failed: %7$s\n"
msgstr "%1$s%2$s%3$s:%4$s%5$d%6$s: Échec d'assertion: %7$s\n"
#: src/log/normal.c:60
#: src/log/normal.c:52
#, fuzzy, c-format
msgid " Theory %1$s::%2$s failed with the following parameters: (%3$s)\n"
msgstr ""
" La théorie %1$s::%2$s a échoué avec les paramètres suivants: (%3$s)\n"
#: src/log/normal.c:61
#: src/log/normal.c:53
#, fuzzy, c-format
msgid "%1$s::%2$s: Timed out. (%3$3.2fs)\n"
msgstr "%1$s::%2$s: Délai expiré. (%3$3.2fs)\n"
#: src/log/normal.c:62
#: src/log/normal.c:54
#, c-format
msgid "%1$s%2$s%3$s:%4$s%5$u%6$s: Unexpected signal caught below this line!\n"
msgstr ""
"%1$s%2$s%3$s:%4$s%5$u%6$s: Un signal inattendu a été reçu après cette "
"ligne!\n"
#: src/log/normal.c:63
#: src/log/normal.c:55
#, c-format
msgid "%1$s::%2$s: CRASH!\n"
msgstr "%1$s::%2$s: PLANTAGE!\n"
#: src/log/normal.c:64
#: src/log/normal.c:56
#, fuzzy, c-format
msgid "%1$s::%2$s: %3$s\n"
msgstr "%1$s::%2$s: (%3$3.2fs)\n"
#: src/log/normal.c:57
#, fuzzy, c-format
msgid ""
"%1$sWarning! The test `%2$s::%3$s` crashed during its setup or teardown."
@ -85,7 +90,7 @@ msgstr ""
"%1$sAttention! Le test `%2$s::%3$s` a planté pendant son initialisation ou "
"sa finalisation.%4$s\n"
#: src/log/normal.c:65
#: src/log/normal.c:58
#, fuzzy, c-format
msgid ""
"%1$sWarning! The test `%2$s::%3$s` exited during its setup or teardown.%4$s\n"
@ -93,14 +98,14 @@ msgstr ""
"%1$sAttention! Le test `%2$s::%3$s` a quitté pendant son initialisation ou "
"sa finalisation.%4$s\n"
#: src/log/normal.c:66
#: src/log/normal.c:59
#, c-format
msgid "Running %1$s%2$lu%3$s test from %4$s%5$s%6$s:\n"
msgid_plural "Running %1$s%2$lu%3$s tests from %4$s%5$s%6$s:\n"
msgstr[0] "Lancement de %1$s%2$lu%3$s test dans %4$s%5$s%6$s:\n"
msgstr[1] "Lancement de %1$s%2$lu%3$s tests dans %4$s%5$s%6$s:\n"
#: src/log/normal.c:68
#: src/log/normal.c:61
#, c-format
msgid ""
"%1$sSynthesis: Tested: %2$s%3$lu%4$s | Passing: %5$s%6$lu%7$s | Failing: %8$s"
@ -109,6 +114,11 @@ msgstr ""
"%1$sSynthèse: Testés: %2$s%3$lu%4$s | Validés: %5$s%6$lu%7$s | Échoués: %8$s"
"%9$lu%10$s | Plantages: %11$s%12$lu%13$s %14$s\n"
#: src/log/normal.c:77
#, fuzzy, c-format
msgid "%s::%s: %s\n"
msgstr "%1$s::%2$s: (%3$3.2fs)\n"
#: src/string/i18n.c:13
msgid "The conditions for this assertion were not met."
msgstr "Les conditions de cette assertion n'ont pas été remplies."
@ -174,3 +184,36 @@ msgstr "L'instruction `%1$s` a levé une instance de l'exception `%2$s`."
#, c-format
msgid "The statement `%1$s` did not throw an instance of the `%2$s` exception."
msgstr "L'instruction `%1$s` n'a pas levé d'instance de l'exception `%2$s`."
#: src/core/runner.c:58
#, c-format
msgid ""
"%1$sWarning! Criterion has detected that it is running under valgrind, but "
"the no_early_exit option is explicitely disabled. Reports will not be "
"accurate!%2$s\n"
msgstr ""
"%1$sAttention! Criterion a détecté qu'il a été lancé avec valgrind, mais "
"l'option no_early_exit est explicitement désactivée. Les rapports d'erreur "
"ne seront pas précis!%2$s\n"
#: src/core/runner.c:62
#, c-format
msgid ""
"%1$sWarning! Criterion has detected that it is running under valgrind, but "
"the number of jobs have been explicitely set. Reports might appear confusing!"
"%2$s\n"
msgstr ""
"%1$sAttention! Criterion a détecté qu'il a été lancé avec valgrind, mais le "
"nombre de tâches est explicitement défini. Les rapports d'erreur risquent "
"d'être déroutants!%2$s\n"
#: src/io/output.c:13
#, fuzzy, c-format
msgid "Could not open the file @ `%1$s` for %2$s reporting: %3$s.\n"
msgstr ""
"Impossible d'ouvrir le fichier `%1$s` pour faire le rapport %2$s: %3$s.\n"
#: src/io/output.c:14
#, c-format
msgid "Writing %1$s report in `%2$s`.\n"
msgstr "Écriture du rapport %1$s dans `%2$s`.\n"

View file

@ -1,6 +1,6 @@
if (NOT MSVC)
set(CMAKE_C_FLAGS "-std=c99 -Wall -Wextra -pedantic")
set(CMAKE_CXX_FLAGS "-std=c++11 -Wall -Wextra -pedantic")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS_DEFAULT} -std=c99 -Wall -Wextra -pedantic")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS_DEFAULT} ${CXX11_FLAG} -Wall -Wextra -pedantic")
endif ()
include_directories(../include)
@ -14,25 +14,38 @@ set(SAMPLES
more-suites.c
description.c
simple.c
theories.c
timeout.c
redirect.c
parameterized.c
signal.cc
report.cc
suites.cc
fixtures.cc
asserts.cc
more-suites.cc
description.cc
simple.cc
theories.cc
redirect.cc
)
if (CMAKE_CXX_COMPILER_WORKS)
set(SAMPLES ${SAMPLES}
signal.cc
report.cc
suites.cc
fixtures.cc
asserts.cc
more-suites.cc
description.cc
simple.cc
redirect.cc
parameterized.cc
)
endif ()
if (THEORIES)
set(SAMPLES ${SAMPLES} theories.c)
if (CMAKE_CXX_COMPILER_WORKS)
set(SAMPLES ${SAMPLES} theories.cc)
endif ()
endif ()
set(SCRIPTS
tap_test
xml_test
json_test
early_exit
verbose
list
@ -65,6 +78,8 @@ macro(add_samples DIR_ SAMPLES_)
ENVIRONMENT "CRITERION_ALWAYS_SUCCEED=1"
ENVIRONMENT "CRITERION_SHORT_FILENAME=1"
ENVIRONMENT "CRITERION_NO_EARLY_EXIT=1" # for coverage
ENVIRONMENT "CRITERION_JOBS=1" # for output ordering
ENVIRONMENT "CRITERION_DISABLE_TIME_MEASUREMENTS=1" # do not compare timings
)
endif ()
endforeach()
@ -75,18 +90,19 @@ add_samples("${CMAKE_CURRENT_LIST_DIR}/tests" "${SAMPLES}")
if (NOT MSVC) # we disable the scripted tests when building with MSVC
foreach(script ${SCRIPTS})
add_test(${script} sh ${CMAKE_CURRENT_LIST_DIR}/tests/${script}.sh)
add_test(${script} sh "${CMAKE_CURRENT_LIST_DIR}/tests/${script}.sh")
set_property(TEST ${script} PROPERTY
ENVIRONMENT "CRITERION_ALWAYS_SUCCEED=1"
ENVIRONMENT "CRITERION_NO_EARLY_EXIT=1" # for coverage
)
add_test(${script}_compare sh ${CMAKE_CURRENT_LIST_DIR}/tests/run_test.sh "${CMAKE_CURRENT_LIST_DIR}" . "${CMAKE_CURRENT_LIST_DIR}" tests/${script})
add_test(${script}_compare sh ${CMAKE_CURRENT_LIST_DIR}/tests/run_test.sh "${CMAKE_CURRENT_LIST_DIR}" . "${CMAKE_CURRENT_LIST_DIR}" "tests/${script}.sh")
set_property(TEST ${script}_compare PROPERTY
ENVIRONMENT "LC_ALL=en_US.utf8"
ENVIRONMENT "CRITERION_ALWAYS_SUCCEED=1"
ENVIRONMENT "CRITERION_SHORT_FILENAME=1"
ENVIRONMENT "CRITERION_NO_EARLY_EXIT=1" # for coverage
ENVIRONMENT "CRITERION_JOBS=1" # for output ordering
)
endforeach()

View file

@ -1,7 +1,7 @@
[----] asserts.c:11: Assertion failed: assert is fatal, expect isn't
[----] asserts.c:12: Assertion failed: This assert runs
[FAIL] asserts::base: (0.00s)
[FAIL] asserts::base
[----] asserts.c:17: Assertion failed: You can fail an assertion with a message from anywhere
[----] asserts.c:18: Assertion failed: The conditions for this assertion were not met.
[FAIL] asserts::old_school: (0.00s)
[FAIL] asserts::old_school
[====] Synthesis: Tested: 6 | Passing: 4 | Failing: 2 | Crashing: 0 

View file

@ -1,11 +1,11 @@
[----] asserts.cc:83: Assertion failed: The expression (&s1)[0 .. 2] == (&s2)[0 .. 2] is false.
[FAIL] asserts::array: (0.00s)
[FAIL] asserts::array
[----] asserts.cc:13: Assertion failed: assert is fatal, expect isn't
[----] asserts.cc:14: Assertion failed: This assert runs
[FAIL] asserts::base: (0.00s)
[FAIL] asserts::base
[----] asserts.cc:89: Assertion failed: The statement `throw std::exception()` did not throw an instance of the `std::bad_alloc` exception.
[FAIL] asserts::exception: (0.00s)
[FAIL] asserts::exception
[----] asserts.cc:19: Assertion failed: You can fail an assertion with a message from anywhere
[----] asserts.cc:20: Assertion failed: The conditions for this assertion were not met.
[FAIL] asserts::old_school: (0.00s)
[FAIL] asserts::old_school
[====] Synthesis: Tested: 7 | Passing: 3 | Failing: 4 | Crashing: 0 

View file

@ -1,3 +1,3 @@
[----] description.c:4: Assertion failed: The expression 0 is false.
[FAIL] misc::failing: (0.00s)
[FAIL] misc::failing
[====] Synthesis: Tested: 1 | Passing: 0 | Failing: 1 | Crashing: 0 

View file

@ -1,3 +1,3 @@
[----] description.cc:4: Assertion failed: The expression 0 is false.
[FAIL] misc::failing: (0.00s)
[FAIL] misc::failing
[====] Synthesis: Tested: 1 | Passing: 0 | Failing: 1 | Crashing: 0 

View file

@ -1,19 +1,19 @@
[----] parameterized.c:76: Assertion failed: Parameters: (1, 2.000000)
[FAIL] params::cleanup: (0.00s)
[FAIL] params::cleanup
[----] parameterized.c:76: Assertion failed: Parameters: (3, 4.000000)
[FAIL] params::cleanup: (0.00s)
[FAIL] params::cleanup
[----] parameterized.c:76: Assertion failed: Parameters: (5, 6.000000)
[FAIL] params::cleanup: (0.00s)
[FAIL] params::cleanup
[----] parameterized.c:36: Assertion failed: Parameters: (1, 2.000000)
[FAIL] params::multiple: (0.00s)
[FAIL] params::multiple
[----] parameterized.c:36: Assertion failed: Parameters: (3, 4.000000)
[FAIL] params::multiple: (0.00s)
[FAIL] params::multiple
[----] parameterized.c:36: Assertion failed: Parameters: (5, 6.000000)
[FAIL] params::multiple: (0.00s)
[FAIL] params::multiple
[----] parameterized.c:15: Assertion failed: Parameter: foo
[FAIL] params::str: (0.00s)
[FAIL] params::str
[----] parameterized.c:15: Assertion failed: Parameter: bar
[FAIL] params::str: (0.00s)
[FAIL] params::str
[----] parameterized.c:15: Assertion failed: Parameter: baz
[FAIL] params::str: (0.00s)
[FAIL] params::str
[====] Synthesis: Tested: 9 | Passing: 0 | Failing: 9 | Crashing: 0 

View file

@ -1,3 +1,3 @@
[----] report.c:5: Assertion failed: The expression 0 is false.
[FAIL] sample::test: (0.00s)
[FAIL] sample::test
[====] Synthesis: Tested: 1 | Passing: 0 | Failing: 1 | Crashing: 0 

View file

@ -1,3 +1,3 @@
[----] report.cc:5: Assertion failed: The expression 0 is false.
[FAIL] sample::test: (0.00s)
[FAIL] sample::test
[====] Synthesis: Tested: 1 | Passing: 0 | Failing: 1 | Crashing: 0 

View file

@ -1,4 +1,4 @@
[----] signal.c:16: Unexpected signal caught below this line!
[FAIL] simple::uncaught: CRASH!
[FAIL] simple::wrong_signal: (0.00s)
[FAIL] simple::wrong_signal
[====] Synthesis: Tested: 3 | Passing: 1 | Failing: 2 | Crashing: 1 

View file

@ -1,4 +1,4 @@
[----] signal.cc:16: Unexpected signal caught below this line!
[FAIL] simple::uncaught: CRASH!
[FAIL] simple::wrong_signal: (0.00s)
[FAIL] simple::wrong_signal
[====] Synthesis: Tested: 3 | Passing: 1 | Failing: 2 | Crashing: 1 

View file

@ -1,3 +1,3 @@
[----] simple.c:4: Assertion failed: The expression 0 is false.
[FAIL] misc::failing: (0.00s)
[FAIL] misc::failing
[====] Synthesis: Tested: 2 | Passing: 1 | Failing: 1 | Crashing: 0 

View file

@ -1,3 +1,3 @@
[----] simple.cc:4: Assertion failed: The expression 0 is false.
[FAIL] misc::failing: (0.00s)
[FAIL] misc::failing
[====] Synthesis: Tested: 2 | Passing: 1 | Failing: 1 | Crashing: 0 

75
samples/parameterized.cc Normal file
View file

@ -0,0 +1,75 @@
#include <criterion/parameterized.h>
// Basic usage
ParameterizedTestParameters(params, str) {
static const char *strings[] = {
"foo", "bar", "baz"
};
return cr_make_param_array(const char *, strings, sizeof (strings) / sizeof (const char *));
}
ParameterizedTest(const char **str, params, str) {
cr_assert_fail("Parameter: %s", *str);
}
// Multiple parameters must be coalesced in a single parameter
struct parameter_tuple {
int i;
double d;
};
ParameterizedTestParameters(params, multiple) {
static struct parameter_tuple params[] = {
{1, 2},
{3, 4},
{5, 6},
};
return criterion_test_params(params);
}
ParameterizedTest(struct parameter_tuple *tup, params, multiple) {
cr_assert_fail("Parameters: (%d, %f)", tup->i, tup->d);
}
// Using dynamically generated parameters
// you **MUST** use new_obj, new_arr, delete_obj, delete_arr instead of
// the new, new[], delete and delete[] operators (respectively) to allocate and
// deallocate dynamic memory in parameters, otherwise this will crash on
// Windows builds of the test.
// the criterion::allocator<T> allocator may be used with STL containers to
// allocate objects with the functions described above.
using criterion::new_obj;
using criterion::new_arr;
using criterion::delete_obj;
using criterion::delete_arr;
struct parameter_tuple_dyn {
int i;
std::unique_ptr<double, decltype(criterion::free)> d;
parameter_tuple_dyn() : i(0), d(nullptr, criterion::free) {}
parameter_tuple_dyn(int i, double *d) : i(i), d(d, criterion::free) {}
};
ParameterizedTestParameters(params, cleanup) {
static criterion::parameters<parameter_tuple_dyn> params;
params.push_back(parameter_tuple_dyn(1, new_obj<double>(2)));
params.push_back(parameter_tuple_dyn(3, new_obj<double>(4)));
params.push_back(parameter_tuple_dyn(5, new_obj<double>(6)));
// A criterion::parameters<T> can be returned in place of a
// criterion_test_params.
return params;
}
ParameterizedTest(parameter_tuple_dyn *tup, params, cleanup) {
cr_assert_fail("Parameters: (%d, %f)", tup->i, *tup->d);
}

View file

@ -4,10 +4,24 @@ set(SAMPLES
long-messages.c
other-crashes.c
failmessages.cc
exit.cc
long-messages.cc
other-crashes.cc
)
if (CMAKE_CXX_COMPILER_WORKS)
set(SAMPLES ${SAMPLES}
failmessages.cc
exit.cc
long-messages.cc
other-crashes.cc
exception.cc
)
endif ()
if (THEORIES)
set(SAMPLES ${SAMPLES} theories_regression.c)
if (CMAKE_CXX_COMPILER_WORKS)
set(SAMPLES ${SAMPLES} theories_regression.cc)
endif ()
endif ()
add_samples("${CMAKE_CURRENT_LIST_DIR}" "${SAMPLES}")

View file

@ -0,0 +1,18 @@
#include <criterion/criterion.h>
#include <stdexcept>
void raise_std(void) {
throw std::invalid_argument("Some exception message");
}
void raise_any(void) {
throw 1;
}
Test(exception, raise_std) { raise_std(); }
Test(exception, raise_any) { raise_any(); }
Test(exception, raise_std_init, .init = raise_std) {}
Test(exception, raise_any_init, .init = raise_any) {}
Test(exception, raise_std_fini, .fini = raise_std) {}
Test(exception, raise_any_fini, .fini = raise_any) {}

7
samples/tests/json_test.sh Executable file
View file

@ -0,0 +1,7 @@
#!/bin/sh
./simple.c.bin --json --always-succeed
./signal.c.bin --json --always-succeed
./asserts.c.bin --json --always-succeed
./more-suites.c.bin --json --always-succeed
./tests/long-messages.c.bin --json --always-succeed
./description.c.bin --json --always-succeed

View file

@ -17,7 +17,7 @@
[----] failmessages.c:22: Assertion failed: The expression (as strings) ("abc") <= ("aba") is false.
[----] failmessages.c:23: Assertion failed: The expression (as strings) ("abc") > ("abd") is false.
[----] failmessages.c:24: Assertion failed: The expression (as strings) ("abc") >= ("abd") is false.
[FAIL] messages::default: (0.00s)
[FAIL] messages::default
[----] failmessages.c:28: Assertion failed: foo bar
[----] failmessages.c:29: Assertion failed: foo bar
[----] failmessages.c:30: Assertion failed: foo bar
@ -37,5 +37,5 @@
[----] failmessages.c:46: Assertion failed: foo bar
[----] failmessages.c:47: Assertion failed: foo bar
[----] failmessages.c:48: Assertion failed: foo bar
[FAIL] messages::user: (0.00s)
[FAIL] messages::user
[====] Synthesis: Tested: 2 | Passing: 0 | Failing: 2 | Crashing: 0 

View file

@ -21,7 +21,7 @@
[----] failmessages.cc:28: Assertion failed: The statement `throw std::exception()` did throw an instance of the `std::exception` exception.
[----] failmessages.cc:29: Assertion failed: The statement `{}` did not throw any exception.
[----] failmessages.cc:30: Assertion failed: The statement `throw std::exception()` threw some exception.
[FAIL] messages::default: (0.00s)
[FAIL] messages::default
[----] failmessages.cc:34: Assertion failed: foo bar
[----] failmessages.cc:35: Assertion failed: foo bar
[----] failmessages.cc:36: Assertion failed: foo bar
@ -45,5 +45,5 @@
[----] failmessages.cc:57: Assertion failed: foo bar
[----] failmessages.cc:58: Assertion failed: foo bar
[----] failmessages.cc:59: Assertion failed: foo bar
[FAIL] messages::user: (0.00s)
[FAIL] messages::user
[====] Synthesis: Tested: 2 | Passing: 0 | Failing: 2 | Crashing: 0 

View file

@ -0,0 +1,237 @@
{
"id": "Criterion v2.1.0",
"passed": 1,
"failed": 1,
"errored": 0,
"skipped": 0,
"test_suites": [
{
"name": "misc",
"passed": 1,
"failed": 1,
"errored": 0,
"skipped": 0,
"tests": [
{
"name": "passing",
"assertions": 1,
"status": "PASSED"
},
{
"name": "failing",
"assertions": 1,
"status": "FAILED",
"messages": [
"simple.c:4: The expression 0 is false."
]
}
]
}
]
}
{
"id": "Criterion v2.1.0",
"passed": 1,
"failed": 2,
"errored": 1,
"skipped": 0,
"test_suites": [
{
"name": "simple",
"passed": 1,
"failed": 2,
"errored": 1,
"skipped": 0,
"tests": [
{
"name": "wrong_signal",
"assertions": 0,
"status": "FAILED",
"messages": [
]
},
{
"name": "uncaught",
"assertions": 0,
"status": "ERRORED",
"messages": ["The test crashed."]
},
{
"name": "caught",
"assertions": 0,
"status": "PASSED"
}
]
}
]
}
{
"id": "Criterion v2.1.0",
"passed": 4,
"failed": 2,
"errored": 0,
"skipped": 0,
"test_suites": [
{
"name": "asserts",
"passed": 4,
"failed": 2,
"errored": 0,
"skipped": 0,
"tests": [
{
"name": "string",
"assertions": 10,
"status": "PASSED"
},
{
"name": "old_school",
"assertions": 2,
"status": "FAILED",
"messages": [
"asserts.c:18: The conditions for this assertion were not met.",
"asserts.c:17: You can fail an assertion with a message from anywhere"
]
},
{
"name": "native",
"assertions": 8,
"status": "PASSED"
},
{
"name": "float",
"assertions": 2,
"status": "PASSED"
},
{
"name": "base",
"assertions": 6,
"status": "FAILED",
"messages": [
"asserts.c:12: This assert runs",
"asserts.c:11: assert is fatal, expect isn't"
]
},
{
"name": "array",
"assertions": 3,
"status": "PASSED"
}
]
}
]
}
{
"id": "Criterion v2.1.0",
"passed": 2,
"failed": 0,
"errored": 0,
"skipped": 1,
"test_suites": [
{
"name": "suite2",
"passed": 1,
"failed": 0,
"errored": 0,
"skipped": 0,
"tests": [
{
"name": "test",
"assertions": 1,
"status": "PASSED"
}
]
},
{
"name": "suite1",
"passed": 1,
"failed": 0,
"errored": 0,
"skipped": 0,
"tests": [
{
"name": "test",
"assertions": 1,
"status": "PASSED"
}
]
},
{
"name": "disabled",
"passed": 0,
"failed": 0,
"errored": 0,
"skipped": 1,
"tests": [
{
"name": "test",
"assertions": 0,
"status": "SKIPPED",
"messages": ["The test was skipped."]
}
]
}
]
}
{
"id": "Criterion v2.1.0",
"passed": 0,
"failed": 1,
"errored": 0,
"skipped": 0,
"test_suites": [
{
"name": "sample",
"passed": 0,
"failed": 1,
"errored": 0,
"skipped": 0,
"tests": [
{
"name": "long_msg",
"assertions": 1,
"status": "FAILED",
"messages": [
"long-messages.c:4: This is",
" A long message",
" Spawning multiple lines.",
" Formatting is respected."
]
}
]
}
]
}
{
"id": "Criterion v2.1.0",
"passed": 0,
"failed": 1,
"errored": 0,
"skipped": 1,
"test_suites": [
{
"name": "misc",
"passed": 0,
"failed": 1,
"errored": 0,
"skipped": 1,
"tests": [
{
"name": "skipped",
"assertions": 0,
"status": "SKIPPED",
"messages": ["The test was skipped."]
},
{
"name": "failing",
"assertions": 1,
"status": "FAILED",
"messages": [
"description.c:4: The expression 0 is false."
]
}
]
}
]
}

View file

@ -2,5 +2,5 @@
[----] A long message
[----] Spawning multiple lines.
[----] Formatting is respected.
[FAIL] sample::long_msg: (0.00s)
[FAIL] sample::long_msg
[====] Synthesis: Tested: 1 | Passing: 0 | Failing: 1 | Crashing: 0 

View file

@ -2,5 +2,5 @@
[----] A long message
[----] Spawning multiple lines.
[----] Formatting is respected.
[FAIL] sample::long_msg: (0.00s)
[FAIL] sample::long_msg
[====] Synthesis: Tested: 1 | Passing: 0 | Failing: 1 | Crashing: 0 

View file

@ -0,0 +1,61 @@
TAP version 13
1..2
# Criterion v2.1.0
# Running 2 tests from misc
ok - misc::passing (0.00s)
not ok - misc::failing (0.00s)
simple.c:4: Assertion failed: The expression 0 is false.
TAP version 13
1..3
# Criterion v2.1.0
# Running 3 tests from simple
not ok - simple::wrong_signal (0.00s)
not ok - simple::uncaught unexpected signal after signal.c:16
ok - simple::caught (0.00s)
TAP version 13
1..6
# Criterion v2.1.0
# Running 6 tests from asserts
ok - asserts::string (0.00s)
not ok - asserts::old_school (0.00s)
asserts.c:18: Assertion failed: The conditions for this assertion were not met.
asserts.c:17: Assertion failed: You can fail an assertion with a message from anywhere
ok - asserts::native (0.00s)
ok - asserts::float (0.00s)
not ok - asserts::base (0.00s)
asserts.c:12: Assertion failed: This assert runs
asserts.c:11: Assertion failed: assert is fatal, expect isn't
ok - asserts::array (0.00s)
TAP version 13
1..3
# Criterion v2.1.0
# Running 1 tests from suite2
ok - suite2::test (0.00s)
# Running 1 tests from suite1
ok - suite1::test (0.00s)
# Running 1 tests from disabled
ok - disabled::test # SKIP suite is disabled
TAP version 13
1..1
# Criterion v2.1.0
# Running 1 tests from sample
not ok - sample::long_msg (0.00s)
long-messages.c:4: Assertion failed: This is
A long message
Spawning multiple lines.
Formatting is respected.
TAP version 13
1..2
# Criterion v2.1.0
# Running 2 tests from misc
ok - misc::skipped This one is skipped # SKIP test is disabled
not ok - misc::failing Just a failing test (0.00s)
description.c:4: Assertion failed: The expression 0 is false.

View file

@ -0,0 +1,4 @@
[----] theories_regression.c:34: Assertion failed: The conditions for this assertion were not met.
[----] Theory theory::misc failed with the following parameters: ('a', true, 1, 1, 3.14f, 3.14, "test", "other test")
[FAIL] theory::misc
[====] Synthesis: Tested: 1 | Passing: 0 | Failing: 1 | Crashing: 0 

View file

@ -0,0 +1,4 @@
[----] theories_regression.cc:36: Assertion failed: The conditions for this assertion were not met.
[----] Theory theory::misc failed with the following parameters: ('a', true, 1, 1, 3.14f, 3.14, "test", "other test")
[FAIL] theory::misc
[====] Synthesis: Tested: 1 | Passing: 0 | Failing: 1 | Crashing: 0 

View file

@ -0,0 +1,82 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- Tests compiled with Criterion v2.1.0 -->
<testsuites name="Criterion Tests" tests="2" failures="1" errors="0" disabled="0">
<testsuite name="misc" tests="2" failures="1" errors="0" disabled="0" skipped="0">
<testcase name="passing" assertions="1" status="PASSED">
</testcase>
<testcase name="failing" assertions="1" status="FAILED">
<failure type="assert" message="1 assertion(s) failed.">simple.c:4: The expression 0 is false.&#10;</failure>
</testcase>
</testsuite>
</testsuites>
<?xml version="1.0" encoding="UTF-8"?>
<!-- Tests compiled with Criterion v2.1.0 -->
<testsuites name="Criterion Tests" tests="3" failures="2" errors="1" disabled="0">
<testsuite name="simple" tests="3" failures="2" errors="1" disabled="0" skipped="0">
<testcase name="wrong_signal" assertions="0" status="FAILED">
<failure type="assert" message="0 assertion(s) failed."></failure>
</testcase>
<testcase name="uncaught" assertions="0" status="ERRORED">
<error type="crash" message="The test crashed." /> </testcase>
<testcase name="caught" assertions="0" status="PASSED">
</testcase>
</testsuite>
</testsuites>
<?xml version="1.0" encoding="UTF-8"?>
<!-- Tests compiled with Criterion v2.1.0 -->
<testsuites name="Criterion Tests" tests="6" failures="2" errors="0" disabled="0">
<testsuite name="asserts" tests="6" failures="2" errors="0" disabled="0" skipped="0">
<testcase name="string" assertions="10" status="PASSED">
</testcase>
<testcase name="old_school" assertions="2" status="FAILED">
<failure type="assert" message="2 assertion(s) failed.">asserts.c:18: The conditions for this assertion were not met.&#10;asserts.c:17: You can fail an assertion with a message from anywhere&#10;</failure>
</testcase>
<testcase name="native" assertions="8" status="PASSED">
</testcase>
<testcase name="float" assertions="2" status="PASSED">
</testcase>
<testcase name="base" assertions="6" status="FAILED">
<failure type="assert" message="2 assertion(s) failed.">asserts.c:12: This assert runs&#10;asserts.c:11: assert is fatal, expect isn't&#10;</failure>
</testcase>
<testcase name="array" assertions="3" status="PASSED">
</testcase>
</testsuite>
</testsuites>
<?xml version="1.0" encoding="UTF-8"?>
<!-- Tests compiled with Criterion v2.1.0 -->
<testsuites name="Criterion Tests" tests="3" failures="0" errors="0" disabled="1">
<testsuite name="suite2" tests="1" failures="0" errors="0" disabled="0" skipped="0">
<testcase name="test" assertions="1" status="PASSED">
</testcase>
</testsuite>
<testsuite name="suite1" tests="1" failures="0" errors="0" disabled="0" skipped="0">
<testcase name="test" assertions="1" status="PASSED">
</testcase>
</testsuite>
<testsuite name="disabled" tests="1" failures="0" errors="0" disabled="1" skipped="1">
<testcase name="test" assertions="0" status="SKIPPED">
<skipped/>
</testcase>
</testsuite>
</testsuites>
<?xml version="1.0" encoding="UTF-8"?>
<!-- Tests compiled with Criterion v2.1.0 -->
<testsuites name="Criterion Tests" tests="1" failures="1" errors="0" disabled="0">
<testsuite name="sample" tests="1" failures="1" errors="0" disabled="0" skipped="0">
<testcase name="long_msg" assertions="1" status="FAILED">
<failure type="assert" message="1 assertion(s) failed.">long-messages.c:4: This is&#10; A long message&#10; Spawning multiple lines.&#10; Formatting is respected.&#10;</failure>
</testcase>
</testsuite>
</testsuites>
<?xml version="1.0" encoding="UTF-8"?>
<!-- Tests compiled with Criterion v2.1.0 -->
<testsuites name="Criterion Tests" tests="2" failures="1" errors="0" disabled="1">
<testsuite name="misc" tests="2" failures="1" errors="0" disabled="1" skipped="1">
<testcase name="skipped" assertions="0" status="SKIPPED">
<skipped/>
</testcase>
<testcase name="failing" assertions="1" status="FAILED">
<failure type="assert" message="1 assertion(s) failed.">description.c:4: The expression 0 is false.&#10;</failure>
</testcase>
</testsuite>
</testsuites>

View file

@ -13,14 +13,14 @@ else
sh -c "$bin_dir/$*" > $out_dir/$1.out 2> $out_dir/$1.err
fi
dos2unix $out_dir/$1.err $out_dir/$1.out
if [ -f $cmp_dir/$1.out.expected ] && [ "$(md5sum $out_dir/$1.out | cut -d' ' -f1)" != "$(md5sum $cmp_dir/$1.out.expected | cut -d' ' -f1)" ]; then
diff $out_dir/$1.out $cmp_dir/$1.out.expected
exit 255
if ! diff --strip-trailing-cr $out_dir/$1.out $cmp_dir/$1.out.expected ; then
exit 255
fi
fi
if [ -f $cmp_dir/$1.err.expected ] && [ "$(md5sum $out_dir/$1.err | cut -d' ' -f1)" != "$(md5sum $cmp_dir/$1.err.expected | cut -d' ' -f1)" ]; then
diff $out_dir/$1.err $cmp_dir/$1.err.expected
exit 255
if ! diff --strip-trailing-cr $out_dir/$1.err $cmp_dir/$1.err.expected ; then
exit 255
fi
fi

View file

@ -3,5 +3,5 @@
./signal.c.bin --tap --always-succeed
./asserts.c.bin --tap --always-succeed
./more-suites.c.bin --tap --always-succeed
./long-messages.c.bin --tap --always-succeed
./tests/long-messages.c.bin --tap --always-succeed
./description.c.bin --tap --always-succeed

View file

@ -0,0 +1,35 @@
#ifdef _MSC_VER
#pragma warning(disable : 4090)
#endif
#include <criterion/theories.h>
// Testing for various parameters
TheoryDataPoints(theory, misc) = {
DataPoints(char, 'a'),
DataPoints(bool, true),
DataPoints(short, 1),
DataPoints(int, 1),
DataPoints(float, 3.14f),
DataPoints(double, 3.14),
DataPoints(char *, "test"),
DataPoints(const char *, "other test"),
};
Theory((char c, bool b, short s, int i, float f, double d, char *str, const char *cstr), theory, misc) {
float reff = 3.14f;
double refd = 3.14;
cr_assert(b);
cr_assert_eq(c, 'a');
cr_assert_eq(s, 1);
cr_assert_eq(i, 1);
cr_assert_eq(f, reff);
cr_assert_eq(d, refd);
cr_assert_str_eq(str, "test");
cr_assert_str_eq(cstr, "other test");
// abort to see the formatted string of all parameters
cr_assert_fail();
}

View file

@ -0,0 +1,37 @@
#ifdef _MSC_VER
#pragma warning(disable : 4090)
#endif
#include <criterion/theories.h>
// Testing for various parameters
char test_str[] = {'t', 'e', 's', 't', '\0'};
TheoryDataPoints(theory, misc) = {
DataPoints(char, 'a'),
DataPoints(bool, true),
DataPoints(short, 1),
DataPoints(int, 1),
DataPoints(float, 3.14f),
DataPoints(double, 3.14),
DataPoints(char *, test_str),
DataPoints(const char *, "other test"),
};
Theory((char c, bool b, short s, int i, float f, double d, char *str, const char *cstr), theory, misc) {
float reff = 3.14f;
double refd = 3.14;
cr_assert(b);
cr_assert_eq(c, 'a');
cr_assert_eq(s, 1);
cr_assert_eq(i, 1);
cr_assert_eq(f, reff);
cr_assert_eq(d, refd);
cr_assert_str_eq(str, "test");
cr_assert_str_eq(cstr, "other test");
// abort to see the formatted string of all parameters
cr_assert_fail();
}

7
samples/tests/xml_test.sh Executable file
View file

@ -0,0 +1,7 @@
#!/bin/sh
./simple.c.bin --xml --always-succeed
./signal.c.bin --xml --always-succeed
./asserts.c.bin --xml --always-succeed
./more-suites.c.bin --xml --always-succeed
./tests/long-messages.c.bin --xml --always-succeed
./description.c.bin --xml --always-succeed

View file

@ -87,14 +87,17 @@ TheoryDataPoints(theory, misc) = {
};
Theory((char c, bool b, short s, int i, long l, long long ll, float f, double d, char *str, const char *cstr, struct my_object *obj), theory, misc) {
float reff = 3.14f;
double refd = 3.14;
cr_assert(b);
cr_assert_eq(c, 'a');
cr_assert_eq(s, 1);
cr_assert_eq(i, 1);
cr_assert_eq(l, 1);
cr_assert_eq(ll, 1);
cr_assert_eq(f, 3.14f);
cr_assert_eq(d, 3.14);
cr_assert_eq(f, reff);
cr_assert_eq(d, refd);
cr_assert_str_eq(str, "test");
cr_assert_str_eq(cstr, "other test");
cr_assert_eq(obj->foo, 42);
@ -102,20 +105,3 @@ Theory((char c, bool b, short s, int i, long l, long long ll, float f, double d,
// abort to see the formatted string of all parameters
cr_assert_fail();
}
// Manually generate datapoints
TheoryDataPoints(theory, gen) = {
DataPoints(int, 0), // placeholder
};
static void generate_datapoints(void) {
static int arr[] = {1, 2, 3, 4, 5};
TheoryDataPoint(theory, gen)[0].len = 5;
TheoryDataPoint(theory, gen)[0].arr = &arr;
}
Theory((int i), theory, gen, .init = generate_datapoints) {
(void) i;
cr_assert_fail(); // we fail to display the parameter
}

View file

@ -95,14 +95,17 @@ TheoryDataPoints(theory, misc) = {
};
Theory((char c, bool b, short s, int i, long l, long long ll, float f, double d, char *str, const char *cstr, struct my_object *obj), theory, misc) {
float reff = 3.14f;
double refd = 3.14;
cr_assert(b);
cr_assert_eq(c, 'a');
cr_assert_eq(s, 1);
cr_assert_eq(i, 1);
cr_assert_eq(l, 1);
cr_assert_eq(ll, 1);
cr_assert_eq(f, 3.14f);
cr_assert_eq(d, 3.14);
cr_assert_eq(f, reff);
cr_assert_eq(d, refd);
cr_assert_str_eq(str, "test");
cr_assert_str_eq(cstr, "other test");
cr_assert_eq(obj->foo, 42);
@ -110,20 +113,3 @@ Theory((char c, bool b, short s, int i, long l, long long ll, float f, double d,
// abort to see the formatted string of all parameters
cr_assert_fail();
}
// Manually generate datapoints
TheoryDataPoints(theory, gen) = {
DataPoints(int, 0), // placeholder
};
static void generate_datapoints(void) {
static int arr[] = {1, 2, 3, 4, 5};
TheoryDataPoint(theory, gen)[0].len = 5;
TheoryDataPoint(theory, gen)[0].arr = &arr;
}
Theory((int i), theory, gen, .init = generate_datapoints) {
(void) i;
cr_assert_fail(); // we fail to display the parameter
}

View file

@ -23,6 +23,7 @@
*/
#include "alloc.h"
#include "internal.h"
#include "criterion/logging.h"
#include <stdlib.h>
#ifdef VANILLA_WIN32
@ -51,7 +52,7 @@ void init_inheritable_heap(void) {
HeapDestroy(h->handle);
if (g_heap == (HANDLE) NULL) {
fputs("Could not create the private inheritable heap.", stderr);
criterion_perror("Could not create the private inheritable heap.\n");
abort();
}
}

View file

@ -30,7 +30,22 @@
# undef _WIN32_WINNT
# define _WIN32_WINNT 0x0502
# include <windows.h>
# if defined(MINGW_DEFINE_OFF_T) && (defined(__MINGW32__) || defined(__MINGW64__))
# include "off_t.h"
# if !defined(__MINGW64__)
# define off_t cr_off32
# else
# define off_t cr_off64
# endif
# define off64_t cr_off64
# endif
# include <io.h>
# if defined(MINGW_DEFINE_OFF_T) && (defined(__MINGW32__) || defined(__MINGW64__))
# undef off_t
# undef off64_t
# endif
# include <fcntl.h>
# include <winnt.h>
# include <stdint.h>
@ -40,6 +55,15 @@
# include <sys/wait.h>
# include <sys/signal.h>
# include <sys/fcntl.h>
# include <sys/param.h>
# ifdef BSD
# include <sys/types.h>
typedef unsigned long u_long;
typedef unsigned int u_int;
typedef unsigned short u_short;
typedef unsigned char u_char;
# include <sys/sysctl.h>
# endif
# endif
# include "posix.h"

Some files were not shown because too many files have changed in this diff Show more