Merge branch 'develop' into coverity_scan

This commit is contained in:
Niels 2016-06-19 18:33:46 +02:00
commit 550475b5e1
8 changed files with 423 additions and 234 deletions

3
.gitignore vendored
View file

@ -10,4 +10,5 @@ working
html html
me.nlohmann.json.docset me.nlohmann.json.docset
android android
doc/xml

View file

@ -26,6 +26,7 @@ matrix:
- make json_unit CXXFLAGS="-fprofile-arcs -ftest-coverage -std=c++11 -lstdc++" CXX=$COMPILER - make json_unit CXXFLAGS="-fprofile-arcs -ftest-coverage -std=c++11 -lstdc++" CXX=$COMPILER
- ./json_unit "*" - ./json_unit "*"
- coveralls --exclude test/src/catch.hpp --exclude test/src/unit.cpp --include src/json.hpp --gcov-options '\-lp' --gcov 'gcov-4.9' - coveralls --exclude test/src/catch.hpp --exclude test/src/unit.cpp --include src/json.hpp --gcov-options '\-lp' --gcov 'gcov-4.9'
- bash <(curl -s https://codecov.io/bash)
env: COMPILER=g++-4.9 env: COMPILER=g++-4.9
- os: linux - os: linux
@ -44,6 +45,21 @@ matrix:
branch_pattern: coverity_scan branch_pattern: coverity_scan
env: COMPILER=g++-5 env: COMPILER=g++-5
# from https://github.com/travis-ci/travis-ci/issues/6120
- os: linux
env:
- LLVM_VERSION=3.8.0
- LLVM_ARCHIVE_PATH=$HOME/clang+llvm.tar.xz
- COMPILER=clang++
- CPPFLAGS="-I $HOME/clang-$LLVM_VERSION/include/c++/v1"
- CXXFLAGS=-lc++
- PATH=$HOME/clang-$LLVM_VERSION/bin:$PATH
- LD_LIBRARY_PATH=$HOME/clang-$LLVM_VERSION/lib:$LD_LIBRARY_PATH
before_install:
- wget http://llvm.org/releases/$LLVM_VERSION/clang+llvm-$LLVM_VERSION-x86_64-linux-gnu-ubuntu-14.04.tar.xz -O $LLVM_ARCHIVE_PATH
- mkdir $HOME/clang-$LLVM_VERSION
- tar xf $LLVM_ARCHIVE_PATH -C $HOME/clang-$LLVM_VERSION --strip-components 1
# - os: linux # - os: linux
# compiler: gcc # compiler: gcc
# addons: # addons:
@ -55,29 +71,29 @@ matrix:
# Clang 3.5 is not able to compile the code, # Clang 3.5 is not able to compile the code,
# see https://travis-ci.org/nlohmann/json/jobs/126720186 # see https://travis-ci.org/nlohmann/json/jobs/126720186
- os: linux # - os: linux
compiler: clang # compiler: clang
addons: # addons:
apt: # apt:
sources: ['ubuntu-toolchain-r-test', 'llvm-toolchain-precise-3.6'] # sources: ['ubuntu-toolchain-r-test', 'llvm-toolchain-precise-3.6']
packages: ['clang-3.6', 'valgrind'] # packages: ['clang-3.6', 'valgrind']
env: COMPILER=clang++-3.6 # env: COMPILER=clang++-3.6
#
- os: linux # - os: linux
compiler: clang # compiler: clang
addons: # addons:
apt: # apt:
sources: ['ubuntu-toolchain-r-test', 'llvm-toolchain-precise-3.7'] # sources: ['ubuntu-toolchain-r-test', 'llvm-toolchain-precise-3.7']
packages: ['clang-3.7', 'valgrind'] # packages: ['clang-3.7', 'valgrind']
env: COMPILER=clang++-3.7 # env: COMPILER=clang++-3.7
#
- os: linux # - os: linux
compiler: clang # compiler: clang
addons: # addons:
apt: # apt:
sources: ['ubuntu-toolchain-r-test', 'llvm-toolchain-precise-3.8'] # sources: ['ubuntu-toolchain-r-test', 'llvm-toolchain-precise-3.8']
packages: ['clang-3.8', 'valgrind'] # packages: ['clang-3.8', 'valgrind']
env: COMPILER=clang++-3.8 # env: COMPILER=clang++-3.8
# - os: linux # - os: linux
# compiler: clang # compiler: clang
@ -90,42 +106,63 @@ matrix:
- os: osx - os: osx
osx_image: beta-xcode6.1 osx_image: beta-xcode6.1
compiler: clang compiler: clang
env: COMPILER=clang env:
- COMPILER=clang
- CXXFLAGS=-lstdc++
- os: osx - os: osx
osx_image: beta-xcode6.2 osx_image: beta-xcode6.2
compiler: clang compiler: clang
env: COMPILER=clang env:
- COMPILER=clang
- CXXFLAGS=-lstdc++
# - os: osx - os: osx
# osx_image: beta-xcode6.3 osx_image: beta-xcode6.3
# compiler: clang compiler: clang
# env: COMPILER=clang env:
- COMPILER=clang
- CXXFLAGS=-lstdc++
- os: osx - os: osx
osx_image: xcode6.4 osx_image: xcode6.4
compiler: clang compiler: clang
env: COMPILER=clang env:
- COMPILER=clang
- CXXFLAGS=-lstdc++
- os: osx - os: osx
osx_image: xcode7.1 osx_image: xcode7.1
compiler: clang compiler: clang
env: COMPILER=clang env:
- COMPILER=clang
- CXXFLAGS=-lstdc++
- os: osx - os: osx
osx_image: xcode7.2 osx_image: xcode7.2
compiler: clang compiler: clang
env: COMPILER=clang env:
- COMPILER=clang
- CXXFLAGS=-lstdc++
- os: osx - os: osx
osx_image: xcode7.3 osx_image: xcode7.3
compiler: clang compiler: clang
env: COMPILER=clang env:
- COMPILER=clang
- CXXFLAGS=-lstdc++
- os: osx
osx_image: xcode8
compiler: clang
env:
- COMPILER=clang
- CXXFLAGS=-lstdc++
script: script:
- uname -a - uname -a
- $COMPILER --version - $COMPILER --version
- make CXX=$COMPILER CXXFLAGS="-lstdc++" - make CXX=$COMPILER
- ./json_unit "*" - ./json_unit "*"
- if [ `which valgrind` ]; then - if [ `which valgrind` ]; then
valgrind --error-exitcode=1 --leak-check=full ./json_unit ; valgrind --error-exitcode=1 --leak-check=full ./json_unit ;

View file

@ -41,7 +41,7 @@ using json = nlohmann::json;
to the files you want to use JSON objects. That's it. Do not forget to set the necessary switches to enable C++11 (e.g., `-std=c++11` for GCC and Clang). to the files you want to use JSON objects. That's it. Do not forget to set the necessary switches to enable C++11 (e.g., `-std=c++11` for GCC and Clang).
:beer: If you are using OS X and [Homebrew](http://brew.sh), just type `brew tap nlohmann/json` and `brew install nlohmann_json` and you're set. :beer: If you are using OS X and [Homebrew](http://brew.sh), just type `brew tap nlohmann/json` and `brew install nlohmann_json` and you're set. If you want the bleeding edge rather than the latest release, use `brew install nlohmann_json --HEAD`.
## Supported compilers ## Supported compilers
@ -72,12 +72,9 @@ The following compilers are currently used in [continuous integration](https://t
| Compiler | Operating System | Version String | | Compiler | Operating System | Version String |
|-----------------|------------------------------|----------------| |-----------------|------------------------------|----------------|
| GCC 4.9.3 | Ubuntu 14.04.3 LTS | g++-4.9 (Ubuntu 4.9.3-8ubuntu2~14.04) 4.9.3 | | GCC 4.9.3 | Ubuntu 14.04.4 LTS | g++-4.9 (Ubuntu 4.9.3-8ubuntu2~14.04) 4.9.3 |
| GCC 5.3.0 | Ubuntu 14.04.3 LTS | g++-5 (Ubuntu 5.3.0-3ubuntu1~14.04) 5.3.0 20151204 | | GCC 5.3.0 | Ubuntu 14.04.4 LTS | g++-5 (Ubuntu 5.3.0-3ubuntu1~14.04) 5.3.0 20151204 |
| Clang 3.6.2 | Ubuntu 14.04.3 LTS | Ubuntu clang version 3.6.2-svn240577-1~exp1 (branches/release_36) (based on LLVM 3.6.2) | | Clang 3.8.0 | Ubuntu 14.04.4 LTS | clang version 3.8.0 (tags/RELEASE_380/final) |
| Clang 3.7.1 | Ubuntu 14.04.3 LTS | Ubuntu clang version 3.7.1-svn253571-1~exp1 (branches/release_37) (based on LLVM 3.7.1) |
| Clang 3.8.1 | Ubuntu 14.04.3 LTS | clang version 3.8.1-svn265380-1~exp1 (branches/release_38) |
| Clang 3.9.0 | Ubuntu 14.04.3 LTS | clang version 3.9.0-svn267478-1~exp1 (trunk) |
| Clang Xcode 6.1 | Darwin Kernel Version 13.4.0 (OSX 10.9.5) | Apple LLVM version 6.0 (clang-600.0.54) (based on LLVM 3.5svn) | | Clang Xcode 6.1 | Darwin Kernel Version 13.4.0 (OSX 10.9.5) | Apple LLVM version 6.0 (clang-600.0.54) (based on LLVM 3.5svn) |
| Clang Xcode 6.2 | Darwin Kernel Version 13.4.0 (OSX 10.9.5) | Apple LLVM version 6.0 (clang-600.0.57) (based on LLVM 3.5svn) | | Clang Xcode 6.2 | Darwin Kernel Version 13.4.0 (OSX 10.9.5) | Apple LLVM version 6.0 (clang-600.0.57) (based on LLVM 3.5svn) |
| Clang Xcode 6.3 | Darwin Kernel Version 14.3.0 (OSX 10.10.3) | Apple LLVM version 6.1.0 (clang-602.0.49) (based on LLVM 3.6.0svn) | | Clang Xcode 6.3 | Darwin Kernel Version 14.3.0 (OSX 10.10.3) | Apple LLVM version 6.1.0 (clang-602.0.49) (based on LLVM 3.6.0svn) |
@ -85,6 +82,7 @@ The following compilers are currently used in [continuous integration](https://t
| Clang Xcode 7.1 | Darwin Kernel Version 14.5.0 (OSX 10.10.5) | Apple LLVM version 7.0.0 (clang-700.1.76) | | Clang Xcode 7.1 | Darwin Kernel Version 14.5.0 (OSX 10.10.5) | Apple LLVM version 7.0.0 (clang-700.1.76) |
| Clang Xcode 7.2 | Darwin Kernel Version 15.0.0 (OSX 10.10.5) | Apple LLVM version 7.0.2 (clang-700.1.81) | | Clang Xcode 7.2 | Darwin Kernel Version 15.0.0 (OSX 10.10.5) | Apple LLVM version 7.0.2 (clang-700.1.81) |
| Clang Xcode 7.3 | Darwin Kernel Version 14.5.0 (OSX 10.11.1) | Apple LLVM version 7.3.0 (clang-703.0.29) | | Clang Xcode 7.3 | Darwin Kernel Version 14.5.0 (OSX 10.11.1) | Apple LLVM version 7.3.0 (clang-703.0.29) |
| Clang Xcode 8.0 | Darwin Kernel Version 15.5.0 (OSX 10.11.5) | Apple LLVM version 8.0.0 (clang-800.0.24.1) |
| Visual Studio 14 2015 | Windows Server 2012 R2 (x64) | Microsoft (R) Build Engine version 14.0.25123.0 | | Visual Studio 14 2015 | Windows Server 2012 R2 (x64) | Microsoft (R) Build Engine version 14.0.25123.0 |
## Examples ## Examples
@ -436,6 +434,7 @@ I deeply appreciate the help of the following people.
- [zewt](https://github.com/zewt) added useful notes to the README file about Android. - [zewt](https://github.com/zewt) added useful notes to the README file about Android.
- [Róbert Márki](https://github.com/robertmrk) added a fix to use move iterators and improved the integration via CMake. - [Róbert Márki](https://github.com/robertmrk) added a fix to use move iterators and improved the integration via CMake.
- [Chris Kitching](https://github.com/ChrisKitching) cleaned up the CMake files. - [Chris Kitching](https://github.com/ChrisKitching) cleaned up the CMake files.
- [Tom Needham](https://github.com/06needhamt) fixed a subtle bug with MSVC 2015 which was also proposed by [Michael K.](https://github.com/Epidal).
Thanks a lot for helping out! Thanks a lot for helping out!

View file

@ -236,7 +236,7 @@ MAN_LINKS = NO
#--------------------------------------------------------------------------- #---------------------------------------------------------------------------
# Configuration options related to the XML output # Configuration options related to the XML output
#--------------------------------------------------------------------------- #---------------------------------------------------------------------------
GENERATE_XML = NO GENERATE_XML = YES
XML_OUTPUT = xml XML_OUTPUT = xml
XML_PROGRAMLISTING = YES XML_PROGRAMLISTING = YES
#--------------------------------------------------------------------------- #---------------------------------------------------------------------------

View file

@ -1461,13 +1461,13 @@ class basic_json
@since version 2.0.0 @since version 2.0.0
*/ */
template < typename CompatibleNumberUnsignedType, typename template <typename CompatibleNumberUnsignedType, typename
std::enable_if < std::enable_if <
std::is_constructible<number_unsigned_t, CompatibleNumberUnsignedType>::value and std::is_constructible<number_unsigned_t, CompatibleNumberUnsignedType>::value and
std::numeric_limits<CompatibleNumberUnsignedType>::is_integer and std::numeric_limits<CompatibleNumberUnsignedType>::is_integer and
!std::numeric_limits<CompatibleNumberUnsignedType>::is_signed, not std::numeric_limits<CompatibleNumberUnsignedType>::is_signed,
CompatibleNumberUnsignedType >::type CompatibleNumberUnsignedType>::type
= 0 > = 0>
basic_json(const CompatibleNumberUnsignedType val) noexcept basic_json(const CompatibleNumberUnsignedType val) noexcept
: m_type(value_t::number_unsigned), : m_type(value_t::number_unsigned),
m_value(static_cast<number_unsigned_t>(val)) m_value(static_cast<number_unsigned_t>(val))
@ -5079,6 +5079,7 @@ class basic_json
throw std::domain_error("iterator does not fit current value"); throw std::domain_error("iterator does not fit current value");
} }
// check if range iterators belong to the same JSON object
if (first.m_object != last.m_object) if (first.m_object != last.m_object)
{ {
throw std::domain_error("iterators do not fit"); throw std::domain_error("iterators do not fit");
@ -7277,17 +7278,17 @@ class basic_json
enum class token_type enum class token_type
{ {
uninitialized, ///< indicating the scanner is uninitialized uninitialized, ///< indicating the scanner is uninitialized
literal_true, ///< the "true" literal literal_true, ///< the `true` literal
literal_false, ///< the "false" literal literal_false, ///< the `false` literal
literal_null, ///< the "null" literal literal_null, ///< the `null` literal
value_string, ///< a string -- use get_string() for actual value value_string, ///< a string -- use get_string() for actual value
value_number, ///< a number -- use get_number() for actual value value_number, ///< a number -- use get_number() for actual value
begin_array, ///< the character for array begin "[" begin_array, ///< the character for array begin `[`
begin_object, ///< the character for object begin "{" begin_object, ///< the character for object begin `{`
end_array, ///< the character for array end "]" end_array, ///< the character for array end `]`
end_object, ///< the character for object end "}" end_object, ///< the character for object end `}`
name_separator, ///< the name separator ":" name_separator, ///< the name separator `:`
value_separator, ///< the value separator "," value_separator, ///< the value separator `,`
parse_error, ///< indicating a parse error parse_error, ///< indicating a parse error
end_of_input ///< indicating the end of the input buffer end_of_input ///< indicating the end of the input buffer
}; };
@ -7332,7 +7333,7 @@ class basic_json
@return string representation of the code point @return string representation of the code point
@throw std::out_of_range if code point is >0x10ffff; example: `"code @throw std::out_of_range if code point is > 0x10ffff; example: `"code
points above 0x10FFFF are invalid"` points above 0x10FFFF are invalid"`
@throw std::invalid_argument if the low surrogate is invalid; example: @throw std::invalid_argument if the low surrogate is invalid; example:
`""missing or wrong low surrogate""` `""missing or wrong low surrogate""`
@ -8497,13 +8498,13 @@ basic_json_parser_63:
if (*curptr == '-') if (*curptr == '-')
{ {
type = value_t::number_integer; type = value_t::number_integer;
max = static_cast<uint64_t>(std::numeric_limits<number_integer_t>::max()) + 1; max = static_cast<uint64_t>((std::numeric_limits<number_integer_t>::max)()) + 1;
curptr++; curptr++;
} }
else else
{ {
type = value_t::number_unsigned; type = value_t::number_unsigned;
max = static_cast<uint64_t>(std::numeric_limits<number_unsigned_t>::max()); max = static_cast<uint64_t>((std::numeric_limits<number_unsigned_t>::max)());
} }
// count the significant figures // count the significant figures

View file

@ -1461,13 +1461,13 @@ class basic_json
@since version 2.0.0 @since version 2.0.0
*/ */
template < typename CompatibleNumberUnsignedType, typename template <typename CompatibleNumberUnsignedType, typename
std::enable_if < std::enable_if <
std::is_constructible<number_unsigned_t, CompatibleNumberUnsignedType>::value and std::is_constructible<number_unsigned_t, CompatibleNumberUnsignedType>::value and
std::numeric_limits<CompatibleNumberUnsignedType>::is_integer and std::numeric_limits<CompatibleNumberUnsignedType>::is_integer and
!std::numeric_limits<CompatibleNumberUnsignedType>::is_signed, not std::numeric_limits<CompatibleNumberUnsignedType>::is_signed,
CompatibleNumberUnsignedType >::type CompatibleNumberUnsignedType>::type
= 0 > = 0>
basic_json(const CompatibleNumberUnsignedType val) noexcept basic_json(const CompatibleNumberUnsignedType val) noexcept
: m_type(value_t::number_unsigned), : m_type(value_t::number_unsigned),
m_value(static_cast<number_unsigned_t>(val)) m_value(static_cast<number_unsigned_t>(val))
@ -5079,6 +5079,7 @@ class basic_json
throw std::domain_error("iterator does not fit current value"); throw std::domain_error("iterator does not fit current value");
} }
// check if range iterators belong to the same JSON object
if (first.m_object != last.m_object) if (first.m_object != last.m_object)
{ {
throw std::domain_error("iterators do not fit"); throw std::domain_error("iterators do not fit");
@ -7277,17 +7278,17 @@ class basic_json
enum class token_type enum class token_type
{ {
uninitialized, ///< indicating the scanner is uninitialized uninitialized, ///< indicating the scanner is uninitialized
literal_true, ///< the "true" literal literal_true, ///< the `true` literal
literal_false, ///< the "false" literal literal_false, ///< the `false` literal
literal_null, ///< the "null" literal literal_null, ///< the `null` literal
value_string, ///< a string -- use get_string() for actual value value_string, ///< a string -- use get_string() for actual value
value_number, ///< a number -- use get_number() for actual value value_number, ///< a number -- use get_number() for actual value
begin_array, ///< the character for array begin "[" begin_array, ///< the character for array begin `[`
begin_object, ///< the character for object begin "{" begin_object, ///< the character for object begin `{`
end_array, ///< the character for array end "]" end_array, ///< the character for array end `]`
end_object, ///< the character for object end "}" end_object, ///< the character for object end `}`
name_separator, ///< the name separator ":" name_separator, ///< the name separator `:`
value_separator, ///< the value separator "," value_separator, ///< the value separator `,`
parse_error, ///< indicating a parse error parse_error, ///< indicating a parse error
end_of_input ///< indicating the end of the input buffer end_of_input ///< indicating the end of the input buffer
}; };
@ -7332,7 +7333,7 @@ class basic_json
@return string representation of the code point @return string representation of the code point
@throw std::out_of_range if code point is >0x10ffff; example: `"code @throw std::out_of_range if code point is > 0x10ffff; example: `"code
points above 0x10FFFF are invalid"` points above 0x10FFFF are invalid"`
@throw std::invalid_argument if the low surrogate is invalid; example: @throw std::invalid_argument if the low surrogate is invalid; example:
`""missing or wrong low surrogate""` `""missing or wrong low surrogate""`
@ -7807,13 +7808,13 @@ class basic_json
if (*curptr == '-') if (*curptr == '-')
{ {
type = value_t::number_integer; type = value_t::number_integer;
max = static_cast<uint64_t>(std::numeric_limits<number_integer_t>::max()) + 1; max = static_cast<uint64_t>((std::numeric_limits<number_integer_t>::max)()) + 1;
curptr++; curptr++;
} }
else else
{ {
type = value_t::number_unsigned; type = value_t::number_unsigned;
max = static_cast<uint64_t>(std::numeric_limits<number_unsigned_t>::max()); max = static_cast<uint64_t>((std::numeric_limits<number_unsigned_t>::max)());
} }
// count the significant figures // count the significant figures

View file

@ -1,6 +1,6 @@
/* /*
* Catch v1.3.4 * Catch v1.5.6
* Generated: 2016-02-10 19:24:03.089683 * Generated: 2016-06-09 19:20:41.460328
* ---------------------------------------------------------- * ----------------------------------------------------------
* This file has been merged from multiple headers. Please don't edit it directly * This file has been merged from multiple headers. Please don't edit it directly
* Copyright (c) 2012 Two Blue Cubes Ltd. All rights reserved. * Copyright (c) 2012 Two Blue Cubes Ltd. All rights reserved.
@ -62,7 +62,11 @@
#define INTERNAL_CATCH_UNIQUE_NAME_LINE2( name, line ) name##line #define INTERNAL_CATCH_UNIQUE_NAME_LINE2( name, line ) name##line
#define INTERNAL_CATCH_UNIQUE_NAME_LINE( name, line ) INTERNAL_CATCH_UNIQUE_NAME_LINE2( name, line ) #define INTERNAL_CATCH_UNIQUE_NAME_LINE( name, line ) INTERNAL_CATCH_UNIQUE_NAME_LINE2( name, line )
#define INTERNAL_CATCH_UNIQUE_NAME( name ) INTERNAL_CATCH_UNIQUE_NAME_LINE( name, __LINE__ ) #ifdef CATCH_CONFIG_COUNTER
# define INTERNAL_CATCH_UNIQUE_NAME( name ) INTERNAL_CATCH_UNIQUE_NAME_LINE( name, __COUNTER__ )
#else
# define INTERNAL_CATCH_UNIQUE_NAME( name ) INTERNAL_CATCH_UNIQUE_NAME_LINE( name, __LINE__ )
#endif
#define INTERNAL_CATCH_STRINGIFY2( expr ) #expr #define INTERNAL_CATCH_STRINGIFY2( expr ) #expr
#define INTERNAL_CATCH_STRINGIFY( expr ) INTERNAL_CATCH_STRINGIFY2( expr ) #define INTERNAL_CATCH_STRINGIFY( expr ) INTERNAL_CATCH_STRINGIFY2( expr )
@ -89,7 +93,7 @@
// CATCH_CONFIG_CPP11_OR_GREATER : Is C++11 supported? // CATCH_CONFIG_CPP11_OR_GREATER : Is C++11 supported?
// CATCH_CONFIG_VARIADIC_MACROS : are variadic macros supported? // CATCH_CONFIG_VARIADIC_MACROS : are variadic macros supported?
// CATCH_CONFIG_COUNTER : is the __COUNTER__ macro supported?
// **************** // ****************
// Note to maintainers: if new toggles are added please document them // Note to maintainers: if new toggles are added please document them
// in configuration.md, too // in configuration.md, too
@ -102,6 +106,18 @@
// All the C++11 features can be disabled with CATCH_CONFIG_NO_CPP11 // All the C++11 features can be disabled with CATCH_CONFIG_NO_CPP11
#ifdef __cplusplus
# if __cplusplus >= 201103L
# define CATCH_CPP11_OR_GREATER
# endif
# if __cplusplus >= 201402L
# define CATCH_CPP14_OR_GREATER
# endif
#endif
#ifdef __clang__ #ifdef __clang__
# if __has_feature(cxx_nullptr) # if __has_feature(cxx_nullptr)
@ -112,6 +128,10 @@
# define CATCH_INTERNAL_CONFIG_CPP11_NOEXCEPT # define CATCH_INTERNAL_CONFIG_CPP11_NOEXCEPT
# endif # endif
# if defined(CATCH_CPP11_OR_GREATER)
# define CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS _Pragma( "clang diagnostic ignored \"-Wparentheses\"" )
# endif
#endif // __clang__ #endif // __clang__
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
@ -136,9 +156,13 @@
// GCC // GCC
#ifdef __GNUC__ #ifdef __GNUC__
#if __GNUC__ == 4 && __GNUC_MINOR__ >= 6 && defined(__GXX_EXPERIMENTAL_CXX0X__) # if __GNUC__ == 4 && __GNUC_MINOR__ >= 6 && defined(__GXX_EXPERIMENTAL_CXX0X__)
# define CATCH_INTERNAL_CONFIG_CPP11_NULLPTR # define CATCH_INTERNAL_CONFIG_CPP11_NULLPTR
#endif # endif
# if !defined(CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS) && defined(CATCH_CPP11_OR_GREATER)
# define CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS _Pragma( "GCC diagnostic ignored \"-Wparentheses\"" )
# endif
// - otherwise more recent versions define __cplusplus >= 201103L // - otherwise more recent versions define __cplusplus >= 201103L
// and will get picked up below // and will get picked up below
@ -173,13 +197,20 @@
#endif #endif
// Use __COUNTER__ if the compiler supports it
#if ( defined _MSC_VER && _MSC_VER >= 1300 ) || \
( defined __GNUC__ && __GNUC__ >= 4 && __GNUC_MINOR__ >= 3 ) || \
( defined __clang__ && __clang_major__ >= 3 )
#define CATCH_INTERNAL_CONFIG_COUNTER
#endif
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// C++ language feature support // C++ language feature support
// catch all support for C++11 // catch all support for C++11
#if defined(__cplusplus) && __cplusplus >= 201103L #if defined(CATCH_CPP11_OR_GREATER)
# define CATCH_CPP11_OR_GREATER
# if !defined(CATCH_INTERNAL_CONFIG_CPP11_NULLPTR) # if !defined(CATCH_INTERNAL_CONFIG_CPP11_NULLPTR)
# define CATCH_INTERNAL_CONFIG_CPP11_NULLPTR # define CATCH_INTERNAL_CONFIG_CPP11_NULLPTR
@ -246,6 +277,13 @@
#if defined(CATCH_INTERNAL_CONFIG_CPP11_UNIQUE_PTR) && !defined(CATCH_CONFIG_NO_UNIQUE_PTR) && !defined(CATCH_CONFIG_CPP11_UNIQUE_PTR) && !defined(CATCH_CONFIG_NO_CPP11) #if defined(CATCH_INTERNAL_CONFIG_CPP11_UNIQUE_PTR) && !defined(CATCH_CONFIG_NO_UNIQUE_PTR) && !defined(CATCH_CONFIG_CPP11_UNIQUE_PTR) && !defined(CATCH_CONFIG_NO_CPP11)
# define CATCH_CONFIG_CPP11_UNIQUE_PTR # define CATCH_CONFIG_CPP11_UNIQUE_PTR
#endif #endif
#if defined(CATCH_INTERNAL_CONFIG_COUNTER) && !defined(CATCH_CONFIG_NO_COUNTER) && !defined(CATCH_CONFIG_COUNTER)
# define CATCH_CONFIG_COUNTER
#endif
#if !defined(CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS)
# define CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS
#endif
// noexcept support: // noexcept support:
#if defined(CATCH_CONFIG_CPP11_NOEXCEPT) && !defined(CATCH_NOEXCEPT) #if defined(CATCH_CONFIG_CPP11_NOEXCEPT) && !defined(CATCH_NOEXCEPT)
@ -672,24 +710,28 @@ void registerTestCaseFunction
#ifdef CATCH_CONFIG_VARIADIC_MACROS #ifdef CATCH_CONFIG_VARIADIC_MACROS
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
#define INTERNAL_CATCH_TESTCASE2( TestName, ... ) \
static void TestName(); \
namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( &TestName, CATCH_INTERNAL_LINEINFO, Catch::NameAndDesc( __VA_ARGS__ ) ); }\
static void TestName()
#define INTERNAL_CATCH_TESTCASE( ... ) \ #define INTERNAL_CATCH_TESTCASE( ... ) \
static void INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )(); \ INTERNAL_CATCH_TESTCASE2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ), __VA_ARGS__ )
namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( &INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ), CATCH_INTERNAL_LINEINFO, Catch::NameAndDesc( __VA_ARGS__ ) ); }\
static void INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )()
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
#define INTERNAL_CATCH_METHOD_AS_TEST_CASE( QualifiedMethod, ... ) \ #define INTERNAL_CATCH_METHOD_AS_TEST_CASE( QualifiedMethod, ... ) \
namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( &QualifiedMethod, "&" #QualifiedMethod, Catch::NameAndDesc( __VA_ARGS__ ), CATCH_INTERNAL_LINEINFO ); } namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( &QualifiedMethod, "&" #QualifiedMethod, Catch::NameAndDesc( __VA_ARGS__ ), CATCH_INTERNAL_LINEINFO ); }
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
#define INTERNAL_CATCH_TEST_CASE_METHOD( ClassName, ... )\ #define INTERNAL_CATCH_TEST_CASE_METHOD2( TestName, ClassName, ... )\
namespace{ \ namespace{ \
struct INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ) : ClassName{ \ struct TestName : ClassName{ \
void test(); \ void test(); \
}; \ }; \
Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar ) ( &INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )::test, #ClassName, Catch::NameAndDesc( __VA_ARGS__ ), CATCH_INTERNAL_LINEINFO ); \ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar ) ( &TestName::test, #ClassName, Catch::NameAndDesc( __VA_ARGS__ ), CATCH_INTERNAL_LINEINFO ); \
} \ } \
void INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )::test() void TestName::test()
#define INTERNAL_CATCH_TEST_CASE_METHOD( ClassName, ... ) \
INTERNAL_CATCH_TEST_CASE_METHOD2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ), ClassName, __VA_ARGS__ )
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
#define INTERNAL_CATCH_REGISTER_TESTCASE( Function, ... ) \ #define INTERNAL_CATCH_REGISTER_TESTCASE( Function, ... ) \
@ -697,24 +739,28 @@ void registerTestCaseFunction
#else #else
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
#define INTERNAL_CATCH_TESTCASE2( TestName, Name, Desc ) \
static void TestName(); \
namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( &TestName, CATCH_INTERNAL_LINEINFO, Catch::NameAndDesc( Name, Desc ) ); }\
static void TestName()
#define INTERNAL_CATCH_TESTCASE( Name, Desc ) \ #define INTERNAL_CATCH_TESTCASE( Name, Desc ) \
static void INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )(); \ INTERNAL_CATCH_TESTCASE2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ), Name, Desc )
namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( &INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ), CATCH_INTERNAL_LINEINFO, Catch::NameAndDesc( Name, Desc ) ); }\
static void INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )()
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
#define INTERNAL_CATCH_METHOD_AS_TEST_CASE( QualifiedMethod, Name, Desc ) \ #define INTERNAL_CATCH_METHOD_AS_TEST_CASE( QualifiedMethod, Name, Desc ) \
namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( &QualifiedMethod, "&" #QualifiedMethod, Catch::NameAndDesc( Name, Desc ), CATCH_INTERNAL_LINEINFO ); } namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( &QualifiedMethod, "&" #QualifiedMethod, Catch::NameAndDesc( Name, Desc ), CATCH_INTERNAL_LINEINFO ); }
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
#define INTERNAL_CATCH_TEST_CASE_METHOD( ClassName, TestName, Desc )\ #define INTERNAL_CATCH_TEST_CASE_METHOD2( TestCaseName, ClassName, TestName, Desc )\
namespace{ \ namespace{ \
struct INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ) : ClassName{ \ struct TestCaseName : ClassName{ \
void test(); \ void test(); \
}; \ }; \
Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar ) ( &INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )::test, #ClassName, Catch::NameAndDesc( TestName, Desc ), CATCH_INTERNAL_LINEINFO ); \ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar ) ( &TestCaseName::test, #ClassName, Catch::NameAndDesc( TestName, Desc ), CATCH_INTERNAL_LINEINFO ); \
} \ } \
void INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )::test() void TestCaseName::test()
#define INTERNAL_CATCH_TEST_CASE_METHOD( ClassName, TestName, Desc )\
INTERNAL_CATCH_TEST_CASE_METHOD2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ), ClassName, TestName, Desc )
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
#define INTERNAL_CATCH_REGISTER_TESTCASE( Function, Name, Desc ) \ #define INTERNAL_CATCH_REGISTER_TESTCASE( Function, Name, Desc ) \
@ -1287,37 +1333,37 @@ namespace Internal {
template<typename T1, typename T2> template<typename T1, typename T2>
struct Evaluator<T1, T2, IsEqualTo> { struct Evaluator<T1, T2, IsEqualTo> {
static bool evaluate( T1 const& lhs, T2 const& rhs) { static bool evaluate( T1 const& lhs, T2 const& rhs) {
return opCast( lhs ) == opCast( rhs ); return bool( opCast( lhs ) == opCast( rhs ) );
} }
}; };
template<typename T1, typename T2> template<typename T1, typename T2>
struct Evaluator<T1, T2, IsNotEqualTo> { struct Evaluator<T1, T2, IsNotEqualTo> {
static bool evaluate( T1 const& lhs, T2 const& rhs ) { static bool evaluate( T1 const& lhs, T2 const& rhs ) {
return opCast( lhs ) != opCast( rhs ); return bool( opCast( lhs ) != opCast( rhs ) );
} }
}; };
template<typename T1, typename T2> template<typename T1, typename T2>
struct Evaluator<T1, T2, IsLessThan> { struct Evaluator<T1, T2, IsLessThan> {
static bool evaluate( T1 const& lhs, T2 const& rhs ) { static bool evaluate( T1 const& lhs, T2 const& rhs ) {
return opCast( lhs ) < opCast( rhs ); return bool( opCast( lhs ) < opCast( rhs ) );
} }
}; };
template<typename T1, typename T2> template<typename T1, typename T2>
struct Evaluator<T1, T2, IsGreaterThan> { struct Evaluator<T1, T2, IsGreaterThan> {
static bool evaluate( T1 const& lhs, T2 const& rhs ) { static bool evaluate( T1 const& lhs, T2 const& rhs ) {
return opCast( lhs ) > opCast( rhs ); return bool( opCast( lhs ) > opCast( rhs ) );
} }
}; };
template<typename T1, typename T2> template<typename T1, typename T2>
struct Evaluator<T1, T2, IsGreaterThanOrEqualTo> { struct Evaluator<T1, T2, IsGreaterThanOrEqualTo> {
static bool evaluate( T1 const& lhs, T2 const& rhs ) { static bool evaluate( T1 const& lhs, T2 const& rhs ) {
return opCast( lhs ) >= opCast( rhs ); return bool( opCast( lhs ) >= opCast( rhs ) );
} }
}; };
template<typename T1, typename T2> template<typename T1, typename T2>
struct Evaluator<T1, T2, IsLessThanOrEqualTo> { struct Evaluator<T1, T2, IsLessThanOrEqualTo> {
static bool evaluate( T1 const& lhs, T2 const& rhs ) { static bool evaluate( T1 const& lhs, T2 const& rhs ) {
return opCast( lhs ) <= opCast( rhs ); return bool( opCast( lhs ) <= opCast( rhs ) );
} }
}; };
@ -2020,13 +2066,14 @@ namespace Catch {
do { \ do { \
Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #expr, resultDisposition ); \ Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #expr, resultDisposition ); \
try { \ try { \
CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS \
( __catchResult <= expr ).endExpression(); \ ( __catchResult <= expr ).endExpression(); \
} \ } \
catch( ... ) { \ catch( ... ) { \
__catchResult.useActiveException( Catch::ResultDisposition::Normal ); \ __catchResult.useActiveException( Catch::ResultDisposition::Normal ); \
} \ } \
INTERNAL_CATCH_REACT( __catchResult ) \ INTERNAL_CATCH_REACT( __catchResult ) \
} while( Catch::isTrue( false && static_cast<bool>(expr) ) ) // expr here is never evaluated at runtime but it forces the compiler to give it a look } while( Catch::isTrue( false && !!(expr) ) ) // expr here is never evaluated at runtime but it forces the compiler to give it a look
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
#define INTERNAL_CATCH_IF( expr, resultDisposition, macroName ) \ #define INTERNAL_CATCH_IF( expr, resultDisposition, macroName ) \
@ -2563,10 +2610,12 @@ namespace Catch {
} }
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
#define INTERNAL_CATCH_TRANSLATE_EXCEPTION( signature ) \ #define INTERNAL_CATCH_TRANSLATE_EXCEPTION2( translatorName, signature ) \
static std::string INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionTranslator )( signature ); \ static std::string translatorName( signature ); \
namespace{ Catch::ExceptionTranslatorRegistrar INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionRegistrar )( &INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionTranslator ) ); }\ namespace{ Catch::ExceptionTranslatorRegistrar INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionRegistrar )( &translatorName ); }\
static std::string INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionTranslator )( signature ) static std::string translatorName( signature )
#define INTERNAL_CATCH_TRANSLATE_EXCEPTION( signature ) INTERNAL_CATCH_TRANSLATE_EXCEPTION2( INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionTranslator ), signature )
// #included from: internal/catch_approx.hpp // #included from: internal/catch_approx.hpp
#define TWOBLUECUBES_CATCH_APPROX_HPP_INCLUDED #define TWOBLUECUBES_CATCH_APPROX_HPP_INCLUDED
@ -3331,6 +3380,11 @@ namespace Catch {
InLexicographicalOrder, InLexicographicalOrder,
InRandomOrder InRandomOrder
}; }; }; };
struct UseColour { enum YesOrNo {
Auto,
Yes,
No
}; };
class TestSpec; class TestSpec;
@ -3350,7 +3404,7 @@ namespace Catch {
virtual TestSpec const& testSpec() const = 0; virtual TestSpec const& testSpec() const = 0;
virtual RunTests::InWhatOrder runOrder() const = 0; virtual RunTests::InWhatOrder runOrder() const = 0;
virtual unsigned int rngSeed() const = 0; virtual unsigned int rngSeed() const = 0;
virtual bool forceColour() const = 0; virtual UseColour::YesOrNo useColour() const = 0;
}; };
} }
@ -3404,7 +3458,7 @@ namespace Catch {
}; };
class DebugOutStream : public IStream { class DebugOutStream : public IStream {
std::auto_ptr<StreamBufBase> m_streamBuf; CATCH_AUTO_PTR( StreamBufBase ) m_streamBuf;
mutable std::ostream m_os; mutable std::ostream m_os;
public: public:
DebugOutStream(); DebugOutStream();
@ -3439,14 +3493,14 @@ namespace Catch {
noThrow( false ), noThrow( false ),
showHelp( false ), showHelp( false ),
showInvisibles( false ), showInvisibles( false ),
forceColour( false ),
filenamesAsTags( false ), filenamesAsTags( false ),
abortAfter( -1 ), abortAfter( -1 ),
rngSeed( 0 ), rngSeed( 0 ),
verbosity( Verbosity::Normal ), verbosity( Verbosity::Normal ),
warnings( WarnAbout::Nothing ), warnings( WarnAbout::Nothing ),
showDurations( ShowDurations::DefaultForReporter ), showDurations( ShowDurations::DefaultForReporter ),
runOrder( RunTests::InDeclarationOrder ) runOrder( RunTests::InDeclarationOrder ),
useColour( UseColour::Auto )
{} {}
bool listTests; bool listTests;
@ -3459,7 +3513,6 @@ namespace Catch {
bool noThrow; bool noThrow;
bool showHelp; bool showHelp;
bool showInvisibles; bool showInvisibles;
bool forceColour;
bool filenamesAsTags; bool filenamesAsTags;
int abortAfter; int abortAfter;
@ -3469,6 +3522,7 @@ namespace Catch {
WarnAbout::What warnings; WarnAbout::What warnings;
ShowDurations::OrNot showDurations; ShowDurations::OrNot showDurations;
RunTests::InWhatOrder runOrder; RunTests::InWhatOrder runOrder;
UseColour::YesOrNo useColour;
std::string outputFilename; std::string outputFilename;
std::string name; std::string name;
@ -3534,7 +3588,7 @@ namespace Catch {
virtual ShowDurations::OrNot showDurations() const { return m_data.showDurations; } virtual ShowDurations::OrNot showDurations() const { return m_data.showDurations; }
virtual RunTests::InWhatOrder runOrder() const { return m_data.runOrder; } virtual RunTests::InWhatOrder runOrder() const { return m_data.runOrder; }
virtual unsigned int rngSeed() const { return m_data.rngSeed; } virtual unsigned int rngSeed() const { return m_data.rngSeed; }
virtual bool forceColour() const { return m_data.forceColour; } virtual UseColour::YesOrNo useColour() const { return m_data.useColour; }
private: private:
@ -3552,7 +3606,7 @@ namespace Catch {
} }
ConfigData m_data; ConfigData m_data;
std::auto_ptr<IStream const> m_stream; CATCH_AUTO_PTR( IStream const ) m_stream;
TestSpec m_testSpec; TestSpec m_testSpec;
}; };
@ -3572,7 +3626,7 @@ namespace Catch {
#define STITCH_CLARA_OPEN_NAMESPACE namespace Catch { #define STITCH_CLARA_OPEN_NAMESPACE namespace Catch {
// #included from: ../external/clara.h // #included from: ../external/clara.h
// Version 0.0.1.1 // Version 0.0.2.4
// Only use header guard if we are not using an outer namespace // Only use header guard if we are not using an outer namespace
#if !defined(TWOBLUECUBES_CLARA_H_INCLUDED) || defined(STITCH_CLARA_OPEN_NAMESPACE) #if !defined(TWOBLUECUBES_CLARA_H_INCLUDED) || defined(STITCH_CLARA_OPEN_NAMESPACE)
@ -3888,6 +3942,10 @@ namespace Tbc {
#include <stdexcept> #include <stdexcept>
#include <memory> #include <memory>
#if defined(WIN32) || defined(__WIN32__) || defined(_WIN32) || defined(_MSC_VER)
#define CLARA_PLATFORM_WINDOWS
#endif
// Use optional outer namespace // Use optional outer namespace
#ifdef STITCH_CLARA_OPEN_NAMESPACE #ifdef STITCH_CLARA_OPEN_NAMESPACE
STITCH_CLARA_OPEN_NAMESPACE STITCH_CLARA_OPEN_NAMESPACE
@ -3911,9 +3969,6 @@ namespace Clara {
const unsigned int consoleWidth = 80; const unsigned int consoleWidth = 80;
#endif #endif
// Use this to try and stop compiler from warning about unreachable code
inline bool isTrue( bool value ) { return value; }
using namespace Tbc; using namespace Tbc;
inline bool startsWith( std::string const& str, std::string const& prefix ) { inline bool startsWith( std::string const& str, std::string const& prefix ) {
@ -3949,14 +4004,6 @@ namespace Clara {
else else
throw std::runtime_error( "Expected a boolean value but did not recognise:\n '" + _source + "'" ); throw std::runtime_error( "Expected a boolean value but did not recognise:\n '" + _source + "'" );
} }
inline void convertInto( bool _source, bool& _dest ) {
_dest = _source;
}
template<typename T>
inline void convertInto( bool, T& ) {
if( isTrue( true ) )
throw std::runtime_error( "Invalid conversion" );
}
template<typename ConfigT> template<typename ConfigT>
struct IArgFunction { struct IArgFunction {
@ -3966,7 +4013,6 @@ namespace Clara {
IArgFunction( IArgFunction const& ) = default; IArgFunction( IArgFunction const& ) = default;
#endif #endif
virtual void set( ConfigT& config, std::string const& value ) const = 0; virtual void set( ConfigT& config, std::string const& value ) const = 0;
virtual void setFlag( ConfigT& config ) const = 0;
virtual bool takesArg() const = 0; virtual bool takesArg() const = 0;
virtual IArgFunction* clone() const = 0; virtual IArgFunction* clone() const = 0;
}; };
@ -3988,9 +4034,6 @@ namespace Clara {
void set( ConfigT& config, std::string const& value ) const { void set( ConfigT& config, std::string const& value ) const {
functionObj->set( config, value ); functionObj->set( config, value );
} }
void setFlag( ConfigT& config ) const {
functionObj->setFlag( config );
}
bool takesArg() const { return functionObj->takesArg(); } bool takesArg() const { return functionObj->takesArg(); }
bool isSet() const { bool isSet() const {
@ -4003,7 +4046,6 @@ namespace Clara {
template<typename C> template<typename C>
struct NullBinder : IArgFunction<C>{ struct NullBinder : IArgFunction<C>{
virtual void set( C&, std::string const& ) const {} virtual void set( C&, std::string const& ) const {}
virtual void setFlag( C& ) const {}
virtual bool takesArg() const { return true; } virtual bool takesArg() const { return true; }
virtual IArgFunction<C>* clone() const { return new NullBinder( *this ); } virtual IArgFunction<C>* clone() const { return new NullBinder( *this ); }
}; };
@ -4014,9 +4056,6 @@ namespace Clara {
virtual void set( C& p, std::string const& stringValue ) const { virtual void set( C& p, std::string const& stringValue ) const {
convertInto( stringValue, p.*member ); convertInto( stringValue, p.*member );
} }
virtual void setFlag( C& p ) const {
convertInto( true, p.*member );
}
virtual bool takesArg() const { return !IsBool<M>::value; } virtual bool takesArg() const { return !IsBool<M>::value; }
virtual IArgFunction<C>* clone() const { return new BoundDataMember( *this ); } virtual IArgFunction<C>* clone() const { return new BoundDataMember( *this ); }
M C::* member; M C::* member;
@ -4029,11 +4068,6 @@ namespace Clara {
convertInto( stringValue, value ); convertInto( stringValue, value );
(p.*member)( value ); (p.*member)( value );
} }
virtual void setFlag( C& p ) const {
typename RemoveConstRef<M>::type value;
convertInto( true, value );
(p.*member)( value );
}
virtual bool takesArg() const { return !IsBool<M>::value; } virtual bool takesArg() const { return !IsBool<M>::value; }
virtual IArgFunction<C>* clone() const { return new BoundUnaryMethod( *this ); } virtual IArgFunction<C>* clone() const { return new BoundUnaryMethod( *this ); }
void (C::*member)( M ); void (C::*member)( M );
@ -4047,9 +4081,6 @@ namespace Clara {
if( value ) if( value )
(p.*member)(); (p.*member)();
} }
virtual void setFlag( C& p ) const {
(p.*member)();
}
virtual bool takesArg() const { return false; } virtual bool takesArg() const { return false; }
virtual IArgFunction<C>* clone() const { return new BoundNullaryMethod( *this ); } virtual IArgFunction<C>* clone() const { return new BoundNullaryMethod( *this ); }
void (C::*member)(); void (C::*member)();
@ -4064,9 +4095,6 @@ namespace Clara {
if( value ) if( value )
function( obj ); function( obj );
} }
virtual void setFlag( C& p ) const {
function( p );
}
virtual bool takesArg() const { return false; } virtual bool takesArg() const { return false; }
virtual IArgFunction<C>* clone() const { return new BoundUnaryFunction( *this ); } virtual IArgFunction<C>* clone() const { return new BoundUnaryFunction( *this ); }
void (*function)( C& ); void (*function)( C& );
@ -4080,11 +4108,6 @@ namespace Clara {
convertInto( stringValue, value ); convertInto( stringValue, value );
function( obj, value ); function( obj, value );
} }
virtual void setFlag( C& obj ) const {
typename RemoveConstRef<T>::type value;
convertInto( true, value );
function( obj, value );
}
virtual bool takesArg() const { return !IsBool<T>::value; } virtual bool takesArg() const { return !IsBool<T>::value; }
virtual IArgFunction<C>* clone() const { return new BoundBinaryFunction( *this ); } virtual IArgFunction<C>* clone() const { return new BoundBinaryFunction( *this ); }
void (*function)( C&, T ); void (*function)( C&, T );
@ -4092,8 +4115,20 @@ namespace Clara {
} // namespace Detail } // namespace Detail
struct Parser { inline std::vector<std::string> argsToVector( int argc, char const* const* const argv ) {
Parser() : separators( " \t=:" ) {} std::vector<std::string> args( static_cast<std::size_t>( argc ) );
for( std::size_t i = 0; i < static_cast<std::size_t>( argc ); ++i )
args[i] = argv[i];
return args;
}
class Parser {
enum Mode { None, MaybeShortOpt, SlashOpt, ShortOpt, LongOpt, Positional };
Mode mode;
std::size_t from;
bool inQuotes;
public:
struct Token { struct Token {
enum Type { Positional, ShortOpt, LongOpt }; enum Type { Positional, ShortOpt, LongOpt };
@ -4102,38 +4137,75 @@ namespace Clara {
std::string data; std::string data;
}; };
void parseIntoTokens( int argc, char const* const argv[], std::vector<Parser::Token>& tokens ) const { Parser() : mode( None ), from( 0 ), inQuotes( false ){}
void parseIntoTokens( std::vector<std::string> const& args, std::vector<Token>& tokens ) {
const std::string doubleDash = "--"; const std::string doubleDash = "--";
for( int i = 1; i < argc && argv[i] != doubleDash; ++i ) for( std::size_t i = 1; i < args.size() && args[i] != doubleDash; ++i )
parseIntoTokens( argv[i] , tokens); parseIntoTokens( args[i], tokens);
} }
void parseIntoTokens( std::string arg, std::vector<Parser::Token>& tokens ) const {
while( !arg.empty() ) { void parseIntoTokens( std::string const& arg, std::vector<Token>& tokens ) {
Parser::Token token( Parser::Token::Positional, arg ); for( std::size_t i = 0; i <= arg.size(); ++i ) {
arg = ""; char c = arg[i];
if( token.data[0] == '-' ) { if( c == '"' )
if( token.data.size() > 1 && token.data[1] == '-' ) { inQuotes = !inQuotes;
token = Parser::Token( Parser::Token::LongOpt, token.data.substr( 2 ) ); mode = handleMode( i, c, arg, tokens );
}
else {
token = Parser::Token( Parser::Token::ShortOpt, token.data.substr( 1 ) );
if( token.data.size() > 1 && separators.find( token.data[1] ) == std::string::npos ) {
arg = "-" + token.data.substr( 1 );
token.data = token.data.substr( 0, 1 );
}
}
}
if( token.type != Parser::Token::Positional ) {
std::size_t pos = token.data.find_first_of( separators );
if( pos != std::string::npos ) {
arg = token.data.substr( pos+1 );
token.data = token.data.substr( 0, pos );
}
}
tokens.push_back( token );
} }
} }
std::string separators; Mode handleMode( std::size_t i, char c, std::string const& arg, std::vector<Token>& tokens ) {
switch( mode ) {
case None: return handleNone( i, c );
case MaybeShortOpt: return handleMaybeShortOpt( i, c );
case ShortOpt:
case LongOpt:
case SlashOpt: return handleOpt( i, c, arg, tokens );
case Positional: return handlePositional( i, c, arg, tokens );
default: throw std::logic_error( "Unknown mode" );
}
}
Mode handleNone( std::size_t i, char c ) {
if( inQuotes ) {
from = i;
return Positional;
}
switch( c ) {
case '-': return MaybeShortOpt;
#ifdef CLARA_PLATFORM_WINDOWS
case '/': from = i+1; return SlashOpt;
#endif
default: from = i; return Positional;
}
}
Mode handleMaybeShortOpt( std::size_t i, char c ) {
switch( c ) {
case '-': from = i+1; return LongOpt;
default: from = i; return ShortOpt;
}
}
Mode handleOpt( std::size_t i, char c, std::string const& arg, std::vector<Token>& tokens ) {
if( std::string( ":=\0", 3 ).find( c ) == std::string::npos )
return mode;
std::string optName = arg.substr( from, i-from );
if( mode == ShortOpt )
for( std::size_t j = 0; j < optName.size(); ++j )
tokens.push_back( Token( Token::ShortOpt, optName.substr( j, 1 ) ) );
else if( mode == SlashOpt && optName.size() == 1 )
tokens.push_back( Token( Token::ShortOpt, optName ) );
else
tokens.push_back( Token( Token::LongOpt, optName ) );
return None;
}
Mode handlePositional( std::size_t i, char c, std::string const& arg, std::vector<Token>& tokens ) {
if( inQuotes || std::string( "\0", 1 ).find( c ) == std::string::npos )
return mode;
std::string data = arg.substr( from, i-from );
tokens.push_back( Token( Token::Positional, data ) );
return None;
}
}; };
template<typename ConfigT> template<typename ConfigT>
@ -4436,21 +4508,21 @@ namespace Clara {
return oss.str(); return oss.str();
} }
ConfigT parse( int argc, char const* const argv[] ) const { ConfigT parse( std::vector<std::string> const& args ) const {
ConfigT config; ConfigT config;
parseInto( argc, argv, config ); parseInto( args, config );
return config; return config;
} }
std::vector<Parser::Token> parseInto( int argc, char const* argv[], ConfigT& config ) const { std::vector<Parser::Token> parseInto( std::vector<std::string> const& args, ConfigT& config ) const {
std::string processName = argv[0]; std::string processName = args[0];
std::size_t lastSlash = processName.find_last_of( "/\\" ); std::size_t lastSlash = processName.find_last_of( "/\\" );
if( lastSlash != std::string::npos ) if( lastSlash != std::string::npos )
processName = processName.substr( lastSlash+1 ); processName = processName.substr( lastSlash+1 );
m_boundProcessName.set( config, processName ); m_boundProcessName.set( config, processName );
std::vector<Parser::Token> tokens; std::vector<Parser::Token> tokens;
Parser parser; Parser parser;
parser.parseIntoTokens( argc, argv, tokens ); parser.parseIntoTokens( args, tokens );
return populate( tokens, config ); return populate( tokens, config );
} }
@ -4481,7 +4553,7 @@ namespace Clara {
arg.boundField.set( config, tokens[++i].data ); arg.boundField.set( config, tokens[++i].data );
} }
else { else {
arg.boundField.setFlag( config ); arg.boundField.set( config, "true" );
} }
break; break;
} }
@ -4624,6 +4696,21 @@ namespace Catch {
? ShowDurations::Always ? ShowDurations::Always
: ShowDurations::Never; : ShowDurations::Never;
} }
inline void setUseColour( ConfigData& config, std::string const& value ) {
std::string mode = toLower( value );
if( mode == "yes" )
config.useColour = UseColour::Yes;
else if( mode == "no" )
config.useColour = UseColour::No;
else if( mode == "auto" )
config.useColour = UseColour::Auto;
else
throw std::runtime_error( "colour mode must be one of: auto, yes or no" );
}
inline void forceColour( ConfigData& config ) {
config.useColour = UseColour::Yes;
}
inline void loadTestNamesFromFile( ConfigData& config, std::string const& _filename ) { inline void loadTestNamesFromFile( ConfigData& config, std::string const& _filename ) {
std::ifstream f( _filename.c_str() ); std::ifstream f( _filename.c_str() );
if( !f.is_open() ) if( !f.is_open() )
@ -4710,7 +4797,7 @@ namespace Catch {
cli["-d"]["--durations"] cli["-d"]["--durations"]
.describe( "show test durations" ) .describe( "show test durations" )
.bind( &setShowDurations, "yes/no" ); .bind( &setShowDurations, "yes|no" );
cli["-f"]["--input-file"] cli["-f"]["--input-file"]
.describe( "load test names to run from a file" ) .describe( "load test names to run from a file" )
@ -4738,8 +4825,12 @@ namespace Catch {
.bind( &setRngSeed, "'time'|number" ); .bind( &setRngSeed, "'time'|number" );
cli["--force-colour"] cli["--force-colour"]
.describe( "force colourised output" ) .describe( "force colourised output (deprecated)" )
.bind( &ConfigData::forceColour ); .bind( &forceColour );
cli["--use-colour"]
.describe( "should output be colourised" )
.bind( &setUseColour, "yes|no" );
return cli; return cli;
} }
@ -5170,6 +5261,8 @@ namespace Catch
bool aborting; bool aborting;
}; };
class MultipleReporters;
struct IStreamingReporter : IShared { struct IStreamingReporter : IShared {
virtual ~IStreamingReporter(); virtual ~IStreamingReporter();
@ -5197,6 +5290,8 @@ namespace Catch
virtual void testRunEnded( TestRunStats const& testRunStats ) = 0; virtual void testRunEnded( TestRunStats const& testRunStats ) = 0;
virtual void skipTest( TestCaseInfo const& testInfo ) = 0; virtual void skipTest( TestCaseInfo const& testInfo ) = 0;
virtual MultipleReporters* tryAsMulti() { return CATCH_NULL; }
}; };
struct IReporterFactory : IShared { struct IReporterFactory : IShared {
@ -5414,6 +5509,10 @@ namespace TestCaseTracking {
virtual void addChild( Ptr<ITracker> const& child ) = 0; virtual void addChild( Ptr<ITracker> const& child ) = 0;
virtual ITracker* findChild( std::string const& name ) = 0; virtual ITracker* findChild( std::string const& name ) = 0;
virtual void openChild() = 0; virtual void openChild() = 0;
// Debug/ checking
virtual bool isSectionTracker() const = 0;
virtual bool isIndexTracker() const = 0;
}; };
class TrackerContext { class TrackerContext {
@ -5538,6 +5637,10 @@ namespace TestCaseTracking {
m_parent->openChild(); m_parent->openChild();
} }
} }
virtual bool isSectionTracker() const CATCH_OVERRIDE { return false; }
virtual bool isIndexTracker() const CATCH_OVERRIDE { return false; }
void open() { void open() {
m_runState = Executing; m_runState = Executing;
moveToThis(); moveToThis();
@ -5601,13 +5704,16 @@ namespace TestCaseTracking {
{} {}
virtual ~SectionTracker(); virtual ~SectionTracker();
virtual bool isSectionTracker() const CATCH_OVERRIDE { return true; }
static SectionTracker& acquire( TrackerContext& ctx, std::string const& name ) { static SectionTracker& acquire( TrackerContext& ctx, std::string const& name ) {
SectionTracker* section = CATCH_NULL; SectionTracker* section = CATCH_NULL;
ITracker& currentTracker = ctx.currentTracker(); ITracker& currentTracker = ctx.currentTracker();
if( ITracker* childTracker = currentTracker.findChild( name ) ) { if( ITracker* childTracker = currentTracker.findChild( name ) ) {
section = dynamic_cast<SectionTracker*>( childTracker ); assert( childTracker );
assert( section ); assert( childTracker->isSectionTracker() );
section = static_cast<SectionTracker*>( childTracker );
} }
else { else {
section = new SectionTracker( name, ctx, &currentTracker ); section = new SectionTracker( name, ctx, &currentTracker );
@ -5632,13 +5738,16 @@ namespace TestCaseTracking {
{} {}
virtual ~IndexTracker(); virtual ~IndexTracker();
virtual bool isIndexTracker() const CATCH_OVERRIDE { return true; }
static IndexTracker& acquire( TrackerContext& ctx, std::string const& name, int size ) { static IndexTracker& acquire( TrackerContext& ctx, std::string const& name, int size ) {
IndexTracker* tracker = CATCH_NULL; IndexTracker* tracker = CATCH_NULL;
ITracker& currentTracker = ctx.currentTracker(); ITracker& currentTracker = ctx.currentTracker();
if( ITracker* childTracker = currentTracker.findChild( name ) ) { if( ITracker* childTracker = currentTracker.findChild( name ) ) {
tracker = dynamic_cast<IndexTracker*>( childTracker ); assert( childTracker );
assert( tracker ); assert( childTracker->isIndexTracker() );
tracker = static_cast<IndexTracker*>( childTracker );
} }
else { else {
tracker = new IndexTracker( name, ctx, &currentTracker, size ); tracker = new IndexTracker( name, ctx, &currentTracker, size );
@ -5845,6 +5954,11 @@ namespace Catch {
while( getCurrentContext().advanceGeneratorsForCurrentTest() && !aborting() ); while( getCurrentContext().advanceGeneratorsForCurrentTest() && !aborting() );
Totals deltaTotals = m_totals.delta( prevTotals ); Totals deltaTotals = m_totals.delta( prevTotals );
if( testInfo.expectedToFail() && deltaTotals.testCases.passed > 0 ) {
deltaTotals.assertions.failed++;
deltaTotals.testCases.passed--;
deltaTotals.testCases.failed++;
}
m_totals.testCases += deltaTotals.testCases; m_totals.testCases += deltaTotals.testCases;
m_reporter->testCaseEnded( TestCaseStats( testInfo, m_reporter->testCaseEnded( TestCaseStats( testInfo,
deltaTotals, deltaTotals,
@ -6236,10 +6350,10 @@ namespace Catch {
Catch::cout() << "For more detail usage please see the project docs\n" << std::endl; Catch::cout() << "For more detail usage please see the project docs\n" << std::endl;
} }
int applyCommandLine( int argc, char const* argv[], OnUnusedOptions::DoWhat unusedOptionBehaviour = OnUnusedOptions::Fail ) { int applyCommandLine( int argc, char const* const* const argv, OnUnusedOptions::DoWhat unusedOptionBehaviour = OnUnusedOptions::Fail ) {
try { try {
m_cli.setThrowOnUnrecognisedTokens( unusedOptionBehaviour == OnUnusedOptions::Fail ); m_cli.setThrowOnUnrecognisedTokens( unusedOptionBehaviour == OnUnusedOptions::Fail );
m_unusedTokens = m_cli.parseInto( argc, argv, m_configData ); m_unusedTokens = m_cli.parseInto( Clara::argsToVector( argc, argv ), m_configData );
if( m_configData.showHelp ) if( m_configData.showHelp )
showHelp( m_configData.processName ); showHelp( m_configData.processName );
m_config.reset(); m_config.reset();
@ -6263,16 +6377,13 @@ namespace Catch {
m_config.reset(); m_config.reset();
} }
int run( int argc, char const* argv[] ) { int run( int argc, char const* const* const argv ) {
int returnCode = applyCommandLine( argc, argv ); int returnCode = applyCommandLine( argc, argv );
if( returnCode == 0 ) if( returnCode == 0 )
returnCode = run(); returnCode = run();
return returnCode; return returnCode;
} }
int run( int argc, char* argv[] ) {
return run( argc, const_cast<char const**>( argv ) );
}
int run() { int run() {
if( m_configData.showHelp ) if( m_configData.showHelp )
@ -6336,13 +6447,31 @@ namespace Catch {
#include <iostream> #include <iostream>
#include <algorithm> #include <algorithm>
#ifdef CATCH_CPP14_OR_GREATER
#include <random>
#endif
namespace Catch { namespace Catch {
struct LexSort {
bool operator() (TestCase i,TestCase j) const { return (i<j);}
};
struct RandomNumberGenerator { struct RandomNumberGenerator {
int operator()( int n ) const { return std::rand() % n; } typedef int result_type;
result_type operator()( result_type n ) const { return std::rand() % n; }
#ifdef CATCH_CPP14_OR_GREATER
static constexpr result_type min() { return 0; }
static constexpr result_type max() { return 1000000; }
result_type operator()() const { return std::rand() % max(); }
#endif
template<typename V>
static void shuffle( V& vector ) {
RandomNumberGenerator rng;
#ifdef CATCH_CPP14_OR_GREATER
std::shuffle( vector.begin(), vector.end(), rng );
#else
std::random_shuffle( vector.begin(), vector.end(), rng );
#endif
}
}; };
inline std::vector<TestCase> sortTests( IConfig const& config, std::vector<TestCase> const& unsortedTestCases ) { inline std::vector<TestCase> sortTests( IConfig const& config, std::vector<TestCase> const& unsortedTestCases ) {
@ -6351,14 +6480,12 @@ namespace Catch {
switch( config.runOrder() ) { switch( config.runOrder() ) {
case RunTests::InLexicographicalOrder: case RunTests::InLexicographicalOrder:
std::sort( sorted.begin(), sorted.end(), LexSort() ); std::sort( sorted.begin(), sorted.end() );
break; break;
case RunTests::InRandomOrder: case RunTests::InRandomOrder:
{ {
seedRng( config ); seedRng( config );
RandomNumberGenerator::shuffle( sorted );
RandomNumberGenerator rng;
std::random_shuffle( sorted.begin(), sorted.end(), rng );
} }
break; break;
case RunTests::InDeclarationOrder: case RunTests::InDeclarationOrder:
@ -6377,13 +6504,15 @@ namespace Catch {
it != itEnd; it != itEnd;
++it ) { ++it ) {
std::pair<std::set<TestCase>::const_iterator, bool> prev = seenFunctions.insert( *it ); std::pair<std::set<TestCase>::const_iterator, bool> prev = seenFunctions.insert( *it );
if( !prev.second ){ if( !prev.second ) {
Catch::cerr() std::ostringstream ss;
<< Colour( Colour::Red )
<< "error: TEST_CASE( \"" << it->name << "\" ) already defined.\n" ss << Colour( Colour::Red )
<< "\tFirst seen at " << prev.first->getTestCaseInfo().lineInfo << "\n" << "error: TEST_CASE( \"" << it->name << "\" ) already defined.\n"
<< "\tRedefined at " << it->getTestCaseInfo().lineInfo << std::endl; << "\tFirst seen at " << prev.first->getTestCaseInfo().lineInfo << "\n"
exit(1); << "\tRedefined at " << it->getTestCaseInfo().lineInfo << std::endl;
throw std::runtime_error(ss.str());
} }
} }
} }
@ -6971,7 +7100,18 @@ namespace {
IColourImpl* platformColourInstance() { IColourImpl* platformColourInstance() {
static Win32ColourImpl s_instance; static Win32ColourImpl s_instance;
return &s_instance;
Ptr<IConfig const> config = getCurrentContext().getConfig();
UseColour::YesOrNo colourMode = config
? config->useColour()
: UseColour::Auto;
if( colourMode == UseColour::Auto )
colourMode = !isDebuggerActive()
? UseColour::Yes
: UseColour::No;
return colourMode == UseColour::Yes
? &s_instance
: NoColourImpl::instance();
} }
} // end anon namespace } // end anon namespace
@ -7022,7 +7162,14 @@ namespace {
IColourImpl* platformColourInstance() { IColourImpl* platformColourInstance() {
Ptr<IConfig const> config = getCurrentContext().getConfig(); Ptr<IConfig const> config = getCurrentContext().getConfig();
return (config && config->forceColour()) || isatty(STDOUT_FILENO) UseColour::YesOrNo colourMode = config
? config->useColour()
: UseColour::Auto;
if( colourMode == UseColour::Auto )
colourMode = (!isDebuggerActive() && isatty(STDOUT_FILENO) )
? UseColour::Yes
: UseColour::No;
return colourMode == UseColour::Yes
? PosixColourImpl::instance() ? PosixColourImpl::instance()
: NoColourImpl::instance(); : NoColourImpl::instance();
} }
@ -7047,9 +7194,7 @@ namespace Catch {
Colour::~Colour(){ if( !m_moved ) use( None ); } Colour::~Colour(){ if( !m_moved ) use( None ); }
void Colour::use( Code _colourCode ) { void Colour::use( Code _colourCode ) {
static IColourImpl* impl = isDebuggerActive() static IColourImpl* impl = platformColourInstance();
? NoColourImpl::instance()
: platformColourInstance();
impl->use( _colourCode ); impl->use( _colourCode );
} }
@ -7426,7 +7571,7 @@ namespace Catch {
return os; return os;
} }
Version libraryVersion( 1, 3, 4, "", 0 ); Version libraryVersion( 1, 5, 6, "", 0 );
} }
@ -8405,13 +8550,18 @@ public: // IStreamingReporter
++it ) ++it )
(*it)->skipTest( testInfo ); (*it)->skipTest( testInfo );
} }
virtual MultipleReporters* tryAsMulti() CATCH_OVERRIDE {
return this;
}
}; };
Ptr<IStreamingReporter> addReporter( Ptr<IStreamingReporter> const& existingReporter, Ptr<IStreamingReporter> const& additionalReporter ) { Ptr<IStreamingReporter> addReporter( Ptr<IStreamingReporter> const& existingReporter, Ptr<IStreamingReporter> const& additionalReporter ) {
Ptr<IStreamingReporter> resultingReporter; Ptr<IStreamingReporter> resultingReporter;
if( existingReporter ) { if( existingReporter ) {
MultipleReporters* multi = dynamic_cast<MultipleReporters*>( existingReporter.get() ); MultipleReporters* multi = existingReporter->tryAsMulti();
if( !multi ) { if( !multi ) {
multi = new MultipleReporters; multi = new MultipleReporters;
resultingReporter = Ptr<IStreamingReporter>( multi ); resultingReporter = Ptr<IStreamingReporter>( multi );
@ -8591,7 +8741,7 @@ namespace Catch {
virtual void assertionStarting( AssertionInfo const& ) CATCH_OVERRIDE {} virtual void assertionStarting( AssertionInfo const& ) CATCH_OVERRIDE {}
virtual bool assertionEnded( AssertionStats const& assertionStats ) { virtual bool assertionEnded( AssertionStats const& assertionStats ) CATCH_OVERRIDE {
assert( !m_sectionStack.empty() ); assert( !m_sectionStack.empty() );
SectionNode& sectionNode = *m_sectionStack.back(); SectionNode& sectionNode = *m_sectionStack.back();
sectionNode.assertions.push_back( assertionStats ); sectionNode.assertions.push_back( assertionStats );
@ -9722,7 +9872,7 @@ namespace Catch {
if( totals.testCases.total() == 0 ) { if( totals.testCases.total() == 0 ) {
stream << Colour( Colour::Warning ) << "No tests ran\n"; stream << Colour( Colour::Warning ) << "No tests ran\n";
} }
else if( totals.assertions.total() > 0 && totals.assertions.allPassed() ) { else if( totals.assertions.total() > 0 && totals.testCases.allPassed() ) {
stream << Colour( Colour::ResultSuccess ) << "All tests passed"; stream << Colour( Colour::ResultSuccess ) << "All tests passed";
stream << " (" stream << " ("
<< pluralise( totals.assertions.passed, "assertion" ) << " in " << pluralise( totals.assertions.passed, "assertion" ) << " in "

View file

@ -1285,7 +1285,7 @@ TEST_CASE("constructors")
SECTION("create a JSON value from an input stream") SECTION("create a JSON value from an input stream")
{ {
SECTION("sts::stringstream") SECTION("std::stringstream")
{ {
std::stringstream ss; std::stringstream ss;
ss << "[\"foo\",1,2,3,false,{\"one\":1}]"; ss << "[\"foo\",1,2,3,false,{\"one\":1}]";
@ -14065,7 +14065,7 @@ TEST_CASE("regression tests")
CHECK(dest == expected); CHECK(dest == expected);
} }
SECTION("issue ##235 - ambiguous overload for 'push_back' and 'operator+='") SECTION("issue #235 - ambiguous overload for 'push_back' and 'operator+='")
{ {
json data = {{"key", "value"}}; json data = {{"key", "value"}};
data.push_back({"key2", "value2"}); data.push_back({"key2", "value2"});