pax_global_header 0000666 0000000 0000000 00000000064 13666233252 0014522 g ustar 00root root 0000000 0000000 52 comment=6926de4263e794c33abb75007404a053277ba2f9
cgreen-1.3.0/ 0000775 0000000 0000000 00000000000 13666233252 0012766 5 ustar 00root root 0000000 0000000 cgreen-1.3.0/.cproject 0000664 0000000 0000000 00000005201 13666233252 0014576 0 ustar 00root root 0000000 0000000
make
all
true
false
true
rm
-rf build
true
false
true
cgreen-1.3.0/.dir-locals.el 0000664 0000000 0000000 00000000116 13666233252 0015415 0 ustar 00root root 0000000 0000000 ((c-mode . (
(indent-tabs-mode . nil)
(c-basic-offset . 4)
)
)
)
cgreen-1.3.0/.gitattributes 0000664 0000000 0000000 00000000572 13666233252 0015665 0 ustar 00root root 0000000 0000000 # Auto detect text files and perform LF normalization
* text=auto
# Custom for Visual Studio
*.cs diff=csharp
# Standard to msysgit
*.doc diff=astextplain
*.DOC diff=astextplain
*.docx diff=astextplain
*.DOCX diff=astextplain
*.dot diff=astextplain
*.DOT diff=astextplain
*.pdf diff=astextplain
*.PDF diff=astextplain
*.rtf diff=astextplain
*.RTF diff=astextplain
cgreen-1.3.0/.gitignore 0000664 0000000 0000000 00000000212 13666233252 0014751 0 ustar 00root root 0000000 0000000 build
.idea
CMakeCache.txt
CMakeFiles
Testing
*.exe
*.stackdump
build-stamp
configure-stamp
*~
#*#
.#*
bin
lib
valgrind.log
gitrevision.h
cgreen-1.3.0/.project 0000664 0000000 0000000 00000004363 13666233252 0014443 0 ustar 00root root 0000000 0000000
cgreen
org.eclipse.cdt.managedbuilder.core.genmakebuilder
clean,full,incremental,
?name?
org.eclipse.cdt.make.core.append_environment
true
org.eclipse.cdt.make.core.autoBuildTarget
all
org.eclipse.cdt.make.core.buildArguments
org.eclipse.cdt.make.core.buildCommand
make
org.eclipse.cdt.make.core.cleanBuildTarget
clean
org.eclipse.cdt.make.core.contents
org.eclipse.cdt.make.core.activeConfigSettings
org.eclipse.cdt.make.core.enableAutoBuild
false
org.eclipse.cdt.make.core.enableCleanBuild
true
org.eclipse.cdt.make.core.enableFullBuild
true
org.eclipse.cdt.make.core.fullBuildTarget
all
org.eclipse.cdt.make.core.stopOnError
true
org.eclipse.cdt.make.core.useDefaultBuildCmd
true
org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder
org.eclipse.cdt.core.cnature
org.eclipse.cdt.managedbuilder.core.ScannerConfigNature
org.eclipse.cdt.managedbuilder.core.managedBuildNature
org.eclipse.cdt.core.ccnature
cgreen-1.3.0/.travis.yml 0000664 0000000 0000000 00000001736 13666233252 0015106 0 ustar 00root root 0000000 0000000 sudo: false
language: c
# Build matrix
compiler:
- gcc
- clang
env:
- CGREEN_WITH_STATIC_LIBRARY="OFF"
- CGREEN_WITH_STATIC_LIBRARY="ON"
addons:
apt:
packages:
- cmake
- lcov
- g++
before_install:
- if [[ $CC == gcc ]] ; then export CXX=g++ ; else export CXX=clang++ ; fi
- $CC --version
- $CXX --version
- gem install coveralls-lcov
- if [ "$CC" = "gcc" ]; then export WITH_GCOV=ON; else WITH_GCOV=OFF; fi
script:
- mkdir -p build
- cd build
- cmake -DCGREEN_WITH_UNIT_TESTS:BOOL=ON -DCGREEN_WITH_STATIC_LIBRARY:BOOL=$CGREEN_WITH_STATIC_LIBRARY -DCGREEN_INTERNAL_WITH_GCOV:BOOL=$WITH_GCOV ..
- make -j2
- ctest --output-on-failure
after_success:
- if [ "$CC" = "gcc" ];
then
lcov -d tests -d src -d tools -base-directory .. -c -o coverage.info;
lcov --remove coverage.info '/usr/*' -o coverage.info;
cd ..;
coveralls-lcov build/coverage.info;
fi
notifications:
slack: cgreen:EC3bZqwnyBsaqyeIndEewwNT
cgreen-1.3.0/CMakeLists.txt 0000664 0000000 0000000 00000010575 13666233252 0015536 0 ustar 00root root 0000000 0000000 # Required cmake version
cmake_minimum_required(VERSION 2.8.5)
project(cgreen)
if (NOT(CMAKE_MAJOR_VERSION LESS 3) AND APPLE)
if(POLICY CMP0042)
cmake_policy(SET CMP0042 NEW) # CMake 3.0 to use @rpath on MacOSX libraries
endif()
endif()
find_package (Threads)
enable_testing()
# global needed variables
set(APPLICATION_NAME ${PROJECT_NAME})
set(APPLICATION_VERSION_MAJOR "1")
set(APPLICATION_VERSION_MINOR "3")
set(APPLICATION_VERSION_PATCH "0")
set(APPLICATION_VERSION ${APPLICATION_VERSION_MAJOR}.${APPLICATION_VERSION_MINOR}.${APPLICATION_VERSION_PATCH}${APPLICATION_VERSION_STATUS})
add_definitions(-DVERSION="${APPLICATION_VERSION}")
set(LIBRARY_VERSION ${APPLICATION_VERSION_MAJOR}.${APPLICATION_VERSION_MINOR}.${APPLICATION_VERSION_PATCH})
set(LIBRARY_SOVERSION ${APPLICATION_VERSION_MAJOR})
include(GNUInstallDirs)
if(MSVC)
# these have sensible defaults on other platforms
set(CMAKE_INSTALL_BINDIR ".")
set(CMAKE_INSTALL_LIBDIR ".")
endif(MSVC)
# where to look first for cmake modules, before ${CMAKE_ROOT}/Modules/ is checked
set(CMAKE_MODULE_PATH
${PROJECT_SOURCE_DIR}/cmake/Modules
)
# add definitions
include(DefineCMakeDefaults)
include(DefineCompilerFlags)
include(DefineOptions.cmake)
include(DefineCPackConfig)
# add macros
include(MacroAddPlugin)
include(MacroCopyFile)
# Generate gitrevision.h if Git is available and the .git directory is found.
find_program(GIT_EXECUTABLE git DOC "Git version control")
mark_as_advanced(GIT_EXECUTABLE)
# Find path to .git/logs/HEAD so that the gitrevision.h generation will only
# happen on new commits. This is done from $PROJECT_SOURCE_DIR because git rev-parse
# doesn't always return an absolute path so need to use get_filename_component()
# to get a cross-platform `readlink -f $(git rev-parse --git-path logs/HEAD)`
execute_process(
COMMAND ${GIT_EXECUTABLE} rev-parse --git-path logs/HEAD
WORKING_DIRECTORY "${PROJECT_SOURCE_DIR}"
OUTPUT_VARIABLE GITDIR
OUTPUT_STRIP_TRAILING_WHITESPACE
)
get_filename_component(GITDIR "${GITDIR}" ABSOLUTE)
# config.h checks
include(ConfigureChecks.cmake)
configure_file(config.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/config.h)
# check subdirectories
add_subdirectory(doc)
add_subdirectory(include)
add_subdirectory(src)
if (UNIX OR MSYS)
# reflective runner only supported on UNIX/binutils platforms
add_subdirectory(tools)
endif(UNIX OR MSYS)
# add_subdirectory(samples)
if (CGREEN_WITH_UNIT_TESTS)
include(MacroAddUnitTest)
include(MacroAddTest)
add_subdirectory(tests)
if (UNIX OR MSYS)
# reflective runner only supported on UNIX/binutils platforms
add_subdirectory(tools/tests)
endif(UNIX OR MSYS)
endif (CGREEN_WITH_UNIT_TESTS)
# add custom 'check' target to run tests with output-on-failure
if (CMAKE_CONFIGURATION_TYPES)
add_custom_target(check COMMAND ${CMAKE_CTEST_COMMAND}
--force-new-ctest-process --output-on-failure
--build-config "$")
else()
add_custom_target(check COMMAND ${CMAKE_CTEST_COMMAND}
--force-new-ctest-process --output-on-failure)
endif()
IF(CGREEN_INTERNAL_WITH_GCOV)
IF(CMAKE_C_COMPILER_ID STREQUAL GNU)
include(CodeCoverage)
add_custom_target(coverage
COMMAND ${LCOV_PATH} --directory . --capture --output-file coverage.info
COMMAND ${LCOV_PATH} --remove coverage.info '/usr/*' -o coverage.info
COMMAND ${GENHTML_PATH} -o coverage coverage.info
)
ENDIF()
ELSE()
add_custom_target(coverage
COMMAND echo "WARNING: Configure CGREEN_INTERNAL_WITH_GCOV to get coverage")
ENDIF()
#### Begin cgreen package configuration steps. ####
# After install other CMake projects can
# use find_package( cgreen )
set( CONFIG_INSTALL_DIR
"${CMAKE_INSTALL_LIBDIR}/cmake/${APPLICATION_NAME}" )
set( PROJECT_CONFIG_IN
"${CMAKE_CURRENT_SOURCE_DIR}/cgreen-config.cmake.in" )
set( VERSION_CONFIG_IN
"${CMAKE_CURRENT_SOURCE_DIR}/cgreen-config-version.cmake.in" )
set( PROJECT_CONFIG
"${PROJECT_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/cgreen-config.cmake" )
set( VERSION_CONFIG
"${PROJECT_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/cgreen-config-version.cmake" )
configure_file( ${PROJECT_CONFIG_IN}
"${PROJECT_CONFIG}" @ONLY )
configure_file( ${VERSION_CONFIG_IN}
"${VERSION_CONFIG}" @ONLY )
install(FILES
"${PROJECT_CONFIG}" "${VERSION_CONFIG}"
DESTINATION
"${CONFIG_INSTALL_DIR}" )
#### End cgreen package configuration steps. ####
cgreen-1.3.0/CTestConfig.cmake 0000664 0000000 0000000 00000001021 13666233252 0016132 0 ustar 00root root 0000000 0000000 ## This file should be placed in the root directory of your project.
## Then modify the CMakeLists.txt file in the root directory of your
## project to incorporate the testing dashboard.
## # The following are required to uses Dart and the Cdash dashboard
## ENABLE_TESTING()
## INCLUDE(CTest)
set(CTEST_PROJECT_NAME "CGreen")
set(CTEST_NIGHTLY_START_TIME "00:00:00 EST")
set(CTEST_DROP_METHOD "http")
set(CTEST_DROP_SITE "my.cdash.org")
set(CTEST_DROP_LOCATION "/submit.php?project=CGreen")
set(CTEST_DROP_SITE_CDASH TRUE)
cgreen-1.3.0/ConfigureChecks.cmake 0000664 0000000 0000000 00000000731 13666233252 0017033 0 ustar 00root root 0000000 0000000 include(CheckIncludeFile)
include(CheckSymbolExists)
include(CheckFunctionExists)
include(CheckLibraryExists)
include(CheckTypeSize)
include(CheckCXXSourceCompiles)
set(PACKAGE ${APPLICATION_NAME})
set(VERSION ${APPLICATION_VERSION})
set(DATADIR ${DATA_INSTALL_DIR})
set(LIBDIR ${LIB_INSTALL_DIR})
set(PLUGINDIR "${PLUGIN_INSTALL_DIR}-${LIBRARY_SOVERSION}")
set(SYSCONFDIR ${SYSCONF_INSTALL_DIR})
set(BINARYDIR ${PROJECT_BINARY_DIR})
set(SOURCEDIR ${PROJECT_SOURCE_DIR})
cgreen-1.3.0/DefineOptions.cmake 0000664 0000000 0000000 00000000367 13666233252 0016544 0 ustar 00root root 0000000 0000000 option(CGREEN_WITH_STATIC_LIBRARY "Build with a static library" OFF)
option(CGREEN_WITH_UNIT_TESTS "Build unit tests" ON)
option(CGREEN_INTERNAL_WITH_GCOV "Build with test coverage instrumentation" OFF)
mark_as_advanced(CGREEN_INTERNAL_WITH_GCOV)
cgreen-1.3.0/INSTALL 0000664 0000000 0000000 00000005374 13666233252 0014030 0 ustar 00root root 0000000 0000000 Building and Installing Cgreen
==============================
This document is incomplete. ??? are placeholders.
There are several ways to use Cgreen:
1) You want to write some tests for a personal project, but don't need to ship
the test suite with the product, or you just want to try out Cgreen.
2) You want to write some tests that will be used by other developers. This
is the normal way to use Cgreen.
3) You want to ship working tests with a product and want to bundle Cgreen
as the test runner.
4) You are pulling Cgreen directly from github:
git clone git@github.com:cgreen-devs/cgreen.git
We'll walk you through these in order...
1) So you want to write a test quickly.
As a user wanting to write some quick tests, the quickest way is to
download the prebuilt binaries for your platform. Just install the
files in some private tree.
You will see a cgreen.h and both a cgreen shared object or DLL, and a
static library for your system.
Include the header and link the library as you normally would.
2) Cgreen needs to be installed to be usable by everyone.
This is the same as scenario 1, but install the files in a public
/usr/local (or equivalent). The Cgreen header should just be available
through...
#include
...and adding -lcgreen should be enough to link under gcc.
3) ???
4) You will have to carry out some additional steps if you work straight off
of a Git clone.
We are using the CMake (www.cmake.org) build system. The following
steps are called "out-of-source building", because we will build all
the project files outside of the sources directory to completely
retain the original source tree.
Assuming you have the cloned cgreen sources into a subdirectory
"cgreen" in the current directory we want to create a build directory
parallel to the source directory.
The default Makefile will create a separate 'build' directory and inside
that subdirectories for C and C++. That means that you can just do:
$ make
$ make test
$ make install
You also have some options
- build with static libraries
- build HTML or PDF documentation
To enable any of these use the cmake graphical user interface (CMakeSetup
on Windows or ccmake on UNIX) to turn these options on or off.
Note on CYGWIN: Cygwin is not a WIN32 platform, but it is a
DLL-platform where libraries normally goes in the bin directory. Running
the self-tests handles this automatically but if you want to use the binaries
in the 'build'-tree you can either:
1) install before running the tests and also set your PATH to include
"/usr/local/lib"
2) setting the PATH to include the build directory where the libraries are
there is a sh-compatible command script to do that for you. From the top
of the Cgreen source directory do:
. cygwin-setup.sh
/Thomas 2015-12-29
cgreen-1.3.0/LICENSE 0000664 0000000 0000000 00000001350 13666233252 0013772 0 ustar 00root root 0000000 0000000 ISC License
Copyright (c) [year], [fullname]
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
cgreen-1.3.0/Makefile 0000775 0000000 0000000 00000010126 13666233252 0014431 0 ustar 00root root 0000000 0000000 # This Makefile ensures that the build is made out of source in a
# subdirectory called 'build' If it doesn't exist, it is created.
#
# This Makefile also contains delegation of the most common make commands
#
# If you have cmake installed you should be able to do:
#
# make
# make test
# make install
# make package
#
# That should build Cgreen in the build directory, run some tests,
# install it locally and generate a distributable package.
all: build/Makefile
cd build; make
.PHONY:debug
debug: build
cd build; cmake -DCMAKE_BUILD_TYPE:string=Debug ..; make
32bit: build
-rm -rf build; mkdir build; cd build; cmake -DCMAKE_C_FLAGS="-m32" -DCMAKE_CXX_FLAGS="-m32" ..; make
.PHONY:test
test: build/Makefile
cd build; make check
.PHONY:clean
clean: build/Makefile
cd build; make clean
.PHONY:package
package: build/Makefile
cd build; make package
.PHONY:install
install: build
ifeq ($(OS),Msys)
# Thanks to https://stackoverflow.com/a/46027426/204658
cd build; make install DESTDIR=/
else
cd build; make install
endif
# This is kind of a hack to get a quicker and clearer feedback when
# developing Cgreen by allowing 'make unit'. Must be updated when new
# test libraries or output comparisons are added.
# Find out if 'uname -o' works, if it does - use it, otherwise use 'uname -s'
UNAMEOEXISTS=$(shell uname -o &>/dev/null; echo $$?)
ifeq ($(UNAMEOEXISTS),0)
OS=$(shell uname -o)
else
OS=$(shell uname -s)
endif
# Set prefix and suffix for shared libraries depending on platform
ifeq ($(OS),Darwin)
LDPATH=DYLD_LIBRARY_PATH=$(PWD)/build/src
PREFIX=lib
SUFFIX=.dylib
else ifeq ($(OS),Cygwin)
LDPATH=PATH=$(PWD)/build/src:"$$PATH"
PREFIX=cyg
SUFFIX=.dll
else ifeq ($(OS),Msys)
LDPATH=PATH=$(PWD)/build/src:"$$PATH"
PREFIX=lib
SUFFIX=.dll
else
LDPATH=LD_LIBRARY_PATH=$(PWD)/build/src
PREFIX=lib
SUFFIX=.so
endif
DIFF_TOOL=../../tools/cgreen_runner_output_diff
XML_DIFF_TOOL=../../tools/cgreen_xml_output_diff
DIFF_TOOL_ARGUMENTS = $(1)_tests \
../../tests \
$(1)_tests.expected
unit: build-it
SOURCEDIR=$$PWD/tests/ ; \
cd build ; \
$(LDPATH) tools/cgreen-runner -c `find tests -name $(PREFIX)cgreen_c_tests$(SUFFIX)` ; \
r=$$((r + $$?)) ; \
$(LDPATH) tools/cgreen-runner -c `find tests -name $(PREFIX)cgreen_cpp_tests$(SUFFIX)` ; \
r=$$((r + $$?)) ; \
$(LDPATH) tools/cgreen-runner -c `find tools/tests -name $(PREFIX)cgreen_runner_tests$(SUFFIX)` ; \
r=$$((r + $$?)) ; \
cd tests ; \
$(LDPATH) $(XML_DIFF_TOOL) $(call DIFF_TOOL_ARGUMENTS,xml_output) ; \
r=$$((r + $$?)) ; \
$(LDPATH) $(DIFF_TOOL) $(call DIFF_TOOL_ARGUMENTS,assertion_messages) ; \
r=$$((r + $$?)) ; \
$(LDPATH) $(DIFF_TOOL) $(call DIFF_TOOL_ARGUMENTS,mock_messages) ; \
r=$$((r + $$?)) ; \
$(LDPATH) $(DIFF_TOOL) $(call DIFF_TOOL_ARGUMENTS,constraint_messages) ; \
r=$$((r + $$?)) ; \
$(LDPATH) $(DIFF_TOOL) $(call DIFF_TOOL_ARGUMENTS,custom_constraint_messages) ; \
r=$$((r + $$?)) ; \
$(LDPATH) $(DIFF_TOOL) $(call DIFF_TOOL_ARGUMENTS,ignore_messages) ; \
r=$$((r + $$?)) ; \
$(LDPATH) CGREEN_PER_TEST_TIMEOUT=1 $(DIFF_TOOL) $(call DIFF_TOOL_ARGUMENTS,failure_messages) ; \
r=$$((r + $$?)) ; \
exit $$r
.PHONY: doc
doc: build
cd build; cmake -DCGREEN_WITH_HTML_DOCS:bool=TRUE ..; make; cmake -DCGREEN_WITH_HTML_DOCS:bool=False ..; echo open $(PWD)/build/doc/cgreen-guide-en.html
pdf: build
cd build; cmake -DCGREEN_WITH_PDF_DOCS:bool=TRUE ..; make; cmake -DCGREEN_WITH_PDF_DOCS:bool=False ..; echo open $(PWD)/build/doc/cgreen-guide-en.pdf
chunked: doc
asciidoctor-chunker build/doc/cgreen-guide-en.html -o docs
echo open $(PWD)/docs/index.html
.PHONY:valgrind
valgrind: build-it
> valgrind.log
for lib in `ls build/tests/$(PREFIX)*_tests$(SUFFIX)` ; \
do \
LD_LIBRARY_PATH=build/src valgrind --leak-check=full build/tools/cgreen-runner $$lib >> valgrind.log 2>&1 ; \
done
grep " lost:" valgrind.log | grep -v " 0 bytes" | wc -l
############# Internal
build-it: build/Makefile
make -C build
build:
mkdir build
build/Makefile: build
ifeq ($(OS),Msys)
# Thanks to https://stackoverflow.com/a/46027426/204658
cd build; cmake -G"MSYS Makefiles" -DCMAKE_INSTALL_PREFIX=/usr/local ..
else
cd build; cmake ..
endif
.SILENT:
cgreen-1.3.0/README.md 0000664 0000000 0000000 00000016154 13666233252 0014254 0 ustar 00root root 0000000 0000000 [](https://travis-ci.org/cgreen-devs/cgreen)
[](https://coveralls.io/github/cgreen-devs/cgreen?branch=master)
[](https://gitter.im/cgreen-devs/chat)

Cgreen - The Modern Unit Test and Mocking Framework for C and C++
=================================================================
Do you TDD? In C or C++? Maybe you want to have your tests read out in
a fluent fashion? Like this
Ensure(Converter, converts_XIV_to_14) {
assert_that(convert_roman_to_decimal("XIV"), is_equal_to(14));
}
And you want output like this
roman_test.c:12: Failure: Converter -> converts_XIV_to_14
Expected [convert_roman_to_decimal("XIV")] to [equal] [14]
actual value: [0]
expected value: [14]
Then *Cgreen* is the thing for you!
**TLDR;** The full tutorial is on
[github.io](https://cgreen-devs.github.io). Or have a look at the
[cheat sheet](doc/cheat-sheet.md).
## What It Is
Cgreen is a modern unit test and mocking framework for C and C++. Here
are some of Cgreens unique selling points:
- fast build, clean code, highly portable
- auto-discovery of tests without the abuse of static initializers or globals
- extensible without recompiling
- fluent, expressive and readable API with the same modern syntax across C and C++
- process isolation for each test preventing intermittent failures
and cross-test dependencies
- built-in mocking for C, compatible with mockitopp and other C++ mocking libraries
- expressive and clear output using the default reporter
- fully functional mocks, both strict, loose and learning
- mocks with side effects
- extensive and expressive constraints for many datatypes
- custom constraints can be constructed by user
- bdd-flavoured test declarations with Before and After declarations
- extensible reporting mechanism
- fully composable test suites
- a single test can be run in a single process for easier debugging
## Getting It
Cgreen is hosted on GitHub. As of now there are no pre-built packages
to download, so you have to clone the repository or download the
source zip from [GitHub](http://www.github.com/cgreen-devs/cgreen) and
build it yourself.
We are hoping to get Cgreen into Debian and Fedora repositories, but in
the mean time there are some packaging scripts available, not all official:
- [debian packaging is ongoing in #208](https://github.com/cgreen-devs/cgreen/issues/208)
- [fedora/rpm packaging is part of cgreens source tree](https://github.com/cgreen-devs/cgreen/tree/master/contrib/rpm) and actual Fedora repo work is ongoing in [#225](https://github.com/cgreen-devs/cgreen/issues/225)
- [PACMAN script](https://github.com/voins/cgreen-pkg)
- [MacOS packagesbuild](https://github.com/cgreen-devs/cgreen-macosx-packaging)
- [Cygwin package script](https://github.com/cgreen-devs/cgreen-cygport)
## Building It
You need the [CMake](http://www.cmake.org) build system. Most standard
C/C++ compilers should work. GCC definitely does.
In the root directory run ``make``. That will configure and build the
library and the `cgreen-runner`, both supporting both C and C++. See
also the documentation.
## Using It
Tests are fairly easy write, as shown by the examples in the beginning
of this readme. You should probably read the
[tutorial](https://cgreen-devs.github.io) once before writing your
first test, though.
Basically you can run your tests in two ways
1. Compile and link all your tests with a test driver (as shown in the
fist chapters of the tutorial)
2. Link your tests into separate shared libraries (`.so`, `.dylib` or
similar) and run them with the `cgreen-runner` (described in chapter
6 of the tutorial)
Option 2 is very handy, you can run multiple libraries in the same
run, but also specify single tests that you want to run. And with the
completion script available for bash you can get TAB-completion not
only for files and options but also for tests inside the libraries.
`cgreen-debug` is a small script that you invoke in the same way as
the runner but runs a single, specified, test and puts you in the
debugger at the start of that test. Awesome!
## Using Cgreen in other CMake projects
Once Cgreen is installed you can use ``find_package(cgreen)`` in your CMake
projects to get access to useful variables like ``${CGREEN_LIBRARIES}``,
``${CGREEN_EXECUTABLE}`` and ``${CGREEN_INCLUDE_DIRS}``. Version can be
specified in ``find_package`` as well. For example, in order to enforce a minimum
version of Cgreen in your project use ``find_package(cgreen 1.1.0)``
## Reading Up!
You can read the extensive tutorial directly on
[GitHub](https://cgreen-devs.github.io).
There is a [cheat sheet](https://github.com/cgreen-devs/cgreen/blob/master/doc/cheat-sheet.md)
available.
You can also build the documentation yourself in HTML and PDF format.
Generate it using Asciidoctor, which can be done using the CMake
configuration. Of course you need
[Asciidoctor](http://www.asciidoctor.org).
make docs
make pdf
(Generating PDF also requires [asciidoctor-pdf](https://asciidoctor.org/docs/asciidoctor-pdf/).)
## License
Cgreen is licensed under the ISC License
(http://spdx.org/licenses/ISC), sometimes known as the OpenBSD
license. If there is no licence agreement with this package please
download a version from the location above. You must read and accept
that licence to use this software. The file is titled simply LICENSE.
## The Original Version
What is it? It's a framework for unit testing, written in C. A tool
for C developers writing tests of their own code.
If you have used JUnit, or any of the xUnit clones, you will find
the concept familiar. In particular the tool supports a range of
assertions, composable test suites and setup/teardown facilities.
Because of the peculiarities of C programming, each test function
is normally run in it's own process.
This project is very close in scope to the "Check" unit tester and
was influenced by it...
http://check.sourceforge.net/projects/check/
The main difference from this tool and other xUnit tools, such as
"Check", is that test results are not stored. Instead they are
streamed to the reporter psuedo-class, one that is easily
overridden by the end user.
The other main extra feature is the support for writing mock
callbacks. This includes generating sequences for return values
or parameter expectations.
Feedback, queries and request should be put to the cgreen developers
through https://github.com/cgreen-devs/cgreen.
This tool is basically a spin off from a research project at
Wordtracker and would not have happened without the generous
financial support of the Wordtracker keyword tool...
http://www.wordtracker.com/
Substantial inital work by Marcus Baker . Recent
additions by Matt Hargett , Thomas Nilefalk
, João Freitas and others.
cgreen-1.3.0/cgreen-config-version.cmake.in 0000664 0000000 0000000 00000000711 13666233252 0020565 0 ustar 00root root 0000000 0000000 set(PACKAGE_VERSION "@APPLICATION_VERSION_MAJOR@.@APPLICATION_VERSION_MINOR@.@APPLICATION_VERSION_PATCH@")
# Check whether the requested PACKAGE_FIND_VERSION is compatible
if("${PACKAGE_VERSION}" VERSION_LESS "${PACKAGE_FIND_VERSION}")
set(PACKAGE_VERSION_COMPATIBLE FALSE)
else()
set(PACKAGE_VERSION_COMPATIBLE TRUE)
if ("${PACKAGE_VERSION}" VERSION_EQUAL "${PACKAGE_FIND_VERSION}")
set(PACKAGE_VERSION_EXACT TRUE)
endif()
endif()
cgreen-1.3.0/cgreen-config.cmake.in 0000664 0000000 0000000 00000001002 13666233252 0017074 0 ustar 00root root 0000000 0000000 # - Config file for the cgreen package
# It defines the following variables
# CGREEN_CMAKE_DIR - include directories for cgreen
# CGREEN_INCLUDE_DIRS - include directories for cgreen
# CGREEN_LIBRARIES - libraries to link against
# CGREEN_EXECUTABLE - the cgreen executable
get_filename_component( CGREEN_CMAKE_DIRS "${CMAKE_CURRENT_LIST_FILE}" PATH )
# leave this up to cmake
find_path(CGREEN_INCLUDE_DIRS NAMES cgreen/cgreen.h)
set( CGREEN_LIBRARIES cgreen )
set( CGREEN_EXECUTABLE cgreen-runner )
cgreen-1.3.0/cmake/ 0000775 0000000 0000000 00000000000 13666233252 0014046 5 ustar 00root root 0000000 0000000 cgreen-1.3.0/cmake/Modules/ 0000775 0000000 0000000 00000000000 13666233252 0015456 5 ustar 00root root 0000000 0000000 cgreen-1.3.0/cmake/Modules/COPYING-CMAKE-SCRIPTS 0000664 0000000 0000000 00000002457 13666233252 0020464 0 ustar 00root root 0000000 0000000 Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
1. Redistributions of source code must retain the copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
3. The name of the author may not be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
cgreen-1.3.0/cmake/Modules/CodeCoverage.cmake 0000664 0000000 0000000 00000007361 13666233252 0021015 0 ustar 00root root 0000000 0000000 # - Enable Code Coverage
#
# 2012-01-31, Lars Bilke
#
# USAGE:
# 1. Copy this file into your cmake modules path
# 2. Add the following line to your CMakeLists.txt:
# INCLUDE(CodeCoverage)
#
# 3. Use the function SETUP_TARGET_FOR_COVERAGE to create a custom make target
# which runs your test executable and produces a lcov code coverage report.
#
# Check prereqs
FIND_PROGRAM( GCOV_PATH gcov )
FIND_PROGRAM( LCOV_PATH lcov )
FIND_PROGRAM( GENHTML_PATH genhtml )
FIND_PROGRAM( GCOVR_PATH gcovr PATHS ${CMAKE_SOURCE_DIR}/tests)
IF(NOT GCOV_PATH)
MESSAGE(FATAL_ERROR "gcov not found! Aborting...")
ENDIF() # NOT GCOV_PATH
IF(NOT CMAKE_C_COMPILER_ID STREQUAL GNU)
MESSAGE(FATAL_ERROR "Compiler is not GNU gcc! Aborting...")
ENDIF()
IF ( NOT CMAKE_BUILD_TYPE STREQUAL "Debug" )
MESSAGE( WARNING "Code coverage results with an optimised (non-Debug) build may be misleading" )
ENDIF() # NOT CMAKE_BUILD_TYPE STREQUAL "Debug"
# Setup compiler options
ADD_DEFINITIONS(-fprofile-arcs -ftest-coverage)
LINK_LIBRARIES(gcov)
# Param _targetname The name of new the custom make target
# Param _testrunner The name of the target which runs the tests
# Param _outputname lcov output is generated as _outputname.info
# HTML report is generated in _outputname/index.html
# Optional fourth parameter is passed as arguments to _testrunner
# Pass them in list form, e.g.: "-j;2" for -j 2
FUNCTION(SETUP_TARGET_FOR_COVERAGE _targetname _testrunner _outputname)
IF(NOT LCOV_PATH)
MESSAGE(FATAL_ERROR "lcov not found! Aborting...")
ENDIF() # NOT LCOV_PATH
IF(NOT GENHTML_PATH)
MESSAGE(FATAL_ERROR "genhtml not found! Aborting...")
ENDIF() # NOT GENHTML_PATH
# Setup target
ADD_CUSTOM_TARGET(${_targetname}
# Cleanup lcov
${LCOV_PATH} --directory . --zerocounters
# Run tests
COMMAND ${_testrunner} ${ARGV3}
# Capturing lcov counters and generating report
COMMAND ${LCOV_PATH} --directory . --capture --output-file ${_outputname}.info
COMMAND ${LCOV_PATH} --remove ${_outputname}.info 'tests/*' '/usr/*' --output-file ${_outputname}.info.cleaned
COMMAND ${GENHTML_PATH} -o ${_outputname} ${_outputname}.info.cleaned
COMMAND ${CMAKE_COMMAND} -E remove ${_outputname}.info ${_outputname}.info.cleaned
WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
COMMENT "Resetting code coverage counters to zero.\nProcessing code coverage counters and generating report."
)
# Show info where to find the report
ADD_CUSTOM_COMMAND(TARGET ${_targetname} POST_BUILD
COMMAND ;
COMMENT "Open ./${_outputname}/index.html in your browser to view the coverage report."
)
ENDFUNCTION() # SETUP_TARGET_FOR_COVERAGE
# Param _targetname The name of new the custom make target
# Param _testrunner The name of the target which runs the tests
# Param _outputname cobertura output is generated as _outputname.xml
# Optional fourth parameter is passed as arguments to _testrunner
# Pass them in list form, e.g.: "-j;2" for -j 2
FUNCTION(SETUP_TARGET_FOR_COVERAGE_COBERTURA _targetname _testrunner _outputname)
IF(NOT PYTHON_EXECUTABLE)
MESSAGE(FATAL_ERROR "Python not found! Aborting...")
ENDIF() # NOT PYTHON_EXECUTABLE
IF(NOT GCOVR_PATH)
MESSAGE(FATAL_ERROR "gcovr not found! Aborting...")
ENDIF() # NOT GCOVR_PATH
ADD_CUSTOM_TARGET(${_targetname}
# Run tests
${_testrunner} ${ARGV3}
# Running gcovr
COMMAND ${GCOVR_PATH} -x -r ${CMAKE_SOURCE_DIR} -e '${CMAKE_SOURCE_DIR}/tests/' -o ${_outputname}.xml
WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
COMMENT "Running gcovr to produce Cobertura code coverage report."
)
# Show info where to find the report
ADD_CUSTOM_COMMAND(TARGET ${_targetname} POST_BUILD
COMMAND ;
COMMENT "Cobertura code coverage report saved in ${_outputname}.xml."
)
ENDFUNCTION() # SETUP_TARGET_FOR_COVERAGE_COBERTURA
cgreen-1.3.0/cmake/Modules/DefineCMakeDefaults.cmake 0000664 0000000 0000000 00000001577 13666233252 0022255 0 ustar 00root root 0000000 0000000 # Always include srcdir and builddir in include path
# This saves typing ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY} in
# about every subdir
# since cmake 2.4.0
set(CMAKE_INCLUDE_CURRENT_DIR ON)
# Put the include dirs which are in the source or build tree
# before all other include dirs, so the headers in the sources
# are prefered over the already installed ones
# since cmake 2.4.1
set(CMAKE_INCLUDE_DIRECTORIES_PROJECT_BEFORE ON)
# Use colored output
# since cmake 2.4.0
set(CMAKE_COLOR_MAKEFILE ON)
# Define the generic version of the libraries here
set(GENERIC_LIB_VERSION "0.1.0")
set(GENERIC_LIB_SOVERSION "0")
# Set the default build type to release with debug info
if (NOT CMAKE_BUILD_TYPE)
set(CMAKE_BUILD_TYPE RelWithDebInfo
CACHE STRING
"Choose the type of build, options are: None Debug Release RelWithDebInfo MinSizeRel."
)
endif (NOT CMAKE_BUILD_TYPE)
cgreen-1.3.0/cmake/Modules/DefineCPackConfig.cmake 0000664 0000000 0000000 00000004302 13666233252 0021701 0 ustar 00root root 0000000 0000000 include(InstallRequiredSystemLibraries)
# For help take a look at:
# http://www.cmake.org/Wiki/CMake:CPackConfiguration
### general settings
set(CPACK_PACKAGE_NAME ${APPLICATION_NAME})
set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "The modern C/C++ unit testing/mocking framework")
set(CPACK_PACKAGE_DESCRIPTION_FILE "${PROJECT_SOURCE_DIR}/README.md")
set(CPACK_PACKAGE_VENDOR "The CGreen Development Team")
set(CPACK_RESOURCE_FILE_LICENSE "${PROJECT_SOURCE_DIR}/LICENSE")
### versions
set(CPACK_PACKAGE_VERSION_MAJOR ${APPLICATION_VERSION_MAJOR})
set(CPACK_PACKAGE_VERSION_MINOR ${APPLICATION_VERSION_MINOR})
set(CPACK_PACKAGE_VERSION_PATCH ${APPLICATION_VERSION_PATCH})
set(CPACK_PACKAGE_VERSION_STATUS ${APPLICATION_VERSION_STATUS})
set(CPACK_PACKAGE_VERSION "${CPACK_PACKAGE_VERSION_MAJOR}.${CPACK_PACKAGE_VERSION_MINOR}.${CPACK_PACKAGE_VERSION_PATCH}${CPACK_PACKAGE_VERSION_STATUS}")
### source generator
set(CPACK_SOURCE_GENERATOR "TGZ")
set(CPACK_SOURCE_IGNORE_FILES "~$;[.]swp$;/[.]svn/;/[.]git/;.gitignore;/build/;tags;cscope.*")
set(CPACK_SOURCE_PACKAGE_FILE_NAME "${CPACK_PACKAGE_NAME}-${CPACK_PACKAGE_VERSION}-src")
### binary generator
if (WIN32)
### nsis generator
set(CPACK_GENERATOR "NSIS")
set(CPACK_NSIS_DISPLAY_NAME ${CPACK_PACKAGE_DESCRIPTION_SUMMARY})
set(CPACK_NSIS_COMPRESSOR "/SOLID zlib")
set(CPACK_NSIS_MENU_LINKS "http://cgreen.sourceforge.net" "Cgreen Homepage")
set(CPACK_PACKAGE_INSTALL_DIRECTORY ${CPACK_PACKAGE_NAME})
endif()
set(CPACK_COMPONENTS_ALL_IN_ONE_PACKAGE 1)
set(PACKAGE_NAME ${APPLICATION_NAME})
if (CMAKE_SIZEOF_VOID_P EQUAL 8)
set(BITS 64)
else()
set(BITS 32)
endif()
set(CPACK_PACKAGE_FILE_NAME ${PACKAGE_NAME}-${CPACK_PACKAGE_VERSION}-${CMAKE_SYSTEM_NAME}${BITS})
set(CPACK_COMPONENT_LIBRARIES_DISPLAY_NAME "Libraries")
set(CPACK_COMPONENT_LIBRARIES_DESCRIPTION
"Libraries used to build programs which use cgreen")
set(CPACK_COMPONENT_HEADERS_DISPLAY_NAME "C/C++ Headers")
set(CPACK_COMPONENT_HEADERS_DESCRIPTION
"C/C++ header files for use with cgreen")
set(CPACK_COMPONENT_HEADERS_DEPENDS libraries)
set(CPACK_COMPONENT_APPLICATIONS_GROUP "Runtime")
set(CPACK_COMPONENT_LIBRARIES_GROUP "Development")
set(CPACK_COMPONENT_HEADERS_GROUP "Development")
include(CPack)
cgreen-1.3.0/cmake/Modules/DefineCompilerFlags.cmake 0000664 0000000 0000000 00000003760 13666233252 0022330 0 ustar 00root root 0000000 0000000 # define system dependent compiler flags
include(CheckCCompilerFlag)
set (COMPILER_IS_CLANG FALSE)
if (${CMAKE_C_COMPILER_ID} MATCHES "Clang")
set (COMPILER_IS_CLANG TRUE)
endif (${CMAKE_C_COMPILER_ID} MATCHES "Clang")
if (UNIX)
if (CMAKE_COMPILER_IS_GNUCC OR COMPILER_IS_CLANG)
# add_compile_options(-Wall -Wextra -Wunused) # only since CMake 2.8.12, so...
add_definitions(-Wall -Wextra -Wunused)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++98 -Weffc++")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=c99 -Wstrict-prototypes")
if (CGREEN_INTERNAL_WITH_GCOV)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -ftest-coverage -fprofile-arcs")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -ftest-coverage -fprofile-arcs")
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_C_FLAGS} -ftest-coverage -fprofile-arcs")
endif (CGREEN_INTERNAL_WITH_GCOV)
add_definitions(-D_REENTRANT) # for gmtime_r()
add_definitions(-D_XOPEN_SOURCE) # for popen() and pclose()
add_definitions(-D_XOPEN_SOURCE_EXTENDED) # for strdup(), which isn't part of C99
add_definitions(-D__STDC_FORMAT_MACROS) # for PRI*PTR format macros, required by C99
if (NOT CYGWIN)
# with -fPIC
check_c_compiler_flag("-fPIC" WITH_FPIC)
if (WITH_FPIC)
# add_compile_options(-fPIC) # Only since CMake 2.8.12, so...
add_definitions(-fPIC)
endif (WITH_FPIC)
endif (NOT CYGWIN)
check_c_compiler_flag("-D_FORTIFY_SOURCE=2" WITH_FORTIFY_SOURCE)
if (WITH_FORTIFY_SOURCE)
add_definitions(-D_FORTIFY_SOURCE=2)
endif (WITH_FORTIFY_SOURCE)
if (NOT CMAKE_BUILD_TYPE STREQUAL "Debug")
add_definitions(-O)
else ()
check_c_compiler_flag("-Og" WITH_OPTIMIZE_FOR_DEBUG)
if (WITH_OPTIMIZE_FOR_DEBUG)
add_definitions(-Og)
endif ()
endif ()
endif (CMAKE_COMPILER_IS_GNUCC OR COMPILER_IS_CLANG)
endif (UNIX)
if (WIN32)
if (MSVC)
add_definitions(-D_CRT_SECURE_NO_WARNINGS=1)
endif (MSVC)
endif (WIN32)
cgreen-1.3.0/cmake/Modules/FindAsciidoc.cmake 0000664 0000000 0000000 00000001705 13666233252 0021002 0 ustar 00root root 0000000 0000000 # - Find Asciidoc
# this module looks for asciidoc and a2x
#
# ASCIIDOC_EXECUTABLE - the full path to asciidoc
# ASCIIDOC_FOUND - If false, don't attempt to use asciidoc.
# A2X_EXECUTABLE - the full path to a2x
# A2X_FOUND - If false, don't attempt to use a2x.
FIND_PROGRAM(ASCIIDOC_EXECUTABLE
asciidoc
)
MARK_AS_ADVANCED(
ASCIIDOC_EXECUTABLE
)
IF (NOT ASCIIDOC_EXECUTABLE)
SET(ASCIIDOC_FOUND "NO")
ELSE (NOT ASCIIDOC_EXECUTABLE)
SET(ASCIIDOC_FOUND "YES")
ENDIF (NOT ASCIIDOC_EXECUTABLE)
IF (NOT ASCIIDOC_FOUND AND Asciidoc_FIND_REQUIRED)
MESSAGE(FATAL_ERROR "Could not find asciidoc")
ENDIF (NOT ASCIIDOC_FOUND AND Asciidoc_FIND_REQUIRED)
FIND_PROGRAM(A2X_EXECUTABLE
a2x
)
MARK_AS_ADVANCED(
A2X_EXECUTABLE
)
IF (NOT A2X_EXECUTABLE)
SET(A2X_FOUND "NO")
ELSE (NOT A2X_EXECUTABLE)
SET(A2X_FOUND "YES")
ENDIF (NOT A2X_EXECUTABLE)
IF (NOT A2X_FOUND AND A2x_FIND_REQUIRED)
MESSAGE(FATAL_ERROR "Could not find a2x")
ENDIF (NOT A2X_FOUND AND A2x_FIND_REQUIRED)
cgreen-1.3.0/cmake/Modules/FindAsciidoctor.cmake 0000664 0000000 0000000 00000001775 13666233252 0021536 0 ustar 00root root 0000000 0000000 # Find Asciidoctor - a better AsciiDoc
#
# ASCIIDOCTOR_FOUND
# ASCIIDOCTORPDF_FOUND
# ASCIIDOCTOR_EXECUTABLE
# ASCIIDOCTORPDF_EXECUTABLE
FIND_PROGRAM(ASCIIDOCTOR_EXECUTABLE asciidoctor)
FIND_PROGRAM(ASCIIDOCTORPDF_EXECUTABLE asciidoctor-pdf)
MARK_AS_ADVANCED(ASCIIDOCTOR_EXECUTABLE)
MARK_AS_ADVANCED(ASCIIDOCTORPDF_EXECUTABLE)
IF (NOT ASCIIDOCTOR_EXECUTABLE)
SET(ASCIIDOCTOR_FOUND "NO")
ELSE (NOT ASCIIDOCTOR_EXECUTABLE)
SET(ASCIIDOCTOR_FOUND "YES")
ENDIF (NOT ASCIIDOCTOR_EXECUTABLE)
IF (NOT ASCIIDOCTORPDF_EXECUTABLE)
SET(ASCIIDOCTORPDF_FOUND "NO")
ELSE (NOT ASCIIDOCTORPDF_EXECUTABLE)
SET(ASCIIDOCTORPDF_FOUND "YES")
ENDIF (NOT ASCIIDOCTORPDF_EXECUTABLE)
IF (NOT ASCIIDOCTOR_FOUND AND ASCIIDOCTOR_FIND_REQUIRED)
MESSAGE(FATAL_ERROR "Could not find asciidoctor")
ENDIF (NOT ASCIIDOCTOR_FOUND AND ASCIIDOCTOR_FIND_REQUIRED)
IF (NOT ASCIIDOCTORPDF_FOUND AND ASCIIDOCTOR_FIND_REQUIRED)
MESSAGE(FATAL_ERROR "Could not find asciidoctor-pdf")
ENDIF (NOT ASCIIDOCTORPDF_FOUND AND ASCIIDOCTOR_FIND_REQUIRED)
cgreen-1.3.0/cmake/Modules/FindFLEX.cmake 0000664 0000000 0000000 00000013472 13666233252 0020026 0 ustar 00root root 0000000 0000000 # - Find flex executable and provides a macro to generate custom build rules
# The module defines the following variables:
# FLEX_FOUND - true is flex executable is found
# FLEX_VERSION - the version of flex
# If flex is found on the system, the module provides the macro:
# FLEX_TARGET(Name FlexInput FlexOutput [COMPILE_FLAGS ])
# which creates a custom command to generate the file from
# the file. If COMPILE_FLAGS option is specified, the next
# parameter is added to the flex command line. Name is an alias used to
# get details of this custom command. Indeed the macro defines the
# following variables:
# FLEX_${Name}_DEFINED - true is the macro ran successfully
# FLEX_${Name}_OUTPUTS - the source file generated by the custom rule, an
# alias for FlexOutput
# FLEX_${Name}_INPUT - the flex source file, an alias for ${FlexInput}
#
# Flex scanners oftenly use tokens defined by Bison: the code generated
# by Flex depends of the header generated by Bison. This module also
# defines a macro:
# ADD_FLEX_BISON_DEPENDENCY(FlexTarget BisonTarget)
# which adds the required dependency between a scanner and a parser
# where and are the first parameters of
# respectively FLEX_TARGET and BISON_TARGET macros.
#
# Example:
# FIND_PACKAGE(BISON)
# FIND_PACKAGE(FLEX)
# BISON_TARGET(MyParser parser.y ${PROJECT_BINARY_DIR}/parser.cpp
# FLEX_TARGET(MyScanner lexer.l ${PROJECT_BINARY_DIR}/lexer.cpp)
# ADD_FLEX_BISON_DEPENDENCY(MyScanner MyParser)
#
# Copyright (c) 2006, Tristan Carel
# All rights reserved.
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
# * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
# * Neither the name of the University of California, Berkeley nor the
# names of its contributors may be used to endorse or promote products
# derived from this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY
# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
# DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY
# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
# $Id:: FindFLEX.cmake 3 2006-11-03 02:42:02Z ken $
SET(FLEX_FOUND FALSE)
FIND_PROGRAM(FLEX_EXECUTABLE flex DOC "path to the flex executable")
MARK_AS_ADVANCED(FLEX_EXECUTABLE)
FIND_LIBRARY(FL_LIBRARY NAMES fl
PATHS /usr/lib DOC "path to the fl library")
SET(FLEX_LIBRARIES ${FL_LIBRARY})
IF(FLEX_EXECUTABLE)
SET(FLEX_FOUND TRUE)
EXECUTE_PROCESS(COMMAND ${FLEX_EXECUTABLE} --version
OUTPUT_VARIABLE FLEX_version_output
ERROR_VARIABLE FLEX_version_error
RESULT_VARIABLE FLEX_version_result
OUTPUT_STRIP_TRAILING_WHITESPACE)
IF(NOT ${FLEX_version_result} EQUAL 0)
MESSAGE(SEND_ERROR "Command \"${FLEX_EXECUTABLE} --version\" failed with output:\n${FLEX_version_error}")
ELSE(NOT ${FLEX_version_result} EQUAL 0)
STRING(REGEX REPLACE "^flex (.*)$" "\\1"
FLEX_VERSION "${FLEX_version_output}")
ENDIF(NOT ${FLEX_version_result} EQUAL 0)
MACRO(FLEX_TARGET Name Input Output)
SET(FLEX_TARGET_usage "FLEX_TARGET( [COMPILE_FLAGS ]")
IF(${ARGC} GREATER 3)
IF(${ARGC} EQUAL 5)
IF("${ARGV3}" STREQUAL "COMPILE_FLAGS")
SET(FLEX_EXECUTABLE_opts "${ARGV4}")
SEPARATE_ARGUMENTS(FLEX_EXECUTABLE_opts)
ELSE("${ARGV3}" STREQUAL "COMPILE_FLAGS")
MESSAGE(SEND_ERROR ${FLEX_TARGET_usage})
ENDIF("${ARGV3}" STREQUAL "COMPILE_FLAGS")
ELSE(${ARGC} EQUAL 5)
MESSAGE(SEND_ERROR ${FLEX_TARGET_usage})
ENDIF(${ARGC} EQUAL 5)
ENDIF(${ARGC} GREATER 3)
ADD_CUSTOM_COMMAND(OUTPUT ${Output}
COMMAND ${FLEX_EXECUTABLE} ${FLEX_EXECUTABLE_opts} -o${Output} ${Input}
DEPENDS ${Input}
COMMENT "[FLEX][${Name}] Building scanner with flex ${FLEX_VERSION}"
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR})
SET(FLEX_${Name}_DEFINED TRUE)
SET(FLEX_${Name}_OUTPUTS ${Output})
SET(FLEX_${Name}_INPUT ${Input})
SET(FLEX_${Name}_COMPILE_FLAGS ${FLEX_EXECUTABLE_opts})
ENDMACRO(FLEX_TARGET)
MACRO(ADD_FLEX_BISON_DEPENDENCY FlexTarget BisonTarget)
IF(NOT FLEX_${FlexTarget}_OUTPUTS)
MESSAGE(SEND_ERROR "Flex target `${FlexTarget}' does not exists.")
ENDIF(NOT FLEX_${FlexTarget}_OUTPUTS)
IF(NOT BISON_${BisonTarget}_OUTPUT_HEADER)
MESSAGE(SEND_ERROR "Bison target `${BisonTarget}' does not exists.")
ENDIF(NOT BISON_${BisonTarget}_OUTPUT_HEADER)
SET_SOURCE_FILES_PROPERTIES(${FLEX_${FlexTarget}_OUTPUTS}
PROPERTIES OBJECT_DEPENDS ${BISON_${BisonTarget}_OUTPUT_HEADER})
ENDMACRO(ADD_FLEX_BISON_DEPENDENCY)
ENDIF(FLEX_EXECUTABLE)
IF(NOT FLEX_FOUND)
IF(NOT FLEX_FIND_QUIETLY)
MESSAGE(STATUS "FLEX was not found.")
ELSE(NOT FLEX_FIND_QUIETLY)
IF(FLEX_FIND_REQUIRED)
MESSAGE(FATAL_ERROR "FLEX was not found.")
ENDIF(FLEX_FIND_REQUIRED)
ENDIF(NOT FLEX_FIND_QUIETLY)
ENDIF(NOT FLEX_FOUND)
# FindFLEX.cmake ends here
cgreen-1.3.0/cmake/Modules/MacroAddCompileFlags.cmake 0000664 0000000 0000000 00000001167 13666233252 0022425 0 ustar 00root root 0000000 0000000 # - MACRO_ADD_COMPILE_FLAGS(target_name flag1 ... flagN)
# Copyright (c) 2006, Oswald Buddenhagen,
# Copyright (c) 2006, Andreas Schneider,
#
# Redistribution and use is allowed according to the terms of the BSD license.
# For details see the accompanying COPYING-CMAKE-SCRIPTS file.
macro (MACRO_ADD_COMPILE_FLAGS _target)
get_target_property(_flags ${_target} COMPILE_FLAGS)
if (_flags)
set(_flags ${_flags} ${ARGN})
else (_flags)
set(_flags ${ARGN})
endif (_flags)
set_target_properties(${_target} PROPERTIES COMPILE_FLAGS ${_flags})
endmacro (MACRO_ADD_COMPILE_FLAGS)
cgreen-1.3.0/cmake/Modules/MacroAddLinkFlags.cmake 0000664 0000000 0000000 00000001155 13666233252 0021727 0 ustar 00root root 0000000 0000000 # - MACRO_ADD_LINK_FLAGS(target_name flag1 ... flagN)
# Copyright (c) 2006, Oswald Buddenhagen,
# Copyright (c) 2006, Andreas Schneider,
#
# Redistribution and use is allowed according to the terms of the BSD license.
# For details see the accompanying COPYING-CMAKE-SCRIPTS file.
macro (MACRO_ADD_LINK_FLAGS _target)
get_target_property(_flags ${_target} LINK_FLAGS)
if (_flags)
set(_flags "${_flags} ${ARGN}")
else (_flags)
set(_flags "${ARGN}")
endif (_flags)
set_target_properties(${_target} PROPERTIES LINK_FLAGS "${_flags}")
endmacro (MACRO_ADD_LINK_FLAGS)
cgreen-1.3.0/cmake/Modules/MacroAddPlugin.cmake 0000664 0000000 0000000 00000001741 13666233252 0021314 0 ustar 00root root 0000000 0000000 # - MACRO_ADD_PLUGIN(name [WITH_PREFIX] file1 .. fileN)
#
# Create a plugin from the given source files.
# If WITH_PREFIX is given, the resulting plugin will have the
# prefix "lib", otherwise it won't.
#
# Copyright (c) 2006, Alexander Neundorf,
# Copyright (c) 2006, Laurent Montel,
# Copyright (c) 2006, Andreas Schneider,
#
# Redistribution and use is allowed according to the terms of the BSD license.
# For details see the accompanying COPYING-CMAKE-SCRIPTS file.
macro (MACRO_ADD_PLUGIN _target_NAME _with_PREFIX)
if (${_with_PREFIX} STREQUAL "WITH_PREFIX")
set(_first_SRC)
else (${_with_PREFIX} STREQUAL "WITH_PREFIX")
set(_first_SRC ${_with_PREFIX})
endif (${_with_PREFIX} STREQUAL "WITH_PREFIX")
add_library(${_target_NAME} MODULE ${_first_SRC} ${ARGN})
if (_first_SRC)
set_target_properties(${_target_NAME} PROPERTIES PREFIX "")
endif (_first_SRC)
endmacro (MACRO_ADD_PLUGIN _name _sources)
cgreen-1.3.0/cmake/Modules/MacroAddTest.cmake 0000664 0000000 0000000 00000000715 13666233252 0020775 0 ustar 00root root 0000000 0000000 # - MACRO_ADD_TEST()
#
# Calls add_test() with all the but if on Win32 or Cygwin also adds the
# directory where the Cgreen library is generated to the path so that it will
# be used when running the test
#
# @thoni56/Thomas Nilefalk 2015-09-13
macro (macro_add_test)
add_test(${ARGN})
if (CYGWIN OR WIN32)
set_tests_properties(${ARGV1} PROPERTIES ENVIRONMENT PATH=${PROJECT_BINARY_DIR}/src:$ENV{PATH})
endif ()
endmacro(macro_add_test)
cgreen-1.3.0/cmake/Modules/MacroAddUnitTest.cmake 0000664 0000000 0000000 00000002422 13666233252 0021632 0 ustar 00root root 0000000 0000000 # - MACRO_ADD_UNIT_TEST(test_name test_source linklib1 ... linklibN)
# Copyright (c) 2007, Daniel Gollub,
# Copyright (c) 2007, Andreas Schneider,
#
# Redistribution and use is allowed according to the terms of the BSD license.
# For details see the accompanying COPYING-CMAKE-SCRIPTS file.
enable_testing()
include(CTest)
#set(CMAKE_C_FLAGS_PROFILING "-g -O0 -Wall -W -Wshadow -Wunused-variable -Wunused-parameter -Wunused-function -Wunused -Wno-system-headers -Wwrite-strings -fprofile-arcs -ftest-coverage" CACHE STRING "Profiling Compiler Flags")
#set(CMAKE_SHARED_LINKER_FLAGS_PROFILING " -fprofile-arcs -ftest-coverage" CACHE STRING "Profiling Linker Flags")
#set(CMAKE_MODULE_LINKER_FLAGS_PROFILING " -fprofile-arcs -ftest-coverage" CACHE STRING "Profiling Linker Flags")
#set(CMAKE_EXEC_LINKER_FLAGS_PROFILING " -fprofile-arcs -ftest-coverage" CACHE STRING "Profiling Linker Flags")
# custom options
configure_file(tests/CTestCustom.cmake ${PROJECT_BINARY_DIR}/CTestCustom.cmake COPYONLY)
macro (MACRO_ADD_UNIT_TEST _testName _testSource)
add_executable(${_testName} ${_testSource})
target_link_libraries(${_testName} ${ARGN})
macro_add_test(NAME ${_testName} COMMAND ${CMAKE_CURRENT_BINARY_DIR}/${_testName})
endmacro (MACRO_ADD_UNIT_TEST)
cgreen-1.3.0/cmake/Modules/MacroCopyFile.cmake 0000664 0000000 0000000 00000002157 13666233252 0021161 0 ustar 00root root 0000000 0000000 # - macro_copy_file(_src _dst)
# Copies a file to ${_dst} only if ${_src} is different (newer) than ${_dst}
#
# Example:
# macro_copy_file(${CMAKE_CURRENT_SOURCE_DIR}/icon.png ${CMAKE_CURRENT_BINARY_DIR}/.)
# Copies file icon.png to ${CMAKE_CURRENT_BINARY_DIR} directory
#
# Copyright (c) 2006-2007 Wengo
# Copyright (c) 2006-2008 Andreas Schneider
#
# Redistribution and use is allowed according to the terms of the BSD license.
# For details see the accompanying COPYING file.
macro (macro_copy_file _src _dst)
# Removes all path containing .svn or CVS or CMakeLists.txt during the copy
if (NOT ${_src} MATCHES ".*\\.svn|CVS|CMakeLists\\.txt.*")
if (CMAKE_VERBOSE_MAKEFILE)
message(STATUS "Copy file from ${_src} to ${_dst}")
endif (CMAKE_VERBOSE_MAKEFILE)
# Creates directory if necessary
get_filename_component(_path ${_dst} PATH)
file(MAKE_DIRECTORY ${_path})
execute_process(
COMMAND
${CMAKE_COMMAND} -E copy_if_different ${_src} ${_dst}
OUTPUT_QUIET
)
endif (NOT ${_src} MATCHES ".*\\.svn|CVS|CMakeLists\\.txt.*")
endmacro (macro_copy_file)
cgreen-1.3.0/cmake/Modules/MacroEnsureOutOfSourceBuild.cmake 0000664 0000000 0000000 00000001235 13666233252 0024022 0 ustar 00root root 0000000 0000000 # - MACRO_ENSURE_OUT_OF_SOURCE_BUILD()
# MACRO_ENSURE_OUT_OF_SOURCE_BUILD()
# Copyright (c) 2006, Alexander Neundorf,
#
# Redistribution and use is allowed according to the terms of the BSD license.
# For details see the accompanying COPYING-CMAKE-SCRIPTS file.
macro (MACRO_ENSURE_OUT_OF_SOURCE_BUILD _errorMessage)
string(COMPARE EQUAL "${PROJECT_SOURCE_DIR}" "${PROJECT_BINARY_DIR}" _insource)
if (_insource)
message(SEND_ERROR "${_errorMessage}")
message(FATAL_ERROR "Remove the file CMakeCache.txt in ${PROJECT_SOURCE_DIR} first.")
endif (_insource)
endmacro (MACRO_ENSURE_OUT_OF_SOURCE_BUILD)
cgreen-1.3.0/cmake/Modules/UseDoxygen.cmake 0000664 0000000 0000000 00000012714 13666233252 0020557 0 ustar 00root root 0000000 0000000 # -helper macro to add a "doc" target with CMake build system.
# and configure doxy.config.in to doxy.config
#
# target "doc" allows building the documentation with doxygen/dot on WIN32 and Linux
# Creates .chm windows help file if MS HTML help workshop
# (available from http://msdn.microsoft.com/workshop/author/htmlhelp)
# is installed with its DLLs in PATH.
#
#
# Please note, that the tools, e.g.:
# doxygen, dot, latex, dvips, makeindex, gswin32, etc.
# must be in path.
#
# Note about Visual Studio Projects:
# MSVS has its own path environment which may differ from the shell.
# See "Menu Tools/Options/Projects/VC++ Directories" in VS 7.1
#
# author Jan Woetzel 2004-2006
# www.mip.informatik.uni-kiel.de/~jw
FIND_PACKAGE(Doxygen)
IF (DOXYGEN_FOUND)
# click+jump in Emacs and Visual Studio (for doxy.config) (jw)
IF (CMAKE_BUILD_TOOL MATCHES "(msdev|devenv)")
SET(DOXY_WARN_FORMAT "\"$file($line) : $text \"")
ELSE (CMAKE_BUILD_TOOL MATCHES "(msdev|devenv)")
SET(DOXY_WARN_FORMAT "\"$file:$line: $text \"")
ENDIF (CMAKE_BUILD_TOOL MATCHES "(msdev|devenv)")
# we need latex for doxygen because of the formulas
FIND_PACKAGE(LATEX)
IF (NOT LATEX_COMPILER)
MESSAGE(STATUS "latex command LATEX_COMPILER not found but usually required. You will probably get warnings and user inetraction on doxy run.")
ENDIF (NOT LATEX_COMPILER)
IF (NOT MAKEINDEX_COMPILER)
MESSAGE(STATUS "makeindex command MAKEINDEX_COMPILER not found but usually required.")
ENDIF (NOT MAKEINDEX_COMPILER)
IF (NOT DVIPS_CONVERTER)
MESSAGE(STATUS "dvips command DVIPS_CONVERTER not found but usually required.")
ENDIF (NOT DVIPS_CONVERTER)
FIND_PROGRAM(DOXYGEN_DOT_EXECUTABLE_PATH NAMES dot)
IF (DOXYGEN_DOT_EXECUTABLE_PATH)
SET(DOXYGEN_DOT_FOUND "YES")
ENDIF (DOXYGEN_DOT_EXECUTABLE_PATH)
IF (EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/doxy.config.in")
MESSAGE(STATUS "Generate ${CMAKE_CURRENT_BINARY_DIR}/doxy.config from doxy.config.in")
CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/doxy.config.in
${CMAKE_CURRENT_BINARY_DIR}/doxy.config
@ONLY )
# use (configured) doxy.config from (out of place) BUILD tree:
SET(DOXY_CONFIG "${CMAKE_CURRENT_BINARY_DIR}/doxy.config")
ELSE (EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/doxy.config.in")
# use static hand-edited doxy.config from SOURCE tree:
SET(DOXY_CONFIG "${CMAKE_CURRENT_SOURCE_DIR}/doxy.config")
IF (EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/doxy.config")
MESSAGE(STATUS "WARNING: using existing ${CMAKE_CURRENT_SOURCE_DIR}/doxy.config instead of configuring from doxy.config.in file.")
ELSE (EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/doxy.config")
IF (EXISTS "${CMAKE_MODULE_PATH}/doxy.config.in")
# using template doxy.config.in
MESSAGE(STATUS "Generate ${CMAKE_CURRENT_BINARY_DIR}/doxy.config from doxy.config.in")
CONFIGURE_FILE(${CMAKE_MODULE_PATH}/doxy.config.in
${CMAKE_CURRENT_BINARY_DIR}/doxy.config
@ONLY )
SET(DOXY_CONFIG "${CMAKE_CURRENT_BINARY_DIR}/doxy.config")
ELSE (EXISTS "${CMAKE_MODULE_PATH}/doxy.config.in")
# failed completely...
MESSAGE(SEND_ERROR "Please create ${CMAKE_CURRENT_SOURCE_DIR}/doxy.config.in (or doxy.config as fallback)")
ENDIF(EXISTS "${CMAKE_MODULE_PATH}/doxy.config.in")
ENDIF(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/doxy.config")
ENDIF(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/doxy.config.in")
ADD_CUSTOM_TARGET(doc ${DOXYGEN_EXECUTABLE} ${DOXY_CONFIG} DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/doxy.config)
# create a windows help .chm file using hhc.exe
# HTMLHelp DLL must be in path!
# fallback: use hhw.exe interactively
IF (WIN32)
FIND_PACKAGE(HTMLHelp)
IF (HTML_HELP_COMPILER)
SET (TMP "${CMAKE_CURRENT_BINARY_DIR}\\doc\\html\\index.hhp")
STRING(REGEX REPLACE "[/]" "\\\\" HHP_FILE ${TMP} )
# MESSAGE(SEND_ERROR "DBG HHP_FILE=${HHP_FILE}")
ADD_CUSTOM_TARGET(winhelp ${HTML_HELP_COMPILER} ${HHP_FILE})
ADD_DEPENDENCIES (winhelp doc)
IF (NOT TARGET_DOC_SKIP_INSTALL)
# install windows help?
# determine useful name for output file
# should be project and version unique to allow installing
# multiple projects into one global directory
IF (EXISTS "${PROJECT_BINARY_DIR}/doc/html/index.chm")
IF (PROJECT_NAME)
SET(OUT "${PROJECT_NAME}")
ELSE (PROJECT_NAME)
SET(OUT "Documentation") # default
ENDIF(PROJECT_NAME)
IF (${PROJECT_NAME}_VERSION_MAJOR)
SET(OUT "${OUT}-${${PROJECT_NAME}_VERSION_MAJOR}")
IF (${PROJECT_NAME}_VERSION_MINOR)
SET(OUT "${OUT}.${${PROJECT_NAME}_VERSION_MINOR}")
IF (${PROJECT_NAME}_VERSION_PATCH)
SET(OUT "${OUT}.${${PROJECT_NAME}_VERSION_PATCH}")
ENDIF(${PROJECT_NAME}_VERSION_PATCH)
ENDIF(${PROJECT_NAME}_VERSION_MINOR)
ENDIF(${PROJECT_NAME}_VERSION_MAJOR)
# keep suffix
SET(OUT "${OUT}.chm")
#MESSAGE("DBG ${PROJECT_BINARY_DIR}/doc/html/index.chm \n${OUT}")
# create target used by install and package commands
INSTALL(FILES "${PROJECT_BINARY_DIR}/doc/html/index.chm"
DESTINATION "doc"
RENAME "${OUT}"
)
ENDIF(EXISTS "${PROJECT_BINARY_DIR}/doc/html/index.chm")
ENDIF(NOT TARGET_DOC_SKIP_INSTALL)
ENDIF(HTML_HELP_COMPILER)
# MESSAGE(SEND_ERROR "HTML_HELP_COMPILER=${HTML_HELP_COMPILER}")
ENDIF (WIN32)
ENDIF(DOXYGEN_FOUND)
cgreen-1.3.0/config.h.cmake 0000664 0000000 0000000 00000001417 13666233252 0015466 0 ustar 00root root 0000000 0000000 /* Name of package */
#cmakedefine PACKAGE "${APPLICATION_NAME}"
/* Version number of package */
#cmakedefine VERSION "${APPLICATION_VERSION}"
#cmakedefine LOCALEDIR "${LOCALE_INSTALL_DIR}"
#cmakedefine DATADIR "${DATADIR}"
#cmakedefine LIBDIR "${LIBDIR}"
#cmakedefine PLUGINDIR "${PLUGINDIR}"
#cmakedefine SYSCONFDIR "${SYSCONFDIR}"
#cmakedefine BINARYDIR "${BINARYDIR}"
#cmakedefine SOURCEDIR "${SOURCEDIR}"
/************************** HEADER FILES *************************/
/*************************** FUNCTIONS ***************************/
/*************************** LIBRARIES ***************************/
/**************************** OPTIONS ****************************/
/* Define if building with gcov instrumentation */
#cmakedefine CGREEN_INTERNAL_WITH_GCOV
cgreen-1.3.0/contrib/ 0000775 0000000 0000000 00000000000 13666233252 0014426 5 ustar 00root root 0000000 0000000 cgreen-1.3.0/contrib/README.contrib 0000664 0000000 0000000 00000000614 13666233252 0016746 0 ustar 00root root 0000000 0000000 All files under this contrib directory are UNSUPPORTED. There were
provided by users of Cgreen and were not tested by the authors of Cgreen.
Use at your own risk.
SCons/ by Kevin Fitch
Add a sample demonstrating using cgreen with SCons
http://www.scons.org/
upgrade/ by Thomas Nilsson and Colm Dougan
Will upgrade a pre-beta version of tests to newer API
cgreen-1.3.0/contrib/SCons/ 0000775 0000000 0000000 00000000000 13666233252 0015453 5 ustar 00root root 0000000 0000000 cgreen-1.3.0/contrib/SCons/SConstruct 0000664 0000000 0000000 00000002357 13666233252 0017514 0 ustar 00root root 0000000 0000000 env = Environment()
# Add the cgreen headers to the include path
env.Append(CPPPATH=['../../include', ])
# Build the cgreen library
cgreendir = '../../src/'
cgreenfiles = """unit.c messaging.c breadcrumb.c reporter.c
assertions.c vector.c mocks.c constraint.c
parameters.c text_reporter.c""".split()
cgreensources = ['../../src/'+f for f in cgreenfiles]
cgreenlib = env.StaticLibrary('cgreen', cgreensources)
#Build our code to be tested
env.Append(CPPPATH=['include'])
mainlib = env.StaticLibrary('main', env.Glob('src/*.c'))
for test in env.Glob('tests/*.c'):
testprog = env.Program(test, LIBS=[cgreenlib, mainlib])
# This is a nasty little hack here.
# We run the test twice, the first time is so we can see the output on the
# console, and get the results logged. Unfortunately it will not cause the
# build to stop on test failures since the result of the command is the
# return value of tee, not the tests. So we run it again to catch the
# possibly failed return value ... those tests better be repeatable!
env.Command(testprog[0].path+'.results', testprog,
'$SOURCE 2>&1 | tee $TARGET')
env.Command(testprog[0].path+'.results_', testprog,
'$SOURCE > $TARGET 2>&1 ')
cgreen-1.3.0/contrib/android/ 0000775 0000000 0000000 00000000000 13666233252 0016046 5 ustar 00root root 0000000 0000000 cgreen-1.3.0/contrib/android/Android.mk 0000664 0000000 0000000 00000004304 13666233252 0017760 0 ustar 00root root 0000000 0000000 #======================================================================#
# Android.mk for CGgreen C++ unit test framework
#
# (Suggest building as .so and only including lib for debug builds
# when running e.g. android instrumented tests)
#
# Steve Madsen, 10 Aug 2016
#======================================================================#
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := cgreen
MY_CGREEN_BASE_PATH := ../..
MY_CGREEN_BASE_PATH_ABS := $(LOCAL_PATH)/$(MY_CGREEN_BASE_PATH)
MY_CGREEN_SRC_PATH := $(MY_CGREEN_BASE_PATH)/src
LOCAL_SRC_FILES := \
$(MY_CGREEN_SRC_PATH)/cpp_assertions.cpp \
$(MY_CGREEN_SRC_PATH)/cpp_constraint.cpp \
$(MY_CGREEN_SRC_PATH)/local_messaging.cpp
LOCAL_SRC_FILES += \
$(MY_CGREEN_SRC_PATH)/assertions.c \
$(MY_CGREEN_SRC_PATH)/boxed_double.c \
$(MY_CGREEN_SRC_PATH)/breadcrumb.c \
$(MY_CGREEN_SRC_PATH)/cdash_reporter.c \
$(MY_CGREEN_SRC_PATH)/cgreen_time.c \
$(MY_CGREEN_SRC_PATH)/constraint.c \
$(MY_CGREEN_SRC_PATH)/constraint_syntax_helpers.c \
$(MY_CGREEN_SRC_PATH)/cute_reporter.c \
$(MY_CGREEN_SRC_PATH)/memory.c \
$(MY_CGREEN_SRC_PATH)/message_formatting.c \
$(MY_CGREEN_SRC_PATH)/mocks.c \
$(MY_CGREEN_SRC_PATH)/parameters.c \
$(MY_CGREEN_SRC_PATH)/posix_cgreen_pipe.c \
$(MY_CGREEN_SRC_PATH)/posix_cgreen_time.c \
$(MY_CGREEN_SRC_PATH)/posix_runner_platform.c \
$(MY_CGREEN_SRC_PATH)/reporter.c \
$(MY_CGREEN_SRC_PATH)/runner.c \
$(MY_CGREEN_SRC_PATH)/string_comparison.c \
$(MY_CGREEN_SRC_PATH)/suite.c \
$(MY_CGREEN_SRC_PATH)/text_reporter.c \
$(MY_CGREEN_SRC_PATH)/utils.c \
$(MY_CGREEN_SRC_PATH)/vector.c \
$(MY_CGREEN_SRC_PATH)/xml_reporter.c
LOCAL_C_INCLUDES := \
$(MY_CGREEN_BASE_PATH_ABS)/include \
$(MY_CGREEN_BASE_PATH_ABS)/src
LOCAL_EXPORT_C_INCLUDES := \
$(MY_CGREEN_BASE_PATH_ABS) \
$(MY_CGREEN_BASE_PATH_ABS)/include \
$(MY_CGREEN_BASE_PATH_ABS)/src
LOCAL_CFLAGS += -O3 -DVERSION="\"OnAndroid\""
# DO_MAKE_DYNAMIC_LIB: boolean-as-int
# 0: build .a (static) lib
# 1: build .so ("dynamic"/"shared") lib
DO_MAKE_DYNAMIC_LIB := 0
ifeq ($(DO_MAKE_DYNAMIC_LIB),1)
LOCAL_LDLIBS := -llog
include $(BUILD_SHARED_LIBRARY)
else
include $(BUILD_STATIC_LIBRARY)
endif
cgreen-1.3.0/contrib/cgreen-mocker/ 0000775 0000000 0000000 00000000000 13666233252 0017147 5 ustar 00root root 0000000 0000000 cgreen-1.3.0/contrib/cgreen-mocker/.gitignore 0000664 0000000 0000000 00000000070 13666233252 0021134 0 ustar 00root root 0000000 0000000 double.mock
complex_types.mock
pycparser
.vscode
*.mock
cgreen-1.3.0/contrib/cgreen-mocker/Makefile 0000664 0000000 0000000 00000001641 13666233252 0020611 0 ustar 00root root 0000000 0000000 all:
@echo "Testing..."
@echo -n "double... "
@./cgreen-mocker.py double.h > double.mock
@diff double.mock double.mock.expected
@if [ "$$?" -eq 0 ] ; then echo "Ok" ; fi
@echo -n "complex_types... "
@./cgreen-mocker.py complex_types.h > complex_types.mock
@diff complex_types.mock complex_types.mock.expected
@if [ "$$?" -eq 0 ] ; then echo "Ok" ; fi
@echo -n "simple_types... "
@./cgreen-mocker.py simple_types.h > simple_types.mock
@diff simple_types.mock simple_types.mock.expected
@if [ "$$?" -eq 0 ] ; then echo "Ok" ; fi
@echo -n "multiple_types... "
@./cgreen-mocker.py multiple_types.h > multiple_types.mock
@diff multiple_types.mock multiple_types.mock.expected
@if [ "$$?" -eq 0 ] ; then echo "Ok" ; fi
@echo -n "multiple_args... "
@./cgreen-mocker.py -Da=b -Dc=d multiple_types.h > multiple_args.mock
@diff multiple_args.mock multiple_types.mock.expected
@if [ "$$?" -eq 0 ] ; then echo "Ok" ; fi
cgreen-1.3.0/contrib/cgreen-mocker/cgreen-mocker.py 0000775 0000000 0000000 00000022534 13666233252 0022253 0 ustar 00root root 0000000 0000000 #!/usr/bin/env python
# -----------------------------------------------------------------
# cgreen-mocker.py
#
# Create Cgreen mocks from extern declarations of functions,
# typically in a header file.
#
# Usage:
# cgreen-mocker.py { }
#
# : any 'cpp' directive but most useful is e.g.
# "-I " to ensure cpp finds files.
#
# : file with function declarations that you want
# to mock
#
# Simplistically adapted from pycparser example: func_defs.py
#
# Since it uses pycparser it will only handle C functions and you will
# probably need the pycparsers "fake_libc_include" to avoid parsing
# the whole world of libc headers. To use it, make a soft link with
# the name 'pycparser' in the directory you are running this from, or
# in the directory of 'cgreen-mocker' itself, to the top directory of
# the pycparser source, and cgreen-mocker will pick it up
# automatically. Or you can point to it using a command line
# 'cpp_directive' arg.
#
# Thanks to @gardenia for the pointer to pycparser!
#
# https://github.com/eliben/pycparser
#
# (C) 2016, Thomas Nilefalk
#
# Using pycparser for printing out all the functions defined in a
# C file.
#
# PyCParser - Copyright (C) 2008-2015, Eli Bendersky
# License: BSD
# -----------------------------------------------------------------
from __future__ import print_function
from pycparser.plyparser import ParseError
from pycparser import c_parser, c_ast, parse_file, c_generator
from functools import reduce
import sys
import os
# This is not required if you've installed pycparser into
# your site-packages/ with setup.py
sys.path.extend(['.', '..'])
# Print on stderr
def eprint(*args, **kwargs):
print(*args, file=sys.stderr, **kwargs)
# A visitor for FuncDef nodes that prints the
# Cgreen mock equivalent of the function
class FuncDefVisitor(c_ast.NodeVisitor):
def __init__(self, filename):
self._types = {}
self.filename = filename
def visit_FuncDecl(self, node):
if node.coord.file == self.filename:
# Only consider definitions that are in the processed file
generator = c_generator.CGenerator()
try:
print(generator.visit(node), end="")
print(" { ")
self.should_return(node)
print("mock(%s);" % ", ".join(arg_list(node.args)))
print("}")
print()
except Exception as e:
print("ERROR: {} - Unexpected AST @ {}:{}:{}:".format(e, node.coord.file,
node.coord.line, node.coord.column))
node.show()
return
def visit_Typedef(self, node):
self._types[node.name] = {
'is_pointer': isinstance(node.type, c_ast.PtrDecl),
}
if self._types[node.name]['is_pointer']:
self._types[node.name]['to_class'] = node.type.type.type.names
else:
self._types[node.name]['to_class'] = None
def should_return(self, node):
generator = c_generator.CGenerator()
type = node.type
if is_double_decl(node):
print(" return unbox_double(", end="")
elif not is_void_decl(node):
print(" return %s(" %
("*" if self.is_return_struct_by_value(node) else ""), end="")
print(generator.visit(node.type), end="")
if isinstance(node.type, c_ast.PtrDecl) or self.is_return_struct_by_value(node):
print(" *", end="")
print(") ", end="")
else:
print(" ", end="")
def is_return_struct_by_value(self, node):
type = node.type
return not isinstance(type, c_ast.PtrDecl) and type.type.names[0] in self._types and not self._types[type.type.names[0]]['is_pointer']
def is_return_by_value_pointer(self, node):
type = node.type
return not isinstance(type, c_ast.PtrDecl) and self._types[type.type.names[0]]['is_pointer']
def arg_list(args):
if args != None and len(args.params) > 0:
return [el for el in map(parameter_name_or_box_double,
filter(lambda x: not is_ellipsis_param(x),
args.params))
if el is not None]
else:
return []
def parameter_name_or_box_double(node):
if is_double_decl(node):
return "box_double({})".format(node.name)
else:
return node.name
def is_void_decl(node):
type = node.type
return isinstance(type, c_ast.TypeDecl) and type.type.names == ['void']
def is_double_decl(node):
type = node.type
return isinstance(type, c_ast.TypeDecl) and type.type.names == ['double']
def is_ellipsis_param(node):
return isinstance(node, c_ast.EllipsisParam)
def show_func_defs(args):
# Note that cpp is used. Provide a path to your own cpp or
# make sure one exists in PATH.
pycparser_path = None
# Try to find a fake_libc
# In current directory?
if verbose:
eprint("Called in {0}".format(
os.path.abspath(os.path.dirname(sys.argv[0]))))
eprint("Looking for fake_lib in current directory...")
if os.path.isdir('pycparser'):
pycparser_path = r'./pycparser'
else:
this_script = os.path.abspath(__file__)
if verbose:
eprint(
"Looking for fake_lib in directory of script ({0})...".format(this_script))
# Look in the directory of this script
while os.path.islink(this_script):
# If the script is a symlink, resolve it first, recursively...
# Note: can only handle absolute symlinks?
this_script = os.readlink(this_script)
if verbose:
eprint(
"Script was a symlink, resolving it to '{0}'...".format(this_script))
if os.path.isdir(os.path.join(os.path.dirname(this_script),
'pycparser')):
# Yes, there is a pycparser symlink here
pycparser_path = os.path.join(os.path.dirname(this_script),
'pycparser')
if pycparser_path:
pycparser_lib = reduce(
os.path.join, [pycparser_path, 'utils', 'fake_libc_include'])
if verbose:
print("/* Generated with cgreen-mocker and pycparser's fake_libc from %s */" %
(pycparser_path))
elif verbose:
eprint("Not found")
try:
options = [
'-I'+pycparser_lib] if pycparser_path else []
if add_gnuisms:
# And add some common GNUisms
options = options + [
r'-D__gnuc_va_list(c)=',
r'-D__attribute__(x)=',
r'-D__extension__=',
r'-D__restrict=',
r'-D__inline='
]
if verbose:
eprint("Parsing with options = {0}".format(options))
cpp_args = list(filter(None, options))
ast = parse_file(args[-1], use_cpp=True,
cpp_args=cpp_args + args[0:-1])
except ParseError as e:
print("ERROR: {} - C99 parse error".format(e))
return
print('/* -*- c -*-*/') # Suggest c-mode for Emacs
print('#include "%s"' % args[len(args)-1])
print('#include ')
print()
v = FuncDefVisitor(args[-1])
v.visit(ast)
def usage():
print("""
Usage:
cgreen-mocker.py { }
: any 'cpp' directive but most useful are e.g.
"-I " to ensure cpp finds files and
"-D " to create an inline define
: file with function declarations that you want
to mock
Cgreen-mocker takes a header file and generates cgreen mocks for
all functions in it. It will print the generated mocks to standard
output so you can inspect it, or pipe it to a file that can be
compiled and linked with your tests.
The mocker will only handle functions that are declared in the
header file you provide. This is based on the presumtion that the
header file represents functions in a unit. Aggregating functions
from multiple units into a single header for convenience is not
supported. Also the mocker cannot handle data declarations (yet?).
If your header does not name some arguments you will not be able
to use those arguments in 'expect when' statements, of course.
Cgreen-mocker will only generate mocks for the external functions
in the file you give as an argument, not those in included files.
If cgreen-mocker encounters parse errors and they look like
gnu-isms you should get a copy of the source for pycparser (on
which cgreen-mocker is built). In it you will find a
'fake_libc_include' which help. Create a symbolic link named
'pycparser' that links to the root of pycparser source and
cgreen-mocker will find it itself.
You can find pycparser at https://github.com/eliben/pycparser
""")
if __name__ == "__main__":
if len(sys.argv) <= 1:
usage()
exit(-1)
if '-v' in sys.argv:
verbose = True
sys.argv.remove('-v')
else:
verbose = False
if '-gnu' in sys.argv:
add_gnuisms = True
sys.argv.remove('-gnu')
else:
add_gnuisms = False
show_func_defs(sys.argv[1:])
cgreen-1.3.0/contrib/cgreen-mocker/complex_types.h 0000664 0000000 0000000 00000000375 13666233252 0022220 0 ustar 00root root 0000000 0000000 typedef struct BasicStruct {
int someValue;
} BasicStruct;
typedef BasicStruct* BasicStructPtr;
BasicStruct return_struct_by_value(int i);
BasicStructPtr return_pointer_to_struct(char string[]);
BasicStruct* direct_return_pointer_to_struct(void);
cgreen-1.3.0/contrib/cgreen-mocker/complex_types.mock.expected 0000664 0000000 0000000 00000000527 13666233252 0024521 0 ustar 00root root 0000000 0000000 /* -*- c -*-*/
#include "complex_types.h"
#include
BasicStruct return_struct_by_value(int i) {
return *(BasicStruct *) mock(i);
}
BasicStructPtr return_pointer_to_struct(char string[]) {
return (BasicStructPtr) mock(string);
}
BasicStruct *direct_return_pointer_to_struct(void) {
return (BasicStruct *) mock();
}
cgreen-1.3.0/contrib/cgreen-mocker/double.h 0000664 0000000 0000000 00000000047 13666233252 0020573 0 ustar 00root root 0000000 0000000 double return_double(double d, int i);
cgreen-1.3.0/contrib/cgreen-mocker/double.mock.expected 0000664 0000000 0000000 00000000230 13666233252 0023067 0 ustar 00root root 0000000 0000000 /* -*- c -*-*/
#include "double.h"
#include
double return_double(double d, int i) {
return unbox_double(mock(box_double(d), i);
}
cgreen-1.3.0/contrib/cgreen-mocker/multiple_types.h 0000664 0000000 0000000 00000001017 13666233252 0022376 0 ustar 00root root 0000000 0000000 typedef struct Struct1 {
int someValue;
} Struct1;
typedef Struct1* Struct1Ptr;
Struct1 return_struct1_by_value(int i);
Struct1Ptr return_pointer_to_struct1(char string[]);
Struct1* direct_return_pointer_to_struct1(void);
typedef struct Struct2 {
int someValue;
} Struct2;
typedef Struct2* Struct2Ptr;
Struct2 return_struct2_by_value(int i);
Struct2Ptr return_pointer_to_struct2(char string[]);
Struct2* direct_return_pointer_to_struct2(void);
extern void return_nothing(void);
extern int return_int(int ints[]);
cgreen-1.3.0/contrib/cgreen-mocker/multiple_types.mock.expected 0000664 0000000 0000000 00000001246 13666233252 0024704 0 ustar 00root root 0000000 0000000 /* -*- c -*-*/
#include "multiple_types.h"
#include
Struct1 return_struct1_by_value(int i) {
return *(Struct1 *) mock(i);
}
Struct1Ptr return_pointer_to_struct1(char string[]) {
return (Struct1Ptr) mock(string);
}
Struct1 *direct_return_pointer_to_struct1(void) {
return (Struct1 *) mock();
}
Struct2 return_struct2_by_value(int i) {
return *(Struct2 *) mock(i);
}
Struct2Ptr return_pointer_to_struct2(char string[]) {
return (Struct2Ptr) mock(string);
}
Struct2 *direct_return_pointer_to_struct2(void) {
return (Struct2 *) mock();
}
void return_nothing(void) {
mock();
}
int return_int(int ints[]) {
return (int) mock(ints);
}
cgreen-1.3.0/contrib/cgreen-mocker/simple_types.h 0000664 0000000 0000000 00000000134 13666233252 0022033 0 ustar 00root root 0000000 0000000 int return_int(void);
char return_char(char c);
char* return_pointer_to_char(char *string);
cgreen-1.3.0/contrib/cgreen-mocker/simple_types.mock.expected 0000664 0000000 0000000 00000000377 13666233252 0024346 0 ustar 00root root 0000000 0000000 /* -*- c -*-*/
#include "simple_types.h"
#include
int return_int(void) {
return (int) mock();
}
char return_char(char c) {
return (char) mock(c);
}
char *return_pointer_to_char(char *string) {
return (char *) mock(string);
}
cgreen-1.3.0/contrib/cgreen-mocker/test/ 0000775 0000000 0000000 00000000000 13666233252 0020126 5 ustar 00root root 0000000 0000000 cgreen-1.3.0/contrib/cgreen-mocker/test/cgreen-mocker 0000777 0000000 0000000 00000000000 13666233252 0026073 2../cgreen-mocker.py ustar 00root root 0000000 0000000 cgreen-1.3.0/contrib/completion/ 0000775 0000000 0000000 00000000000 13666233252 0016577 5 ustar 00root root 0000000 0000000 cgreen-1.3.0/contrib/completion/cgreen_bash_completion 0000664 0000000 0000000 00000004402 13666233252 0023213 0 ustar 00root root 0000000 0000000 #/usr/bin/env bash
#
# Contributed by Yavor Lulchev @RookieWookiee
# Improved a bit by @thoni56
# Thanks to https://stackoverflow.com/a/57243443/204658
removeFromArray() {
arrayName="$1"
arrayNameAt="$arrayName"'[@]'
removeValue="$2"
mapfile -d '' -t "$arrayName" < <(
printf %s\\0 "${!arrayNameAt}" | grep -zvFx -- "$removeValue")
}
_cgreen_runner_completion()
{
local options libraries tests
options=("--colours" "--no-colours" "--xml" "--suite" "--verbose" "--no-run" "--help" " --version")
#echo options:"${options[@]}" > log
libraries=" $(\ls | grep -e '\b\.so\b' | tr '\n' ' ')"
tests=""
# If a partial test is given we should match and only complete the matching tests
# Look for words in the command given so far
for word in ${COMP_WORDS[@]}; do
if echo $word | grep -q -E "\b\.so\b"; then
# If it was a library, check for tests in it
if test ! -f $word || test ! -x $word; then continue; fi
local SUT="$(nm -f posix $word | grep -o -E 'CgreenSpec\w*?\b' | awk -F '__' '{ print $2 }' | uniq)"
local test_names=($(nm -f posix $word | grep -o -E 'CgreenSpec\w*?\b' | sed -e 's/CgreenSpec__[a-zA-Z0-9]\+\?__//' -e 's/__$//'))
if test $SUT = "default" ; then
tests+=" $test_names"
else
local prefix="$SUT\\:"
tests+=" ${test_names[@]/#/$prefix}"
fi
fi
done
# Remove all suggestions already used
# Strangely this only removes things from options, not libraries or tests
#echo "options:${options[@]}" >> log
#echo "libraries:${libraries[@]}" >> log
#echo "tests:${tests[@]}" >> log
for word in ${COMP_WORDS[@]}; do
echo \'$word\' >> log
removeFromArray options $word
removeFromArray libraries $word
removeFromArray tests $word
done
#echo "options:${options[@]}" >> log
#echo "libraries:${libraries[@]}" >> log
#echo "tests:${tests[@]}" >> log
COMPREPLY=($(compgen -W '$(printf "%s " ${options[@]} ${libraries[@]} ${tests[@]})' -- "${COMP_WORDS[$COMP_CWORD]}"))
}
complete -o nosort -o dirnames -F _cgreen_runner_completion cgreen-runner
complete -o nosort -o dirnames -F _cgreen_runner_completion cgreen-debug
cgreen-1.3.0/contrib/rpm/ 0000775 0000000 0000000 00000000000 13666233252 0015224 5 ustar 00root root 0000000 0000000 cgreen-1.3.0/contrib/rpm/cgreen.spec 0000664 0000000 0000000 00000006202 13666233252 0017343 0 ustar 00root root 0000000 0000000 # Mini-HOWTO:
#
# 1. Update gitcommit, gitncommits and gitversion in this file with
# data from "git describe --tags". (See below).
#
# 2. Fetch the latest source archive from github:
#
# curl -Lo ~/rpmbuild/SOURCES/cgreen-master.zip https://github.com/cgreen-devs/cgreen/archive/master.zip
#
# 3. Build the source and binary RPMs:
#
# mock $(rpmbuild -bs cgreen.spec | cut -d" " -f2)
#
# You could also provide your own source archive if that's what you're
# looking for. Make sure to adjust Source0: and the %prep phase
# accordingly.
# $ git describe --tags
# 1.0.0-387-g8130aa7
# | | +--v
%define gitcommit g8130aa7
# | +----------v
%define gitncommits 387
# +--------------v
%define gitversion 1.0.0
Summary: Cgreen is a modern unit test and mocking framework for C and C++.
Name: cgreen
Version: %{gitversion}
Release: %{gitncommits}.%{gitcommit}
License: ISC
URL: https://github.com/cgreen-devs/cgreen
Source0: %{name}-master.zip
BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root
BuildRequires: cmake
%description
A modern, portable, cross-language unit testing and mocking framework for C and C++
%prep
%setup -q -n cgreen-master
%build
%cmake .
%install
rm -rf $RPM_BUILD_ROOT
# Don't put things into /usr/lib/cmake on 64-bit systems
%if "%{?_lib}" == "lib64"
sed -i -e "s@/lib/cmake/cgreen@/lib64/cmake/cgreen@g" cmake_install.cmake
%endif
%make_install
%clean
rm -rf $RPM_BUILD_ROOT
%files
%defattr(-,root,root,-)
%{_bindir}/cgreen-runner
%dir %{_includedir}/cgreen
%{_includedir}/cgreen/assertions.h
%{_includedir}/cgreen/boxed_double.h
%{_includedir}/cgreen/breadcrumb.h
%{_includedir}/cgreen/cdash_reporter.h
%{_includedir}/cgreen/cgreen.h
%{_includedir}/cgreen/cgreen_value.h
%{_includedir}/cgreen/constraint.h
%{_includedir}/cgreen/constraint_syntax_helpers.h
%{_includedir}/cgreen/cpp_assertions.h
%{_includedir}/cgreen/cpp_constraint.h
%{_includedir}/cgreen/cute_reporter.h
%{_includedir}/cgreen/internal/assertions_internal.h
%{_includedir}/cgreen/internal/c_assertions.h
%{_includedir}/cgreen/internal/cgreen_pipe.h
%{_includedir}/cgreen/internal/cgreen_time.h
%{_includedir}/cgreen/internal/cpp_assertions.h
%{_includedir}/cgreen/internal/function_macro.h
%{_includedir}/cgreen/internal/mock_table.h
%{_includedir}/cgreen/internal/mocks_internal.h
%{_includedir}/cgreen/internal/runner_platform.h
%{_includedir}/cgreen/internal/stringify_token.h
%{_includedir}/cgreen/internal/suite_internal.h
%{_includedir}/cgreen/internal/unit_implementation.h
%{_includedir}/cgreen/legacy.h
%{_includedir}/cgreen/mocks.h
%{_includedir}/cgreen/reporter.h
%{_includedir}/cgreen/runner.h
%{_includedir}/cgreen/string_comparison.h
%{_includedir}/cgreen/suite.h
%{_includedir}/cgreen/text_reporter.h
%{_includedir}/cgreen/unit.h
%{_includedir}/cgreen/vector.h
%dir %{_libdir}/cmake/cgreen
%{_libdir}/cmake/cgreen/cgreen-config-version.cmake
%{_libdir}/cmake/cgreen/cgreen-config.cmake
%{_libdir}/libcgreen.so
%{_libdir}/libcgreen.so.1
%{_libdir}/libcgreen.so.1.1.0
%{_mandir}/man1/cgreen-runner.1.gz
%{_mandir}/man5/cgreen.5.gz
%changelog
* Tue Feb 6 2018 Karl Mikaelsson - 1.0.0-387.g8130aa7
- Initial build of git master.
cgreen-1.3.0/contrib/upgrade/ 0000775 0000000 0000000 00000000000 13666233252 0016055 5 ustar 00root root 0000000 0000000 cgreen-1.3.0/contrib/upgrade/upgrade.sh 0000775 0000000 0000000 00000001401 13666233252 0020037 0 ustar 00root root 0000000 0000000 # Perl-script to upgrade from pre-beta versions
# Initial version by Colm Dougan, contributed by Thomas Nilsson
perl -pi -e 's/\bEnsure\s+(\w+)\s*\(\)/Ensure($1)/' $@
perl -pi -e 's/\bEnsure\s+(\w+)\s*\(void\)/Ensure($1)/' $@
perl -pi -e 's/\bfail\(\)/fail("expected exception")/' $@
perl -pi -e 's/\bexpect_call/expect/' $@
perl -pi -e 's/\bwant\((\w+), ([^)]+)/when($1, is_equal_to($2)/' $@
perl -pi -e 's/\bwill_respond\((\w+),\ ([^,\)]+)/expect($1, will_return($2)/' $@
perl -pi -e 's/\bwill_return\((\w+),\ ([^,\)]+)/expect($1, will_return($2)/' $@
perl -pi -e 's/\bwant_non_null_?\(\"(\w+)\"\)/when($1, is_non_null)/' $@
perl -pi -e 's/\bsetup\(/set_setup(/g' $@
perl -pi -e 's/\bteardown\(/set_teardown(/g' $@
perl -pi -e 's/\bexpect_never\(/never_expect(/g' $@
cgreen-1.3.0/debian-control 0000664 0000000 0000000 00000001222 13666233252 0015606 0 ustar 00root root 0000000 0000000 Source: cgreen
Section: devel
Priority: optional
Maintainer: Thomas Nilefalk
Build-Depends: debhelper (>= 10), cmake
Standards-Version: 4.0.0
Homepage: https://github.com/cgreen-devs/cgreen
Package: cgreen
Version: 1.3.0
Architecture: amd64
Description: Unit tests and mocking framework for C and C++
A modern unit test and mocking framework for C and C++. Cgreen features
- fast build, clean code, highly portable
- simple auto-discovery of tests
- fluent, expressive and readable API
- each test runs in isolation to prevent cross-test dependencies
- built-in mocking for C, compatible other C++ mocking libraries
cgreen-1.3.0/doc/ 0000775 0000000 0000000 00000000000 13666233252 0013533 5 ustar 00root root 0000000 0000000 cgreen-1.3.0/doc/.gitignore 0000664 0000000 0000000 00000000041 13666233252 0015516 0 ustar 00root root 0000000 0000000 cgreen-guide-en.html
html_chunks
cgreen-1.3.0/doc/CMakeLists.txt 0000664 0000000 0000000 00000003415 13666233252 0016276 0 ustar 00root root 0000000 0000000 FIND_PACKAGE(Asciidoctor)
SET(ASCIIDOC_CONFFILE "${PROJECT_SOURCE_DIR}/doc/cgreen_asciidoc.conf")
OPTION(CGREEN_WITH_HTML_DOCS "with HTML output" FALSE)
OPTION(CGREEN_WITH_PDF_DOCS "with PDF output" FALSE)
IF (CGREEN_WITH_HTML_DOCS AND NOT ASCIIDOCTOR_FOUND)
MESSAGE(FATAL_ERROR "Can't produce HTML without 'asciidoctor'")
ENDIF (CGREEN_WITH_HTML_DOCS AND NOT ASCIIDOCTOR_FOUND)
IF (CGREEN_WITH_PDF_DOCS AND NOT ASCIIDOCTORPDF_FOUND)
MESSAGE(FATAL_ERROR "Can't produce PDF without 'asciidoctor-pdf'")
ENDIF (CGREEN_WITH_PDF_DOCS AND NOT ASCIIDOCTORPDF_FOUND)
IF(CGREEN_WITH_HTML_DOCS OR CGREEN_WITH_PDF_DOCS)
FILE(GLOB _docfiles *.asciidoc)
FOREACH(_file ${_docfiles})
GET_FILENAME_COMPONENT(_file_we ${_file} NAME_WE)
SET(_in "${_file_we}")
IF (CGREEN_WITH_HTML_DOCS)
SET(_out "${_file_we}.html")
ADD_CUSTOM_COMMAND(
OUTPUT "${_out}-html"
COMMAND ${ASCIIDOCTOR_EXECUTABLE}
-a VERSION=${APPLICATION_VERSION}
-o ${_out} ${_file}
DEPENDS ${_file}
COMMENT "asciidoctor ${_in}"
)
ADD_CUSTOM_TARGET(${_in}-html ALL echo
DEPENDS "${_out}-html"
)
ENDIF (CGREEN_WITH_HTML_DOCS)
IF (CGREEN_WITH_PDF_DOCS)
SET(_out "${_file_we}.pdf")
ADD_CUSTOM_COMMAND(
OUTPUT "${_out}-pdf"
COMMAND ${ASCIIDOCTORPDF_EXECUTABLE}
-a toc
-a VERSION=${APPLICATION_VERSION}
-a docinfo -o ${_out} ${_file}
DEPENDS ${_file}
COMMENT "asciidoctor-pdf ${_in}"
)
ADD_CUSTOM_TARGET(${_in}-pdf ALL echo
DEPENDS "${_out}-pdf"
)
ENDIF (CGREEN_WITH_PDF_DOCS)
ENDFOREACH(_file)
ENDIF(CGREEN_WITH_HTML_DOCS OR CGREEN_WITH_PDF_DOCS)
IF(UNIX)
set(MANPAGES man)
INSTALL(DIRECTORY ${MANPAGES} DESTINATION share/)
ENDIF(UNIX)
cgreen-1.3.0/doc/README 0000664 0000000 0000000 00000003550 13666233252 0014416 0 ustar 00root root 0000000 0000000 HOW-TO: Compiling the Cgreen Guide
===================================
The Cgreen Guide Book is written using Asciidoctor. Asciidoctor builds
upon the asciidoc format, is 100 times faster than the Python asciidoc
toolchain and can generate PDF in the same step. Writing in
asciidoc(tor) is a wonderful way to write textual docs. Please visit
http://www.asciidoctor.org for more information.
You also need a source-highlighter as described in
(http://asciidoctor.org/docs/asciidoc-syntax-quick-reference/#source-code)
There are a number of source examples in the documentation that are
automatically included from the `tutorial_src` subdirectory. They are
kept separate so that they can be compiled to ensure that they
actually are correct. Then all, or a part of, the file can be
included. To do that, go to the subdirectory, ensure you have the
correct version of cgreen in your path and do `make`.
The one drawback of this strategy is that you cannot read the source
of the examples in a raw asciidoc-conversion, like on github, since it
requires including other files, which is not allowed for security
reasons. So we need to generate the documentation and upload it to
`cgreen-devs.github.io`. Ensure you have *asciidoctor* installed
(`sudo apt install asciidoctor` or similar).
It is preferred to generate multi-page HTML, which currently
asciidoctor does not do natively yet. There is an extension in the
asciidoctor-extension-lab, which I have not
tried. [asciidoctor-chunker](https://github.com/wshito/asciidoctor-chunker)
works well, but requires installing Roswell (a Common Lisp
environment). If you use asciidoctor-chunker, first generate the HTML with asciidoctor
asciidoctor cgreen-guide-en.asciidoc -o html/cgreen-guide-en.html
then chunk it using asciidoctor-chunker (assuming some convenience
links in your path...)
asciidoctor-chunker html/cgreen-guide-en.html
cgreen-1.3.0/doc/cgreen-guide-en-docinfo.html 0000664 0000000 0000000 00000001775 13666233252 0021010 0 ustar 00root root 0000000 0000000
Thomas
Nilefalk
thomas@junovagen.se
Marcus
Baker
lastcraft
marcus@lastcraft.com
João
Freitas
joaohf
joaohf@gmail.com
Cgreen Unit Test for C/C++ language
2009-2012
Cgreen Team
Permission to use, copy, modify and distribute.
The copyright holders make no representation about the suitability of
this document for any purpose. It is provided
as is
without expressed or implied warranty.
cgreen-1.3.0/doc/cgreen-guide-en-docinfo.xml 0000664 0000000 0000000 00000002031 13666233252 0020626 0 ustar 00root root 0000000 0000000
Marcus
Baker
lastcraft
marcus@lastcraft.com
João
Freitas
joaohf
joaohf@gmail.com
Thomas
Nilefalk
thoni56
thomas@junovagen.se
Cgreen Unit Test for C language
2012
Cgreen Team
Permission to use, copy, modify and distribute.
The copyright holders make no representation about the suitability of
this document for any purpose. It is provided
as is
without expressed or implied warranty.
cgreen-1.3.0/doc/cgreen-guide-en.asciidoc 0000664 0000000 0000000 00000356407 13666233252 0020210 0 ustar 00root root 0000000 0000000 :source-highlighter: highlightjs
:icons: font
:numbered:
:toc: left
:pp: ++
ifdef::env-github[]
:tip-caption: :bulb:
:note-caption: :information_source:
:important-caption: :heavy_exclamation_mark:
:caution-caption: :fire:
:warning-caption: :warning:
endif::[]
= Cgreen : Unit Tests, Stubbing and Mocking for C and C++
v{VERSION}
== Cgreen Quickstart Guide
=== What is Cgreen?
*Cgreen* is a unit tester for the C and C++ software developer, a test
automation and software quality assurance tool for programmers and
development teams. The tool is completely open source published under
the https://github.com/cgreen-devs/cgreen/blob/master/LICENSE[ISC,
OpenBSD, license].
Unit testing is a development practice popularised by the agile
development community. It is characterised by writing many small
tests alongside the normal code. Often the tests are written before
the code they are testing, in a tight test-code-refactor loop. Done
this way, the practice is known as Test Driven Development. *Cgreen*
was designed specifically to support this style of development.
Unit tests are written in the same language as the code, in our case
C or C++. This avoids the mental overhead of constantly switching language,
and also allows you to use any application code in your tests.
Here are some of its features:
- Fluent API resulting in very readable tests
- Expressive and clear output using the default reporter
- Fully functional mocks, both strict, loose and learning
- Mocks with side effects
- Each test runs in its own process for test suite robustness
- Automatic discovery and running of tests using dynamic library inspection
- Extensive and expressive constraints for many datatypes
- Custom constraints can be constructed by user
- BDD-flavoured test declarations with Before and After declarations
- Extensible reporting mechanism
- Fully composable test suites
- A single test can be run in a single process for easier debugging
*Cgreen* also supports the classic xUnit-style assertions for easy
porting from other frameworks.
*Cgreen* was initially developed to support C programming, but there
is also support for C{pp}. It was initially a spinoff from a research
project at Wordtracker and created by Marcus Baker. Significant
additions by Matt Hargett and continuous nurturing by Thomas Nilefalk
has made *Cgreen* what it is today.
=== Cgreen - Vanilla or Chocolate?
Test driven development (TDD) really catched on when the JUnit
framework for Java spread to other langauges, giving us a family of
https://en.wikipedia.org/wiki/XUnit[xUnit] tools. *Cgreen* was born in
this wave and have many similarities to the xUnit family.
But TDD evolved over time and modern thinking and practice is more
along the lines of BDD, an acronym for Behaviour Driven Development,
made popular by people like Dan North and frameworks like JBehave,
RSpec, Cucumber and Jasmine.
*Cgreen* follows this trend and has evolved to embrace a BDD-flavoured
style of testing. Although the fundamental mechanisms in TDD and
'technical' BDD are much the same, the shift in focus by changing
wording from 'tests' to 'behaviour specifications' is very
significant.
This document will present *Cgreen* using the more modern and better
BDD-style. In a later section you can have a peek at the classic TDD
API, but you should consider that as outdated.
=== Installing Cgreen
There are two ways to install *Cgreen* in your system.
==== Installing a package
NOTE: At this point there are few supported pre-built packages
available. For now you'll probably have to build from source.
The first way is to use packages provided by the *Cgreen* Team. If
your system uses a package manager ('apt' or 'port' and so on) there
might be a prebuilt package that you can just install using your
systems package manager.
If no *Cgreen* package is distributed for your system you can download
a package from https://github.com/cgreen-devs/cgreen/releases[Cgreen
GitHub project]. Install it using the normal procedures for your
system.
==== Installing from source
The second way is available for developers and advanced
users. Basically this consists of fetching the sources of the project
on https://github.com/cgreen-devs/cgreen[GitHub], just click on
"Download ZIP", and compiling them. To do this you need the
http://www.cmake.org[CMake] build system.
Once you have the CMake tool installed, the steps are:
-----------------------------------------
$ unzip cgreen-master.zip
$ cd cgreen-master
$ make
$ make test
$ make install
-----------------------------------------
The initial `make` command will configure the build process and
create a separate `build` directory before going there and building
using *CMake*. This is called an 'out of source build'. It compiles
*Cgreen* from outside the sources directory. This helps the overall
file organization and enables multi-target builds from the same
sources by leaving the complete source tree untouched.
TIP: Experienced users may tweak the build configuration by going to
the build subdirectory and use `ccmake ..` to modify the build
configuration in that subtree.
TIP: The Makefile is just there for convenience, it just creates the
build directory and invokes *CMake* there, so that you don't have
to. This means that experienced *CMake* users can just do as they
normally do with a *CMake*-based project instead of invoking `make`.
The build process will create a library (on unix called
`libcgreen.so`) which can be used in conjunction with the `cgreen.h`
header file to compile and link your test code. The created library is
installed in the system, by default in the `/usr/local/lib/`.
==== Your First Test
We will start demonstrating the use of *Cgreen* by writing some tests for *Cgreen* itself
to confirm that everything is working as it should. Let's start with a
simple test module with no tests, called `first_test.c`...
[source,c]
---------------------------------------
include::tutorial_src/first_tests0.c[]
---------------------------------------
This is very unexciting. It just creates an empty test suite and runs
it. It's usually easier to proceed in small steps, and this is the
smallest one I could think of. The only complication is the `cgreen.h`
header file and the mysterious looking "declarations" at the beginning
of the file.
The BDD flavoured *Cgreen* notation calls for a System Under Test
(SUT), or a 'context'. The declarations give a context to the tests
and it also makes it more natural to talk about which module or class,
the system under test, is actually responsible for the functionality
we are expressing. In one way we are 'describing', or spec'ing, the
functionality of the SUT. That's what the `Describe();` does. And for
technical reasons (actually requirements of the C language), you must
declare the `BeforeEach()` and `AfterEach()` functions even if they
are empty. (You will get strange errors if you don't!)
NOTE: We are using the name "Cgreen" as the SUT in these first
examples, as *Cgreen* itself is the object or class we want to
test or describe.
I am assuming you have the *Cgreen* folder in the include search
path to ensure compilation works, otherwise you'll need to add that in
the compilation command.
Then, building this test is, of course, trivial...
-----------------------------
$ gcc -c first_test.c
$ gcc first_test.o -lcgreen -o first_test
$ ./first_test
-----------------------------
Invoking the executable should give...
-----------------------------
include::tutorial_src/first0.out[]
-----------------------------
All of the above rather assumes you are working in a Unix like
environment, probably with 'gcc'. The code is pretty much standard
C99, so any C compiler should work. *Cgreen* should compile on all
systems that support the `sys/msg.h` messaging library. It has been
tested on Linux, MacOSX, Cygwin and Windows.
So far we have tried compilation, and shown that the test suite
actually runs. Let's add a meaningless test or two so that you can
see how it runs...
[source,c]
-----------------------------
include::tutorial_src/first_tests1.c[]
-----------------------------
A test is denoted by the macro `Ensure` which takes an optional
context (`Cgreen`) and a, hopefully descriptive, testname
(`passes_this_test`). You add the test to your suite using
`add_test_with_context()`.
On compiling and running, we now get the output...
-----------------------------
include::tutorial_src/first1.out[]
-----------------------------
The `TextReporter`, created by the call to `create_text_reporter()`, is
the easiest way to output the test results. It prints the failures as
intelligent and expressive text messages on your console.
Of course "0" would never equal "1", but this shows that *Cgreen*
presents the value you expect (`[be true]`) __and__ the expression
that you want to assert (`[0 == 1]`). We can also see a handy short
form for asserting boolean expressions (`assert_that(0 == 1);`).
[[tdd_with_cgreen]]
=== Five Minutes Doing TDD with Cgreen
For a more realistic example we need something to test. We'll pretend
that we are writing a function to split the words of a sentence in
place. It would do this by replacing any spaces with string
terminators and returns the number of conversions plus one. Here is
an example of what we have in mind...
[source,c]
-------------------------------
char *sentence = strdup("Just the first test");
word_count = split_words(sentence);
-------------------------------
The variable `sentence` should now point at
"Just\0the\0first\0test". Not an obviously useful function, but we'll
be using it for something more practical later.
This time around we'll add a little more structure to our
tests. Rather than having the test as a stand alone program, we'll
separate the runner from the test cases. That way, multiple test
suites of test cases can be included in the `main()` runner file.
This makes it less work to add more tests later.
Here is the, so far empty, test case in `words_test.c`...
[source,c]
-------------------------------
include::tutorial_src/words_tests0.c[]
-------------------------------
Here is the `all_tests.c` test runner...
[source,c]
-------------------------------
include::tutorial_src/all_tests.c[]
-------------------------------
*Cgreen* has two ways of running tests. The default is to run all
tests in their own protected processes. This is what happens if you
invoke `run_test_suite()`. All tests are then completely independent
since they run in separate processes, preventing a single run-away
test from bringing the whole program down with it. It also ensures
that one test cannot leave any state to the next, thus forcing you to
setup the prerequisites for each test correctly and clearly.
Building this scaffolding...
-------------------------------
$ gcc -c words_test.c
$ gcc -c all_tests.c
$ gcc words_test.o all_tests.o -lcgreen -o all_tests
-------------------------------
...and executing the result gives the familiar...
-------------------------------
include::tutorial_src/words0.out[]
-------------------------------
Note that we get an extra level of output here, we have both `main`
and `words_tests`. That's because `all_tests.c` adds the words test
suite to its own (named `main` since it was created in the function
`main()`). All this scaffolding is pure overhead, but from now on
adding tests will be a lot easier.
Here is a first test for `split_words()` in `words_test.c`...
[source,c]
-------------------------------
include::tutorial_src/words_tests1.c[]
-------------------------------
The `assert_that()` macro takes two parameters, the value to assert
and a constraint. The constraints comes in various forms. In this case
we use the probably most common, `is_equal_to()`. With the default
`TextReporter` the message is sent to `STDOUT`.
To get this to compile we need to create the `words.h` header file...
[source,c]
-------------------------------
include::tutorial_src/words.h[lines=1]
-------------------------------
...and to get the code to link we need a stub function in `words.c`...
[source,c]
-------------------------------
include::tutorial_src/words1.c[lines=3..5]
-------------------------------
A full build later...
-------------------------------
$ gcc -c all_tests.c
$ gcc -c words_test.c
$ gcc -c words.c
$ gcc all_tests.o words_test.o words.o -lcgreen -o all_tests
$ ./all_tests
-------------------------------
...and we get the more useful response...
-------------------------------
include::tutorial_src/words1.out[]
-------------------------------
The breadcrumb trail following the "Failure" text is the nesting of
the tests. It goes from the test suites, which can be nested in each
other, through the test function, and finally to the message from the
assertion. In the language of *Cgreen*, a "failure" is a mismatched
assertion, or constraint, and an "exception" occurs when a test fails
to complete for any reason, e.g. a segmentation fault.
We could get this to pass just by returning the value 4. Doing TDD in
really small steps, you would actually do this, but we're not teaching
TDD here. Instead we'll go straight to the core of the
implementation...
[source,c]
--------------------------------
include::tutorial_src/words2.c[]
--------------------------------
Running it gives...
---------------------------------
include::tutorial_src/words2.out[]
---------------------------------
There is actually a hidden problem here, but our tests still passed so
we'll pretend we didn't notice.
So it's time to add another test. We want to confirm that the string
is broken into separate words...
[source,c]
---------------------------------
...
include::tutorial_src/words_tests2.c[lines=10]
...
include::tutorial_src/words_tests2.c[lines=15..23]
---------------------------------
Sure enough, we get a failure...
----------------------------------
include::tutorial_src/words3.out[]
----------------------------------
Not surprising given that we haven't written the code yet.
The fix...
[source,c]
----------------------------------
include::tutorial_src/words3.c[]
----------------------------------
...reveals our previous hack...
----------------------------------
include::tutorial_src/words4.out[]
----------------------------------
Our earlier test now fails, because we have affected the `strlen()`
call in our loop. Moving the length calculation out of the loop...
[source,c]
----------------------------------
include::tutorial_src/words4.c[lines=3..5]
...
include::tutorial_src/words4.c[lines=10..-1]
----------------------------------
...restores order...
----------------------------------
include::tutorial_src/words5.out[]
----------------------------------
It's nice to keep the code under control while we are actually writing
it, rather than debugging later when things are more complicated.
That was pretty straight forward. Let's do something more interesting.
=== What are Mock Functions?
The next example is a more realistic extension of our previous
attempts. As in real life we first implement something basic and then
we go for the functionality that we need. In this case a function that
invokes a callback for each word found in a sentence. Something
like...
[source,c]
----------------------------------
void act_on_word(const char *word, void *memo) { ... }
words("This is a sentence", &act_on_word, &memo);
----------------------------------
Here the `memo` pointer is just some accumulated data that the
`act_on_word()` callback might work with. Other people will write the
`act_on_word()` function and probably many other functions like
it. The callback is actually a flex point, and not of interest right
now.
The function under test is the `words()` function and we want to make
sure it walks the sentence correctly, dispatching individual words as
it goes. So what calls are made are very important. How to test this?
Let's start with a one word sentence. In this case we would expect
the callback to be invoked once with the only word, right? Here is
the test for that...
[source,c]
---------------------------------
include::tutorial_src/words_tests3.c[lines=1..2]
...
include::tutorial_src/words_tests3.c[lines=27..38]
...
include::tutorial_src/words_tests3.c[lines=41..-1]
---------------------------------
What is the funny looking `mock()` function?
A mock is basically a programmable object. In C objects are limited
to functions, so this is a mock function. The macro `mock()` compares
the incoming parameters with any expected values and dispatches
messages to the test suite if there is a mismatch. It also returns
any values that have been preprogrammed in the test.
The test is `invokes_callback_once_for_single_word_sentence()`. It
programs the mock function using the `expect()` macro. It expects a
single call, and that single call should use the parameters `"Word"`
and `NULL`. If they don't match, we will get a test failure.
So when the code under test (our `words()` function) calls the
injected `mocked_callback()` it in turn will call `mock()` with the
actual parameters.
Of course, we don't add the mock callback to the test suite, it's not
a test.
For a successful compile and link, the `words.h` file must now look
like...
[source,c]
----------------------------
include::tutorial_src/words.h[]
----------------------------
...and the `words.c` file should have the stub...
[source,c]
----------------------------
include::tutorial_src/words5.c[lines=14..15]
----------------------------
This gives us the expected failing test...
----------------------------
include::tutorial_src/words6.out[]
----------------------------
*Cgreen* reports that the callback was never invoked. We can easily
get the test to pass by filling out the implementation with...
[source,c]
----------------------------
include::tutorial_src/words6.c[lines=14..16]
----------------------------
That is, we just invoke it once with the whole string. This is a
temporary measure to get us moving. For now everything should pass,
although it doesn't drive much functionality yet.
----------------------------
include::tutorial_src/words7.out[]
----------------------------
That was all pretty conventional, but let's tackle the trickier case
of actually splitting the sentence. Here is the test function we will
add to `words_test.c`...
[source,c]
----------------------------
include::tutorial_src/words_tests4.c[lines=37..43]
----------------------------
Each call is expected in sequence. Any failures, or left-over or
extra calls, and we get failures. We can see all this when we run the
tests...
----------------------------
include::tutorial_src/words8.out[]
----------------------------
The first failure tells the story. Our little `words()` function
called the mock callback with the entire sentence. This makes sense,
because that was the hack we did to get to the next test.
Although not relevant to this guide, I cannot resist getting these
tests to pass. Besides, we get to use the function we created
earlier...
[source,c]
-----------------------------
include::tutorial_src/words7.c[lines=15..29]
-----------------------------
And with some work we are rewarded with...
------------------------------
include::tutorial_src/words9.out[]
------------------------------
More work than I like to admit as it took me three goes to get this
right. I firstly forgot the `+ 1` added on to `strlen()`, then forgot
to swap `sentence` for `word` in the `(*callback)()` call, and
finally third time lucky. Of course running the tests each time made
these mistakes very obvious. It's taken me far longer to write these
paragraphs than it has to write the code.
== Building Cgreen test suites
*Cgreen* is a tool for building unit tests in the C or C++
languages. These are usually written alongside the production code by
the programmer to prevent bugs. Even though the test suites are
created by software developers, they are intended to be human
readable C code, as part of their function is an executable
specification. Used in this way, the test harness delivers constant
quality assurance.
In other words you'll get less bugs.
=== Writing Basic Tests
*Cgreen* tests are like C, or C++, functions with no parameters and
no return value. To signal that they actually are tests we mark them
with the `Ensure` macro. Here's an example...
[source,c]
-----------------------------
include::tutorial_src/strlen_tests1.c[lines=8..10]
-----------------------------
The `Ensure` macro takes two arguments (in the BDD style) where the
first is the System Under Test (SUT) which must be declared with the
`Describe` macro.
[source,c]
-----------------------------
include::tutorial_src/strlen_tests1.c[lines=4]
-----------------------------
The second argument is the test name and can be anything you want as
long as it fullfills the rules for an identifier in C and C++. A
typical way to choose the named of the tests is what we see here,
reading the declaration of the test makes sense since it is almost
plain english, "Ensure strlen returns five for 'hello'". No problem
understanding what we aim to test, or in TDD lingo, test drive. And
it can be viewed as an example from a description of what strlen
should be able to do. In a way, extracting all the `Ensure`:s from
your test might give you all the documentation you'll need.
The call to `assert_that()` is the primary part of an assertion,
which is complemented with a constraint, in this case
`is_equal_to()`, as a parameter. This makes a very fluent interface
to the asserts, that actually reads like English. The general format
is then
[source, C]
---------------
assert_that(actual, );
---------------
NOTE: Sometimes you just want to fail the test explicitly, and there
is a function for that too, `fail_test(const char *message)`. And
there is a function to explicitly pass, `pass_test(void)`.
Assertions send messages to *Cgreen*, which in turn outputs the
results.
=== The Standard Constraints
Here are the standard constraints...
|=========================================================
|*Constraint* |*Passes if actual value/expression...*
| _Basic_ |
| `is_true` | evaluates to true, buy you can also just leave out the constraint,
e.g. `assert_that(found)` if `found` is of boolean type
| `is_false` | evaluates to false
| `is_null` | equals null
| `is_non_null` | is a non null value
| `is_not_null` | d:o
||
| _Integer compatible_ |
| `is_equal_to(value)` | '== value'
| `is_equal_to_hex(value)` | '== value', but will show values in HEX
| `is_not_equal_to(value)` | '!= value'
| `is_greater_than(value)` | '> value'
| `is_less_than(value)` | '< value'
||
| _Structs and general data_ |
| `is_equal_to_contents_of(pointer, size)` | matches the data pointed
to by `pointer` to a size
of `size` bytes
| `is_not_equal_to_contents_of(pointer, size)` | does not match the data
pointed to by `pointer`
to a size of `size` bytes
||
| _Strings_ |
| `is_equal_to_string(value)` | are equal when compared using `strcmp()`
| `is_not_equal_to_string(value)` | are not equal when compared using `strcmp()`
| `contains_string(value)` | contains `value` when evaluated using `strstr()`
| `does_not_contain_string(value)` | does not contain `value` when evaluated
using `strstr()`
| `begins_with_string(value)` | starts with the string `value`
| `does_not_begin_with_string(value)` | does not start with the string `value`
| `ends_with_string(value)` | ends with the string `value`
| `does_not_end_with_string(value)` | does not end with the string `value`
||
| _Double floats_ |
| `is_equal_to_double(value)` | are equal to `value` within the number of
significant digits (which you can set with a call
to `significant_figures_for_assert_double_are(int figures)`)
| `is_not_equal_to_double(value)` | are not equal to `value` within the number of
significant digits
| `is_less_than_double(value)` | `< value` withing the number of significant digits
| `is_greater_than_double(value)` | `> value` within the number of significant digits
|=========================================================
The boolean assertion macros accept an `int` value. The equality
assertions accept anything that can be cast to `intptr_t` and simply
perform an `==` operation. The string comparisons are slightly
different in that they use the `` library function
`strcmp()`. If you use `is_equal_to()` with `char *` pointers then
it is the value of the pointers themselves that has to be the same,
i.e. the pointers have to point at the same string for the test to
pass.
The constraints above should be used as the second argument to one of the
assertion functions:
|=========================================================
|*Assertion* |*Description*
| `assert_that(expected, constraint)` | Passes if `expected` fullfulls `constraint`,
to be used for all assertions except `double`
type values
| `assert_that_double(expected, constraint)` | Passes if `expected` fullfulls `constraint`,
only to be used for assertions on `double`
type values
|=========================================================
WARNING: You cannot use C/C++ string literal concatenation (like
`"don't" "use" "string" "concatenation"`) in the parameters to the
constraints. If you do, you will get weird error messages about missing
arguments to the constraint macros. This is caused by the macros using
argument strings to produce nice failure messages.
=== Asserting C++ Exceptions
When you use *CGreen* with C++ there is one extra assertion available:
|=========================================================
|*Assertion* |*Description*
| `assert_throws(exception, expression)` | Passes if evaluating `expression` throws `exception`
|=========================================================
=== BDD Style vs. TDD Style
So far we have encouraged the modern BDD style. It has merits that we
really want you to benefit from. But you might come across *Cgreen*
test in another style, more like the standard TDD style, which is
more inline with previous thinking and might be more similar to other
frameworks.
The only difference, in principle, is the use of the SUT or
'context'. In the BDD style you have it, in the TDD style you don't.
[source,c]
.BDD style:
-----------------------------
include::tutorial_src/strlen_tests2.c[lines=4..16]
-----------------------------
<1> The `Describe` macro must name the SUT
<2> The `BeforeEach` function...
<3> ... and the `AfterEach` functions must exist and name the SUT
<4> The test need to name the SUT
<5> Adding to the test suite
CAUTION: You can only have tests for a single SUT in the same source file.
If you use the older pure-TDD style you skip the `Describe` macro, the
`BeforeEach` and `AfterEach` functions. You don't need a SUT in the
`Ensure()` macro or when you add the test to the suite.
[source,c]
.TDD style:
-----------------------------
include::tutorial_src/strlen_tests3.c[lines=3..12]
-----------------------------
<1> No `Describe`, `BeforeEach()` or `AfterEach()`
<2> No SUT/context in the `Ensure()` macro
<3> No SUT/context in `add_test()` and you should use this function instead
of `..with_context()`.
TIP: You might think of the TDD style as the BDD style with a default
SUT or context.
=== Legacy Style Assertions
Cgreen have been around for a while, developed and matured. There is
an older style of assertions that was the initial version, a style
that we now call the 'legacy style', because it was more aligned with
the original, now older, unit test frameworks. If you are not interested
in historical artifacts, I recommend that you skip this section.
But for completeness of documentation, here are the legacy style
assertion macros:
|=========================================================
|*Assertion* |*Description*
| `assert_true(boolean)` | Passes if boolean evaluates true
| `assert_false(boolean)` | Fails if boolean evaluates true
| `assert_equal(first, second)` | Passes if 'first == second'
| `assert_not_equal(first, second)` | Passes if 'first != second'
| `assert_string_equal(char *, char *)` | Uses 'strcmp()' and passes if
the strings are equal
| `assert_string_not_equal(char *, char *)` | Uses 'strcmp()' and fails
if the strings are equal
|=========================================================
Each assertion has a default message comparing the two values. If you
want to substitute your own failure messages, then you must use the
`*_with_message()` counterparts...
|=========================================================
|*Assertion*
| `assert_true_with_message(boolean, message, ...)`
| `assert_false_with_message(boolean, message, ...)`
| `assert_equal_with_message(tried, expected, message, ...)`
| `assert_not_equal_with_message(tried, unexpected, message, ...)`
| `assert_string_equal_with_message(char *, char *, message, ...)`
| `assert_string_not_equal_with_message(char *, char *, message, ...)`
|=========================================================
All these assertions have an additional `char *` message parameter,
which is the message you wished to display on failure. If this is set
to `NULL`, then the default message is shown instead. The most useful
assertion from this group is `assert_true_with_message()` as you can
use that to create your own assertion functions with your own
messages.
Actually the assertion macros have variable argument lists. The
failure message acts like the template in `printf()`. We could change
the test above to be...
[source,c]
-----------------------------
include::tutorial_src/strlen_tests4.c[lines=4..8]
-----------------------------
This should produce a slightly more user friendly message when things
go wrong. But, actually, Cgreens default messages are so good that you
are encouraged to skip the legacy style and go for the more modern
constraints style assertions. Particularly in conjuction with the BDD
style test notation.
IMPORTANT: We strongly recommend the use of BDD Style notation with
constraints based assertions.
=== A Runner
The tests are only run by running a test suite in some form. (But see
also <>.) We can create and run one especially for this test like
so...
[source,c]
-----------------------------
include::tutorial_src/strlen_tests5.c[lines=12..16]
-----------------------------
In case you have spotted that the reference to
`returns_five_for_hello` should have an ampersand in front of it,
`add_test_with_context()` is actually a macro. The `&` is added
automatically. Further more, the `Ensure()`-macro actually mangles the
tests name, so it is not actually a function name. (This might also
make them a bit difficult to find in the debugger....)
To run the test suite, we call `run_test_suite()` on it. So we can
just write...
[source,c]
-----------------------------
include::tutorial_src/strlen_tests5.c[lines=19]
-----------------------------
The results of assertions are ultimately delivered as passes and
failures to a collection of callbacks defined in a `TestReporter`
structure. There is a predefined `TestReporter` in *Cgreen* called the
`TextReporter` that delivers messages in plain text like we have
already seen.
The return value of `run_test_suite()` is a standard C library/Unix
exit code that can be returned directly by the `main()` function.
The complete test code now looks like...
[source,c]
-----------------------------
include::tutorial_src/strlen_tests5.c[]
-----------------------------
Compiling and running gives...
-----------------------------
$ gcc -c strlen_test.c
$ gcc strlen_test.o -lcgreen -o strlen_test
$ ./strlen_test
include::tutorial_src/strlen2.out[]
-----------------------------
We can see that the outer test suite is called `our_tests` since it
was in `our_tests()` we created the test suite. There are no messages
shown unless there are failures. So, let's break our test to see it...
[source,c]
-----------------------------
include::tutorial_src/strlen_tests6.c[lines=8..10]
-----------------------------
...we'll get the helpful message...
-----------------------------
include::tutorial_src/strlen6.out[]
-----------------------------
*Cgreen* starts every message with the location of the test failure so
that the usual error message identifying tools (like Emacs's
`next-error`) will work out of the box.
Once we have a basic test scaffold up, it's pretty easy to add more
tests. Adding a test of `strlen()` with an empty string for example...
[source,c]
-----------------------------
...
include::tutorial_src/strlen_tests7.c[lines=12..21]
...
-----------------------------
And so on.
=== BeforeEach and AfterEach
It's common for test suites to have a lot of duplicate code,
especially when setting up similar tests. Take this database code for
example...
[source,c]
------------------------------
include::tutorial_src/schema_tests1.c[]
------------------------------
We have already factored out the duplicate code into its own functions
`create_schema()` and `drop_schema()`, so things are not so bad. At
least not yet. But what happens when we get dozens of tests? For a
test subject as complicated as a database
http://www.martinfowler.com/eaaCatalog/activeRecord.html[ActiveRecord],
having dozens of tests is very likely.
We can get *Cgreen* to do some of the work for us by calling these
methods before and after each test in the test suite.
Here is the new version...
[source,c]
---------------------------
...
include::tutorial_src/schema_tests2.c[lines=6]
...
include::tutorial_src/schema_tests2.c[lines=11..13]
...
include::tutorial_src/schema_tests2.c[lines=18..41]
...
---------------------------
With this new arrangement *Cgreen* runs the `create_schema()` function
before each test, and the `drop_schema()` function after each
test. This saves some repetitive typing and reduces the chance of
accidents. It also makes the tests more focused.
The reason we try so hard to strip everything out of the test
functions is the fact that the test suite acts as documentation. In
our `person.h` example we can easily see that `Person` has some kind
of name property, and that this value must be unique. For the tests to
act like a readable specification we have to remove as much mechanical
clutter as we can.
In this particular case there are more lines that we could move from
the tests to `BeforeEach()`:
[source,c]
---------------------------
include::tutorial_src/schema_tests2.c[lines=25..26]
---------------------------
Of course that would require an extra variable, and it might make the
tests less clear. And as we add more tests, it might turn out to not
be common to all tests. This is a typical judgement call that you
often get to make with `BeforeEach()` and `AfterEach()`.
NOTE: If you use the pure-TDD notation, not having the test subject
named by the `Describe` macro, you can't have the `BeforeEach()` and
`AfterEach()` either. In this case you can still run a function before
and after every test. Just nominate any `void(void)` function by
calling the function `set_setup()` and/or `set_teardown()` with the
suite and the function that you want to run before/after each test,
e.g. in the example above `set_setup(suite, create_schema);` and
`set_teardown(suite, drop_schema);`.
A couple of details. There is only one `BeforeEach()` and one
`AfterEach()` allowed in each `TestSuite`. Also, the `AfterEach()`
function may not be run if the test crashes, causing some test
interference. This brings us nicely onto the next section...
=== Each Test in its Own Process
Consider this test method...
[source,c]
-----------------------------
include::tutorial_src/crash_tests1.c[lines=8..11]
-----------------------------
Crashes are not something you would normally want to have in a test
run. Not least because it will stop you receiving the very test output
you need to tackle the problem.
To prevent segmentation faults and other problems bringing down the
test suites, *Cgreen* runs every test in its own process.
Just before calling the `BeforeEach()` (or `setup`) function, *Cgreen*
`fork()`:s. The main process waits for the test to complete normally
or die. This includes calling the `AfterEach()`(or `teardown`)
function, if any. If the test process dies, an exception is reported
and the main test process carries on with the next test.
For example...
[source,c]
-----------------------------
include::tutorial_src/crash_tests1.c[]
-----------------------------
When built and run, this gives...
-----------------------------
include::tutorial_src/crash1.out[]
-----------------------------
The normal thing to do in this situation is to fire up the
debugger. Unfortunately, the constant `fork()`:ing of *Cgreen* can be
one extra complication too many when debugging. It's enough of a
problem to find the bug.
To get around this, and also to allow the running of one test at a
time, *Cgreen* has the `run_single_test()` function. The signatures of
the two run methods are...
- `int run_test_suite(TestSuite *suite, TestReporter *reporter);`
- `int run_single_test(TestSuite *suite, char *test, TestReporter *reporter);`
The extra parameter of `run_single_test()`, the `test` string, is the
name of the test to select. This could be any test, even in nested
test suites (see below). Here is how we would use it to debug our
crashing test...
[source,c]
-----------------------------
include::tutorial_src/crash_tests2.c[lines=13..17]
-----------------------------
When run in this way, *Cgreen* will not `fork()`. But see the section
on <>.
The following is a typical session:
-----------------------------------
$ gdb crash2
...
(gdb) break main
(gdb) run
...
(gdb) break run
(gdb) continue
...
Running "main" (1 tests)...
Breakpoint 2, run_the_test_code (suite=suite@entry=0x2003abb0,
spec=spec@entry=0x402020 ,
reporter=reporter@entry=0x2003abe0) at /cygdrive/c/Users/Thomas/Utveckling/Cgreen/cgreen/src/runner.c:270
270 run(spec);
(gdb) step
run (spec=0x402020 )
at /cygdrive/c/Users/Thomas/Utveckling/Cgreen/cgreen/src/runner.c:217
217 spec->run();
(gdb) step
CrashExample__seg_faults_for_null_dereference () at crash_test2.c:9
9 int *p = NULL;
(gdb) step
10 (*p)++;
(gdb) step
Program received signal SIGSEGV, Segmentation fault.
0x004011ea in CrashExample__seg_faults_for_null_dereference () at crash_test2.c:10
10 (*p)++;
-----------------------------------
Which shows exactly where the problem is.
This deals with the case where your code throws an exception like
segmentation fault, but what about a process that fails to complete by
getting stuck in a loop?
Well, *Cgreen* will wait forever too. But, using the C signal
handlers, we can place a time limit on the process by sending it an
interrupt. To save us writing this ourselves, *Cgreen* includes the
`die_in()` function to help us out.
Here is an example of time limiting a test...
[source,c]
---------------------------
...
include::tutorial_src/crash_tests3.c[lines=8]
...
include::tutorial_src/crash_tests3.c[lines=11..23]
---------------------------
When executed, the code will slow for a second, and then finish with...
---------------------------
include::tutorial_src/crash3.out[]
---------------------------
Note that you see the test results as they come in. *Cgreen* streams the
results as they happen, making it easier to figure out where the test
suite has problems.
Of course, if you want to set a general time limit on all your tests,
then you can add a `die_in()` to a `BeforeEach()` (or `setup()`)
function. *Cgreen* will then apply the limit to each of the tests in
that context, of course.
Another possibility is the use of an environment variable named
`CGREEN_TIMEOUT_PER_TEST` which, if set to a number will apply that
timeout to every test run. This will apply to all tests in the same
run.
[[debugging]]
=== Debugging *Cgreen* tests
*Cgreen* protects itself from being torn down by an exception in a
test by `fork()`-ing each test into a separate process. A catastrophic
error will then only affect the child process for that specific test
and *Cgreen* can catch it, rather than crashing too. It can then
report the exception and continue with the next test.
==== No fork, please
If you want to debug any of your tests the constant `fork()`-ing
might make that difficult or impossible. There are also other
circumstances that might require that you don't use `fork()`.
There are two ways to make *Cgreen* refrain from `fork()`-ing.
*Cgreen* does not `fork()` when only a single test is run by name with
the function `run_single_test()`. To debug you can then obviously set
a breakpoint at that test (but note that its actual name probably have
been mangled). *Cgreen* does some book-keeping before actually getting
to the test, so a function easier to find might be the one simply
called `run()`.
The second way is to define the environment variable
`CGREEN_NO_FORK`. If *Cgreen* can get that variable from the
environment using `getenv()` it will run the test(s) in the same
process. In this case the non-forking applies to *all* tests run, so
all test will run in the same process, namely *Cgreen*s main process.
WARNING: This might bring your whole test suite down if a single test
causes an exception. So it is not a recommended setting for normal
use.
==== Debugging with `cgreen-runner`
If you use the convenient auto-discovery feature of *Cgreen* (see
<>) by running dynamic loadable libraries through
`cgreen-runner`, it might be tricky to figure out to where to put
breaks and to get them to "take".
`cgreen-runner` obviously loads the library (or libraries) with your
tests dynamically so the tests are not available before executing the
code that loads them.
TIP: The function `run()` is a good place to place a breakpoint.
==== `cgreen-debug`
For some platforms a utility script, `cgreen-debug`, is installed when
you install *Cgreen*. It makes it very convenient to start a debugging
session for a particular test.
Find out the logical name of the test, which is composed of the
Context and the Testname, in the form :. Then just
invoke `cgreen-debug`
----
$ cgreen-debug :
----
The script will try to find a debugger, invoke it on the
`cgreen-runner` and break on that test.
NOTE: Currently it only supports `gdb` and will prefer `cgdb` if
that's available.
=== Building Composite Test Suites
The `TestSuite` is a composite structure. This means test suites can
be added to test suites, building a tree structure that will be
executed in order.
Let's combine the `strlen()` tests with the `Person` tests above.
Firstly we need to remove the `main()` functions. E.g...
[source,c]
----------------------------
include::tutorial_src/suite_strlen_tests.c[lines=8]
...
include::tutorial_src/suite_strlen_tests.c[lines=10..12]
...
include::tutorial_src/suite_strlen_tests.c[lines=14..-1]
----------------------------
Then we can write a small runner with a new `main()` function...
[source,c]
-----------------------
include::tutorial_src/suite1.c[]
-----------------------
It's usually easier to place the `TestSuite` prototypes directly in
the runner source, rather than have lot's of header files. This is
the same reasoning that let us drop the prototypes for the test
functions in the actual test scripts. We can get away with this,
because the tests are more about documentation than encapsulation.
As we saw above, we can run a single test using the
`run_single_test()` function, and we'd like to be able to do that from
the command line. So we added a simple `if` block to take the test
name as an optional argument. The entire test suite will be searched
for the named test. This trick also saves us a recompile when we
debug.
When you use the BDD notation you can only have a single test subject
(which is actually equivalent of a suite) in a single file because you
can only have one `Describe()` macro in each file. But using this
strategy you can create composite suites that takes all your tests and
run them in one go.
CAUTION: Rewrite pending. The next couple of sections does not reflect
the current best thinking. They are remnants of the TDD
notation. Using BDD notation you would create separate contexts, each
in its own file, with separate names, for each of the fixture cases.
NOTE: If you use the TDD (non-BDD) notation you can build several test
suites in the same file, even nesting them. We can even add mixtures
of test functions and test suites to the same parent test suite.
Loops will give trouble, however.
NOTE: If we do place several suites in the same file, then all the suites
will be named the same in the breadcrumb trail in the test message.
They will all be named after the function the create call sits in. If
you want to get around this, or you just like to name your test
suites, you can use `create_named_test_suite()` instead of
`create_test_suite()`. This takes a single string parameter. In fact
`create_test_suite()` is just a macro that inserts the `__func__`
constant into `create_named_test_suite()`.
What happens to `setup` and `teardown` functions in a `TestSuite` that
contains other `TestSuite`:s?
Well firstly, *Cgreen* does not `fork()` when running a suite. It
leaves it up to the child suite to `fork()` the individual tests.
This means that a `setup` and `teardown` will run in the main
process. They will be run once for each child suite.
We can use this to speed up our `Person` tests above. Remember we
were creating a new connection and closing it again in the fixtures.
This means opening and closing a lot of connections. At the slight
risk of some test interference, we could reuse the connection accross
tests...
[source,c]
-----------------------
...
static MYSQL *connection;
static void create_schema() {
mysql_query(connection, "create table people (name, varchar(255) unique)");
}
static void drop_schema() {
mysql_query(connection, "drop table people");
}
Ensure(can_add_person_to_database) { ... }
Ensure(cannot_add_duplicate_person) { ... }
void open_connection() {
connection = mysql_init(NULL);
mysql_real_connect(connection, "localhost", "me", "secret", "test", 0, NULL, 0);
}
void close_connection() {
mysql_close(connection);
}
TestSuite *person_tests() {
TestSuite *suite = create_test_suite();
set_setup(suite, create_schema);
set_teardown(suite, drop_schema);
add_test(suite, can_add_person_to_database);
add_test(suite, cannot_add_duplicate_person);
TestSuite *fixture = create_named_test_suite("Mysql fixture");
add_suite(fixture, suite);
set_setup(fixture, open_connection);
set_teardown(fixture, close_connection);
return fixture;
}
-----------------------
The trick here is creating a test suite as a wrapper whose sole
purpose is to wrap the main test suite in the fixture. This is our
'fixture' pointer. This code is a little confusing, because we have
two sets of fixtures in the same test script.
We have the MySQL connection fixture. This will run
`open_connection()` and `close_connection()` just once at the
beginning and end of the person tests. This is because the `suite`
pointer is the only member of `fixture`.
We also have the schema fixture, the `create_schema()` and
`drop_schema()`, which is run before and after every test. Those are
still attached to the inner `suite`.
In the real world we would probably place the connection
fixture in its own file...
[source,c]
-----------------------
static MYSQL *connection;
MYSQL *get_connection() {
return connection;
}
static void open_connection() {
connection = mysql_init(NULL);
mysql_real_connect(connection, "localhost", "me", "secret", "test", 0, NULL, 0);
}
static void close_connection() {
mysql_close(connection);
}
TestSuite *connection_fixture(TestSuite *suite) {
TestSuite *fixture = create_named_test_suite("Mysql fixture");
add_suite(fixture, suite);
set_setup(fixture, open_connection);
set_teardown(fixture, close_connection);
return fixture;
}
-----------------------
This allows the reuse of common fixtures across projects.
== Mocking functions with Cgreen
When testing you want certainty above all else. Random events destroy
confidence in your test suite and force needless extra runs "to be
sure". A good test places the system under test into a tightly
controlled environment. A test chamber if you like. This makes the
tests fast, repeatable and reliable.
To create a test chamber for testing code, we have to control any
outgoing calls from the code under test. We won't believe our test
failure if our code is making calls to the internet for example. The
internet can fail all by itself. Not only do we not have total
control, but it also means we have to get dependent components working
before we can test the higher level code. This makes it difficult to
code top down.
The solution to this dilemma is to write stub code for the components
whilst the higher level code is written. This pollutes the code base
with temporary code, and the test isolation disappears when the system
is eventually fleshed out.
The ideal is to have minimal stubs written for each individual test.
*Cgreen* encourages this approach by making such tests easier to write.
=== The Problem with Streams
How would we test the following code...?
[source,c]
-----------------------
include::tutorial_src/read_paragraph1.c[lines=4..-1]
-----------------------
This is a fairly generic stream filter that turns the incoming
characters into C string paragraphs. Each call creates one paragraph,
returning a pointer to it or returning `NULL` if there is no
paragraph. The paragraph has memory allocated to it and the stream is
advanced ready for the next call. That's quite a bit of functionality,
and there are plenty of nasty boundary conditions. I really want this
code tested before I deploy it.
The problem is the stream dependency. We could use a real stream, but
that will cause all sorts of headaches. It makes the test of our
paragraph formatter dependent on a working stream. It means we have
to write the stream first, bottom up coding rather than top down. It
means we will have to simulate stream failures - not easy. It will
also mean setting up external resources. This is more work, will run
slower, and could lead to spurious test failures.
By contrast, we could write a simulation of the stream for each test,
called a "server stub".
For example, when the stream is empty nothing should happen. We
hopefully get `NULL` from `read_paragraph` when the stream is
exhausted. That is, it just returns a steady stream of `EOF`s.
[source,c]
-----------------------
include::tutorial_src/stream_tests0.c[lines=6..22]
-----------------------
Our simulation is easy here, because our fake stream returns only one
value. Things are harder when the function result changes from call
to call as a real stream would. Simulating this would mean messing
around with static variables and counters that are reset for each
test. And of course, we will be writing quite a few stubs. Often a
different one for each test. That's a lot of clutter.
*Cgreen* can handle this clutter for us by letting us write a single
programmable function for all our tests.
=== Record and Playback
We can redo our example by creating a `stream_stub()` function. We can
call it anything we want, and since I thought we wanted to have a
stubbed stream...
[source,c]
-----------------------
include::tutorial_src/stream_tests1.c[lines=6..8]
-----------------------
Hardly longer that our trivial server stub above, it is just a macro
to generate a return value, but we can reuse this in test after
test. Let's see how.
For our simple example above we just tell it to always return `EOF`...
[source,c]
-----------------------
include::tutorial_src/stream_tests1.c[lines=1..17]
-----------------------
<1> The `always_expect()` macro takes as arguments the function
name and defines the return value using the call to
`will_return()`. This is a declaration of an expectation of a call to
the stub, and we have told our `stream_stub()` to always return `EOF`
when called.
Let's see if our production code actually works...
-----------------------
include::tutorial_src/stream1.out[]
-----------------------
So far, so good. On to the next test.
If we want to test a one character line, we have to send the
terminating `EOF` or `"\n"` as well as the single character.
Otherwise our code will loop forever, giving an infinite line of that
character.
Here is how we can do this...
[source,c]
-----------------------
include::tutorial_src/stream_tests2.c[lines=19..25]
-----------------------
Unlike the `always_expect()` instruction, `expect()` sets up an
expectation of a single call and specifying `will_return()` sets the
single return value for just that call. It acts like a record and
playback model. Successive expectations map out the return sequence
that will be given back once the test proper starts.
We'll add this test to the suite and run it...
-----------------------
include::tutorial_src/stream2.out[]
-----------------------
Oops. Our code under test doesn't work. Already we need a fix...
[source,c]
-----------------------
include::tutorial_src/read_paragraph2.c[lines=4..19]
-----------------------
<1> After moving the indexing here...
<2> and here...
around a bit everything is fine:
-----------------------
include::tutorial_src/stream3.out[]
-----------------------
So, how do the *Cgreen* stubs work? Each `expect()` describes one
call to the stub and a call to `will_return()` is included it will
aggregate into a list of return values which are used and returned in
order as the expected calls arrive.
The `mock()` macro captures the parameter names and the `__func__`
property (the name of the stub function). *Cgreen* can then use these
to look up entries in the return list, and also to generate more
helpful messages.
We can now crank out our tests quite quickly...
[source,c]
-----------------------
include::tutorial_src/stream_tests3.c[lines=27..33]
-----------------------
I've been a bit naughty. As each test runs in its own process, I
haven't bothered to free the pointers to the paragraphs. I've just
let the operating system do it. Purists may want to add the extra
clean up code.
I've also used `always_expect()` for the last instruction. Without
this, if the stub is given an instruction it does not expect, it will
throw a test failure. This is overly restrictive, as our
`read_paragraph()` function could quite legitimately call the stream
after it had run off of the end. OK, that would be odd behaviour, but
that's not what we are testing here. If we were, it would be placed
in a test of its own. The `always_expect()` call tells *Cgreen* to
keep going after the first three letters, allowing extra calls.
As we build more and more tests, they start to look like a
specification of the wanted behaviour...
[source,c]
-----------------------
include::tutorial_src/stream_tests4.c[lines=35..41]
-----------------------
...and just for luck...
[source,c]
-----------------------
include::tutorial_src/stream_tests4.c[lines=43..46]
-----------------------
This time we must not use `always_return()`. We want to leave the
stream where it is, ready for the next call to `read_paragraph()`. If
we call the stream beyond the line ending, we want to fail.
Oops, that was a little too fast. Turns out we are failing anyway...
-----------------------
include::tutorial_src/stream5.out[]
-----------------------
Clearly we are passing through the line ending.
Another fix later...
[source,c]
-----------------------
include::tutorial_src/read_paragraph3.c[lines=4..20]
-----------------------
And we are passing again...
-----------------------
include::tutorial_src/stream6.out[]
-----------------------
There are no limits to the number of stubbed methods within a test,
only that two stubs cannot have the same name. The following will
cause problems...
[source,c]
-----------------------
include::tutorial_src/multiple_streams1.c[lines=10..-1]
-----------------------
You __could__ program the same stub to return values for the two
streams, but that would make a very brittle test. Since we'd be making
it heavily dependent on the exact internal behaviour that we are
trying to test, or test drive, it will break as soon as we change that
implementation. The test will also become very much harder to read and
understand. And we really don't want that.
So, it will be necessary to have two stubs to make this test behave,
but that's not a problem...
[source,c]
-----------------------
include::tutorial_src/multiple_streams2.c[lines=10..-1]
-----------------------
We now have a way of writing fast, clear tests with no external
dependencies. The information flow is still one way though, from stub
to the code under test. When our code calls complex procedures, we
won't want to pick apart the effects to infer what happened. That's
too much like detective work. And why should we? We just want to
know that we dispatched the correct information down the line.
Things get more interesting when we think of the traffic going the
other way, from code to stub. This gets us into the same territory as
mock objects.
=== Mocks with side effects
Sometimes returning simple values is not enough. The function that you
want to mock might have some side effect, like setting a global error
code, or aggregate some data.
Let's assume that the `reader` increments a counter every time it gets
called and we need to mimic that behaviour. There are many ways to do
this, but here is one using the side effect feature. It works by
calling a callback function that you provide, allowing you to
feed some data to it.
We create the "side effect function" which needs to take a single
argument which should be a pointer to the "side effect data". You will
have to cast that datapointer to the correct type.
[source, c]
-----------------------
include::tutorial_src/side_effect.c[lines=29..44]
-----------------------
=== Setting Expectations on Mock Functions
To swap the traffic flow, we'll look at an outgoing example instead.
Here is the prewritten production code...
[source,c]
-----------------------
include::tutorial_src/stream.c[lines=23..32]
-----------------------
This is the start of a formatter utility. Later filters will probably
break the paragaphs up into justified text, but right now that is all
abstracted behind the `void write(void *, char *)` interface. Our
current interests are: does it loop through the paragraphs, and does
it crash?
We could test correct paragraph formation by writing a stub that
collects the paragraphs into a `struct`. We could then pick apart
that `struct` and test each piece with assertions. This approach is
extremely clumsy in C. The language is just not suited to building
and tearing down complex edifices, never mind navigating them with
assertions. We would badly clutter our tests.
Instead we'll test the output as soon as possible, right in
the called function...
[source,c]
-----------------------
...
include::tutorial_src/formatter_tests0.c[lines=12..-1]
...
-----------------------
By placing the assertions into the mocked function, we keep the tests
minimal. The catch with this method is that we are back to writing
individual functions for each test. We have the same problem as we
had with hand coded stubs.
Again, *Cgreen* has a way to automate this. Here is the rewritten
test...
[source,c]
-----------------------
include::tutorial_src/formatter_tests1.c[lines=10..-1]
-----------------------
Where are the assertions?
Unlike our earlier stub, `reader()` can now check its parameters. In
object oriented circles, an object that checks its parameters as well
as simulating behaviour is called a mock object. By analogy
`reader()` is a mock function, or mock callback.
Using the `expect` macro, we have set up the expectation that
`writer()` will be called just once. That call must have the string
`"a"` for the `paragraph` parameter. If the actual value of that
parameter does not match, the mock function will issue a failure
straight to the test suite. This is what saves us writing a lot of
assertions.
When specifying behavior of mocks there are three parts. First, how
often the specified behaviour or expectation will be executed:
|=======================================================================
|*Macro* |*Description*
|`expect(function, ...)` |Expected once, in order
|`always_expect(function, ...)`|Expect this behavior from here onwards
|`never_expect(function)` |From this point this mock function must never be called
|=======================================================================
You can specify constraints and behaviours for each expectation
(except for `never_expect()` naturally). A constraint places
restrictions on the parameters (and will tell you if the expected
restriction was not met), and a behaviour specifies what the mock
should do if the parameter constraints are met.
A parameter constraint is defined using the `when(parameter,
constraint)` macro. It takes two parameters:
|=================================================
|*Parameter* |*Description*
|`parameter` |The name of the parameter to the mock function
|`constraint`|A constraint placed on that parameter
|=================================================
There is a multitude of constraints available (actually, exactly the
same as for the assertions we saw earlier):
|==========================================================================
|*Constraint* |*Type*
|`is_equal_to(value)` | Integers
|`is_not_equal_to(value)` | Integers
|`is_greater_than(value)` | Integers
|`is_less_than(value)` | Integers
| |
|`is_equal_to_contents_of(pointer, size_of_contents)` |Bytes/Structures
|`is_not_equal_to_contents_of(pointer, size_of_contents)` |Bytes/Structures
||
|`is_equal_to_string(value)` |String
|`is_not_equal_to_string(value)` |String
|`contains_string(value)` |String
|`does_not_contain_string(value)` |String
|`begins_with_string(value)` |String
||
|`is_equal_to_double(value)` |Double
|`is_not_equal_to_double(value)` |Double
|`is_less_than_double(value)` |Double
|`is_greater_than_double(value)` |Double
|==========================================================================
For the double valued constraints you can set the number of
significant digits to consider a match with a call to
`significant_figures_for_assert_double_are(int figures)`.
The <> has a more detailed
discussion of the algorithm used for comparing floating point numbers.
Then there are a couple of ways to return results from the mock:
|===========================================================================================
|*Macro* |*Description*
|`will_return(value)` |Return the value from the mock function (which needs to be declared returning that type)
|`will_return_by_value(value, size)` |Ditto for generic by value variables.
|`will_return_double(value)` |Ditto for double values (required because of C's type coercion rules which would otherwise convert a double into an int)
|`will_set_contents_of_parameter(parameter_name, pointer_to_value, size)`|Writes 'size' bytes from the pointed out value into the referenced parameter
|`with_side_effect(pointer_to_function, pointer_to_data)` |Executes the side effect function and passes data to it
|===========================================================================================
Note: The `pointer_to_data` passed to `with_side_effect` need to fit inside a `intptr_t`
You can combine these in various ways:
[source,c]
-----------------------
expect(mocked_file_writer,
when(data, is_equal_to(42)),
will_return(EOF));
expect(mocked_file_reader,
when(file, is_equal_to_contents_of(&FD, sizeof(FD))),
when(input, is_equal_to_string("Hello world!"),
with_side_effect(&update_counter, &counter),
will_set_contents_of_parameter(status, FD_CLOSED, sizeof(bool))));
-----------------------
If multiple `when()` are specified they all need to be fullfilled. You
can of course only have one for each of the parameters of your mock
function.
You can also have multiple `will_set_contents_of_parameter()` in an
expectation, one for each reference parameter, but naturally only one
`will_return()`.
To ensure that a specific call happens `n` times the macro `times(number_times_called)` can be passed
as a constraint to a specific call:
[source,c]
-----------------------
expect(mocked_file_writer,
when(data, is_equal_to(42)),
times(1));
-----------------------
This feature only works for `expect`.
The expections still need to respect the order of calling, so if we call the function
`mocker_file_writer` with the following pattern:
[source,c]
-----------------------
mocked_file_writer(42);
mocked_file_writer(42);
mocked_file_writer(43);
mocked_file_writer(42);
-----------------------
The expectation code should look like the following
[source,c]
-----------------------
expect(mocked_file_writer,
when(data, is_equal_to(42)),
times(2));
expect(mocked_file_writer,
when(data, is_equal_to(43)),
times(1));
expect(mocked_file_writer,
when(data, is_equal_to(42)),
times(1));
-----------------------
If the function we are mocking returns structs by value our mock
function need to do that too. So we need use another return function,
`will_return_by_value`. Here is some example code using an imaginary
struct typdef'ed as `Box` and a corresponding function,
`retrieve_box()`, which we want to mock:
[source,c]
-----------------------
expect(retrieve_box,
will_return_by_value(box, sizeof(Box));
-----------------------
And the mock function will then look like this:
[source,c]
-----------------------
Box retrieve_box() {
return *(Box *)mock();
}
-----------------------
=== Running tests with mocked functions
It's about time we actually ran our test...
-----------------------
include::tutorial_src/formatter1.out[]
-----------------------
Confident that a single character works, we can further specify the
behaviour. Firstly an input sequence...
[source,c]
-----------------------
include::tutorial_src/formatter_tests2.c[lines=25..34]
-----------------------
A more intelligent programmer than me would place all these calls in a
loop.
-------------------------
include::tutorial_src/formatter2.out[]
-------------------------
Next, checking an output sequence...
[source,c]
-----------------------
include::tutorial_src/formatter_tests3.c[lines=36..-1]
-----------------------
Again we can se that the `expect()` calls follow a record and playback
model. Each one tests a successive call. This sequence confirms that
we get `"a"`, `"b"` and `"c"` in order.
-----------------------
include::tutorial_src/formatter3.out[]
-----------------------
So, why the 5 passes? Each `expect()` with a constrait is actually
an assert. It asserts that the call specified is actually made with
the parameters given and in the specified order. In this case all the
expected calls were made.
Then we'll make sure the correct stream pointers are passed to the
correct functions. This is a more realistic parameter check...
[source,c]
-----------------------
include::tutorial_src/formatter_tests4.c[lines=49..-1]
-----------------------
-----------------------
include::tutorial_src/formatter4.out[]
-----------------------
And finally we'll specify that the writer is not called if
there is no paragraph.
[source,c]
-----------------------
include::tutorial_src/formatter_tests5.c[lines=56..-1]
-----------------------
This last test is our undoing...
-----------------------
include::tutorial_src/formatter5.out[]
-----------------------
Obviously blank lines are still being dispatched to the `writer()`.
Once this is pointed out, the fix is obvious...
[source,c]
-----------------------
include::tutorial_src/stream2.c[lines=23..-1]
-----------------------
Tests with `never_expect()` can be very effective at uncovering subtle
bugs.
-----------------------
include::tutorial_src/formatter6.out[]
-----------------------
All done.
=== Mocks Are...
Using mocks is a very handy way to isolate a unit by catching and
controlling calls to external units. Depending on your style of coding
two schools of thinking have emerged. And of course *Cgreen* supports
both!
==== Strict or Loose Mocks
The two schools are thinking a bit differently about what mock
expectations means. Does it mean that all external calls must be
declared and expected? What happens if a call was made to a mock that
wasn't expected? And vice versa, if an expected call was not made?
Actually, the thinking is not only a school of thought, you might want
to switch from one to the other depending on the test. So *Cgreen*
allows for that too.
By default *Cgreen* mocks are 'strict', which means that a call to
an non-expected mock will be considered a failure. So will an expected
call that was not fullfilled. You might consider this a way to define
a unit through all its exact behaviours towards its neighbours.
On the other hand, 'loose' mocks are looser. They allow both
unfulfilled expectations and try to handle unexpected calls in a
reasonable way.
You can use both with in the same suite of tests using the call
`cgreen_mocks_are(strict_mocks);` and `cgreen_mocks_are(loose_mocks);`
respectively. Typically you would place that call at the beginning of
the test, or in a setup or `BeforeEach()` if it applies to all tests
in a suite.
==== Learning Mocks
Working with legacy code and trying to apply TDD, BDD, or even simply
adding some unit tests, is not easy. You're working with unknown code
that does unknown things with unknown counterparts.
So the first step would be to isolate the unit. We won't go into
details on how to do that here, but basically you would replace the
interface to other units with mocks. This is a somewhat tedious manual
labor, but will result in an isolated unit where you can start
applying your unit tests.
Once you have your unit isolated in a harness of mocks, we need to
figure out which calls it does to other units, now replaced by mocks,
in the specific case we are trying to test.
This might be complicated, so *Cgreen* makes that a bit simpler. There
is a third 'mode' of the *Cgreen* mocks, the __learning mocks__.
If you temporarily add the call `cgreen_mocks_are(learning_mocks);` at
the beginning of your unit test, the mocks will record all calls and
present a list of those calls in order, including the actual parameter
values, on the standard output.
So let's look at the following example from the *Cgreen* unit
tests. It's a bit contorted since the test actually call the mocked
functions directly, but I believe it will serve as an example.
[source,c]
-----
include::tutorial_src/learning_mocks.c[lines=8..-1]
-----
We can see the call to `cgreen_mocks_are()` starting the test and
setting the mocks into learning mode.
If we run this, just as we usually run tests, the following will show
up in our terminal:
// This needs to be copied and pasted from the output of make in tutorial_src
// At least, I couldn't make 'make' capture it into the output file
// It ought to be:
// include::tutorial_src/learning_mocks.out[]
----
Running "learning_mocks" (1 tests)...
LearningMocks -> emit_pastable_code : Learned mocks are
expect(string_out, when(p1, is_equal_to(1)));
expect(string_out, when(p1, is_equal_to(2)));
expect(integer_out);
expect(integer_out);
expect(string_out, when(p1, is_equal_to(3)));
expect(integer_out);
Completed "LearningMocks": 0 passes, 0 failures, 0 exceptions.
Completed "learning_mocks": 0 passes, 0 failures, 0 exceptions.
----
If this was for real we could just copy this and paste it in place of
the call to `cgreen_mocks_are()` and we have all the expectations
done.
NOTE: Before you can do this you need to implement the mock functions, of
course. I.e. write functions that replaces the real
functions and instead calls `mock()`.
TIP: You can try the `cgreen-mocker` for this, as described in
<>.
== Special Cases
=== Working with `doubles`
We are not talking about
http://www.hostettler.net/blog/2014/05/18/fakes-stubs-dummy-mocks-doubles-and-all-that/[test doubles]
here, but about values of C/C++ ``double`` type (a.k.a double float.)
*Cgreen* is designed to make it easy and natural to write assertions
and expectations. Many functions can be used for multiple data types,
e.g. `is_equal_to()` applies to all integer type values, actually
including pointers.
But the C language has its quirks. One of them is the fact that it is
impossible to inspect the datatypes of values during run-time. This
has e.g. forced the introduction of `is_equal_to_string()` to enable
string comparisons.
==== Assertions and Constraints
When it comes to double typed values this has spilled over even further. For
double typed values we have
|==========================================================================
| *Constraint*
| `is_equal_to_double(value)`
| `is_not_equal_to_double(value)`
| `is_less_than_double(value)`
| `is_greater_than_double(value)`
|==========================================================================
But there is also the special assert that you must use when asserting doubles
|=========================================================
| *Assertion*
| `assert_that_double(expected, constraint)`
|=========================================================
and the utility function
|====================
| *Utility*
| `significant_figures_for_assert_double_are(int figures)`
|====================
And of course they are designed to go together. So, if you want to assert
an expression yeilding a `double` typed value, you need to combine them:
[source,c]
-----------------------------
include::tutorial_src/double_tests1.c[lines=11..14]
-----------------------------
NOTE: You have to use `assert_that_double()` and `is_equal_to_double()`
together.
and you would get
-----------------------------
include::tutorial_src/double1.out[lines=2..5]
-----------------------------
[[double_mocks]]
==== Mocks
The general mechanism *Cgreen* uses to transport values to and from
mock functions is based on the simple idea that most types fit into a
"large" integer and can be type converted to and from whatever type
you need.
Since a `double float` will not fit into the same memory space as an
integer *Cgreen* handles that by encapsulating ("boxing") the `double`
into an area which is represented by the pointer to it. And that
pointer can fit into the integer type value (`intptr_t`) that *Cgreen*
uses to transport values into and out of `mock()`. To get the value
back you "unbox" it.
There are two possible uses of `double` that you need to be
aware of
1. When a parameter to the mocked function is of `double` type and
needs to be matched in an constraint in an `expect` call.
2. When the mock function itself should return a `double` type value.
In the test you should use the special `double` type constraints and
the `will_return_double()` convenience function. In the mock function
you will have to take care to box and unbox as required.
|=================================================================
|*Boxing and unboxing in mock functions* | *Description*
| `box_double(double value)` | Wrap the value in an allocated
memory area and return a pointer
to it
| `unbox_double(BoxedDouble *box)` | Unwrap the value by freeing the
area and returning the value
|=================================================================
Here's an example of that:
[source,c]
-----------------------------
include::tutorial_src/double_tests1.c[lines=16..26]
-----------------------------
<1> We can see that the parameter `d` to the mock function, since it is a
`double`, it will have to be used as `box_double(d)` in the call to
`mock()`.
<2> The corresponding `expect()` uses a double constraint.
<3> The mock function in this small example also returns a `double`. The
`expect()` uses `will_return_double()` so the mock function needs to
unbox the return value from `mock()` to be able to return the `double`
type value.
NOTE: Strange errors may occur if you box and/or unbox or combine
`double` constraints incorrectly.
[[floating_point_comparison_algorithm]]
==== Details of floating point comparison algorithm
The number of significant digits set with
`significant_figures_for_assert_double_are()` specifies a _relative_
tolerance. Cgreen considers two double precision numbers +x+ and +y+
equal if their difference normalized by the larger of the two is
smaller than +10^(1 - significant_figures)^+. Mathematically, we check
that +|x - y| < max(|x|, |y|) * 10^(1 - significant_figures)^+.
Well documented subtleties arise when comparing floating point numbers
close to zero using this algorithm. The article
https://randomascii.wordpress.com/2012/02/25/comparing-floating-point-numbers-2012-edition/[Comparing
Floating Point Numbers, 2012 Edition] by Bruce Dawson has an excellent
discussion of the issue. The essence of the problem can be appreciated
if we consider the special case where +y == 0+. In that case, our
condition reduces to +|x| < |x| * 10^(1 - significant_figures)^+.
After cancelling +|x|+ this simplifies to +1 < 10^(1 -
significant_figures)^+. But this is only true if +significant_figures
< 1+. In words this can be summarized by saying that, in a relative
sense, _all_ numbers are very different from zero. To circumvent this
difficulty we recommend to use a constraint of the following form when
comparing numbers close to zero:
[source,c]
-----------------------
assert_that(fabs(x - y) < abs_tolerance);
-----------------------
=== Using Cgreen with C{pp}
The examples in this guide uses the C langauge to shows how to use
*CGreen*. You can also use *CGreen* with C++.
NOTE: The following needs expansion and more details as the support
for C++ is extended.
All you have to do is
* Use the `cgreen` namespace by adding `using namespace cgreen;`
at the beginning of the file with your tests
There is also one extra feature when you use C++, the `assert_throws`
function.
NOTE: If you use the runner, as described in <>, and thus link
your tests into a shared library, don't forget to link it with the
same C++ library that was used to create the `cgreen-runner`.
== Context, System Under Test & Suites
As mentioned earlier, *Cgreen* promotes the behaviour driven
style of test driving code. The thinking behind BDD is that we don't
really want to test anything, if we just could specify the behaviour
of our code and ensure that it actually behaves this way we would be
fine.
This might seem like an age old dream, but when you think about it,
there is actually very little difference in the mechanics from
vanillla TDD. First we write how we want it, then implement it. But
the small change in wording, from `test´ to `behaviour´, from `test
that´ to `ensure that´, makes a huge difference in thinking, and also
very often in quality of the resulting code.
=== The SUT - System Under Test
Since BDD talks about behaviour, there has to be something that we can
talk about as having that wanted behaviour. This is usually called the
SUT, the System Under Test. The "system" might be whatever we are testing,
such as a C module ("MUT"), class ("CUT"), object ("OUT"), function ("FUT")
or method ("MUT"). We will stick with SUT in this document. To use *Cgreen*
in BDD-ish mode you must define a name for it.
[source, c]
-----------------------
#include
Describe(SUT);
-----------------------
*Cgreen* supports C++ and there you naturally have the objects and
also the Class Under Test. But in plain C you will have to think about
what is actually the "class" under test. E.g. in `sort_test.c` you might
see
[source, c]
---------------------
#include
Describe(Sorter);
Ensure(Sorter, can_sort_an_empty_list) {
assert_that(sorter(NULL), is_null);
}
---------------------
In this example you can clearly see what difference the BDD-ish style
makes when it comes to naming. Convention, and natural language,
dictates that typical names for what TDD would call tests, now starts
with 'can' or 'finds' or other verbs, which makes the specification so
much easier to read.
Yes, I wrote 'specification'. Because that is how BDD views what TDD
basically calls a test suite. The suite specifies the behaviour of a
`class´. (That's why some BDD frameworks draw on 'spec', like
*RSpec*.)
=== Contexts and Before and After
The complete specification of the behaviour of a SUT might become long
and require various forms of setup. When using TDD style you
would probably break this up into multiple suites having their own
`setup()` and `teardown()`.
With BDD-ish style we could consider a suite as a behaviour
specification for our SUT 'in a particular context'. E.g.
[source, c]
------------------------
#include
Describe(shopping_basket_for_returning_customer);
Customer *customer;
BeforeEach(shopping_basket_for_returning_customer){
customer = create_test_customer();
login(customer);
}
AfterEach(shopping_basket_for_returning_customer) {
logout(customer);
destroy_customer(customer);
}
Ensure(shopping_basket_for_returning_customer, allows_use_of_discounts) {
...
}
------------------------
The 'context' would then be `shopping_basket_for_returning_customer`,
with the SUT being the shopping basket 'class'.
So 'context', 'system under test' and 'suite' are mostly
interchangable concepts in *Cgreen* lingo. It's a named group of
'tests' that share the same `BeforeEach` and `AfterEach` and lives in
the same source file.
[[auto-discovery]]
== Automatic Test Discovery
=== Forgot to Add Your Test?
When we write a new test we focus on the details about the test we are
trying to write. And writing tests is no trivial matter so this might
well take a lot of brain power.
So, it comes as no big surprise, that sometimes you write your test
and then forget to add it to the suite. When we run it it appears that it
passed on the first try! Although this *should* really make you
suspicious, sometimes you get so happy that you just continue with
churning out more tests and more code. It's not until some (possibly
looong) time later that you realize, after much headache and
debugging, that the test did not actually pass. It was never even run!
There are practices to minimize the risk of this happening, such as
always running the test as soon as you can set up the test. This way
you will see it fail before trying to get it to pass.
But it is still a practice, something we, as humans, might fail to do
at some point. Usually this happens when we are most stressed and in
need of certainty.
=== The Solution - the 'cgreen-runner'
*Cgreen* gives you a tool to avoid not only the risk of this
happening, but also the extra work and extra code. It is called the
`cgreen-runner`.
The `cgreen-runner` should come with your *Cgreen* installation if
your platform supports the technique that is required, which is
'programatic access to dynamic loading of libraries'. This means
that a program can load an external library of code into memory and
inspect it. Kind of self-inspection, or reflexion.
So all you have to do is to build a dynamically loadable library of
all tests (and of course your objects under test and other necessary
code). Then you can run the `cgreen-runner` and point it to the
library. The runner will then load the library, enumerate all tests in
it, and run every test.
It's automatic, and there is nothing to forget.
=== Using the Runner
Assuming your tests are in `first_test.c` the typical command to
build your library using `gcc` would be
--------------------------
$ gcc -shared -o first_test.so -fPIC first_test.c -lcgreen
--------------------------
The `-fPIC` means to generate 'position independent code' which is
required if you want to load the library dynamically. To explicitly
state this is required on many platforms.
How to build a dynamically loadable shared library might vary a lot
depending on your platform. Can't really help you there, sorry!
As soon as we have linked it we can run the tests using the
`cgreen-runner` by just giving it the shared, dynamically loadable,
object library as an argument:
-------------------------
$ cgreen-runner first_test.so
include::tutorial_src/runner1.out[]
-------------------------
More or less exactly the same output as when we ran our first test in
the beginning of this quickstart tutorial. We can see that the top
level of the tests will be named as the library it was discovered in,
and the second level is the context for our System Under Test, in
this case 'Cgreen'. We also see that the context is mentioned in the
failure message, giving a fairly obvious `Cgreen -> fails_this_test`.
Now we can actually delete the main function in our source code. We
don't need all this, since the runner will discover all tests
automatically.
[source,c]
------------------------
include::tutorial_src/first_tests1.c[lines=15..20]
------------------------
It always feel good to delete code, right?
We can also select which test to run:
-------------------------
$ cgreen-runner first_test.so Cgreen:this_test_should_fail
include::tutorial_src/runner2.out[]
-------------------------
We recommend the BDD notation to discover tests, and you indicate
which context the test we want to run is in. In this example it is
`Cgreen` so the test should be refered to as `Cgreen:this_test_should_fail`.
If you don't use the BDD notation there is actually a context anyway,
it is called `default`.
[[runner-options]]
=== Cgreen Runner Options
Once you get the build set up right for the cgreen-runner everything
is fairly straight-forward. But you have a few options:
--xml :: Instead of messages on stdout with the TextReporter,
write results into one XML-file per suite or context,
compatible with Hudson/Jenkins CI. The filename(s)
will be `-.xml`
--suite :: Name the top level suite
--no-run:: Don't run the tests
--verbose:: Show progress information and list discovered tests
--colours:: Use colours (or colors) to emphasis result (requires ANSI-capable terminal)
--quiet:: Be more quiet
The `verbose` option is particularly handy since it will give you the
actual names of all tests discovered. So if you have long test names
you can avoid mistyping them by copying and pasting from the output of
`cgreen-runner --verbose`. It will also give the mangled name of the
test which should make it easier to find in the debugger. Here's an
example:
------------------------
include::tutorial_src/runner3.out[]
------------------------
=== Selecting Tests To Run
You can name a single test to be run by giving it as the last argument
on the command line. The name should be in the format
`:`. If not obvious you can get that name by using the
`--verbose` command option which will show you all tests discovered
and both there C/C++ and Cgreen names. Copying the Cgreen name from
that output is an easy way to run only that particular test. When a
single test is named it is run using `run_single_test()`. As described
in <> this means that it is __not__ protected by
`fork()`-ing it to run in its own process.
The `cgreen-runner` supports selecting tests with limited pattern
matching. Using an asterisk as a simple 'match many' symbol you can
say things like
--------------------
$ cgreen-runner Cgreen:*
$ cgreen-runner C*:*this*
--------------------
=== Multiple Test Libraries
You can run tests in multiple libraries in one go by adding them
to the `cgreen-runner` command:
-----------------------
$ cgreen-runner first_set.so second_set.so ...
-----------------------
=== Setup, Teardown and Custom Reporters
The `cgreen-runner` will only run setup and teardown functions if you
use the BDD-ish style with `BeforeEach()` and `AfterEach()` as
described above. The runner does not pickup `setup()` and `teardown()`
added to suites, because it actually doesn't run suites. It discovers
all tests and runs them one by one. The macros required by the BDD-ish
style ensures that the corresponding `BeforeEach()` and `AfterEach()`
are run before and after each test.
CAUTION: The `cgreen-runner` __will__ discover your tests in a shared
library even if you don't use the BDD-ish style. But it will not be
able to find and run the `setup()` and/or `teardown()` attached to your
suite(s). This will probably cause your tests to fail or crash.
In case you have non-BDD style tests __without__ any `setup()` and/or
`teardown()` you can still use the runner. The default suite/context
where the tests live in this case is called `default`. But why don't
you convert your tests to BDD notation? This removes the risk of
frustrating trouble-shooting when you added `setup()`
and `teardown()` and can't understand why they are not run...
So, the runner encourages you to use the BDD notation. But since we
recommend that you do anyway, that's no extra problem if you are
starting out from scratch. But see <> for some easy
tips on how to get you there if you already have non-BDD
tests.
You can choose between the TextReporter, which we have been seeing so
far, and the built-in JUnit/Ant compatible XML-reporter using the
`--xml` option. But it is not currently possible to use custom
reporters as outlined in <> with the runner.
If you require another custom reporter you need to resort to the
standard, programatic, way of invoking your tests. For now...
[[xensure]]
=== Skipping Tests
Sometimes you find that you need to temporarily remove a test, perhaps
to do a refactoring when you have a failing test. Ignoring that test will
allow you to do the refactoring while still in the green.
An old practice is then to comment it out. That is a slightly cumbersome.
It is also hazardous habit as there is no indication of a missing test if you
forget to uncomment it when you are done.
*Cgreen* offers a much better solution. You can just add an 'x' infront
of the `Ensure` for the test and that test will be skipped.
[source, C]
----------------------------
...
xEnsure(Reader, ...) {
...
}
...
----------------------------
With this method, it is a one character change to temporarily ignore,
and un-ignore, a test. It is also easily found using text searches through
a complete source tree. *Cgreen* will also tally the skipped tests, so
it is clearly visible that you have some skipped test when you run them.
[[changing_style]]
== Changing Style
If you already have some TDD style *Cgreen* test suites, it is quite
easy to change them over to BDD-ish style. Here are the steps required
* Add `Describe(SUT);`
* Turn your current setup function into a `BeforeEach()` definition by
changing its signature to match the macro, or simply call the existing
setup function from the BeforeEach(). If you don't have any setup function
you still need to define an empty `BeforeEach()`.
* Ditto for `AfterEach()`.
* Add the SUT to each `Ensure()` by inserting it as a first parameter.
* Change the call to add the tests to `add_test_with_context()` by
adding the name of the SUT as the second parameter.
* Optionally remove the calls to `set_setup()` and `set_teardown()`.
Done.
If you want to continue to run the tests using a hand-coded runner,
you can do that by keeping the setup and teardown functions and their
corresponding `set_`-calls.
It's nice that this is a simple process, because you can change over
from TDD style to BDD-ish style in small steps. You can convert one source
file at a time, by just following the recipe above. Everything will
still work as before but your tests and code will likely improve.
And once you have changed style you can fully benefit from the
automatic discovery of tests as described in <>.
[[reporter]]
== Changing Cgreen Reporting
Replacing the Reporter
~~~~~~~~~~~~~~~~~~~~~~
In every test suite so far, we have run the tests with this line...
[source,c]
-----------------------
return run_test_suite(our_tests(), create_text_reporter());
-----------------------
We can change the reporting mechanism just by changing this
call to create another reporter.
[[builtin_reporters]]
=== Built-in Reporters
*Cgreen* has the following built-in reporters that you can choose from
when your code runs the test suite.
[options="header", cols=4]
|====================================================================================
| Reporter | Purpose
| Signature | Note
| Text | Human readable, with clear messages
| `create_text_reporter(void)` |
| XML | ANT/Jenkins compatible
| `create_xml_reporter(const char *file_prefix)` | `file_prefix` is the prefix of the XML files generated.
| CUTE | CUTE Eclipse-plugin (http://cute-test.org) compatible output
| `create_cute_reporter(void)` |
| CDash | CMake (http://cmake.org) dashboard
| `create_cdash_reporter(CDashInfo *info)` | `info` is a structure defined in `cdash_reporter.h`
|====================================================================================
If you write a runner function like in most examples above, you can
just substitute which runner to create. If you use the `cgreen-runner`
(<>) to dynamically find all your tests you can force
it to use the XML-reporter with the `-x ` option.
NOTE: Currently `cgreen-runner` only supports the test and XML
built-in reporters.
=== Rolling Our Own
Althoug *Cgreen* has a number of options, there are times when you'd like
a different output from the reporter, the CUTE and CDash reporters are
examples that grew out of such a need.
Perhaps your Continuous Integration server want the result in a different
format, or you just don't like the text reporter...
Writing your own reporter is supported. And we'll go through how that can
be done using an XML-reporter as an example.
NOTE: *Cgreen* already has an XML-reporter compatible with ANT/Jenkins, see
<>.
Here is the code for `create_text_reporter()`...
[source,c]
-----------------------
TestReporter *create_text_reporter(void) {
TestReporter *reporter = create_reporter();
if (reporter == NULL) {
return NULL;
}
reporter->start_suite = &text_reporter_start_suite;
reporter->start_test = &text_reporter_start_test;
reporter->show_fail = &show_fail;
reporter->show_skip = &show_skip;
reporter->show_incomplete = &show_incomplete;
reporter->finish_test = &text_reporter_finish_test;
reporter->finish_suite = &text_reporter_finish;
return reporter;
}
-----------------------
The `TestReporter` structure contains function pointers that control
the reporting. When called from `create_reporter()` constructor,
these pointers are set up with functions that display nothing. The
text reporter code replaces these with something more dramatic, and
then returns a pointer to this new object. Thus the
`create_text_reporter()` function effectively extends the object from
`create_reporter()`.
The text reporter only outputs content at the start of the first test,
at the end of the test run to display the results, when a failure
occurs, and when a test fails to complete. A quick look at the
`text_reporter.c` file in *Cgreen* reveals that the overrides just
output a message and chain to the versions in `reporter.h`.
To change the reporting mechanism ourselves, we just have to know a little
about the methods in the `TestReporter` structure.
=== The TestReporter Structure
The *Cgreen* `TestReporter` is a pseudo class that looks
something like...
[source,c]
-----------------------
typedef struct _TestReporter TestReporter;
struct _TestReporter {
void (*destroy)(TestReporter *reporter);
void (*start_suite)(TestReporter *reporter, const char *name, const int count);
void (*start_test)(TestReporter *reporter, const char *name);
void (*show_pass)(TestReporter *reporter, const char *file, int line,
const char *message, va_list arguments);
void (*show_skip)(TestReporter *reporter, const char *file, int line);
void (*show_fail)(TestReporter *reporter, const char *file, int line,
const char *message, va_list arguments);
void (*show_incomplete)(TestReporter *reporter, const char *file, int line,
const char *message, va_list arguments);
void (*assert_true)(TestReporter *reporter, const char *file, int line, int result,
const char * message, ...);
void (*finish_test)(TestReporter *reporter, const char *file, int line);
void (*finish_suite)(TestReporter *reporter, const char *file, int line);
int passes;
int failures;
int exceptions;
void *breadcrumb;
int ipc;
void *memo;
void *options;
};
-----------------------
The first block are the methods that can be overridden:
`void (*destroy)(TestReporter *reporter)`::
This is the destructor for the default structure. If this is
overridden, then the overriding function must call
`destroy_reporter(TestReporter *reporter)` to finish the clean up.
`void (*start_suite)(TestReporter *reporter, const char *name, const int count)`::
This is the first of the callbacks. At the start of
each test suite *Cgreen* will call this method on the reporter with
the name of the suite being entered and the number of tests in that
suite. The default version keeps track of the stack of tests in the
`breadcrumb` pointer of `TestReporter`. If you make use of the
breadcrumb functions, as the defaults do, then you will need to call
`reporter_start_suite()` to keep the book-keeping in sync.
`void (*start_test)(TestReporter *reporter, const char *name)`::
At the start of each test *Cgreen* will call this method on the
reporter with the name of the test being entered. Again, the default
version keeps track of the stack of tests in the `breadcrumb` pointer
of `TestReporter`. If you make use of the breadcrumb functions, as the
defaults do, then you will need to call `reporter_start_test()` to keep the
book-keeping in sync.
`void (*show_pass)(TestReporter *reporter, const char *file, int line, const char *message, va_list arguments)`::
This method is initially empty as most reporters see little point in
reporting passing tests (but you might do), so there is no need to
chain the call to any other function. Besides the pointer to the
reporter structure, *Cgreen* also passes the file name of the test,
the line number of failed assertion, the message to show and any
additional parameters to substitute into the message. The message
comes in as `printf()` style format string, and so the variable
argument list should match the substitutions.
`void (*show_fail)(TestReporter *reporter, const char *file, int line, const char *message, va_list arguments)`::
The partner of `show_pass()`, and the one you'll likely overload first.
`void (*show_skip)(TestReporter *reporter, const char *file, int line)`::
This method will be called when a skipped test is encountered, see <>.
`void (*show_incomplete)(TestReporter *reporter, const char *file, int line, const char *message, va_list arguments)`::
When a test fails to complete, this is the handler that is called. As
it's an unexpected outcome, no message is received, but we do get the
name of the test. The text reporter combines this with the breadcrumb
to produce the exception report.
`void (*assert_true)(TestReporter *reporter, const char *file, int line, int result, const char * message, ...)`::
This is not normally overridden and is really internal. It is the raw
entry point for the test messages from the test suite. By default it
dispatches the call to either `show_pass()` or `show_fail()`.
`void (*finish_test)(TestReporter *reporter, const char *file, int line)`::
The counterpart to the `(*start_test)()` call. It is called on leaving
the test. It needs to be chained to the `reporter_finish()` to keep
track of the breadcrumb book keeping.
`void (*finish_suite)(TestReporter *reporter, const char *file, int line)`::
The counterpart to the `(*start_suite)()` call called on leaving the
test suite, and similar to the `(*finish_test)()` if your reporter
needs a handle on that event too. The default text reporter chains
both this and `(*finish_test)()` to the same function where it figures
out if it is the end of the top level suite. If so, it prints the
familiar summary of passes and fails.
NOTE: The `show_fail()` and `show_pass()` functions are called from
the child process, i.e. the isolated process that is `fork()`:ed to
run a single test case. All others, notably `start_...()`,
`finish_...()`, `show_incomplete()` and `show_skip()` are run in the
main (parent) process. This fact might be important since the
processes do not share memory. Information is passed from the child to
the parent using messaging performed within the `show_...()`
functions.
The second block is simply resources and book keeping that the reporter
can use to liven up the messages...
[horizontal]
`passes`:: The number of passes so far.
`skips`:: The number of tests that has been skipped by the `xEnsure` mechanism (see <>)
`failures`:: The number of failures generated so far.
`exceptions`:: The number of test functions that have failed to complete so far.
`breadcrumb`:: This is a pointer to the list of test names in the stack.
The `breadcrumb` pointer is different and needs a little explanation.
Basically it is a stack, analogous to the breadcrumb trail you see on
websites. Everytime a `start()` handler is invoked, the name is
placed in this stack. When a `finish()` message handler is invoked, a
name is popped off.
There are a bunch of utility functions in `cgreen/breadcrumb.h` that
can read the state of this stack. Most useful are
`get_current_from_breadcrumb()` which takes the breadcrumb pointer and
returns the current test name, and `get_breadcrumb_depth()` which gives
the current depth of the stack. A depth of zero means that the test
run has finished.
If you need to traverse all the names in the breadcrumb, then you can
call `walk_breadcrumb()`. Here is the full signature...
[source,c]
-----------------------
void walk_breadcrumb(Breadcrumb *breadcrumb, void (*walker)(const char *, void *), void *memo);
-----------------------
The `void (*walker)(const char *, void *)` is a callback that will be
passed the name of the test suite for each level of nesting.
It is also passed the `memo` pointer that was passed to the
`walk_breadcrumb()` call. You can use this pointer for anything you
want, as all *Cgreen* does is pass it from call to call. This is so
aggregate information can be kept track of whilst still being
reentrant.
The last parts of the `TestReporter` structure are...
[horizontal]
`ipc`:: This is an internal structure for handling the messaging between reporter
and test suite. You shouldn't touch this.
`memo`:: By contrast, this is a spare pointer for your own expansion.
`options`:: A pointer to a reporter specific structure that can be
used to set options. E.g. the textreporter defines the structure
`TextReporterOptions` which can be used by calling code to define the
use of colors when printing passes and failures. You set it with
`set_reporter_options(*void)`.
=== An Example XML Reporter
Let's make things real with an example. Suppose we want to send the
output from *Cgreen* in XML format, say for storing in a repository or
for sending across the network.
NOTE: The `cgreen-runner` already has an XML-reporter that you can
use if you need to produce Jenkins/ANT compatible XML output.
See <>.
Suppose also that we have come up with the following format...
[source,xml]
-----------------------
A failure
-----------------------
In other words a simple nesting of tests with only failures encoded.
The absence of "fail" XML node is a pass.
Here is a test script, `test_as_xml.c` that we can use to construct the
above output...
[source,c]
-----------------------
include::tutorial_src/test_as_xml0.c[]
-----------------------
We can't use the auto-discovering `cgreen-runner` (see
<>) here since we need to ensure that the nested
suites are reported as a nested xml structure. And we're not actually
writing real tests, just something that we can use to drive our new
reporter.
The text reporter is used just to confirm that everything is
working. So far it is.
-----------------------
include::tutorial_src/test_as_xml0.out[]
-----------------------
Our first move is to switch the reporter from text, to our
not yet written XML version...
[source,c]
-----------------------
#include "xml_reporter.h"
...
include::tutorial_src/test_as_xml1.c[lines=24..-1]
-----------------------
We'll start the ball rolling with the `xml_reporter.h`
header file...
[source,c]
-----------------------
include::tutorial_src/xml_reporter.h[]
-----------------------
...and the simplest possible reporter in `xml_reporter.c`.
[source,c]
-----------------------
include::tutorial_src/xml_reporter0.c[]
-----------------------
One that outputs nothing.
-----------------------
$ gcc -c test_as_xml.c
$ gcc -c xml_reporter.c
$ gcc xml_reporter.o test_as_xml.o -lcgreen -o xml
$ ./xml
-----------------------
Yep, nothing.
Let's add the outer XML tags first, so that we can see *Cgreen*
navigating the test suite...
[source,c]
-----------------------
include::tutorial_src/xml_reporter1.c[]
-----------------------
Although chaining to the underlying `reporter_start_*()`
and `reporter_finish_*()` functions is optional, I want to
make use of some of the facilities later.
Our output meanwhile, is making its first tentative steps...
[source,xml]
-----------------------
include::tutorial_src/test_as_xml1.out[]
-----------------------
We don't require an XML node for passing tests, so the `show_fail()`
function is all we need...
[source,c]
-----------------------
...
include::tutorial_src/xml_reporter2.c[lines=18..25]
...
include::tutorial_src/xml_reporter2.c[lines=37..-1]
-----------------------
We have to use `vprintf()` to handle the variable argument list passed
to us. This will probably mean including the `stdarg.h` header as
well as `stdio.h`.
This gets us pretty close to what we want...
[source,xml]
-----------------------
include::tutorial_src/test_as_xml2.out[]
-----------------------
For completeness we should add a tag for a test that doesn't complete.
We'll output this as a failure, although we don't bother with the
location this time...
[source,c]
-----------------------
include::tutorial_src/xml_reporter3.c[lines=27..31]
...
include::tutorial_src/xml_reporter3.c[lines=44..-1]
-----------------------
All that's left then is the XML declaration and the thorny issue of
indenting. Although the indenting is not strictly necessary, it would
make the output a lot more readable.
Given that the test depth is kept track of for us with the
`breadcrumb` object in the `TestReporter` structure, indentation will
actually be quite simple. We'll add an `indent()` function that
outputs the correct number of tabs...
[source,c]
-----------------------
include::tutorial_src/xml_reporter4.c[lines=7..12]
-----------------------
The `get_breadcrumb_depth()` function just gives the current test
depth as recorded in the reporters breadcrumb (from
`cgreen/breadcrumb.h`). As that is just the number of tabs to output,
the implementation is trivial.
We can then use this function in the rest of the code. Here is the
complete listing...
[source,c]
-----------------------
include::tutorial_src/xml_reporter4.c[]
-----------------------
And finally the desired output...
[source,xml]
-----------------------
include::tutorial_src/test_as_xml4.out[]
-----------------------
Job done.
Possible other reporter customizations include reporters that write to
`syslog`, talk to IDE plug-ins, paint pretty printed documents or just
return a boolean for monitoring purposes.
== Advanced Usage
=== Custom Constraints
Sometimes the built-in constraints that *Cgreen* provide are not
sufficient. With *Cgreen* it is possible to create custom constraints,
although you will be depending on some internal structures if you do
so.
Here's how to implement a simple example custom constraint that
asserts that the value is bigger than 5. We'll implement this using a
static constraint since it does not take any parameter.
First we need the actual compare function:
[source,c]
-----------------------------
include::tutorial_src/custom_constraint1.c[lines=1..1]
include::tutorial_src/custom_constraint1.c[lines=9..12]
-----------------------------
And then the static constraint structure, for which we'll need some of
*Cgreen*'s internal functions:
[source,c]
-----------------------------
include::tutorial_src/custom_constraint1.c[lines=2..3]
include::tutorial_src/custom_constraint1.c[lines=13..26]
-----------------------------
This implementation can use a statically declared `Constraint`
structure that is prefilled since it does not need to store the value
to be checked. This static custom constraint can then be used directly
in the `assert` like this:
[source,c]
-----------------------------
include::tutorial_src/custom_constraint1.c[lines=28..31]
-----------------------------
To create a custom constraint that takes an input parameter, we need
to add a function that creates a constraint structure that correctly
saves the value to be checked, and, for convenience, a macro. This
time we need to dig into how *Cgreen* stores expected values and we'll
also make use of *Cgreen*'s utility function `string_dup()`.
[source,c]
-----------------------------
include::tutorial_src/custom_constraint2.c[lines=2..4]
include::tutorial_src/custom_constraint2.c[lines=9..28]
-----------------------------
This gives a custom constraint that can be used in the `assert` in the
same way as *Cgreen*'s built-in constraints:
[source,c]
-----------------------------
include::tutorial_src/custom_constraint2.c[lines=31..33]
-----------------------------
The last, and definitely more complex, example is a constraint that
takes two structures and compares fields in them. The constraint will,
given a structure representing a piece and another structure
representing a box, check if the piece can fit inside the box using a
size field.
Assuming two "application" structures with `size` fields:
[source,c]
-----------------------------
include::tutorial_src/custom_constraint3.c[lines=9..17]
-----------------------------
We want to be able to write a test like this:
[source,c]
-----------------------------
include::tutorial_src/custom_constraint3.c[lines=54..58]
-----------------------------
To implement the `can_fit_in_box` constraint we first need a comparer
function:
[source,c]
-----------------------------
include::tutorial_src/custom_constraint3.c[lines=19..22]
-----------------------------
And this time we can't rely on *Cgreen*'s checker and message
generating function `test_want()` which we used in the previous
examples. So we also need a custom function that calls the comparison
and formats a possible error message:
[source,c]
-----------------------------
include::tutorial_src/custom_constraint3.c[lines=24..36]
-----------------------------
Finally we'll use both of those in the constraint creating function
and add the convenience macro:
[source,c]
-----------------------------
include::tutorial_src/custom_constraint3.c[lines=38..52]
-----------------------------
CAUTION: As stated above, using custom constraints makes your tests
vulnurable to changes in *Cgreen*'s internals. Hopefully a method to
avoid this will emerge in the future.
TIP: You can write custom constraints directly in a test file, but
they can of course also be collected into a separately compiled module
which is linked with your tests.
== Hints and Tips
CAUTION: This chapter is intended to contain tips for situations that
you might need some help with, but it is nowhere near complete at this
time.
[[cgreen-mocker]]
=== `cgreen-mocker` - Automated Mocking
Are you starting out with *Cgreen* on a largish legacy system? And there
are loads and loads of functions to mock to get a unit under test?
You could try the `cgreen-mocker` that is supplied as a contributed
part of the *Cgreen* source distribution.
It is a Python program that parses C language header files and tries
to create a corresponding `.mock` file where each function declaration
is replaced with a call to `mock()`.
-----------------
Usage:
cgreen-mocker.py { }
: file with function declarations that you want
to mock
: any 'cpp' directive but most useful is e.g.
"-I " to ensure cpp finds files.
-----------------
So given a header file containing lines like
[source,c]
----------------------------
extern Value make_integer_value(int integer);
extern Value make_string_value(const char *string);
----------------------------
`cgreen-mocker` will, given that there are no errors, print something
like this on the screen:
[source,c]
----------------------------
Value make_integer_value(int integer) {
return mock(integer);
}
Value make_string_value(const char *string) {
return mock(string);
}
----------------------------
Of course, you would pipe this output to a file.
To use `cgreen-mocker` you need Python and `pycparser`. The latter
can be found at [https://github.com/eliben/pycparser] or can easily
be installed with
----------------
$ pip install pycparser
----------------
NOTE: `cgreen-mocker` is an unsupported contribution to the *Cgreen*
project by Thomas Nilefalk.
=== Compiler Error Messages
Sometimes you might get cryptic and strange error messages from the
compiler. Since *Cgreen* uses some C/C++ macro magic this can happen
and the error messages might not be straight forward to interpret.
Here are some examples, but the exact messages differ between compilers
and versions.
|=========================================================
|*Compiler error message* |*Probable cause...*
|`"contextFor" is undeclared here` | Missing `Describe();`
|`undefined reference to 'AfterEach_For_'`| Missing `AfterEach()`
|`CgreenSpec______ is undeclared` | Missing test subject/context in the `Ensure` of a BDD style test
|`use of undeclared identifier 'contextFor'` | Missing `Describe();`
|=========================================================
=== Signed, Unsigned, Hex and Byte
*Cgreen* attempts to handle primitive type comparisons with a single
constraint, `is_equal_to()`. This means that it must store the actual
and expected values in a form that will accomodate all possible values
that primitive types might take, typically an `intptr_t`.
This might sometimes cause unexpected comparisons since all actual
values will be cast to match `intptr_t`, which is a signed value. E.g.
[source, c]
------------------------------
Ensure(Char, can_compare_byte) {
char chars[4] = {0xaa, 0xaa, 0xaa, 0};
assert_that(chars[0], is_equal_to(0xaa));
}
------------------------------
On a system which considers `char` to be signed this will cause the
following *Cgreen* assertion error:
------------------------------
char_tests.c:11: Failure: Char -> can_compare_byte
Expected [chars[0]] to [equal] [0xaa]
actual value: [-86]
expected value: [170]
------------------------------
This is caused by the C rules forcing an implicit cast of the `signed
char` to `intptr_t` by sign-extension. This might not be what you
expected. The correct solution, by any standard, is to cast the actual
value to `unsigned char` which will then be interpreted correctly. And
the test passes.
NOTE: Casting to `unsigned` will not always suffice since that is
interpreted as `unsigned int` which will cause a sign-extension from
the `signed char` and might or might not work depending on the size of
`int` on your machine.
In order to reveal what really happens you might want to see the actual and
expected values in hex. This can easily be done with the
`is_equal_to_hex()`.
[source, c]
------------------------------
Ensure(Char, can_compare_byte) {
char chars[4] = {0xaa, 0xaa, 0xaa, 0};
assert_that(chars[0], is_equal_to_hex(0xaa));
}
------------------------------
This might make the mistake easier to spot:
------------------------------
char_tests.c:11: Failure: Char -> can_compare_byte
Expected [chars[0]] to [equal] [0xaa]
actual value: [0xfffffffffffffaa]
expected value: [0xaa]
------------------------------
=== Cgreen and Coverage
*Cgreen* is compatible with coverage tools, in particular
`gcov`/`lcov`. So generating coverage data for your application should
be straight forward.
This is what you need to do (using `gcc` or `clang`):
- compile with `-ftest-coverage` and `-fprofile-arcs`
- run tests
- `lcov --directory . --capture --output-file coverage.info`
- `genhtml -o coverage coverage.info`
Your coverage data will be available in `coverage/index.html`.
=== Garbled Output
If the output from your *Cgreen* based tests appear garbled or
duplicated, this can be caused by the way *Cgreen* terminates its
test-running child process. In many unix-like environments the
termination of a child process should be done with `_exit()`. However,
this interfers severily with the ability to collect coverage data. As
this is important for many of us, *Cgreen* instead terminates its
child process with the much cruder `exit()` (note: no underscore).
Under rare circumstances this might have the unwanted effect of output
becoming garbled and/or duplicated.
If this happens you can change that behaviour using an environment
variable `CGREEN_CHILD_EXIT_WITH__EXIT` (note: two underscores). If
set, *Cgreen* will terminate its test-running child process with the
more POSIX-compliant `_exit()`. But as mentioned before, this is, at
least at this point in time, incompatible with collecting coverage
data.
So, it's coverage __or__ POSIX-correct child exits and guaranteed
output consistency. You can't have both...
[appendix]
== License
Copyright (c) 2006-2018, Cgreen Development Team and contributors +
(https://github.com/cgreen-devs/cgreen/graphs/contributors)
Permission to use, copy, modify, and/or distribute this software and
its documentation for any purpose with or without fee is hereby
granted, provided that the above copyright notice and this permission
notice appear in all copies, regardless of form, including printed and
compiled.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHORS DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
[appendix]
== Acknowledgements
Thanks to
- Marcus Baker - initiator and substantial
inital work
- Matt Hargett - upgrading to the modern
BDD-ish syntax
- João Freitas - asciidoc documentation and Cmake
build system
- Thomas Nilefalk - cgreen-runner and current
maintainer
Thanks also go to @gardenia, @d-meiser, @stevemadsenblippar and others
for their contributions.
cgreen-1.3.0/doc/cgreen_asciidoc.conf 0000664 0000000 0000000 00000000043 13666233252 0017500 0 ustar 00root root 0000000 0000000 [attributes]
toclevels=3
numbered=
cgreen-1.3.0/doc/cheat-sheet.md 0000664 0000000 0000000 00000004377 13666233252 0016262 0 ustar 00root root 0000000 0000000 # Cgreen Cheat Sheet
## Pre-amble
#include
#include
Describe( );
BeforeEach( ) {}
AfterEach( ) {}
## A test
Ensure( , ) {
assert_that( );
assert_that( , );
assert_that_double(...);
}
## Constraints
is_true
is_false
is_null
is_non_null
is_equal_to( )
is_equal_to_hex( )
is_not_equal_to( )
is_greater_than( )
is_less_than( )
### Structs and general data
is_equal_to_contents_of( , )
is_not_equal_to_contents_of( , )
### Strings
is_equal_to_string( )
is_not_equal_to_string( )
contains_string( )
does_not_contain_string( )
begins_with_string( )
does_not_begin_with_string( )
ends_with_string( )
does_not_end_with_string( )
### Doubles
is_equal_to_double( )
is_not_equal_to_double( )
is_less_than_double( )
is_greater_than_double( )
significant_figures_for_assert_double_are( )
## Mocks
( ) {
mock( );
mock( box_double( ) );
return ( ) mock( );
return mock_double( );
}
Ensure( ) {
expect( {, when(, ) }
[, ]
[, times( ) ] );
always_expect(...);
never_expect(...);
}
cgreen_mocks_are( strict_mocks | loose_mocks | learning_mocks );
### Returns
will_return( )
will_return_double( )
will_return_by_value( , )
with_side_effect( , )
will_set_contents_of_parameter( , , )
## C++
namespace cgreen;
assert_throws( , );
## Minimal Makefile
all: $(UNIT)_tests.so
cgreen-runner $^
$(UNIT)_tests.so: $(UNIT)_tests.o $(UNIT).o
$(CC) -shared -o $@ $^ -lcgreen
%.o: %.c
$(CC) $(CFLAGS) -fPIC -c -o $@ $^
cgreen-1.3.0/doc/doxy.config.in 0000664 0000000 0000000 00000175207 13666233252 0016326 0 ustar 00root root 0000000 0000000 # Doxyfile 1.5.8
# This file describes the settings to be used by the documentation system
# doxygen (www.doxygen.org) for a project
#
# All text after a hash (#) is considered a comment and will be ignored
# The format is:
# TAG = value [value, ...]
# For lists items can also be appended using:
# TAG += value [value, ...]
# Values that contain spaces should be placed between quotes (" ")
#---------------------------------------------------------------------------
# Project related configuration options
#---------------------------------------------------------------------------
# This tag specifies the encoding used for all characters in the config file
# that follow. The default is UTF-8 which is also the encoding used for all
# text before the first occurrence of this tag. Doxygen uses libiconv (or the
# iconv built into libc) for the transcoding. See
# http://www.gnu.org/software/libiconv for the list of possible encodings.
DOXYFILE_ENCODING = UTF-8
# The PROJECT_NAME tag is a single word (or a sequence of words surrounded
# by quotes) that should identify the project.
PROJECT_NAME = @APPLICATION_NAME@
# The PROJECT_NUMBER tag can be used to enter a project or revision number.
# This could be handy for archiving the generated documentation or
# if some version control system is used.
PROJECT_NUMBER = @APPLICATION_VERSION@
# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute)
# base path where the generated documentation will be put.
# If a relative path is entered, it will be relative to the location
# where doxygen was started. If left blank the current directory will be used.
OUTPUT_DIRECTORY = @CMAKE_CURRENT_BINARY_DIR@
# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create
# 4096 sub-directories (in 2 levels) under the output directory of each output
# format and will distribute the generated files over these directories.
# Enabling this option can be useful when feeding doxygen a huge amount of
# source files, where putting all generated files in the same directory would
# otherwise cause performance problems for the file system.
CREATE_SUBDIRS = NO
# The OUTPUT_LANGUAGE tag is used to specify the language in which all
# documentation generated by doxygen is written. Doxygen will use this
# information to generate all constant output in the proper language.
# The default language is English, other supported languages are:
# Afrikaans, Arabic, Brazilian, Catalan, Chinese, Chinese-Traditional,
# Croatian, Czech, Danish, Dutch, Farsi, Finnish, French, German, Greek,
# Hungarian, Italian, Japanese, Japanese-en (Japanese with English messages),
# Korean, Korean-en, Lithuanian, Norwegian, Macedonian, Persian, Polish,
# Portuguese, Romanian, Russian, Serbian, Serbian-Cyrilic, Slovak, Slovene,
# Spanish, Swedish, and Ukrainian.
OUTPUT_LANGUAGE = English
# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will
# include brief member descriptions after the members that are listed in
# the file and class documentation (similar to JavaDoc).
# Set to NO to disable this.
BRIEF_MEMBER_DESC = YES
# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend
# the brief description of a member or function before the detailed description.
# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the
# brief descriptions will be completely suppressed.
REPEAT_BRIEF = YES
# This tag implements a quasi-intelligent brief description abbreviator
# that is used to form the text in various listings. Each string
# in this list, if found as the leading text of the brief description, will be
# stripped from the text and the result after processing the whole list, is
# used as the annotated text. Otherwise, the brief description is used as-is.
# If left blank, the following values are used ("$name" is automatically
# replaced with the name of the entity): "The $name class" "The $name widget"
# "The $name file" "is" "provides" "specifies" "contains"
# "represents" "a" "an" "the"
ABBREVIATE_BRIEF = "The $name class" \
"The $name widget" \
"The $name file" \
is \
provides \
specifies \
contains \
represents \
a \
an \
the
# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then
# Doxygen will generate a detailed section even if there is only a brief
# description.
ALWAYS_DETAILED_SEC = NO
# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all
# inherited members of a class in the documentation of that class as if those
# members were ordinary class members. Constructors, destructors and assignment
# operators of the base classes will not be shown.
INLINE_INHERITED_MEMB = NO
# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full
# path before files name in the file list and in the header files. If set
# to NO the shortest path that makes the file name unique will be used.
FULL_PATH_NAMES = YES
# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag
# can be used to strip a user-defined part of the path. Stripping is
# only done if one of the specified strings matches the left-hand part of
# the path. The tag can be used to show relative paths in the file list.
# If left blank the directory from which doxygen is run is used as the
# path to strip.
STRIP_FROM_PATH = @PROJECT_SOURCE_DIR@
# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of
# the path mentioned in the documentation of a class, which tells
# the reader which header file to include in order to use a class.
# If left blank only the name of the header file containing the class
# definition is used. Otherwise one should specify the include paths that
# are normally passed to the compiler using the -I flag.
STRIP_FROM_INC_PATH = @PROJECT_SOURCE_DIR@
# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter
# (but less readable) file names. This can be useful is your file systems
# doesn't support long names like on DOS, Mac, or CD-ROM.
SHORT_NAMES = NO
# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen
# will interpret the first line (until the first dot) of a JavaDoc-style
# comment as the brief description. If set to NO, the JavaDoc
# comments will behave just like regular Qt-style comments
# (thus requiring an explicit @brief command for a brief description.)
JAVADOC_AUTOBRIEF = YES
# If the QT_AUTOBRIEF tag is set to YES then Doxygen will
# interpret the first line (until the first dot) of a Qt-style
# comment as the brief description. If set to NO, the comments
# will behave just like regular Qt-style comments (thus requiring
# an explicit \brief command for a brief description.)
QT_AUTOBRIEF = NO
# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen
# treat a multi-line C++ special comment block (i.e. a block of //! or ///
# comments) as a brief description. This used to be the default behaviour.
# The new default is to treat a multi-line C++ comment block as a detailed
# description. Set this tag to YES if you prefer the old behaviour instead.
MULTILINE_CPP_IS_BRIEF = NO
# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented
# member inherits the documentation from any documented member that it
# re-implements.
INHERIT_DOCS = YES
# If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce
# a new page for each member. If set to NO, the documentation of a member will
# be part of the file/class/namespace that contains it.
SEPARATE_MEMBER_PAGES = NO
# The TAB_SIZE tag can be used to set the number of spaces in a tab.
# Doxygen uses this value to replace tabs by spaces in code fragments.
TAB_SIZE = 2
# This tag can be used to specify a number of aliases that acts
# as commands in the documentation. An alias has the form "name=value".
# For example adding "sideeffect=\par Side Effects:\n" will allow you to
# put the command \sideeffect (or @sideeffect) in the documentation, which
# will result in a user-defined paragraph with heading "Side Effects:".
# You can put \n's in the value part of an alias to insert newlines.
ALIASES =
# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C
# sources only. Doxygen will then generate output that is more tailored for C.
# For instance, some of the names that are used will be different. The list
# of all members will be omitted, etc.
OPTIMIZE_OUTPUT_FOR_C = YES
# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java
# sources only. Doxygen will then generate output that is more tailored for
# Java. For instance, namespaces will be presented as packages, qualified
# scopes will look different, etc.
OPTIMIZE_OUTPUT_JAVA = NO
# Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran
# sources only. Doxygen will then generate output that is more tailored for
# Fortran.
OPTIMIZE_FOR_FORTRAN = NO
# Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL
# sources. Doxygen will then generate output that is tailored for
# VHDL.
OPTIMIZE_OUTPUT_VHDL = NO
# Doxygen selects the parser to use depending on the extension of the files it parses.
# With this tag you can assign which parser to use for a given extension.
# Doxygen has a built-in mapping, but you can override or extend it using this tag.
# The format is ext=language, where ext is a file extension, and language is one of
# the parsers supported by doxygen: IDL, Java, Javascript, C#, C, C++, D, PHP,
# Objective-C, Python, Fortran, VHDL, C, C++. For instance to make doxygen treat
# .inc files as Fortran files (default is PHP), and .f files as C (default is Fortran),
# use: inc=Fortran f=C
EXTENSION_MAPPING =
# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want
# to include (a tag file for) the STL sources as input, then you should
# set this tag to YES in order to let doxygen match functions declarations and
# definitions whose arguments contain STL classes (e.g. func(std::string); v.s.
# func(std::string) {}). This also make the inheritance and collaboration
# diagrams that involve STL classes more complete and accurate.
BUILTIN_STL_SUPPORT = NO
# If you use Microsoft's C++/CLI language, you should set this option to YES to
# enable parsing support.
CPP_CLI_SUPPORT = NO
# Set the SIP_SUPPORT tag to YES if your project consists of sip sources only.
# Doxygen will parse them like normal C++ but will assume all classes use public
# instead of private inheritance when no explicit protection keyword is present.
SIP_SUPPORT = NO
# For Microsoft's IDL there are propget and propput attributes to indicate getter
# and setter methods for a property. Setting this option to YES (the default)
# will make doxygen to replace the get and set methods by a property in the
# documentation. This will only work if the methods are indeed getting or
# setting a simple type. If this is not the case, or you want to show the
# methods anyway, you should set this option to NO.
IDL_PROPERTY_SUPPORT = YES
# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC
# tag is set to YES, then doxygen will reuse the documentation of the first
# member in the group (if any) for the other members of the group. By default
# all members of a group must be documented explicitly.
DISTRIBUTE_GROUP_DOC = NO
# Set the SUBGROUPING tag to YES (the default) to allow class member groups of
# the same type (for instance a group of public functions) to be put as a
# subgroup of that type (e.g. under the Public Functions section). Set it to
# NO to prevent subgrouping. Alternatively, this can be done per class using
# the \nosubgrouping command.
SUBGROUPING = YES
# When TYPEDEF_HIDES_STRUCT is enabled, a typedef of a struct, union, or enum
# is documented as struct, union, or enum with the name of the typedef. So
# typedef struct TypeS {} TypeT, will appear in the documentation as a struct
# with name TypeT. When disabled the typedef will appear as a member of a file,
# namespace, or class. And the struct will be named TypeS. This can typically
# be useful for C code in case the coding convention dictates that all compound
# types are typedef'ed and only the typedef is referenced, never the tag name.
TYPEDEF_HIDES_STRUCT = NO
# The SYMBOL_CACHE_SIZE determines the size of the internal cache use to
# determine which symbols to keep in memory and which to flush to disk.
# When the cache is full, less often used symbols will be written to disk.
# For small to medium size projects (<1000 input files) the default value is
# probably good enough. For larger projects a too small cache size can cause
# doxygen to be busy swapping symbols to and from disk most of the time
# causing a significant performance penality.
# If the system has enough physical memory increasing the cache will improve the
# performance by keeping more symbols in memory. Note that the value works on
# a logarithmic scale so increasing the size by one will rougly double the
# memory usage. The cache size is given by this formula:
# 2^(16+SYMBOL_CACHE_SIZE). The valid range is 0..9, the default is 0,
# corresponding to a cache size of 2^16 = 65536 symbols
SYMBOL_CACHE_SIZE = 0
#---------------------------------------------------------------------------
# Build related configuration options
#---------------------------------------------------------------------------
# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in
# documentation are documented, even if no documentation was available.
# Private class members and static file members will be hidden unless
# the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES
EXTRACT_ALL = NO
# If the EXTRACT_PRIVATE tag is set to YES all private members of a class
# will be included in the documentation.
EXTRACT_PRIVATE = NO
# If the EXTRACT_STATIC tag is set to YES all static members of a file
# will be included in the documentation.
EXTRACT_STATIC = NO
# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs)
# defined locally in source files will be included in the documentation.
# If set to NO only classes defined in header files are included.
EXTRACT_LOCAL_CLASSES = NO
# This flag is only useful for Objective-C code. When set to YES local
# methods, which are defined in the implementation section but not in
# the interface are included in the documentation.
# If set to NO (the default) only methods in the interface are included.
EXTRACT_LOCAL_METHODS = NO
# If this flag is set to YES, the members of anonymous namespaces will be
# extracted and appear in the documentation as a namespace called
# 'anonymous_namespace{file}', where file will be replaced with the base
# name of the file that contains the anonymous namespace. By default
# anonymous namespace are hidden.
EXTRACT_ANON_NSPACES = NO
# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all
# undocumented members of documented classes, files or namespaces.
# If set to NO (the default) these members will be included in the
# various overviews, but no documentation section is generated.
# This option has no effect if EXTRACT_ALL is enabled.
HIDE_UNDOC_MEMBERS = YES
# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all
# undocumented classes that are normally visible in the class hierarchy.
# If set to NO (the default) these classes will be included in the various
# overviews. This option has no effect if EXTRACT_ALL is enabled.
HIDE_UNDOC_CLASSES = YES
# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all
# friend (class|struct|union) declarations.
# If set to NO (the default) these declarations will be included in the
# documentation.
HIDE_FRIEND_COMPOUNDS = NO
# If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any
# documentation blocks found inside the body of a function.
# If set to NO (the default) these blocks will be appended to the
# function's detailed documentation block.
HIDE_IN_BODY_DOCS = NO
# The INTERNAL_DOCS tag determines if documentation
# that is typed after a \internal command is included. If the tag is set
# to NO (the default) then the documentation will be excluded.
# Set it to YES to include the internal documentation.
INTERNAL_DOCS = NO
# If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate
# file names in lower-case letters. If set to YES upper-case letters are also
# allowed. This is useful if you have classes or files whose names only differ
# in case and if your file system supports case sensitive file names. Windows
# and Mac users are advised to set this option to NO.
CASE_SENSE_NAMES = YES
# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen
# will show members with their full class and namespace scopes in the
# documentation. If set to YES the scope will be hidden.
HIDE_SCOPE_NAMES = NO
# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen
# will put a list of the files that are included by a file in the documentation
# of that file.
SHOW_INCLUDE_FILES = YES
# If the INLINE_INFO tag is set to YES (the default) then a tag [inline]
# is inserted in the documentation for inline members.
INLINE_INFO = YES
# If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen
# will sort the (detailed) documentation of file and class members
# alphabetically by member name. If set to NO the members will appear in
# declaration order.
SORT_MEMBER_DOCS = YES
# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the
# brief documentation of file, namespace and class members alphabetically
# by member name. If set to NO (the default) the members will appear in
# declaration order.
SORT_BRIEF_DOCS = YES
# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the
# hierarchy of group names into alphabetical order. If set to NO (the default)
# the group names will appear in their defined order.
SORT_GROUP_NAMES = NO
# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be
# sorted by fully-qualified names, including namespaces. If set to
# NO (the default), the class list will be sorted only by class name,
# not including the namespace part.
# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES.
# Note: This option applies only to the class list, not to the
# alphabetical list.
SORT_BY_SCOPE_NAME = NO
# The GENERATE_TODOLIST tag can be used to enable (YES) or
# disable (NO) the todo list. This list is created by putting \todo
# commands in the documentation.
GENERATE_TODOLIST = YES
# The GENERATE_TESTLIST tag can be used to enable (YES) or
# disable (NO) the test list. This list is created by putting \test
# commands in the documentation.
GENERATE_TESTLIST = YES
# The GENERATE_BUGLIST tag can be used to enable (YES) or
# disable (NO) the bug list. This list is created by putting \bug
# commands in the documentation.
GENERATE_BUGLIST = YES
# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or
# disable (NO) the deprecated list. This list is created by putting
# \deprecated commands in the documentation.
GENERATE_DEPRECATEDLIST= YES
# The ENABLED_SECTIONS tag can be used to enable conditional
# documentation sections, marked by \if sectionname ... \endif.
ENABLED_SECTIONS =
# The MAX_INITIALIZER_LINES tag determines the maximum number of lines
# the initial value of a variable or define consists of for it to appear in
# the documentation. If the initializer consists of more lines than specified
# here it will be hidden. Use a value of 0 to hide initializers completely.
# The appearance of the initializer of individual variables and defines in the
# documentation can be controlled using \showinitializer or \hideinitializer
# command in the documentation regardless of this setting.
MAX_INITIALIZER_LINES = 30
# Set the SHOW_USED_FILES tag to NO to disable the list of files generated
# at the bottom of the documentation of classes and structs. If set to YES the
# list will mention the files that were used to generate the documentation.
SHOW_USED_FILES = YES
# If the sources in your project are distributed over multiple directories
# then setting the SHOW_DIRECTORIES tag to YES will show the directory hierarchy
# in the documentation. The default is NO.
SHOW_DIRECTORIES = NO
# Set the SHOW_FILES tag to NO to disable the generation of the Files page.
# This will remove the Files entry from the Quick Index and from the
# Folder Tree View (if specified). The default is YES.
SHOW_FILES = YES
# Set the SHOW_NAMESPACES tag to NO to disable the generation of the
# Namespaces page.
# This will remove the Namespaces entry from the Quick Index
# and from the Folder Tree View (if specified). The default is YES.
SHOW_NAMESPACES = YES
# The FILE_VERSION_FILTER tag can be used to specify a program or script that
# doxygen should invoke to get the current version for each file (typically from
# the version control system). Doxygen will invoke the program by executing (via
# popen()) the command , where is the value of
# the FILE_VERSION_FILTER tag, and is the name of an input file
# provided by doxygen. Whatever the program writes to standard output
# is used as the file version. See the manual for examples.
FILE_VERSION_FILTER =
# The LAYOUT_FILE tag can be used to specify a layout file which will be parsed by
# doxygen. The layout file controls the global structure of the generated output files
# in an output format independent way. The create the layout file that represents
# doxygen's defaults, run doxygen with the -l option. You can optionally specify a
# file name after the option, if omitted DoxygenLayout.xml will be used as the name
# of the layout file.
LAYOUT_FILE =
#---------------------------------------------------------------------------
# configuration options related to warning and progress messages
#---------------------------------------------------------------------------
# The QUIET tag can be used to turn on/off the messages that are generated
# by doxygen. Possible values are YES and NO. If left blank NO is used.
QUIET = YES
# The WARNINGS tag can be used to turn on/off the warning messages that are
# generated by doxygen. Possible values are YES and NO. If left blank
# NO is used.
WARNINGS = YES
# If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings
# for undocumented members. If EXTRACT_ALL is set to YES then this flag will
# automatically be disabled.
WARN_IF_UNDOCUMENTED = YES
# If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for
# potential errors in the documentation, such as not documenting some
# parameters in a documented function, or documenting parameters that
# don't exist or using markup commands wrongly.
WARN_IF_DOC_ERROR = YES
# This WARN_NO_PARAMDOC option can be abled to get warnings for
# functions that are documented, but have no documentation for their parameters
# or return value. If set to NO (the default) doxygen will only warn about
# wrong or incomplete parameter documentation, but not about the absence of
# documentation.
WARN_NO_PARAMDOC = NO
# The WARN_FORMAT tag determines the format of the warning messages that
# doxygen can produce. The string should contain the $file, $line, and $text
# tags, which will be replaced by the file and line number from which the
# warning originated and the warning text. Optionally the format may contain
# $version, which will be replaced by the version of the file (if it could
# be obtained via FILE_VERSION_FILTER)
WARN_FORMAT = "$file:$line: $text"
# The WARN_LOGFILE tag can be used to specify a file to which warning
# and error messages should be written. If left blank the output is written
# to stderr.
WARN_LOGFILE = @CMAKE_CURRENT_BINARY_DIR@/doxy.log
#---------------------------------------------------------------------------
# configuration options related to the input files
#---------------------------------------------------------------------------
# The INPUT tag can be used to specify the files and/or directories that contain
# documented source files. You may enter file names like "myfile.cpp" or
# directories like "/usr/src/myproject". Separate the files or directories
# with spaces.
INPUT = @PROJECT_SOURCE_DIR@/include \
@PROJECT_SOURCE_DIR@/src
# This tag can be used to specify the character encoding of the source files
# that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is
# also the default input encoding. Doxygen uses libiconv (or the iconv built
# into libc) for the transcoding. See http://www.gnu.org/software/libiconv for
# the list of possible encodings.
INPUT_ENCODING = UTF-8
# If the value of the INPUT tag contains directories, you can use the
# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp
# and *.h) to filter out the source-files in the directories. If left
# blank the following patterns are tested:
# *.c *.cc *.cxx *.cpp *.c++ *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh *.hxx
# *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm *.py *.f90
FILE_PATTERNS = *.cpp \
*.cc \
*.c \
*.h \
*.hh \
*.hpp \
*.dox
# The RECURSIVE tag can be used to turn specify whether or not subdirectories
# should be searched for input files as well. Possible values are YES and NO.
# If left blank NO is used.
RECURSIVE = YES
# The EXCLUDE tag can be used to specify files and/or directories that should
# excluded from the INPUT source files. This way you can easily exclude a
# subdirectory from a directory tree whose root is specified with the INPUT tag.
EXCLUDE =
# The EXCLUDE_SYMLINKS tag can be used select whether or not files or
# directories that are symbolic links (a Unix filesystem feature) are excluded
# from the input.
EXCLUDE_SYMLINKS = NO
# If the value of the INPUT tag contains directories, you can use the
# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude
# certain files from those directories. Note that the wildcards are matched
# against the file with absolute path, so to exclude all test directories
# for example use the pattern */test/*
EXCLUDE_PATTERNS = */.git/* \
*/cmake/* \
*/doc/* \
*/build/*
# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names
# (namespaces, classes, functions, etc.) that should be excluded from the
# output. The symbol name can be a fully qualified name, a word, or if the
# wildcard * is used, a substring. Examples: ANamespace, AClass,
# AClass::ANamespace, ANamespace::*Test
EXCLUDE_SYMBOLS =
# The EXAMPLE_PATH tag can be used to specify one or more files or
# directories that contain example code fragments that are included (see
# the \include command).
EXAMPLE_PATH = @PROJECT_SOURCE_DIR@/tests \
@PROJECT_SOURCE_DIR@
# If the value of the EXAMPLE_PATH tag contains directories, you can use the
# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp
# and *.h) to filter out the source-files in the directories. If left
# blank all files are included.
EXAMPLE_PATTERNS = *.cpp \
*.cc \
*.h \
*.hh \
INSTALL \
DEPENDENCIES \
CHANGELOG \
LICENSE \
LGPL
# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be
# searched for input files to be used with the \include or \dontinclude
# commands irrespective of the value of the RECURSIVE tag.
# Possible values are YES and NO. If left blank NO is used.
EXAMPLE_RECURSIVE = YES
# The IMAGE_PATH tag can be used to specify one or more files or
# directories that contain image that are included in the documentation (see
# the \image command).
IMAGE_PATH =
# The INPUT_FILTER tag can be used to specify a program that doxygen should
# invoke to filter for each input file. Doxygen will invoke the filter program
# by executing (via popen()) the command , where
# is the value of the INPUT_FILTER tag, and is the name of an
# input file. Doxygen will then use the output that the filter program writes
# to standard output.
# If FILTER_PATTERNS is specified, this tag will be
# ignored.
INPUT_FILTER =
# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern
# basis.
# Doxygen will compare the file name with each pattern and apply the
# filter if there is a match.
# The filters are a list of the form:
# pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further
# info on how filters are used. If FILTER_PATTERNS is empty, INPUT_FILTER
# is applied to all files.
FILTER_PATTERNS =
# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using
# INPUT_FILTER) will be used to filter the input files when producing source
# files to browse (i.e. when SOURCE_BROWSER is set to YES).
FILTER_SOURCE_FILES = NO
#---------------------------------------------------------------------------
# configuration options related to source browsing
#---------------------------------------------------------------------------
# If the SOURCE_BROWSER tag is set to YES then a list of source files will
# be generated. Documented entities will be cross-referenced with these sources.
# Note: To get rid of all source code in the generated output, make sure also
# VERBATIM_HEADERS is set to NO.
SOURCE_BROWSER = NO
# Setting the INLINE_SOURCES tag to YES will include the body
# of functions and classes directly in the documentation.
INLINE_SOURCES = NO
# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct
# doxygen to hide any special comment blocks from generated source code
# fragments. Normal C and C++ comments will always remain visible.
STRIP_CODE_COMMENTS = YES
# If the REFERENCED_BY_RELATION tag is set to YES
# then for each documented function all documented
# functions referencing it will be listed.
REFERENCED_BY_RELATION = YES
# If the REFERENCES_RELATION tag is set to YES
# then for each documented function all documented entities
# called/used by that function will be listed.
REFERENCES_RELATION = YES
# If the REFERENCES_LINK_SOURCE tag is set to YES (the default)
# and SOURCE_BROWSER tag is set to YES, then the hyperlinks from
# functions in REFERENCES_RELATION and REFERENCED_BY_RELATION lists will
# link to the source code.
# Otherwise they will link to the documentation.
REFERENCES_LINK_SOURCE = YES
# If the USE_HTAGS tag is set to YES then the references to source code
# will point to the HTML generated by the htags(1) tool instead of doxygen
# built-in source browser. The htags tool is part of GNU's global source
# tagging system (see http://www.gnu.org/software/global/global.html). You
# will need version 4.8.6 or higher.
USE_HTAGS = NO
# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen
# will generate a verbatim copy of the header file for each class for
# which an include is specified. Set to NO to disable this.
VERBATIM_HEADERS = YES
#---------------------------------------------------------------------------
# configuration options related to the alphabetical class index
#---------------------------------------------------------------------------
# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index
# of all compounds will be generated. Enable this if the project
# contains a lot of classes, structs, unions or interfaces.
ALPHABETICAL_INDEX = YES
# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then
# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns
# in which this list will be split (can be a number in the range [1..20])
COLS_IN_ALPHA_INDEX = 2
# In case all classes in a project start with a common prefix, all
# classes will be put under the same header in the alphabetical index.
# The IGNORE_PREFIX tag can be used to specify one or more prefixes that
# should be ignored while generating the index headers.
IGNORE_PREFIX =
#---------------------------------------------------------------------------
# configuration options related to the HTML output
#---------------------------------------------------------------------------
# If the GENERATE_HTML tag is set to YES (the default) Doxygen will
# generate HTML output.
GENERATE_HTML = YES
# The HTML_OUTPUT tag is used to specify where the HTML docs will be put.
# If a relative path is entered the value of OUTPUT_DIRECTORY will be
# put in front of it. If left blank `html' will be used as the default path.
HTML_OUTPUT = html
# The HTML_FILE_EXTENSION tag can be used to specify the file extension for
# each generated HTML page (for example: .htm,.php,.asp). If it is left blank
# doxygen will generate files with .html extension.
HTML_FILE_EXTENSION = .html
# The HTML_HEADER tag can be used to specify a personal HTML header for
# each generated HTML page. If it is left blank doxygen will generate a
# standard header.
HTML_HEADER =
# The HTML_FOOTER tag can be used to specify a personal HTML footer for
# each generated HTML page. If it is left blank doxygen will generate a
# standard footer.
HTML_FOOTER =
# The HTML_STYLESHEET tag can be used to specify a user-defined cascading
# style sheet that is used by each HTML page. It can be used to
# fine-tune the look of the HTML output. If the tag is left blank doxygen
# will generate a default style sheet. Note that doxygen will try to copy
# the style sheet file to the HTML output directory, so don't put your own
# stylesheet in the HTML output directory as well, or it will be erased!
HTML_STYLESHEET =
# If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes,
# files or namespaces will be aligned in HTML using tables. If set to
# NO a bullet list will be used.
HTML_ALIGN_MEMBERS = YES
# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML
# documentation will contain sections that can be hidden and shown after the
# page has loaded. For this to work a browser that supports
# JavaScript and DHTML is required (for instance Mozilla 1.0+, Firefox
# Netscape 6.0+, Internet explorer 5.0+, Konqueror, or Safari).
HTML_DYNAMIC_SECTIONS = NO
# If the GENERATE_DOCSET tag is set to YES, additional index files
# will be generated that can be used as input for Apple's Xcode 3
# integrated development environment, introduced with OSX 10.5 (Leopard).
# To create a documentation set, doxygen will generate a Makefile in the
# HTML output directory. Running make will produce the docset in that
# directory and running "make install" will install the docset in
# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find
# it at startup.
# See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html for more information.
GENERATE_DOCSET = NO
# When GENERATE_DOCSET tag is set to YES, this tag determines the name of the
# feed. A documentation feed provides an umbrella under which multiple
# documentation sets from a single provider (such as a company or product suite)
# can be grouped.
DOCSET_FEEDNAME = "Doxygen generated docs"
# When GENERATE_DOCSET tag is set to YES, this tag specifies a string that
# should uniquely identify the documentation set bundle. This should be a
# reverse domain-name style string, e.g. com.mycompany.MyDocSet. Doxygen
# will append .docset to the name.
DOCSET_BUNDLE_ID = org.doxygen.Project
# If the GENERATE_HTMLHELP tag is set to YES, additional index files
# will be generated that can be used as input for tools like the
# Microsoft HTML help workshop to generate a compiled HTML help file (.chm)
# of the generated HTML documentation.
GENERATE_HTMLHELP = NO
# If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can
# be used to specify the file name of the resulting .chm file. You
# can add a path in front of the file if the result should not be
# written to the html output directory.
CHM_FILE =
# If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can
# be used to specify the location (absolute path including file name) of
# the HTML help compiler (hhc.exe). If non-empty doxygen will try to run
# the HTML help compiler on the generated index.hhp.
HHC_LOCATION =
# If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag
# controls if a separate .chi index file is generated (YES) or that
# it should be included in the master .chm file (NO).
GENERATE_CHI = NO
# If the GENERATE_HTMLHELP tag is set to YES, the CHM_INDEX_ENCODING
# is used to encode HtmlHelp index (hhk), content (hhc) and project file
# content.
CHM_INDEX_ENCODING =
# If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag
# controls whether a binary table of contents is generated (YES) or a
# normal table of contents (NO) in the .chm file.
BINARY_TOC = NO
# The TOC_EXPAND flag can be set to YES to add extra items for group members
# to the contents of the HTML help documentation and to the tree view.
TOC_EXPAND = NO
# If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and QHP_VIRTUAL_FOLDER
# are set, an additional index file will be generated that can be used as input for
# Qt's qhelpgenerator to generate a Qt Compressed Help (.qch) of the generated
# HTML documentation.
GENERATE_QHP = NO
# If the QHG_LOCATION tag is specified, the QCH_FILE tag can
# be used to specify the file name of the resulting .qch file.
# The path specified is relative to the HTML output folder.
QCH_FILE =
# The QHP_NAMESPACE tag specifies the namespace to use when generating
# Qt Help Project output. For more information please see
# http://doc.trolltech.com/qthelpproject.html#namespace
QHP_NAMESPACE =
# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating
# Qt Help Project output. For more information please see
# http://doc.trolltech.com/qthelpproject.html#virtual-folders
QHP_VIRTUAL_FOLDER = doc
# If QHP_CUST_FILTER_NAME is set, it specifies the name of a custom filter to add.
# For more information please see
# http://doc.trolltech.com/qthelpproject.html#custom-filters
QHP_CUST_FILTER_NAME =
# The QHP_CUST_FILT_ATTRS tag specifies the list of the attributes of the custom filter to add.For more information please see
# Qt Help Project / Custom Filters .
QHP_CUST_FILTER_ATTRS =
# The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this project's
# filter section matches.
# Qt Help Project / Filter Attributes .
QHP_SECT_FILTER_ATTRS =
# If the GENERATE_QHP tag is set to YES, the QHG_LOCATION tag can
# be used to specify the location of Qt's qhelpgenerator.
# If non-empty doxygen will try to run qhelpgenerator on the generated
# .qhp file.
QHG_LOCATION =
# The DISABLE_INDEX tag can be used to turn on/off the condensed index at
# top of each HTML page. The value NO (the default) enables the index and
# the value YES disables it.
DISABLE_INDEX = NO
# This tag can be used to set the number of enum values (range [1..20])
# that doxygen will group on one line in the generated HTML documentation.
ENUM_VALUES_PER_LINE = 4
# The GENERATE_TREEVIEW tag is used to specify whether a tree-like index
# structure should be generated to display hierarchical information.
# If the tag value is set to FRAME, a side panel will be generated
# containing a tree-like index structure (just like the one that
# is generated for HTML Help). For this to work a browser that supports
# JavaScript, DHTML, CSS and frames is required (for instance Mozilla 1.0+,
# Netscape 6.0+, Internet explorer 5.0+, or Konqueror). Windows users are
# probably better off using the HTML help feature. Other possible values
# for this tag are: HIERARCHIES, which will generate the Groups, Directories,
# and Class Hierarchy pages using a tree view instead of an ordered list;
# ALL, which combines the behavior of FRAME and HIERARCHIES; and NONE, which
# disables this behavior completely. For backwards compatibility with previous
# releases of Doxygen, the values YES and NO are equivalent to FRAME and NONE
# respectively.
GENERATE_TREEVIEW = NO
# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be
# used to set the initial width (in pixels) of the frame in which the tree
# is shown.
TREEVIEW_WIDTH = 250
# Use this tag to change the font size of Latex formulas included
# as images in the HTML documentation. The default is 10. Note that
# when you change the font size after a successful doxygen run you need
# to manually remove any form_*.png images from the HTML output directory
# to force them to be regenerated.
FORMULA_FONTSIZE = 10
#---------------------------------------------------------------------------
# configuration options related to the LaTeX output
#---------------------------------------------------------------------------
# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will
# generate Latex output.
GENERATE_LATEX = NO
# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put.
# If a relative path is entered the value of OUTPUT_DIRECTORY will be
# put in front of it. If left blank `latex' will be used as the default path.
LATEX_OUTPUT = latex
# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be
# invoked. If left blank `latex' will be used as the default command name.
LATEX_CMD_NAME = @LATEX_COMPILER@
# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to
# generate index for LaTeX. If left blank `makeindex' will be used as the
# default command name.
MAKEINDEX_CMD_NAME = @MAKEINDEX_COMPILER@
# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact
# LaTeX documents. This may be useful for small projects and may help to
# save some trees in general.
COMPACT_LATEX = NO
# The PAPER_TYPE tag can be used to set the paper type that is used
# by the printer. Possible values are: a4, a4wide, letter, legal and
# executive. If left blank a4wide will be used.
PAPER_TYPE = a4
# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX
# packages that should be included in the LaTeX output.
EXTRA_PACKAGES =
# The LATEX_HEADER tag can be used to specify a personal LaTeX header for
# the generated latex document. The header should contain everything until
# the first chapter. If it is left blank doxygen will generate a
# standard header. Notice: only use this tag if you know what you are doing!
LATEX_HEADER =
# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated
# is prepared for conversion to pdf (using ps2pdf). The pdf file will
# contain links (just like the HTML output) instead of page references
# This makes the output suitable for online browsing using a pdf viewer.
PDF_HYPERLINKS = YES
# If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of
# plain latex in the generated Makefile. Set this option to YES to get a
# higher quality PDF documentation.
USE_PDFLATEX = YES
# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode.
# command to the generated LaTeX files. This will instruct LaTeX to keep
# running if errors occur, instead of asking the user for help.
# This option is also used when generating formulas in HTML.
LATEX_BATCHMODE = YES
# If LATEX_HIDE_INDICES is set to YES then doxygen will not
# include the index chapters (such as File Index, Compound Index, etc.)
# in the output.
LATEX_HIDE_INDICES = NO
#---------------------------------------------------------------------------
# configuration options related to the RTF output
#---------------------------------------------------------------------------
# If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output
# The RTF output is optimized for Word 97 and may not look very pretty with
# other RTF readers or editors.
GENERATE_RTF = NO
# The RTF_OUTPUT tag is used to specify where the RTF docs will be put.
# If a relative path is entered the value of OUTPUT_DIRECTORY will be
# put in front of it. If left blank `rtf' will be used as the default path.
RTF_OUTPUT = rtf
# If the COMPACT_RTF tag is set to YES Doxygen generates more compact
# RTF documents. This may be useful for small projects and may help to
# save some trees in general.
COMPACT_RTF = NO
# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated
# will contain hyperlink fields. The RTF file will
# contain links (just like the HTML output) instead of page references.
# This makes the output suitable for online browsing using WORD or other
# programs which support those fields.
# Note: wordpad (write) and others do not support links.
RTF_HYPERLINKS = NO
# Load stylesheet definitions from file. Syntax is similar to doxygen's
# config file, i.e. a series of assignments. You only have to provide
# replacements, missing definitions are set to their default value.
RTF_STYLESHEET_FILE =
# Set optional variables used in the generation of an rtf document.
# Syntax is similar to doxygen's config file.
RTF_EXTENSIONS_FILE =
#---------------------------------------------------------------------------
# configuration options related to the man page output
#---------------------------------------------------------------------------
# If the GENERATE_MAN tag is set to YES (the default) Doxygen will
# generate man pages
GENERATE_MAN = YES
# The MAN_OUTPUT tag is used to specify where the man pages will be put.
# If a relative path is entered the value of OUTPUT_DIRECTORY will be
# put in front of it. If left blank `man' will be used as the default path.
MAN_OUTPUT = man
# The MAN_EXTENSION tag determines the extension that is added to
# the generated man pages (default is the subroutine's section .3)
MAN_EXTENSION = .3
# If the MAN_LINKS tag is set to YES and Doxygen generates man output,
# then it will generate one additional man file for each entity
# documented in the real man page(s). These additional files
# only source the real man page, but without them the man command
# would be unable to find the correct page. The default is NO.
MAN_LINKS = NO
#---------------------------------------------------------------------------
# configuration options related to the XML output
#---------------------------------------------------------------------------
# If the GENERATE_XML tag is set to YES Doxygen will
# generate an XML file that captures the structure of
# the code including all documentation.
GENERATE_XML = NO
# The XML_OUTPUT tag is used to specify where the XML pages will be put.
# If a relative path is entered the value of OUTPUT_DIRECTORY will be
# put in front of it. If left blank `xml' will be used as the default path.
XML_OUTPUT = xml
# The XML_SCHEMA tag can be used to specify an XML schema,
# which can be used by a validating XML parser to check the
# syntax of the XML files.
XML_SCHEMA =
# The XML_DTD tag can be used to specify an XML DTD,
# which can be used by a validating XML parser to check the
# syntax of the XML files.
XML_DTD =
# If the XML_PROGRAMLISTING tag is set to YES Doxygen will
# dump the program listings (including syntax highlighting
# and cross-referencing information) to the XML output. Note that
# enabling this will significantly increase the size of the XML output.
XML_PROGRAMLISTING = YES
#---------------------------------------------------------------------------
# configuration options for the AutoGen Definitions output
#---------------------------------------------------------------------------
# If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will
# generate an AutoGen Definitions (see autogen.sf.net) file
# that captures the structure of the code including all
# documentation. Note that this feature is still experimental
# and incomplete at the moment.
GENERATE_AUTOGEN_DEF = NO
#---------------------------------------------------------------------------
# configuration options related to the Perl module output
#---------------------------------------------------------------------------
# If the GENERATE_PERLMOD tag is set to YES Doxygen will
# generate a Perl module file that captures the structure of
# the code including all documentation. Note that this
# feature is still experimental and incomplete at the
# moment.
GENERATE_PERLMOD = NO
# If the PERLMOD_LATEX tag is set to YES Doxygen will generate
# the necessary Makefile rules, Perl scripts and LaTeX code to be able
# to generate PDF and DVI output from the Perl module output.
PERLMOD_LATEX = NO
# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be
# nicely formatted so it can be parsed by a human reader.
# This is useful
# if you want to understand what is going on.
# On the other hand, if this
# tag is set to NO the size of the Perl module output will be much smaller
# and Perl will parse it just the same.
PERLMOD_PRETTY = YES
# The names of the make variables in the generated doxyrules.make file
# are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX.
# This is useful so different doxyrules.make files included by the same
# Makefile don't overwrite each other's variables.
PERLMOD_MAKEVAR_PREFIX =
#---------------------------------------------------------------------------
# Configuration options related to the preprocessor
#---------------------------------------------------------------------------
# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will
# evaluate all C-preprocessor directives found in the sources and include
# files.
ENABLE_PREPROCESSING = YES
# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro
# names in the source code. If set to NO (the default) only conditional
# compilation will be performed. Macro expansion can be done in a controlled
# way by setting EXPAND_ONLY_PREDEF to YES.
MACRO_EXPANSION = NO
# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES
# then the macro expansion is limited to the macros specified with the
# PREDEFINED and EXPAND_AS_DEFINED tags.
EXPAND_ONLY_PREDEF = NO
# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files
# in the INCLUDE_PATH (see below) will be search if a #include is found.
SEARCH_INCLUDES = YES
# The INCLUDE_PATH tag can be used to specify one or more directories that
# contain include files that are not input files but should be processed by
# the preprocessor.
INCLUDE_PATH =
# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard
# patterns (like *.h and *.hpp) to filter out the header-files in the
# directories. If left blank, the patterns specified with FILE_PATTERNS will
# be used.
INCLUDE_FILE_PATTERNS =
# The PREDEFINED tag can be used to specify one or more macro names that
# are defined before the preprocessor is started (similar to the -D option of
# gcc). The argument of the tag is a list of macros of the form: name
# or name=definition (no spaces). If the definition and the = are
# omitted =1 is assumed. To prevent a macro definition from being
# undefined via #undef or recursively expanded use the := operator
# instead of the = operator.
PREDEFINED =
# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then
# this tag can be used to specify a list of macro names that should be expanded.
# The macro definition that is found in the sources will be used.
# Use the PREDEFINED tag if you want to use a different macro definition.
EXPAND_AS_DEFINED =
# If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then
# doxygen's preprocessor will remove all function-like macros that are alone
# on a line, have an all uppercase name, and do not end with a semicolon. Such
# function macros are typically used for boiler-plate code, and will confuse
# the parser if not removed.
SKIP_FUNCTION_MACROS = YES
#---------------------------------------------------------------------------
# Configuration::additions related to external references
#---------------------------------------------------------------------------
# The TAGFILES option can be used to specify one or more tagfiles.
# Optionally an initial location of the external documentation
# can be added for each tagfile. The format of a tag file without
# this location is as follows:
#
# TAGFILES = file1 file2 ...
# Adding location for the tag files is done as follows:
#
# TAGFILES = file1=loc1 "file2 = loc2" ...
# where "loc1" and "loc2" can be relative or absolute paths or
# URLs. If a location is present for each tag, the installdox tool
# does not have to be run to correct the links.
# Note that each tag file must have a unique name
# (where the name does NOT include the path)
# If a tag file is not located in the directory in which doxygen
# is run, you must also specify the path to the tagfile here.
TAGFILES =
# When a file name is specified after GENERATE_TAGFILE, doxygen will create
# a tag file that is based on the input files it reads.
GENERATE_TAGFILE = @CMAKE_CURRENT_BINARY_DIR@/html/@PROJECT_NAME@.TAGFILE
# If the ALLEXTERNALS tag is set to YES all external classes will be listed
# in the class index. If set to NO only the inherited external classes
# will be listed.
ALLEXTERNALS = YES
# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed
# in the modules index. If set to NO, only the current project's groups will
# be listed.
EXTERNAL_GROUPS = YES
# The PERL_PATH should be the absolute path and name of the perl script
# interpreter (i.e. the result of `which perl').
PERL_PATH = /usr/bin/perl
#---------------------------------------------------------------------------
# Configuration options related to the dot tool
#---------------------------------------------------------------------------
# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will
# generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base
# or super classes. Setting the tag to NO turns the diagrams off. Note that
# this option is superseded by the HAVE_DOT option below. This is only a
# fallback. It is recommended to install and use dot, since it yields more
# powerful graphs.
CLASS_DIAGRAMS = NO
# You can define message sequence charts within doxygen comments using the \msc
# command. Doxygen will then run the mscgen tool (see
# http://www.mcternan.me.uk/mscgen/) to produce the chart and insert it in the
# documentation. The MSCGEN_PATH tag allows you to specify the directory where
# the mscgen tool resides. If left empty the tool is assumed to be found in the
# default search path.
MSCGEN_PATH =
# If set to YES, the inheritance and collaboration graphs will hide
# inheritance and usage relations if the target is undocumented
# or is not a class.
HIDE_UNDOC_RELATIONS = YES
# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is
# available from the path. This tool is part of Graphviz, a graph visualization
# toolkit from AT&T and Lucent Bell Labs. The other options in this section
# have no effect if this option is set to NO (the default)
HAVE_DOT = @DOXYGEN_DOT_FOUND@
# By default doxygen will write a font called FreeSans.ttf to the output
# directory and reference it in all dot files that doxygen generates. This
# font does not include all possible unicode characters however, so when you need
# these (or just want a differently looking font) you can specify the font name
# using DOT_FONTNAME. You need need to make sure dot is able to find the font,
# which can be done by putting it in a standard location or by setting the
# DOTFONTPATH environment variable or by setting DOT_FONTPATH to the directory
# containing the font.
DOT_FONTNAME = FreeSans
# The DOT_FONTSIZE tag can be used to set the size of the font of dot graphs.
# The default size is 10pt.
DOT_FONTSIZE = 10
# By default doxygen will tell dot to use the output directory to look for the
# FreeSans.ttf font (which doxygen will put there itself). If you specify a
# different font using DOT_FONTNAME you can set the path where dot
# can find it using this tag.
DOT_FONTPATH =
# If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen
# will generate a graph for each documented class showing the direct and
# indirect inheritance relations. Setting this tag to YES will force the
# the CLASS_DIAGRAMS tag to NO.
CLASS_GRAPH = YES
# If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen
# will generate a graph for each documented class showing the direct and
# indirect implementation dependencies (inheritance, containment, and
# class references variables) of the class with other documented classes.
COLLABORATION_GRAPH = YES
# If the GROUP_GRAPHS and HAVE_DOT tags are set to YES then doxygen
# will generate a graph for groups, showing the direct groups dependencies
GROUP_GRAPHS = YES
# If the UML_LOOK tag is set to YES doxygen will generate inheritance and
# collaboration diagrams in a style similar to the OMG's Unified Modeling
# Language.
UML_LOOK = NO
# If set to YES, the inheritance and collaboration graphs will show the
# relations between templates and their instances.
TEMPLATE_RELATIONS = YES
# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT
# tags are set to YES then doxygen will generate a graph for each documented
# file showing the direct and indirect include dependencies of the file with
# other documented files.
INCLUDE_GRAPH = YES
# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and
# HAVE_DOT tags are set to YES then doxygen will generate a graph for each
# documented header file showing the documented files that directly or
# indirectly include this file.
INCLUDED_BY_GRAPH = YES
# If the CALL_GRAPH and HAVE_DOT options are set to YES then
# doxygen will generate a call dependency graph for every global function
# or class method. Note that enabling this option will significantly increase
# the time of a run. So in most cases it will be better to enable call graphs
# for selected functions only using the \callgraph command.
CALL_GRAPH = YES
# If the CALLER_GRAPH and HAVE_DOT tags are set to YES then
# doxygen will generate a caller dependency graph for every global function
# or class method. Note that enabling this option will significantly increase
# the time of a run. So in most cases it will be better to enable caller
# graphs for selected functions only using the \callergraph command.
CALLER_GRAPH = YES
# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen
# will graphical hierarchy of all classes instead of a textual one.
GRAPHICAL_HIERARCHY = YES
# If the DIRECTORY_GRAPH, SHOW_DIRECTORIES and HAVE_DOT tags are set to YES
# then doxygen will show the dependencies a directory has on other directories
# in a graphical way. The dependency relations are determined by the #include
# relations between the files in the directories.
DIRECTORY_GRAPH = YES
# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images
# generated by dot. Possible values are png, jpg, or gif
# If left blank png will be used.
DOT_IMAGE_FORMAT = png
# The tag DOT_PATH can be used to specify the path where the dot tool can be
# found. If left blank, it is assumed the dot tool can be found in the path.
DOT_PATH = @DOXYGEN_DOT_EXECUTABLE_PATH@
# The DOTFILE_DIRS tag can be used to specify one or more directories that
# contain dot files that are included in the documentation (see the
# \dotfile command).
DOTFILE_DIRS =
# The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of
# nodes that will be shown in the graph. If the number of nodes in a graph
# becomes larger than this value, doxygen will truncate the graph, which is
# visualized by representing a node as a red box. Note that doxygen if the
# number of direct children of the root node in a graph is already larger than
# DOT_GRAPH_MAX_NODES then the graph will not be shown at all. Also note
# that the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH.
DOT_GRAPH_MAX_NODES = 50
# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the
# graphs generated by dot. A depth value of 3 means that only nodes reachable
# from the root by following a path via at most 3 edges will be shown. Nodes
# that lay further from the root node will be omitted. Note that setting this
# option to 1 or 2 may greatly reduce the computation time needed for large
# code bases. Also note that the size of a graph can be further restricted by
# DOT_GRAPH_MAX_NODES. Using a depth of 0 means no depth restriction.
MAX_DOT_GRAPH_DEPTH = 0
# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent
# background. This is disabled by default, because dot on Windows does not
# seem to support this out of the box. Warning: Depending on the platform used,
# enabling this option may lead to badly anti-aliased labels on the edges of
# a graph (i.e. they become hard to read).
DOT_TRANSPARENT = NO
# Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output
# files in one run (i.e. multiple -o and -T options on the command line). This
# makes dot run faster, but since only newer versions of dot (>1.8.10)
# support this, this feature is disabled by default.
DOT_MULTI_TARGETS = YES
# If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will
# generate a legend page explaining the meaning of the various boxes and
# arrows in the dot generated graphs.
GENERATE_LEGEND = YES
# If the DOT_CLEANUP tag is set to YES (the default) Doxygen will
# remove the intermediate dot files that are used to generate
# the various graphs.
DOT_CLEANUP = YES
#---------------------------------------------------------------------------
# Options related to the search engine
#---------------------------------------------------------------------------
# The SEARCHENGINE tag specifies whether or not a search engine should be
# used. If set to NO the values of all tags below this one will be ignored.
SEARCHENGINE = NO
cgreen-1.3.0/doc/logo.odt 0000775 0000000 0000000 00000044630 13666233252 0015215 0 ustar 00root root 0000000 0000000 PK :P^2' ' mimetypeapplication/vnd.oasis.opendocument.textPK :P Configurations2/popupmenu/PK :P Configurations2/progressbar/PK :P Configurations2/menubar/PK :P Configurations2/statusbar/PK :P Configurations2/toolbar/PK :P Configurations2/images/Bitmaps/PK :P Configurations2/accelerator/PK :P Configurations2/floater/PK :P Configurations2/toolpanel/PK :P manifest.rdf͓n0