Compare commits

...

25 Commits

Author SHA1 Message Date
Martin Hořeňovský
2e61d38c7c v2.12.1
--- Fixes ---
* Vector matchers now support initializer list literals better

--- Improvements ---
* Added support for `^` (bitwise xor) to `CHECK` and `REQUIRE`
2020-04-21 19:30:38 +02:00
Martin Hořeňovský
5c9f09e94a Add support for bitwise xor to the decomposer 2020-04-21 19:27:12 +02:00
Martin Hořeňovský
f4fc2dab2c Fixup template type argument inference for vector matchers 2020-04-21 19:09:45 +02:00
Martin Hořeňovský
cfb6956698 v2.12.0
--- Improvements ---
* Running tests in random order (`--order rand`) has been reworked significantly (#1908)
  * Given same seed, all platforms now produce the same order
  * Given same seed, the relative order of tests does not change if you select only a subset of them
* Vector matchers support custom allocators (#1909)
* `|` and `&` (bitwise or and bitwise and) are now supported in `CHECK` and `REQUIRE`
  * The resulting type must be convertible to `bool`

--- Fixes ---
* Fixed computation of benchmarking column widths in ConsoleReporter (#1885, #1886)
* Suppressed clang-tidy's `cppcoreguidelines-pro-type-vararg` in assertions (#1901)
  * It was a false positive trigered by the new warning support workaround
* Fixed bug in test specification parser handling of OR'd patterns using escaping (#1905)

--- Miscellaneous ---
* Worked around IBM XL's codegen bug (#1907)
  * It would emit code for _destructors_ of temporaries in an unevaluated context
* Improved detection of stdlib's support for `std::uncaught_exceptions` (#1911)
2020-04-21 16:33:15 +02:00
khyperia
e59fc2c3b3 Fix build with CATCH_CONFIG_DISABLE_EXCEPTIONS enabled 2020-04-21 15:31:15 +02:00
Martin Hořeňovský
4e4171420d Support bitand and bitor in REQUIRE/CHECK
This means that bit-flag-like types with conversion to bool can be
asserted on, like so `REQUIRE(var & Flags::AddNewline)`.
2020-04-21 11:00:08 +02:00
Martin Hořeňovský
37cbf4a4fe Add more tests for test spec parser
Originally the tests were from #1912, but as it turned out, the issue
was somewhere else. Still, the inputs provided were interesting, so
they are now part of our test suite.
2020-04-17 21:19:18 +02:00
schallerr
38f897c887 Support custom allocators in vector Matchers (#1909) 2020-04-16 15:36:54 +02:00
Martin Hořeňovský
fa4a93e051 Update documentation for --order 2020-04-15 16:20:05 +02:00
John Else
6fbe5efc71 Use macro to determine whether std::uncaught_exceptions is available
Catch assumes std::uncaught_exceptions is available whenever C++17 is
available, but for macOS versions older than 10.12 this is not the case.

Instead of checking the C++ version, use a macro to check whether the
feature is available.
2020-04-14 23:03:58 +02:00
Martin Hořeňovský
bad0fb51f8 Refactor implementation of hashed random order test sorting 2020-04-14 16:39:48 +02:00
Martin Hořeňovský
a2fc7cf8c0 Randomize test for subset invariant random ordering of tests
Also removed the iterative checking that seeds 1-100 do not create
the same output, because it used too much runtime.
2020-04-14 16:38:10 +02:00
John Bytheway
da9e3eec65 Add test for consistent random ordering 2020-04-14 12:47:36 +02:00
John Bytheway
f696ab836b Change random test shuffling technique
Previously a random test ordering was obtained by applying std::shuffle
to the tests in declaration order.  This has two problems:

- It depends on the declaration order, so the order in which the tests
  will be run will be platform-specific.
- When trying to debug accidental inter-test dependencies, it is helpful
  to be able to find a minimal subset of tests which exhibits the issue.
  However, any change to the set of tests being run will completely
  change the test ordering, making it difficult or impossible to reduce
  the set of tests being run in any reasonably efficient manner.

Therefore, change the randomization approach to resolve both these
issues.

Generate a random value based on the user-provided RNG seed.  Convert
every test case to an integer by hashing a combination of that value
with the test name.  Sort the test cases by this integer.

The test names and RNG are platform-independent, so this should be
consistent across platforms.  Also, removing one test does not change
the integer value associated with the remaining tests, so they remain in
the same order.

To hash, use the FNV-1a hash, except with the basis being our randomly
selected value rather than the fixed basis set in the algorithm.  Cannot
use std::hash, because it is important that the result be
platform-independent.
2020-04-14 12:47:36 +02:00
Martin Hořeňovský
5d32ce26f4 Fix bug in test spec parser handling of escaping in ORed patterns
It did not clear out all of its internal state when switching from
one pattern to another, so when it should've escaped `,`, it took
its position from its position in the original user-provided string,
rather than its position in the current pattern.

Fixes #1905
2020-04-12 18:48:52 +02:00
Andrew Gaspar
035a062596 Remove usage of __builtin_constant_p under IBM XL 2020-04-10 20:55:23 +02:00
Moritz Haase
d399a308d0 Suppress clang-tidy warning about vararg usage in assertion macros
CATCH_INTERNAL_IGNORE_BUT_WARN() introduced with b7b346c triggers
clang-tidy warning 'cppcoreguidelines-pro-type-vararg' for every usage
of assertion macros like CHECK() and REQUIRE(). Silence it via NOLINT
in the '#if defined(__clang__)' block only, as clang-tidy honors those.
2020-04-02 20:45:57 +02:00
Phoebe
b8ce814ee6 Add vcpkg installation instructions (#1898)
* Add vcpkg installation instructions

* Add index
2020-03-31 19:12:10 +02:00
Mark Gillard
6260962108 Added toml++ to opensource-users.md 2020-03-29 14:21:57 +02:00
Mark Gillard
b4c8967ac5 Fix alphabetical ordering of opensource-users.md 2020-03-29 14:21:57 +02:00
pi1024e
7900fb3abb C-header updates 2020-03-28 18:00:42 +01:00
Invincible
01bdfe3312 Change PARSE_CATCH_TESTS_ADD_FIXTURE_IN_TEST_NAME conditional.
When no TEST_CASE_METHOD function, there is no fixture to get.
2020-03-27 09:55:06 +01:00
Joel Uckelman
e5c9a58d66 Fixed typo in "benchmark name" column width calculation. Closes #1885. 2020-03-26 10:31:35 +01:00
Martin Hořeňovský
255aa5f2af v2.11.3 2020-03-19 13:50:19 +01:00
Martin Hořeňovský
3a33315ff8 Fix compilation error when lambdas are used in assertions
This is a partial revert of b7b346c3e5.
2020-03-19 13:32:45 +01:00
33 changed files with 1044 additions and 164 deletions

View File

@@ -14,7 +14,7 @@ if (CMAKE_BINARY_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR)
endif()
project(Catch2 LANGUAGES CXX VERSION 2.11.2)
project(Catch2 LANGUAGES CXX VERSION 2.12.1)
# Provide path for scripts
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/CMake")

View File

@@ -5,11 +5,11 @@
[![Build Status](https://travis-ci.org/catchorg/Catch2.svg?branch=master)](https://travis-ci.org/catchorg/Catch2)
[![Build status](https://ci.appveyor.com/api/projects/status/github/catchorg/Catch2?svg=true)](https://ci.appveyor.com/project/catchorg/catch2)
[![codecov](https://codecov.io/gh/catchorg/Catch2/branch/master/graph/badge.svg)](https://codecov.io/gh/catchorg/Catch2)
[![Try online](https://img.shields.io/badge/try-online-blue.svg)](https://wandbox.org/permlink/ZI5SYb7JE1UJhAKP)
[![Try online](https://img.shields.io/badge/try-online-blue.svg)](https://wandbox.org/permlink/DQL97fLLJLZXwB8d)
[![Join the chat in Discord: https://discord.gg/4CWS9zD](https://img.shields.io/badge/Discord-Chat!-brightgreen.svg)](https://discord.gg/4CWS9zD)
<a href="https://github.com/catchorg/Catch2/releases/download/v2.11.2/catch.hpp">The latest version of the single header can be downloaded directly using this link</a>
<a href="https://github.com/catchorg/Catch2/releases/download/v2.12.1/catch.hpp">The latest version of the single header can be downloaded directly using this link</a>
## Catch2 is released!

View File

@@ -144,7 +144,7 @@ function(ParseAndAddCatchTests_ParseFile SourceFile TestTarget)
if("${TestType}" STREQUAL "SCENARIO")
set(Name "Scenario: ${Name}")
endif()
if(PARSE_CATCH_TESTS_ADD_FIXTURE_IN_TEST_NAME AND TestFixture)
if(PARSE_CATCH_TESTS_ADD_FIXTURE_IN_TEST_NAME AND "${TestType}" MATCHES "(CATCH_)?TEST_CASE_METHOD" AND TestFixture )
set(CTestName "${TestFixture}:${Name}")
else()
set(CTestName "${Name}")

View File

@@ -6,6 +6,7 @@
[Automatic test registration](#automatic-test-registration)<br>
[CMake project options](#cmake-project-options)<br>
[Installing Catch2 from git repository](#installing-catch2-from-git-repository)<br>
[Installing Catch2 from vcpkg](#installing-catch2-from-vcpkg)<br>
Because we use CMake to build Catch2, we also provide a couple of
integration points for our users.
@@ -220,6 +221,19 @@ when configuring the build, and then modify your calls to
[find_package](https://cmake.org/cmake/help/latest/command/find_package.html)
accordingly.
## Installing Catch2 from vcpkg
Alternatively, you can build and install Catch2 using [vcpkg](https://github.com/microsoft/vcpkg/) dependency manager:
```
git clone https://github.com/Microsoft/vcpkg.git
cd vcpkg
./bootstrap-vcpkg.sh
./vcpkg integrate install
./vcpkg install catch2
```
The catch2 port in vcpkg is kept up to date by microsoft team members and community contributors.
If the version is out of date, please [create an issue or pull request](https://github.com/Microsoft/vcpkg) on the vcpkg repository.
---

View File

@@ -243,15 +243,25 @@ This option lists all available tests in a non-indented form, one on each line.
Test cases are ordered one of three ways:
### decl
Declaration order (this is the default order if no --order argument is provided). The order the tests were originally declared in. Note that ordering between files is not guaranteed and is implementation dependent.
Declaration order (this is the default order if no --order argument is provided).
Tests in the same TU are sorted using their declaration orders, different
TUs are in an implementation (linking) dependent order.
### lex
Lexicographically sorted. Tests are sorted, alpha-numerically, by name.
Lexicographic order. Tests are sorted by their name, their tags are ignored.
### rand
Randomly sorted. Test names are sorted using ```std::random_shuffle()```. By default the random number generator is seeded with 0 - and so the order is repeatable. To control the random seed see <a href="#rng-seed">rng-seed</a>.
Randomly sorted. The order is dependent on Catch2's random seed (see
[`--rng-seed`](#rng-seed)), and is subset invariant. What this means
is that as long as the random seed is fixed, running only some tests
(e.g. via tag) does not change their relative order.
> The subset stability was introduced in Catch2 v2.12.0
<a id="rng-seed"></a>
## Specify a seed for the Random Number Generator

View File

@@ -20,18 +20,21 @@ Listing a project here does not imply endorsement and the plan is to keep these
### [ApprovalTests.cpp](https://github.com/approvals/ApprovalTests.cpp)
C++11 implementation of Approval Tests, for quick, convenient testing of legacy code.
### [args](https://github.com/Taywee/args)
A simple header-only C++ argument parser library.
### [Azmq](https://github.com/zeromq/azmq)
Boost Asio style bindings for ZeroMQ.
### [Cataclysm: Dark Days Ahead](https://github.com/CleverRaven/Cataclysm-DDA)
Post-apocalyptic survival RPG.
### [ChakraCore](https://github.com/Microsoft/ChakraCore)
The core part of the Chakra JavaScript engine that powers Microsoft Edge.
### [ChaiScript](https://github.com/ChaiScript/ChaiScript)
A, header-only, embedded scripting language designed from the ground up to directly target C++ and take advantage of modern C++ development techniques.
### [ChakraCore](https://github.com/Microsoft/ChakraCore)
The core part of the Chakra JavaScript engine that powers Microsoft Edge.
### [Clara](https://github.com/philsquared/Clara)
A, single-header-only, type-safe, command line parser - which also prints formatted usage strings.
@@ -65,9 +68,6 @@ A small C++ library wrapper for the native C ODBC API.
### [Nonius](https://github.com/libnonius/nonius)
A header-only framework for benchmarking small snippets of C++ code.
### [SOCI](https://github.com/SOCI/soci)
The C++ Database Access Library.
### [polymorphic_value](https://github.com/jbcoe/polymorphic_value)
A polymorphic value-type for C++.
@@ -77,18 +77,21 @@ A C++ client library for Consul. Consul is a distributed tool for discovering an
### [Reactive-Extensions/ RxCpp](https://github.com/Reactive-Extensions/RxCpp)
A library of algorithms for values-distributed-in-time.
### [thor](https://github.com/xorz57/thor)
Wrapper Library for CUDA.
### [SOCI](https://github.com/SOCI/soci)
The C++ Database Access Library.
### [TextFlowCpp](https://github.com/philsquared/textflowcpp)
A small, single-header-only, library for wrapping and composing columns of text.
### [thor](https://github.com/xorz57/thor)
Wrapper Library for CUDA.
### [toml++](https://github.com/marzer/tomlplusplus)
A header-only TOML parser and serializer for modern C++.
### [Trompeloeil](https://github.com/rollbear/trompeloeil)
A thread-safe header-only mocking framework for C++14.
### [args](https://github.com/Taywee/args)
A simple header-only C++ argument parser library.
## Applications & Tools
### [ArangoDB](https://github.com/arangodb/arangodb)
@@ -103,6 +106,9 @@ MAME originally stood for Multiple Arcade Machine Emulator.
### [Newsbeuter](https://github.com/akrennmair/newsbeuter)
Newsbeuter is an open-source RSS/Atom feed reader for text terminals.
### [PopHead](https://github.com/SPC-Some-Polish-Coders/PopHead)
A 2D, Zombie, RPG game which is being made on our own engine.
### [raspigcd](https://github.com/pantadeusz/raspigcd)
Low level CLI app and library for execution of GCODE on Raspberry Pi without any additional microcontrolers (just RPi + Stepsticks).
@@ -112,9 +118,6 @@ SpECTRE is a code for multi-scale, multi-physics problems in astrophysics and gr
### [Standardese](https://github.com/foonathan/standardese)
Standardese aims to be a nextgen Doxygen.
### [PopHead](https://github.com/SPC-Some-Polish-Coders/PopHead)
A 2D, Zombie, RPG game which is being made on our own engine.
---
[Home](Readme.md#top)

View File

@@ -2,6 +2,9 @@
# Release notes
**Contents**<br>
[2.12.1](#2121)<br>
[2.12.0](#2120)<br>
[2.11.3](#2113)<br>
[2.11.2](#2112)<br>
[2.11.1](#2111)<br>
[2.11.0](#2110)<br>
@@ -33,6 +36,42 @@
[Older versions](#older-versions)<br>
[Even Older versions](#even-older-versions)<br>
## 2.12.1
### Fixes
* Vector matchers now support initializer list literals better
### Improvements
* Added support for `^` (bitwise xor) to `CHECK` and `REQUIRE`
## 2.12.0
### Improvements
* Running tests in random order (`--order rand`) has been reworked significantly (#1908)
* Given same seed, all platforms now produce the same order
* Given same seed, the relative order of tests does not change if you select only a subset of them
* Vector matchers support custom allocators (#1909)
* `|` and `&` (bitwise or and bitwise and) are now supported in `CHECK` and `REQUIRE`
* The resulting type must be convertible to `bool`
### Fixes
* Fixed computation of benchmarking column widths in ConsoleReporter (#1885, #1886)
* Suppressed clang-tidy's `cppcoreguidelines-pro-type-vararg` in assertions (#1901)
* It was a false positive trigered by the new warning support workaround
* Fixed bug in test specification parser handling of OR'd patterns using escaping (#1905)
### Miscellaneous
* Worked around IBM XL's codegen bug (#1907)
* It would emit code for _destructors_ of temporaries in an unevaluated context
* Improved detection of stdlib's support for `std::uncaught_exceptions` (#1911)
## 2.11.3
### Fixes
* Fixed compilation error caused by lambdas in assertions under MSVC
## 2.11.2

View File

@@ -10,8 +10,8 @@
#define TWOBLUECUBES_CATCH_HPP_INCLUDED
#define CATCH_VERSION_MAJOR 2
#define CATCH_VERSION_MINOR 11
#define CATCH_VERSION_PATCH 2
#define CATCH_VERSION_MINOR 12
#define CATCH_VERSION_PATCH 1
#ifdef __clang__
# pragma clang system_header

View File

@@ -15,6 +15,7 @@
#include "catch_interfaces_registry_hub.h"
#include "catch_capture_matchers.h"
#include "catch_run_context.h"
#include "catch_enforce.h"
namespace Catch {

View File

@@ -51,7 +51,7 @@
CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION \
} INTERNAL_CATCH_CATCH( catchAssertionHandler ) \
INTERNAL_CATCH_REACT( catchAssertionHandler ) \
} while( false )
} while( (void)0, (false) && static_cast<bool>( !!(__VA_ARGS__) ) )
///////////////////////////////////////////////////////////////////////////////
#define INTERNAL_CATCH_IF( macroName, resultDisposition, ... ) \

View File

@@ -39,7 +39,7 @@
#endif
#if defined(CATCH_CPP17_OR_GREATER)
#if defined(__cpp_lib_uncaught_exceptions)
# define CATCH_INTERNAL_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS
#endif
@@ -58,7 +58,20 @@
# define CATCH_INTERNAL_START_WARNINGS_SUPPRESSION _Pragma( "clang diagnostic push" )
# define CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION _Pragma( "clang diagnostic pop" )
# define CATCH_INTERNAL_IGNORE_BUT_WARN(...) (void)__builtin_constant_p(__VA_ARGS__)
// As of this writing, IBM XL's implementation of __builtin_constant_p has a bug
// which results in calls to destructors being emitted for each temporary,
// without a matching initialization. In practice, this can result in something
// like `std::string::~string` being called on an uninitialized value.
//
// For example, this code will likely segfault under IBM XL:
// ```
// REQUIRE(std::string("12") + "34" == "1234")
// ```
//
// Therefore, `CATCH_INTERNAL_IGNORE_BUT_WARN` is not implemented.
# if !defined(__ibmxl__)
# define CATCH_INTERNAL_IGNORE_BUT_WARN(...) (void)__builtin_constant_p(__VA_ARGS__) /* NOLINT(cppcoreguidelines-pro-type-vararg) */
# endif
# define CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
@@ -140,8 +153,6 @@
# define CATCH_INTERNAL_START_WARNINGS_SUPPRESSION __pragma( warning(push) )
# define CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION __pragma( warning(pop) )
# define CATCH_INTERNAL_IGNORE_BUT_WARN(...) (void)sizeof(__VA_ARGS__)
# if _MSC_VER >= 1900 // Visual Studio 2015 or newer
# define CATCH_INTERNAL_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS
# endif

View File

@@ -14,8 +14,7 @@
#if defined(CATCH_PLATFORM_MAC) || defined(CATCH_PLATFORM_IPHONE)
# include <assert.h>
# include <stdbool.h>
# include <cassert>
# include <sys/types.h>
# include <unistd.h>
# include <cstddef>

View File

@@ -200,6 +200,18 @@ namespace Catch {
auto operator <= ( RhsT const& rhs ) -> BinaryExpr<LhsT, RhsT const&> const {
return { static_cast<bool>(m_lhs <= rhs), m_lhs, "<=", rhs };
}
template <typename RhsT>
auto operator | (RhsT const& rhs) -> BinaryExpr<LhsT, RhsT const&> const {
return { static_cast<bool>(m_lhs | rhs), m_lhs, "|", rhs };
}
template <typename RhsT>
auto operator & (RhsT const& rhs) -> BinaryExpr<LhsT, RhsT const&> const {
return { static_cast<bool>(m_lhs & rhs), m_lhs, "&", rhs };
}
template <typename RhsT>
auto operator ^ (RhsT const& rhs) -> BinaryExpr<LhsT, RhsT const&> const {
return { static_cast<bool>(m_lhs ^ rhs), m_lhs, "^", rhs };
}
template<typename RhsT>
auto operator && ( RhsT const& ) -> BinaryExpr<LhsT, RhsT const&> const {

View File

@@ -46,6 +46,9 @@ namespace Catch {
{}
std::string translate( ExceptionTranslators::const_iterator it, ExceptionTranslators::const_iterator itEnd ) const override {
#if defined(CATCH_CONFIG_DISABLE_EXCEPTIONS)
return "";
#else
try {
if( it == itEnd )
std::rethrow_exception(std::current_exception());
@@ -55,6 +58,7 @@ namespace Catch {
catch( T& ex ) {
return m_translateFunction( ex );
}
#endif
}
protected:

View File

@@ -17,12 +17,12 @@ namespace Catch {
namespace Matchers {
namespace Vector {
template<typename T>
struct ContainsElementMatcher : MatcherBase<std::vector<T>> {
template<typename T, typename Alloc>
struct ContainsElementMatcher : MatcherBase<std::vector<T, Alloc>> {
ContainsElementMatcher(T const &comparator) : m_comparator( comparator) {}
bool match(std::vector<T> const &v) const override {
bool match(std::vector<T, Alloc> const &v) const override {
for (auto const& el : v) {
if (el == m_comparator) {
return true;
@@ -38,12 +38,12 @@ namespace Matchers {
T const& m_comparator;
};
template<typename T>
struct ContainsMatcher : MatcherBase<std::vector<T>> {
template<typename T, typename AllocComp, typename AllocMatch>
struct ContainsMatcher : MatcherBase<std::vector<T, AllocMatch>> {
ContainsMatcher(std::vector<T> const &comparator) : m_comparator( comparator ) {}
ContainsMatcher(std::vector<T, AllocComp> const &comparator) : m_comparator( comparator ) {}
bool match(std::vector<T> const &v) const override {
bool match(std::vector<T, AllocMatch> const &v) const override {
// !TBD: see note in EqualsMatcher
if (m_comparator.size() > v.size())
return false;
@@ -65,18 +65,18 @@ namespace Matchers {
return "Contains: " + ::Catch::Detail::stringify( m_comparator );
}
std::vector<T> const& m_comparator;
std::vector<T, AllocComp> const& m_comparator;
};
template<typename T>
struct EqualsMatcher : MatcherBase<std::vector<T>> {
template<typename T, typename AllocComp, typename AllocMatch>
struct EqualsMatcher : MatcherBase<std::vector<T, AllocMatch>> {
EqualsMatcher(std::vector<T> const &comparator) : m_comparator( comparator ) {}
EqualsMatcher(std::vector<T, AllocComp> const &comparator) : m_comparator( comparator ) {}
bool match(std::vector<T> const &v) const override {
bool match(std::vector<T, AllocMatch> const &v) const override {
// !TBD: This currently works if all elements can be compared using !=
// - a more general approach would be via a compare template that defaults
// to using !=. but could be specialised for, e.g. std::vector<T> etc
// to using !=. but could be specialised for, e.g. std::vector<T, Alloc> etc
// - then just call that directly
if (m_comparator.size() != v.size())
return false;
@@ -88,15 +88,15 @@ namespace Matchers {
std::string describe() const override {
return "Equals: " + ::Catch::Detail::stringify( m_comparator );
}
std::vector<T> const& m_comparator;
std::vector<T, AllocComp> const& m_comparator;
};
template<typename T>
struct ApproxMatcher : MatcherBase<std::vector<T>> {
template<typename T, typename AllocComp, typename AllocMatch>
struct ApproxMatcher : MatcherBase<std::vector<T, AllocMatch>> {
ApproxMatcher(std::vector<T> const& comparator) : m_comparator( comparator ) {}
ApproxMatcher(std::vector<T, AllocComp> const& comparator) : m_comparator( comparator ) {}
bool match(std::vector<T> const &v) const override {
bool match(std::vector<T, AllocMatch> const &v) const override {
if (m_comparator.size() != v.size())
return false;
for (std::size_t i = 0; i < v.size(); ++i)
@@ -123,14 +123,14 @@ namespace Matchers {
return *this;
}
std::vector<T> const& m_comparator;
std::vector<T, AllocComp> const& m_comparator;
mutable Catch::Detail::Approx approx = Catch::Detail::Approx::custom();
};
template<typename T>
struct UnorderedEqualsMatcher : MatcherBase<std::vector<T>> {
UnorderedEqualsMatcher(std::vector<T> const& target) : m_target(target) {}
bool match(std::vector<T> const& vec) const override {
template<typename T, typename AllocComp, typename AllocMatch>
struct UnorderedEqualsMatcher : MatcherBase<std::vector<T, AllocMatch>> {
UnorderedEqualsMatcher(std::vector<T, AllocComp> const& target) : m_target(target) {}
bool match(std::vector<T, AllocMatch> const& vec) const override {
// Note: This is a reimplementation of std::is_permutation,
// because I don't want to include <algorithm> inside the common path
if (m_target.size() != vec.size()) {
@@ -143,7 +143,7 @@ namespace Matchers {
return "UnorderedEquals: " + ::Catch::Detail::stringify(m_target);
}
private:
std::vector<T> const& m_target;
std::vector<T, AllocComp> const& m_target;
};
} // namespace Vector
@@ -151,29 +151,29 @@ namespace Matchers {
// The following functions create the actual matcher objects.
// This allows the types to be inferred
template<typename T>
Vector::ContainsMatcher<T> Contains( std::vector<T> const& comparator ) {
return Vector::ContainsMatcher<T>( comparator );
template<typename T, typename AllocComp = std::allocator<T>, typename AllocMatch = AllocComp>
Vector::ContainsMatcher<T, AllocComp, AllocMatch> Contains( std::vector<T, AllocComp> const& comparator ) {
return Vector::ContainsMatcher<T, AllocComp, AllocMatch>( comparator );
}
template<typename T>
Vector::ContainsElementMatcher<T> VectorContains( T const& comparator ) {
return Vector::ContainsElementMatcher<T>( comparator );
template<typename T, typename Alloc = std::allocator<T>>
Vector::ContainsElementMatcher<T, Alloc> VectorContains( T const& comparator ) {
return Vector::ContainsElementMatcher<T, Alloc>( comparator );
}
template<typename T>
Vector::EqualsMatcher<T> Equals( std::vector<T> const& comparator ) {
return Vector::EqualsMatcher<T>( comparator );
template<typename T, typename AllocComp = std::allocator<T>, typename AllocMatch = AllocComp>
Vector::EqualsMatcher<T, AllocComp, AllocMatch> Equals( std::vector<T, AllocComp> const& comparator ) {
return Vector::EqualsMatcher<T, AllocComp, AllocMatch>( comparator );
}
template<typename T>
Vector::ApproxMatcher<T> Approx( std::vector<T> const& comparator ) {
return Vector::ApproxMatcher<T>( comparator );
template<typename T, typename AllocComp = std::allocator<T>, typename AllocMatch = AllocComp>
Vector::ApproxMatcher<T, AllocComp, AllocMatch> Approx( std::vector<T, AllocComp> const& comparator ) {
return Vector::ApproxMatcher<T, AllocComp, AllocMatch>( comparator );
}
template<typename T>
Vector::UnorderedEqualsMatcher<T> UnorderedEquals(std::vector<T> const& target) {
return Vector::UnorderedEqualsMatcher<T>(target);
template<typename T, typename AllocComp = std::allocator<T>, typename AllocMatch = AllocComp>
Vector::UnorderedEqualsMatcher<T, AllocComp, AllocMatch> UnorderedEquals(std::vector<T, AllocComp> const& target) {
return Vector::UnorderedEqualsMatcher<T, AllocComp, AllocMatch>( target );
}
} // namespace Matchers

View File

@@ -15,27 +15,78 @@
#include "catch_string_manip.h"
#include "catch_test_case_info.h"
#include <algorithm>
#include <sstream>
namespace Catch {
namespace {
struct TestHasher {
explicit TestHasher(Catch::SimplePcg32& rng) {
basis = rng();
basis <<= 32;
basis |= rng();
}
uint64_t basis;
uint64_t operator()(TestCase const& t) const {
// Modified FNV-1a hash
static constexpr uint64_t prime = 1099511628211;
uint64_t hash = basis;
for (const char c : t.name) {
hash ^= c;
hash *= prime;
}
return hash;
}
};
} // end unnamed namespace
std::vector<TestCase> sortTests( IConfig const& config, std::vector<TestCase> const& unsortedTestCases ) {
std::vector<TestCase> sorted = unsortedTestCases;
switch( config.runOrder() ) {
case RunTests::InLexicographicalOrder:
std::sort( sorted.begin(), sorted.end() );
break;
case RunTests::InRandomOrder:
seedRng( config );
std::shuffle( sorted.begin(), sorted.end(), rng() );
break;
case RunTests::InDeclarationOrder:
// already in declaration order
break;
case RunTests::InLexicographicalOrder: {
std::vector<TestCase> sorted = unsortedTestCases;
std::sort( sorted.begin(), sorted.end() );
return sorted;
}
case RunTests::InRandomOrder: {
seedRng( config );
TestHasher h( rng() );
using hashedTest = std::pair<uint64_t, TestCase const*>;
std::vector<hashedTest> indexed_tests;
indexed_tests.reserve( unsortedTestCases.size() );
for (auto const& testCase : unsortedTestCases) {
indexed_tests.emplace_back(h(testCase), &testCase);
}
std::sort(indexed_tests.begin(), indexed_tests.end(),
[](hashedTest const& lhs, hashedTest const& rhs) {
if (lhs.first == rhs.first) {
return lhs.second->name < rhs.second->name;
}
return lhs.first < rhs.first;
});
std::vector<TestCase> sorted;
sorted.reserve( indexed_tests.size() );
for (auto const& hashed : indexed_tests) {
sorted.emplace_back(*hashed.second);
}
return sorted;
}
}
return sorted;
return unsortedTestCases;
}
bool isThrowSafe( TestCase const& testCase, IConfig const& config ) {

View File

@@ -168,6 +168,7 @@ namespace Catch {
m_pos = m_arg.size();
m_substring.clear();
m_patternName.clear();
m_realPatternPos = 0;
return false;
}
endMode();
@@ -186,6 +187,7 @@ namespace Catch {
}
m_patternName.clear();
m_realPatternPos = 0;
return token;
}

View File

@@ -37,7 +37,7 @@ namespace Catch {
}
Version const& libraryVersion() {
static Version version( 2, 11, 2, "", 0 );
static Version version( 2, 12, 1, "", 0 );
return version;
}

View File

@@ -362,7 +362,7 @@ ConsoleReporter::ConsoleReporter(ReporterConfig const& config)
else
{
return{
{ "benchmark name", CATCH_CONFIG_CONSOLE_WIDTH - 32, ColumnInfo::Left },
{ "benchmark name", CATCH_CONFIG_CONSOLE_WIDTH - 43, ColumnInfo::Left },
{ "samples mean std dev", 14, ColumnInfo::Right },
{ "iterations low mean low std dev", 14, ColumnInfo::Right },
{ "estimated high mean high std dev", 14, ColumnInfo::Right }

View File

@@ -451,6 +451,8 @@ set_tests_properties(TestsInFile::InvalidTestNames-1 PROPERTIES PASS_REGULAR_EXP
add_test(NAME TestsInFile::InvalidTestNames-2 COMMAND $<TARGET_FILE:SelfTest> "-f ${CATCH_DIR}/projects/SelfTest/Misc/invalid-test-names.input")
set_tests_properties(TestsInFile::InvalidTestNames-2 PROPERTIES PASS_REGULAR_EXPRESSION "No tests ran")
add_test(NAME RandomTestOrdering COMMAND ${PYTHON_EXECUTABLE}
${CATCH_DIR}/projects/TestScripts/testRandomOrder.py $<TARGET_FILE:SelfTest>)
if (CATCH_USE_VALGRIND)
add_test(NAME ValgrindRunTests COMMAND valgrind --leak-check=full --error-exitcode=1 $<TARGET_FILE:SelfTest>)

View File

@@ -123,7 +123,7 @@ add_test(NAME BenchmarkingMacros COMMAND BenchmarkingMacros -r console -s)
set_tests_properties(
BenchmarkingMacros
PROPERTIES
PASS_REGULAR_EXPRESSION "benchmark name samples iterations estimated"
PASS_REGULAR_EXPRESSION "benchmark name[\\r\\n\\t ]+samples[\\r\\n\\t ]+iterations[\\r\\n\\t ]+estimated"
)
# This test touches windows.h, so it should only be compiled under msvc

View File

@@ -23,6 +23,13 @@ This would not be caught previously
Nor would this
Tricky.tests.cpp:<line number>: failed: explicitly with 1 message: '1514'
Compilation.tests.cpp:<line number>: passed: std::is_same<TypeList<int>, TypeList<int>>::value for: true
CmdLine.tests.cpp:<line number>: passed: spec.matches(fakeTestCase("spec . char")) for: true
CmdLine.tests.cpp:<line number>: passed: spec.matches(fakeTestCase("spec , char")) for: true
CmdLine.tests.cpp:<line number>: passed: !(spec.matches(fakeTestCase(R"(spec \, char)"))) for: !false
CmdLine.tests.cpp:<line number>: passed: spec.matches(fakeTestCase(R"(spec {a} char)")) for: true
CmdLine.tests.cpp:<line number>: passed: spec.matches(fakeTestCase(R"(spec [a] char)")) for: true
CmdLine.tests.cpp:<line number>: passed: !(spec.matches(fakeTestCase("differs but has similar tag", "[a]"))) for: !false
CmdLine.tests.cpp:<line number>: passed: spec.matches(fakeTestCase(R"(spec \ char)")) for: true
Exception.tests.cpp:<line number>: failed: unexpected exception with message: 'answer := 42' with 1 message: 'expected exception'
Exception.tests.cpp:<line number>: failed: unexpected exception with message: 'answer := 42'; expression was: thisThrows() with 1 message: 'expected exception'
Exception.tests.cpp:<line number>: passed: thisThrows() with 1 message: 'answer := 42'
@@ -237,6 +244,11 @@ Matchers.tests.cpp:<line number>: passed: 1, Predicate<int>(alwaysTrue, "always
Matchers.tests.cpp:<line number>: passed: 1, !Predicate<int>(alwaysFalse, "always false") for: 1 not matches predicate: "always false"
Matchers.tests.cpp:<line number>: passed: "Hello olleH", Predicate<std::string>( [] (std::string const& str) -> bool { return str.front() == str.back(); }, "First and last character should be equal") for: "Hello olleH" matches predicate: "First and last character should be equal"
Matchers.tests.cpp:<line number>: passed: "This wouldn't pass", !Predicate<std::string>( [] (std::string const& str) -> bool { return str.front() == str.back(); } ) for: "This wouldn't pass" not matches undescribed predicate
Compilation.tests.cpp:<line number>: passed: lhs | rhs for: Val: 1 | Val: 2
Compilation.tests.cpp:<line number>: passed: !(lhs & rhs) for: !(Val: 1 & Val: 2)
Compilation.tests.cpp:<line number>: passed: HasBitOperators{ 1 } & HasBitOperators{ 1 } for: Val: 1 & Val: 1
Compilation.tests.cpp:<line number>: passed: lhs ^ rhs for: Val: 1 ^ Val: 2
Compilation.tests.cpp:<line number>: passed: !(lhs ^ lhs) for: !(Val: 1 ^ Val: 1)
Tricky.tests.cpp:<line number>: passed: true
Tricky.tests.cpp:<line number>: passed: true
Tricky.tests.cpp:<line number>: passed: true
@@ -764,6 +776,7 @@ Condition.tests.cpp:<line number>: passed: data.str_hello != "goodbye" for: "hel
Condition.tests.cpp:<line number>: passed: data.str_hello != "hell" for: "hello" != "hell"
Condition.tests.cpp:<line number>: passed: data.str_hello != "hello1" for: "hello" != "hello1"
Condition.tests.cpp:<line number>: passed: data.str_hello.size() != 6 for: 5 != 6
Compilation.tests.cpp:<line number>: passed: []() { return true; }() for: true
Approx.tests.cpp:<line number>: passed: d <= Approx( 1.24 ) for: 1.23 <= Approx( 1.24 )
Approx.tests.cpp:<line number>: passed: d <= Approx( 1.23 ) for: 1.23 <= Approx( 1.23 )
Approx.tests.cpp:<line number>: passed: !(d <= Approx( 1.22 )) for: !(1.23 <= Approx( 1.22 ))
@@ -1518,6 +1531,7 @@ Approx.tests.cpp:<line number>: passed: approx( d ) != 1.25 for: Approx( 1.23 )
VariadicMacros.tests.cpp:<line number>: passed: with 1 message: 'no assertions'
Matchers.tests.cpp:<line number>: passed: empty, Approx(empty) for: { } is approx: { }
Matchers.tests.cpp:<line number>: passed: v1, Approx(v1) for: { 1.0, 2.0, 3.0 } is approx: { 1.0, 2.0, 3.0 }
Matchers.tests.cpp:<line number>: passed: v1, Approx<double>({ 1., 2., 3. }) for: { 1.0, 2.0, 3.0 } is approx: { 1.0, 2.0, 3.0 }
Matchers.tests.cpp:<line number>: passed: v1, !Approx(temp) for: { 1.0, 2.0, 3.0 } not is approx: { 1.0, 2.0, 3.0, 4.0 }
Matchers.tests.cpp:<line number>: passed: v1, !Approx(v2) for: { 1.0, 2.0, 3.0 } not is approx: { 1.5, 2.5, 3.5 }
Matchers.tests.cpp:<line number>: passed: v1, Approx(v2).margin(0.5) for: { 1.0, 2.0, 3.0 } is approx: { 1.5, 2.5, 3.5 }
@@ -1527,18 +1541,29 @@ Matchers.tests.cpp:<line number>: failed: empty, Approx(t1) for: { } is approx:
Matchers.tests.cpp:<line number>: failed: v1, Approx(v2) for: { 2.0, 4.0, 6.0 } is approx: { 1.0, 3.0, 5.0 }
Matchers.tests.cpp:<line number>: passed: v, VectorContains(1) for: { 1, 2, 3 } Contains: 1
Matchers.tests.cpp:<line number>: passed: v, VectorContains(2) for: { 1, 2, 3 } Contains: 2
Matchers.tests.cpp:<line number>: passed: v5, (VectorContains<int, CustomAllocator<int>>(2)) for: { 1, 2, 3 } Contains: 2
Matchers.tests.cpp:<line number>: passed: v, Contains(v2) for: { 1, 2, 3 } Contains: { 1, 2 }
Matchers.tests.cpp:<line number>: passed: v, Contains<int>({ 1, 2 }) for: { 1, 2, 3 } Contains: { 1, 2 }
Matchers.tests.cpp:<line number>: passed: v5, (Contains<int, std::allocator<int>, CustomAllocator<int>>(v2)) for: { 1, 2, 3 } Contains: { 1, 2 }
Matchers.tests.cpp:<line number>: passed: v, Contains(v2) for: { 1, 2, 3 } Contains: { 1, 2, 3 }
Matchers.tests.cpp:<line number>: passed: v, Contains(empty) for: { 1, 2, 3 } Contains: { }
Matchers.tests.cpp:<line number>: passed: empty, Contains(empty) for: { } Contains: { }
Matchers.tests.cpp:<line number>: passed: v5, (Contains<int, std::allocator<int>, CustomAllocator<int>>(v2)) for: { 1, 2, 3 } Contains: { 1, 2, 3 }
Matchers.tests.cpp:<line number>: passed: v5, Contains(v6) for: { 1, 2, 3 } Contains: { 1, 2 }
Matchers.tests.cpp:<line number>: passed: v, VectorContains(1) && VectorContains(2) for: { 1, 2, 3 } ( Contains: 1 and Contains: 2 )
Matchers.tests.cpp:<line number>: passed: v, Equals(v) for: { 1, 2, 3 } Equals: { 1, 2, 3 }
Matchers.tests.cpp:<line number>: passed: empty, Equals(empty) for: { } Equals: { }
Matchers.tests.cpp:<line number>: passed: v, Equals<int>({ 1, 2, 3 }) for: { 1, 2, 3 } Equals: { 1, 2, 3 }
Matchers.tests.cpp:<line number>: passed: v, Equals(v2) for: { 1, 2, 3 } Equals: { 1, 2, 3 }
Matchers.tests.cpp:<line number>: passed: v5, (Equals<int, std::allocator<int>, CustomAllocator<int>>(v2)) for: { 1, 2, 3 } Equals: { 1, 2, 3 }
Matchers.tests.cpp:<line number>: passed: v5, Equals(v6) for: { 1, 2, 3 } Equals: { 1, 2, 3 }
Matchers.tests.cpp:<line number>: passed: v, UnorderedEquals(v) for: { 1, 2, 3 } UnorderedEquals: { 1, 2, 3 }
Matchers.tests.cpp:<line number>: passed: v, UnorderedEquals<int>({ 3, 2, 1 }) for: { 1, 2, 3 } UnorderedEquals: { 3, 2, 1 }
Matchers.tests.cpp:<line number>: passed: empty, UnorderedEquals(empty) for: { } UnorderedEquals: { }
Matchers.tests.cpp:<line number>: passed: permuted, UnorderedEquals(v) for: { 1, 3, 2 } UnorderedEquals: { 1, 2, 3 }
Matchers.tests.cpp:<line number>: passed: permuted, UnorderedEquals(v) for: { 2, 3, 1 } UnorderedEquals: { 1, 2, 3 }
Matchers.tests.cpp:<line number>: passed: v5, (UnorderedEquals<int, std::allocator<int>, CustomAllocator<int>>(permuted)) for: { 1, 2, 3 } UnorderedEquals: { 2, 3, 1 }
Matchers.tests.cpp:<line number>: passed: v5_permuted, UnorderedEquals(v5) for: { 1, 3, 2 } UnorderedEquals: { 1, 2, 3 }
Matchers.tests.cpp:<line number>: failed: v, VectorContains(-1) for: { 1, 2, 3 } Contains: -1
Matchers.tests.cpp:<line number>: failed: empty, VectorContains(1) for: { } Contains: 1
Matchers.tests.cpp:<line number>: failed: empty, Contains(v) for: { } Contains: { 1, 2, 3 }

View File

@@ -1380,6 +1380,6 @@ due to unexpected exception with message:
Why would you throw a std::string?
===============================================================================
test cases: 306 | 232 passed | 70 failed | 4 failed as expected
assertions: 1676 | 1524 passed | 131 failed | 21 failed as expected
test cases: 310 | 236 passed | 70 failed | 4 failed as expected
assertions: 1701 | 1549 passed | 131 failed | 21 failed as expected

View File

@@ -188,6 +188,61 @@ Compilation.tests.cpp:<line number>: PASSED:
with expansion:
true
-------------------------------------------------------------------------------
#1905 -- test spec parser properly clears internal state between compound tests
-------------------------------------------------------------------------------
CmdLine.tests.cpp:<line number>
...............................................................................
CmdLine.tests.cpp:<line number>: PASSED:
REQUIRE( spec.matches(fakeTestCase("spec . char")) )
with expansion:
true
CmdLine.tests.cpp:<line number>: PASSED:
REQUIRE( spec.matches(fakeTestCase("spec , char")) )
with expansion:
true
CmdLine.tests.cpp:<line number>: PASSED:
REQUIRE_FALSE( spec.matches(fakeTestCase(R"(spec \, char)")) )
with expansion:
!false
-------------------------------------------------------------------------------
#1912 -- test spec parser handles escaping
Various parentheses
-------------------------------------------------------------------------------
CmdLine.tests.cpp:<line number>
...............................................................................
CmdLine.tests.cpp:<line number>: PASSED:
REQUIRE( spec.matches(fakeTestCase(R"(spec {a} char)")) )
with expansion:
true
CmdLine.tests.cpp:<line number>: PASSED:
REQUIRE( spec.matches(fakeTestCase(R"(spec [a] char)")) )
with expansion:
true
CmdLine.tests.cpp:<line number>: PASSED:
REQUIRE_FALSE( spec.matches(fakeTestCase("differs but has similar tag", "[a]")) )
with expansion:
!false
-------------------------------------------------------------------------------
#1912 -- test spec parser handles escaping
backslash in test name
-------------------------------------------------------------------------------
CmdLine.tests.cpp:<line number>
...............................................................................
CmdLine.tests.cpp:<line number>: PASSED:
REQUIRE( spec.matches(fakeTestCase(R"(spec \ char)")) )
with expansion:
true
-------------------------------------------------------------------------------
#748 - captures with unexpected exceptions
outside assertions
@@ -1879,6 +1934,37 @@ Matchers.tests.cpp:<line number>: PASSED:
with expansion:
"This wouldn't pass" not matches undescribed predicate
-------------------------------------------------------------------------------
Assertion macros support bit operators and bool conversions
-------------------------------------------------------------------------------
Compilation.tests.cpp:<line number>
...............................................................................
Compilation.tests.cpp:<line number>: PASSED:
REQUIRE( lhs | rhs )
with expansion:
Val: 1 | Val: 2
Compilation.tests.cpp:<line number>: PASSED:
REQUIRE_FALSE( lhs & rhs )
with expansion:
!(Val: 1 & Val: 2)
Compilation.tests.cpp:<line number>: PASSED:
REQUIRE( HasBitOperators{ 1 } & HasBitOperators{ 1 } )
with expansion:
Val: 1 & Val: 1
Compilation.tests.cpp:<line number>: PASSED:
REQUIRE( lhs ^ rhs )
with expansion:
Val: 1 ^ Val: 2
Compilation.tests.cpp:<line number>: PASSED:
REQUIRE_FALSE( lhs ^ lhs )
with expansion:
!(Val: 1 ^ Val: 1)
-------------------------------------------------------------------------------
Assertions then sections
-------------------------------------------------------------------------------
@@ -5729,6 +5815,17 @@ Condition.tests.cpp:<line number>: PASSED:
with expansion:
5 != 6
-------------------------------------------------------------------------------
Lambdas in assertions
-------------------------------------------------------------------------------
Compilation.tests.cpp:<line number>
...............................................................................
Compilation.tests.cpp:<line number>: PASSED:
REQUIRE( []() { return true; }() )
with expansion:
true
-------------------------------------------------------------------------------
Less-than inequalities with different epsilons
-------------------------------------------------------------------------------
@@ -11090,6 +11187,11 @@ Matchers.tests.cpp:<line number>: PASSED:
with expansion:
{ 1.0, 2.0, 3.0 } is approx: { 1.0, 2.0, 3.0 }
Matchers.tests.cpp:<line number>: PASSED:
REQUIRE_THAT( v1, Approx<double>({ 1., 2., 3. }) )
with expansion:
{ 1.0, 2.0, 3.0 } is approx: { 1.0, 2.0, 3.0 }
-------------------------------------------------------------------------------
Vector Approx matcher
Vectors with elements
@@ -11172,6 +11274,11 @@ Matchers.tests.cpp:<line number>: PASSED:
with expansion:
{ 1, 2, 3 } Contains: 2
Matchers.tests.cpp:<line number>: PASSED:
CHECK_THAT( v5, (VectorContains<int, CustomAllocator<int>>(2)) )
with expansion:
{ 1, 2, 3 } Contains: 2
-------------------------------------------------------------------------------
Vector matchers
Contains (vector)
@@ -11184,6 +11291,16 @@ Matchers.tests.cpp:<line number>: PASSED:
with expansion:
{ 1, 2, 3 } Contains: { 1, 2 }
Matchers.tests.cpp:<line number>: PASSED:
CHECK_THAT( v, Contains<int>({ 1, 2 }) )
with expansion:
{ 1, 2, 3 } Contains: { 1, 2 }
Matchers.tests.cpp:<line number>: PASSED:
CHECK_THAT( v5, (Contains<int, std::allocator<int>, CustomAllocator<int>>(v2)) )
with expansion:
{ 1, 2, 3 } Contains: { 1, 2 }
Matchers.tests.cpp:<line number>: PASSED:
CHECK_THAT( v, Contains(v2) )
with expansion:
@@ -11199,6 +11316,16 @@ Matchers.tests.cpp:<line number>: PASSED:
with expansion:
{ } Contains: { }
Matchers.tests.cpp:<line number>: PASSED:
CHECK_THAT( v5, (Contains<int, std::allocator<int>, CustomAllocator<int>>(v2)) )
with expansion:
{ 1, 2, 3 } Contains: { 1, 2, 3 }
Matchers.tests.cpp:<line number>: PASSED:
CHECK_THAT( v5, Contains(v6) )
with expansion:
{ 1, 2, 3 } Contains: { 1, 2 }
-------------------------------------------------------------------------------
Vector matchers
Contains (element), composed
@@ -11228,11 +11355,26 @@ Matchers.tests.cpp:<line number>: PASSED:
with expansion:
{ } Equals: { }
Matchers.tests.cpp:<line number>: PASSED:
CHECK_THAT( v, Equals<int>({ 1, 2, 3 }) )
with expansion:
{ 1, 2, 3 } Equals: { 1, 2, 3 }
Matchers.tests.cpp:<line number>: PASSED:
CHECK_THAT( v, Equals(v2) )
with expansion:
{ 1, 2, 3 } Equals: { 1, 2, 3 }
Matchers.tests.cpp:<line number>: PASSED:
CHECK_THAT( v5, (Equals<int, std::allocator<int>, CustomAllocator<int>>(v2)) )
with expansion:
{ 1, 2, 3 } Equals: { 1, 2, 3 }
Matchers.tests.cpp:<line number>: PASSED:
CHECK_THAT( v5, Equals(v6) )
with expansion:
{ 1, 2, 3 } Equals: { 1, 2, 3 }
-------------------------------------------------------------------------------
Vector matchers
UnorderedEquals
@@ -11245,6 +11387,11 @@ Matchers.tests.cpp:<line number>: PASSED:
with expansion:
{ 1, 2, 3 } UnorderedEquals: { 1, 2, 3 }
Matchers.tests.cpp:<line number>: PASSED:
CHECK_THAT( v, UnorderedEquals<int>({ 3, 2, 1 }) )
with expansion:
{ 1, 2, 3 } UnorderedEquals: { 3, 2, 1 }
Matchers.tests.cpp:<line number>: PASSED:
CHECK_THAT( empty, UnorderedEquals(empty) )
with expansion:
@@ -11260,6 +11407,16 @@ Matchers.tests.cpp:<line number>: PASSED:
with expansion:
{ 2, 3, 1 } UnorderedEquals: { 1, 2, 3 }
Matchers.tests.cpp:<line number>: PASSED:
CHECK_THAT( v5, (UnorderedEquals<int, std::allocator<int>, CustomAllocator<int>>(permuted)) )
with expansion:
{ 1, 2, 3 } UnorderedEquals: { 2, 3, 1 }
Matchers.tests.cpp:<line number>: PASSED:
CHECK_THAT( v5_permuted, UnorderedEquals(v5) )
with expansion:
{ 1, 3, 2 } UnorderedEquals: { 1, 2, 3 }
-------------------------------------------------------------------------------
Vector matchers that fail
Contains (element)
@@ -13416,6 +13573,6 @@ Misc.tests.cpp:<line number>
Misc.tests.cpp:<line number>: PASSED:
===============================================================================
test cases: 306 | 216 passed | 86 failed | 4 failed as expected
assertions: 1693 | 1524 passed | 148 failed | 21 failed as expected
test cases: 310 | 220 passed | 86 failed | 4 failed as expected
assertions: 1718 | 1549 passed | 148 failed | 21 failed as expected

View File

@@ -188,6 +188,61 @@ Compilation.tests.cpp:<line number>: PASSED:
with expansion:
true
-------------------------------------------------------------------------------
#1905 -- test spec parser properly clears internal state between compound tests
-------------------------------------------------------------------------------
CmdLine.tests.cpp:<line number>
...............................................................................
CmdLine.tests.cpp:<line number>: PASSED:
REQUIRE( spec.matches(fakeTestCase("spec . char")) )
with expansion:
true
CmdLine.tests.cpp:<line number>: PASSED:
REQUIRE( spec.matches(fakeTestCase("spec , char")) )
with expansion:
true
CmdLine.tests.cpp:<line number>: PASSED:
REQUIRE_FALSE( spec.matches(fakeTestCase(R"(spec \, char)")) )
with expansion:
!false
-------------------------------------------------------------------------------
#1912 -- test spec parser handles escaping
Various parentheses
-------------------------------------------------------------------------------
CmdLine.tests.cpp:<line number>
...............................................................................
CmdLine.tests.cpp:<line number>: PASSED:
REQUIRE( spec.matches(fakeTestCase(R"(spec {a} char)")) )
with expansion:
true
CmdLine.tests.cpp:<line number>: PASSED:
REQUIRE( spec.matches(fakeTestCase(R"(spec [a] char)")) )
with expansion:
true
CmdLine.tests.cpp:<line number>: PASSED:
REQUIRE_FALSE( spec.matches(fakeTestCase("differs but has similar tag", "[a]")) )
with expansion:
!false
-------------------------------------------------------------------------------
#1912 -- test spec parser handles escaping
backslash in test name
-------------------------------------------------------------------------------
CmdLine.tests.cpp:<line number>
...............................................................................
CmdLine.tests.cpp:<line number>: PASSED:
REQUIRE( spec.matches(fakeTestCase(R"(spec \ char)")) )
with expansion:
true
-------------------------------------------------------------------------------
#748 - captures with unexpected exceptions
outside assertions
@@ -368,6 +423,6 @@ Condition.tests.cpp:<line number>: FAILED:
CHECK( true != true )
===============================================================================
test cases: 19 | 14 passed | 3 failed | 2 failed as expected
assertions: 42 | 35 passed | 4 failed | 3 failed as expected
test cases: 21 | 16 passed | 3 failed | 2 failed as expected
assertions: 49 | 42 passed | 4 failed | 3 failed as expected

View File

@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<testsuitesloose text artifact
>
<testsuite name="<exe-name>" errors="17" failures="132" tests="1694" hostname="tbd" time="{duration}" timestamp="{iso8601-timestamp}">
<testsuite name="<exe-name>" errors="17" failures="132" tests="1719" hostname="tbd" time="{duration}" timestamp="{iso8601-timestamp}">
<properties>
<property name="filters" value="~[!nonportable]~[!benchmark]~[approvals]"/>
<property name="random-seed" value="1"/>
@@ -30,6 +30,9 @@ Nor would this
</system-err>
</testcase>
<testcase classname="<exe-name>.global" name="#1548" time="{duration}"/>
<testcase classname="<exe-name>.global" name="#1905 -- test spec parser properly clears internal state between compound tests" time="{duration}"/>
<testcase classname="<exe-name>.global" name="#1912 -- test spec parser handles escaping/Various parentheses" time="{duration}"/>
<testcase classname="<exe-name>.global" name="#1912 -- test spec parser handles escaping/backslash in test name" time="{duration}"/>
<testcase classname="<exe-name>.global" name="#748 - captures with unexpected exceptions/outside assertions" time="{duration}">
<error type="TEST_CASE">
FAILED:
@@ -337,6 +340,7 @@ Exception.tests.cpp:<line number>
<testcase classname="<exe-name>.global" name="Approximate comparisons with mixed numeric types" time="{duration}"/>
<testcase classname="<exe-name>.global" name="Arbitrary predicate matcher/Function pointer" time="{duration}"/>
<testcase classname="<exe-name>.global" name="Arbitrary predicate matcher/Lambdas + different type" time="{duration}"/>
<testcase classname="<exe-name>.global" name="Assertion macros support bit operators and bool conversions" time="{duration}"/>
<testcase classname="<exe-name>.global" name="Assertions then sections" time="{duration}"/>
<testcase classname="<exe-name>.global" name="Assertions then sections/A section" time="{duration}"/>
<testcase classname="<exe-name>.global" name="Assertions then sections/A section/Another section" time="{duration}"/>
@@ -753,6 +757,7 @@ Condition.tests.cpp:<line number>
</failure>
</testcase>
<testcase classname="<exe-name>.global" name="Inequality checks that should succeed" time="{duration}"/>
<testcase classname="<exe-name>.global" name="Lambdas in assertions" time="{duration}"/>
<testcase classname="<exe-name>.global" name="Less-than inequalities with different epsilons" time="{duration}"/>
<testcase classname="<exe-name>.global" name="ManuallyRegistered" time="{duration}"/>
<testcase classname="<exe-name>.global" name="Matchers can be (AllOf) composed with the &amp;&amp; operator" time="{duration}"/>

View File

@@ -2,6 +2,9 @@
<testExecutions version="1"loose text artifact
>
<file path="projects/<exe-name>/IntrospectiveTests/CmdLine.tests.cpp">
<testCase name="#1905 -- test spec parser properly clears internal state between compound tests" duration="{duration}"/>
<testCase name="#1912 -- test spec parser handles escaping/Various parentheses" duration="{duration}"/>
<testCase name="#1912 -- test spec parser handles escaping/backslash in test name" duration="{duration}"/>
<testCase name="Parse test names and tags/Empty test spec should have no filters" duration="{duration}"/>
<testCase name="Parse test names and tags/Test spec from empty string should have no filters" duration="{duration}"/>
<testCase name="Parse test names and tags/Test spec from just a comma should have no filters" duration="{duration}"/>
@@ -369,6 +372,8 @@ Class.tests.cpp:<line number>
<testCase name="#809" duration="{duration}"/>
<testCase name="#833" duration="{duration}"/>
<testCase name="#872" duration="{duration}"/>
<testCase name="Assertion macros support bit operators and bool conversions" duration="{duration}"/>
<testCase name="Lambdas in assertions" duration="{duration}"/>
<testCase name="Optionally static assertions" duration="{duration}"/>
</file>
<file path="projects/<exe-name>/UsageTests/Condition.tests.cpp">

View File

@@ -196,6 +196,74 @@ Nor would this
</Expression>
<OverallResult success="true"/>
</TestCase>
<TestCase name="#1905 -- test spec parser properly clears internal state between compound tests" tags="[command-line][test-spec]" filename="projects/<exe-name>/IntrospectiveTests/CmdLine.tests.cpp" >
<Expression success="true" type="REQUIRE" filename="projects/<exe-name>/IntrospectiveTests/CmdLine.tests.cpp" >
<Original>
spec.matches(fakeTestCase("spec . char"))
</Original>
<Expanded>
true
</Expanded>
</Expression>
<Expression success="true" type="REQUIRE" filename="projects/<exe-name>/IntrospectiveTests/CmdLine.tests.cpp" >
<Original>
spec.matches(fakeTestCase("spec , char"))
</Original>
<Expanded>
true
</Expanded>
</Expression>
<Expression success="true" type="REQUIRE_FALSE" filename="projects/<exe-name>/IntrospectiveTests/CmdLine.tests.cpp" >
<Original>
!(spec.matches(fakeTestCase(R"(spec \, char)")))
</Original>
<Expanded>
!false
</Expanded>
</Expression>
<OverallResult success="true"/>
</TestCase>
<TestCase name="#1912 -- test spec parser handles escaping" tags="[command-line][test-spec]" filename="projects/<exe-name>/IntrospectiveTests/CmdLine.tests.cpp" >
<Section name="Various parentheses" filename="projects/<exe-name>/IntrospectiveTests/CmdLine.tests.cpp" >
<Expression success="true" type="REQUIRE" filename="projects/<exe-name>/IntrospectiveTests/CmdLine.tests.cpp" >
<Original>
spec.matches(fakeTestCase(R"(spec {a} char)"))
</Original>
<Expanded>
true
</Expanded>
</Expression>
<Expression success="true" type="REQUIRE" filename="projects/<exe-name>/IntrospectiveTests/CmdLine.tests.cpp" >
<Original>
spec.matches(fakeTestCase(R"(spec [a] char)"))
</Original>
<Expanded>
true
</Expanded>
</Expression>
<Expression success="true" type="REQUIRE_FALSE" filename="projects/<exe-name>/IntrospectiveTests/CmdLine.tests.cpp" >
<Original>
!(spec.matches(fakeTestCase("differs but has similar tag", "[a]")))
</Original>
<Expanded>
!false
</Expanded>
</Expression>
<OverallResults successes="3" failures="0" expectedFailures="0"/>
</Section>
<Section name="backslash in test name" filename="projects/<exe-name>/IntrospectiveTests/CmdLine.tests.cpp" >
<Expression success="true" type="REQUIRE" filename="projects/<exe-name>/IntrospectiveTests/CmdLine.tests.cpp" >
<Original>
spec.matches(fakeTestCase(R"(spec \ char)"))
</Original>
<Expanded>
true
</Expanded>
</Expression>
<OverallResults successes="1" failures="0" expectedFailures="0"/>
</Section>
<OverallResult success="true"/>
</TestCase>
<TestCase name="#748 - captures with unexpected exceptions" tags="[!hide][!shouldfail][!throws][.][failing]" filename="projects/<exe-name>/UsageTests/Exception.tests.cpp" >
<Section name="outside assertions" filename="projects/<exe-name>/UsageTests/Exception.tests.cpp" >
<Info>
@@ -2109,6 +2177,49 @@ Nor would this
</Section>
<OverallResult success="true"/>
</TestCase>
<TestCase name="Assertion macros support bit operators and bool conversions" tags="[bitops][compilation]" filename="projects/<exe-name>/UsageTests/Compilation.tests.cpp" >
<Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/Compilation.tests.cpp" >
<Original>
lhs | rhs
</Original>
<Expanded>
Val: 1 | Val: 2
</Expanded>
</Expression>
<Expression success="true" type="REQUIRE_FALSE" filename="projects/<exe-name>/UsageTests/Compilation.tests.cpp" >
<Original>
!(lhs &amp; rhs)
</Original>
<Expanded>
!(Val: 1 &amp; Val: 2)
</Expanded>
</Expression>
<Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/Compilation.tests.cpp" >
<Original>
HasBitOperators{ 1 } &amp; HasBitOperators{ 1 }
</Original>
<Expanded>
Val: 1 &amp; Val: 1
</Expanded>
</Expression>
<Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/Compilation.tests.cpp" >
<Original>
lhs ^ rhs
</Original>
<Expanded>
Val: 1 ^ Val: 2
</Expanded>
</Expression>
<Expression success="true" type="REQUIRE_FALSE" filename="projects/<exe-name>/UsageTests/Compilation.tests.cpp" >
<Original>
!(lhs ^ lhs)
</Original>
<Expanded>
!(Val: 1 ^ Val: 1)
</Expanded>
</Expression>
<OverallResult success="true"/>
</TestCase>
<TestCase name="Assertions then sections" tags="[Tricky]" filename="projects/<exe-name>/UsageTests/Tricky.tests.cpp" >
<Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/Tricky.tests.cpp" >
<Original>
@@ -7266,6 +7377,17 @@ Nor would this
</Expression>
<OverallResult success="true"/>
</TestCase>
<TestCase name="Lambdas in assertions" filename="projects/<exe-name>/UsageTests/Compilation.tests.cpp" >
<Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/Compilation.tests.cpp" >
<Original>
[]() { return true; }()
</Original>
<Expanded>
true
</Expanded>
</Expression>
<OverallResult success="true"/>
</TestCase>
<TestCase name="Less-than inequalities with different epsilons" tags="[Approx]" filename="projects/<exe-name>/UsageTests/Approx.tests.cpp" >
<Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/Approx.tests.cpp" >
<Original>
@@ -13518,9 +13640,17 @@ There is no extra whitespace here
{ 1.0, 2.0, 3.0 } is approx: { 1.0, 2.0, 3.0 }
</Expanded>
</Expression>
<OverallResults successes="1" failures="0" expectedFailures="0"/>
<Expression success="true" type="REQUIRE_THAT" filename="projects/<exe-name>/UsageTests/Matchers.tests.cpp" >
<Original>
v1, Approx&lt;double>({ 1., 2., 3. })
</Original>
<Expanded>
{ 1.0, 2.0, 3.0 } is approx: { 1.0, 2.0, 3.0 }
</Expanded>
</Expression>
<OverallResults successes="2" failures="0" expectedFailures="0"/>
</Section>
<OverallResults successes="1" failures="0" expectedFailures="0"/>
<OverallResults successes="2" failures="0" expectedFailures="0"/>
</Section>
<Section name="Vectors with elements" filename="projects/<exe-name>/UsageTests/Matchers.tests.cpp" >
<Section name="Different length" filename="projects/<exe-name>/UsageTests/Matchers.tests.cpp" >
@@ -13619,7 +13749,15 @@ There is no extra whitespace here
{ 1, 2, 3 } Contains: 2
</Expanded>
</Expression>
<OverallResults successes="2" failures="0" expectedFailures="0"/>
<Expression success="true" type="CHECK_THAT" filename="projects/<exe-name>/UsageTests/Matchers.tests.cpp" >
<Original>
v5, (VectorContains&lt;int, CustomAllocator&lt;int>>(2))
</Original>
<Expanded>
{ 1, 2, 3 } Contains: 2
</Expanded>
</Expression>
<OverallResults successes="3" failures="0" expectedFailures="0"/>
</Section>
<Section name="Contains (vector)" filename="projects/<exe-name>/UsageTests/Matchers.tests.cpp" >
<Expression success="true" type="CHECK_THAT" filename="projects/<exe-name>/UsageTests/Matchers.tests.cpp" >
@@ -13630,6 +13768,22 @@ There is no extra whitespace here
{ 1, 2, 3 } Contains: { 1, 2 }
</Expanded>
</Expression>
<Expression success="true" type="CHECK_THAT" filename="projects/<exe-name>/UsageTests/Matchers.tests.cpp" >
<Original>
v, Contains&lt;int>({ 1, 2 })
</Original>
<Expanded>
{ 1, 2, 3 } Contains: { 1, 2 }
</Expanded>
</Expression>
<Expression success="true" type="CHECK_THAT" filename="projects/<exe-name>/UsageTests/Matchers.tests.cpp" >
<Original>
v5, (Contains&lt;int, std::allocator&lt;int>, CustomAllocator&lt;int>>(v2))
</Original>
<Expanded>
{ 1, 2, 3 } Contains: { 1, 2 }
</Expanded>
</Expression>
<Expression success="true" type="CHECK_THAT" filename="projects/<exe-name>/UsageTests/Matchers.tests.cpp" >
<Original>
v, Contains(v2)
@@ -13654,7 +13808,23 @@ There is no extra whitespace here
{ } Contains: { }
</Expanded>
</Expression>
<OverallResults successes="4" failures="0" expectedFailures="0"/>
<Expression success="true" type="CHECK_THAT" filename="projects/<exe-name>/UsageTests/Matchers.tests.cpp" >
<Original>
v5, (Contains&lt;int, std::allocator&lt;int>, CustomAllocator&lt;int>>(v2))
</Original>
<Expanded>
{ 1, 2, 3 } Contains: { 1, 2, 3 }
</Expanded>
</Expression>
<Expression success="true" type="CHECK_THAT" filename="projects/<exe-name>/UsageTests/Matchers.tests.cpp" >
<Original>
v5, Contains(v6)
</Original>
<Expanded>
{ 1, 2, 3 } Contains: { 1, 2 }
</Expanded>
</Expression>
<OverallResults successes="8" failures="0" expectedFailures="0"/>
</Section>
<Section name="Contains (element), composed" filename="projects/<exe-name>/UsageTests/Matchers.tests.cpp" >
<Expression success="true" type="CHECK_THAT" filename="projects/<exe-name>/UsageTests/Matchers.tests.cpp" >
@@ -13684,6 +13854,14 @@ There is no extra whitespace here
{ } Equals: { }
</Expanded>
</Expression>
<Expression success="true" type="CHECK_THAT" filename="projects/<exe-name>/UsageTests/Matchers.tests.cpp" >
<Original>
v, Equals&lt;int>({ 1, 2, 3 })
</Original>
<Expanded>
{ 1, 2, 3 } Equals: { 1, 2, 3 }
</Expanded>
</Expression>
<Expression success="true" type="CHECK_THAT" filename="projects/<exe-name>/UsageTests/Matchers.tests.cpp" >
<Original>
v, Equals(v2)
@@ -13692,7 +13870,23 @@ There is no extra whitespace here
{ 1, 2, 3 } Equals: { 1, 2, 3 }
</Expanded>
</Expression>
<OverallResults successes="3" failures="0" expectedFailures="0"/>
<Expression success="true" type="CHECK_THAT" filename="projects/<exe-name>/UsageTests/Matchers.tests.cpp" >
<Original>
v5, (Equals&lt;int, std::allocator&lt;int>, CustomAllocator&lt;int>>(v2))
</Original>
<Expanded>
{ 1, 2, 3 } Equals: { 1, 2, 3 }
</Expanded>
</Expression>
<Expression success="true" type="CHECK_THAT" filename="projects/<exe-name>/UsageTests/Matchers.tests.cpp" >
<Original>
v5, Equals(v6)
</Original>
<Expanded>
{ 1, 2, 3 } Equals: { 1, 2, 3 }
</Expanded>
</Expression>
<OverallResults successes="6" failures="0" expectedFailures="0"/>
</Section>
<Section name="UnorderedEquals" filename="projects/<exe-name>/UsageTests/Matchers.tests.cpp" >
<Expression success="true" type="CHECK_THAT" filename="projects/<exe-name>/UsageTests/Matchers.tests.cpp" >
@@ -13703,6 +13897,14 @@ There is no extra whitespace here
{ 1, 2, 3 } UnorderedEquals: { 1, 2, 3 }
</Expanded>
</Expression>
<Expression success="true" type="CHECK_THAT" filename="projects/<exe-name>/UsageTests/Matchers.tests.cpp" >
<Original>
v, UnorderedEquals&lt;int>({ 3, 2, 1 })
</Original>
<Expanded>
{ 1, 2, 3 } UnorderedEquals: { 3, 2, 1 }
</Expanded>
</Expression>
<Expression success="true" type="CHECK_THAT" filename="projects/<exe-name>/UsageTests/Matchers.tests.cpp" >
<Original>
empty, UnorderedEquals(empty)
@@ -13727,7 +13929,23 @@ There is no extra whitespace here
{ 2, 3, 1 } UnorderedEquals: { 1, 2, 3 }
</Expanded>
</Expression>
<OverallResults successes="4" failures="0" expectedFailures="0"/>
<Expression success="true" type="CHECK_THAT" filename="projects/<exe-name>/UsageTests/Matchers.tests.cpp" >
<Original>
v5, (UnorderedEquals&lt;int, std::allocator&lt;int>, CustomAllocator&lt;int>>(permuted))
</Original>
<Expanded>
{ 1, 2, 3 } UnorderedEquals: { 2, 3, 1 }
</Expanded>
</Expression>
<Expression success="true" type="CHECK_THAT" filename="projects/<exe-name>/UsageTests/Matchers.tests.cpp" >
<Original>
v5_permuted, UnorderedEquals(v5)
</Original>
<Expanded>
{ 1, 3, 2 } UnorderedEquals: { 1, 2, 3 }
</Expanded>
</Expression>
<OverallResults successes="7" failures="0" expectedFailures="0"/>
</Section>
<OverallResult success="true"/>
</TestCase>
@@ -16037,7 +16255,7 @@ loose text artifact
</Section>
<OverallResult success="true"/>
</TestCase>
<OverallResults successes="1524" failures="149" expectedFailures="21"/>
<OverallResults successes="1549" failures="149" expectedFailures="21"/>
</Group>
<OverallResults successes="1524" failures="148" expectedFailures="21"/>
<OverallResults successes="1549" failures="148" expectedFailures="21"/>
</Catch>

View File

@@ -292,6 +292,35 @@ TEST_CASE( "Parse test names and tags", "[command-line][test-spec]" ) {
}
}
TEST_CASE("#1905 -- test spec parser properly clears internal state between compound tests", "[command-line][test-spec]") {
using Catch::parseTestSpec;
using Catch::TestSpec;
// We ask for one of 2 different tests and the latter one of them has a , in name that needs escaping
TestSpec spec = parseTestSpec(R"("spec . char","spec \, char")");
REQUIRE(spec.matches(fakeTestCase("spec . char")));
REQUIRE(spec.matches(fakeTestCase("spec , char")));
REQUIRE_FALSE(spec.matches(fakeTestCase(R"(spec \, char)")));
}
TEST_CASE("#1912 -- test spec parser handles escaping", "[command-line][test-spec]") {
using Catch::parseTestSpec;
using Catch::TestSpec;
SECTION("Various parentheses") {
TestSpec spec = parseTestSpec(R"(spec {a} char,spec \[a] char)");
REQUIRE(spec.matches(fakeTestCase(R"(spec {a} char)")));
REQUIRE(spec.matches(fakeTestCase(R"(spec [a] char)")));
REQUIRE_FALSE(spec.matches(fakeTestCase("differs but has similar tag", "[a]")));
}
SECTION("backslash in test name") {
TestSpec spec = parseTestSpec(R"(spec \\ char)");
REQUIRE(spec.matches(fakeTestCase(R"(spec \ char)")));
}
}
TEST_CASE( "Process can be configured on command line", "[config][command-line]" ) {
#ifndef CATCH_CONFIG_DISABLE_MATCHERS

View File

@@ -228,6 +228,42 @@ namespace { namespace CompilationTests {
REQUIRE( 0 == y.v );
}
TEST_CASE("Lambdas in assertions") {
REQUIRE([]() { return true; }());
}
}} // namespace CompilationTests
namespace {
struct HasBitOperators {
int value;
friend HasBitOperators operator| (HasBitOperators lhs, HasBitOperators rhs) {
return { lhs.value | rhs.value };
}
friend HasBitOperators operator& (HasBitOperators lhs, HasBitOperators rhs) {
return { lhs.value & rhs.value };
}
friend HasBitOperators operator^ (HasBitOperators lhs, HasBitOperators rhs) {
return { lhs.value ^ rhs.value };
}
explicit operator bool() const {
return !!value;
}
friend std::ostream& operator<<(std::ostream& out, HasBitOperators val) {
out << "Val: " << val.value;
return out;
}
};
}
TEST_CASE("Assertion macros support bit operators and bool conversions", "[compilation][bitops]") {
HasBitOperators lhs{ 1 }, rhs{ 2 };
REQUIRE(lhs | rhs);
REQUIRE_FALSE(lhs & rhs);
REQUIRE(HasBitOperators{ 1 } & HasBitOperators{ 1 });
REQUIRE(lhs ^ rhs);
REQUIRE_FALSE(lhs ^ lhs);
}

View File

@@ -214,6 +214,42 @@ namespace { namespace MatchersTests {
CHECK_THAT(testStringForMatching(), !Contains("substring"));
}
template<typename T>
struct CustomAllocator : private std::allocator<T>
{
using size_type = size_t;
using difference_type = ptrdiff_t;
using pointer = T*;
using const_pointer = const T*;
using reference = T&;
using const_reference = const T&;
using value_type = T;
template<typename U>
struct rebind
{ using other = CustomAllocator<U>; };
using propagate_on_container_move_assignment = std::true_type;
using is_always_equal = std::true_type;
CustomAllocator() = default;
CustomAllocator(const CustomAllocator& other)
: std::allocator<T>(other) { }
template<typename U>
CustomAllocator(const CustomAllocator<U>&) { }
~CustomAllocator() = default;
using std::allocator<T>::address;
using std::allocator<T>::allocate;
using std::allocator<T>::construct;
using std::allocator<T>::deallocate;
using std::allocator<T>::max_size;
using std::allocator<T>::destroy;
};
TEST_CASE("Vector matchers", "[matchers][vector]") {
std::vector<int> v;
v.push_back(1);
@@ -234,19 +270,35 @@ namespace { namespace MatchersTests {
v4.push_back(2 + 1e-8);
v4.push_back(3 + 1e-8);
std::vector<int, CustomAllocator<int>> v5;
v5.push_back(1);
v5.push_back(2);
v5.push_back(3);
std::vector<int, CustomAllocator<int>> v6;
v6.push_back(1);
v6.push_back(2);
std::vector<int> empty;
SECTION("Contains (element)") {
CHECK_THAT(v, VectorContains(1));
CHECK_THAT(v, VectorContains(2));
CHECK_THAT(v5, (VectorContains<int, CustomAllocator<int>>(2)));
}
SECTION("Contains (vector)") {
CHECK_THAT(v, Contains(v2));
CHECK_THAT(v, Contains<int>({ 1, 2 }));
CHECK_THAT(v5, (Contains<int, std::allocator<int>, CustomAllocator<int>>(v2)));
v2.push_back(3); // now exactly matches
CHECK_THAT(v, Contains(v2));
CHECK_THAT(v, Contains(empty));
CHECK_THAT(empty, Contains(empty));
CHECK_THAT(v5, (Contains<int, std::allocator<int>, CustomAllocator<int>>(v2)));
CHECK_THAT(v5, Contains(v6));
}
SECTION("Contains (element), composed") {
CHECK_THAT(v, VectorContains(1) && VectorContains(2));
@@ -256,15 +308,21 @@ namespace { namespace MatchersTests {
// Same vector
CHECK_THAT(v, Equals(v));
CHECK_THAT(empty, Equals(empty));
// Different vector with same elements
CHECK_THAT(v, Equals<int>({ 1, 2, 3 }));
v2.push_back(3);
CHECK_THAT(v, Equals(v2));
CHECK_THAT(v5, (Equals<int, std::allocator<int>, CustomAllocator<int>>(v2)));
v6.push_back(3);
CHECK_THAT(v5, Equals(v6));
}
SECTION("UnorderedEquals") {
CHECK_THAT(v, UnorderedEquals(v));
CHECK_THAT(v, UnorderedEquals<int>({ 3, 2, 1 }));
CHECK_THAT(empty, UnorderedEquals(empty));
auto permuted = v;
@@ -273,6 +331,12 @@ namespace { namespace MatchersTests {
std::reverse(begin(permuted), end(permuted));
REQUIRE_THAT(permuted, UnorderedEquals(v));
CHECK_THAT(v5, (UnorderedEquals<int, std::allocator<int>, CustomAllocator<int>>(permuted)));
auto v5_permuted = v5;
std::next_permutation(begin(v5_permuted), end(v5_permuted));
CHECK_THAT(v5_permuted, UnorderedEquals(v5));
}
}
@@ -518,6 +582,7 @@ namespace { namespace MatchersTests {
std::vector<double> v1({1., 2., 3.});
SECTION("A vector is approx equal to itself") {
REQUIRE_THAT(v1, Approx(v1));
REQUIRE_THAT(v1, Approx<double>({ 1., 2., 3. }));
}
std::vector<double> v2({1.5, 2.5, 3.5});
SECTION("Different length") {
@@ -552,7 +617,7 @@ namespace { namespace MatchersTests {
REQUIRE_THROWS_MATCHES(throwsSpecialException(2), SpecialException, !Message("DerivedException::what"));
REQUIRE_THROWS_MATCHES(throwsSpecialException(2), SpecialException, Message("SpecialException::what"));
}
TEST_CASE("Composed matchers are distinct", "[matchers][composed]") {
auto m1 = Contains("string");
auto m2 = Contains("random");

View File

@@ -0,0 +1,59 @@
#!/usr/bin/env python3
"""
This test script verifies that the random ordering of tests inside
Catch2 is invariant in regards to subsetting. This is done by running
the binary 3 times, once with all tests selected, and twice with smaller
subsets of tests selected, and verifying that the selected tests are in
the same relative order.
"""
import subprocess
import sys
import random
def list_tests(self_test_exe, tags, rng_seed):
cmd = [self_test_exe, '--list-test-names-only', '--order', 'rand',
'--rng-seed', str(rng_seed)]
tags_arg = ','.join('[{}]'.format(t) for t in tags)
if tags_arg:
cmd.append(tags_arg + '~[.]')
process = subprocess.Popen(
cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
stdout, stderr = process.communicate()
if stderr:
raise RuntimeError("Unexpected error output:\n" + process.stderr)
result = stdout.split(b'\n')
result = [s for s in result if s]
if len(result) < 2:
raise RuntimeError("Unexpectedly few tests listed (got {})".format(
len(result)))
return result
def check_is_sublist_of(shorter, longer):
assert len(shorter) < len(longer)
assert len(set(longer)) == len(longer)
indexes_in_longer = {s: i for i, s in enumerate(longer)}
for s1, s2 in zip(shorter, shorter[1:]):
assert indexes_in_longer[s1] < indexes_in_longer[s2], (
'{} comes before {} in longer list.\n'
'Longer: {}\nShorter: {}'.format(s2, s1, longer, shorter))
def main():
self_test_exe, = sys.argv[1:]
# We want a random seed for the test, but want to avoid 0,
# because it has special meaning
seed = random.randint(1, 2 ** 32 - 1)
list_one_tag = list_tests(self_test_exe, ['generators'], seed)
list_two_tags = list_tests(self_test_exe, ['generators', 'matchers'], seed)
list_all = list_tests(self_test_exe, [], seed)
# First, verify that restricting to a subset yields the same order
check_is_sublist_of(list_two_tags, list_all)
check_is_sublist_of(list_one_tag, list_two_tags)
if __name__ == '__main__':
sys.exit(main())

View File

@@ -1,6 +1,6 @@
/*
* Catch v2.11.2
* Generated: 2020-03-19 12:35:04.038733
* Catch v2.12.1
* Generated: 2020-04-21 19:29:20.964532
* ----------------------------------------------------------
* This file has been merged from multiple headers. Please don't edit it directly
* Copyright (c) 2020 Two Blue Cubes Ltd. All rights reserved.
@@ -14,8 +14,8 @@
#define CATCH_VERSION_MAJOR 2
#define CATCH_VERSION_MINOR 11
#define CATCH_VERSION_PATCH 2
#define CATCH_VERSION_MINOR 12
#define CATCH_VERSION_PATCH 1
#ifdef __clang__
# pragma clang system_header
@@ -132,7 +132,7 @@ namespace Catch {
#endif
#if defined(CATCH_CPP17_OR_GREATER)
#if defined(__cpp_lib_uncaught_exceptions)
# define CATCH_INTERNAL_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS
#endif
@@ -151,7 +151,20 @@ namespace Catch {
# define CATCH_INTERNAL_START_WARNINGS_SUPPRESSION _Pragma( "clang diagnostic push" )
# define CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION _Pragma( "clang diagnostic pop" )
# define CATCH_INTERNAL_IGNORE_BUT_WARN(...) (void)__builtin_constant_p(__VA_ARGS__)
// As of this writing, IBM XL's implementation of __builtin_constant_p has a bug
// which results in calls to destructors being emitted for each temporary,
// without a matching initialization. In practice, this can result in something
// like `std::string::~string` being called on an uninitialized value.
//
// For example, this code will likely segfault under IBM XL:
// ```
// REQUIRE(std::string("12") + "34" == "1234")
// ```
//
// Therefore, `CATCH_INTERNAL_IGNORE_BUT_WARN` is not implemented.
# if !defined(__ibmxl__)
# define CATCH_INTERNAL_IGNORE_BUT_WARN(...) (void)__builtin_constant_p(__VA_ARGS__) /* NOLINT(cppcoreguidelines-pro-type-vararg) */
# endif
# define CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
_Pragma( "clang diagnostic ignored \"-Wexit-time-destructors\"" ) \
@@ -231,8 +244,6 @@ namespace Catch {
# define CATCH_INTERNAL_START_WARNINGS_SUPPRESSION __pragma( warning(push) )
# define CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION __pragma( warning(pop) )
# define CATCH_INTERNAL_IGNORE_BUT_WARN(...) (void)sizeof(__VA_ARGS__)
# if _MSC_VER >= 1900 // Visual Studio 2015 or newer
# define CATCH_INTERNAL_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS
# endif
@@ -2358,6 +2369,18 @@ namespace Catch {
auto operator <= ( RhsT const& rhs ) -> BinaryExpr<LhsT, RhsT const&> const {
return { static_cast<bool>(m_lhs <= rhs), m_lhs, "<=", rhs };
}
template <typename RhsT>
auto operator | (RhsT const& rhs) -> BinaryExpr<LhsT, RhsT const&> const {
return { static_cast<bool>(m_lhs | rhs), m_lhs, "|", rhs };
}
template <typename RhsT>
auto operator & (RhsT const& rhs) -> BinaryExpr<LhsT, RhsT const&> const {
return { static_cast<bool>(m_lhs & rhs), m_lhs, "&", rhs };
}
template <typename RhsT>
auto operator ^ (RhsT const& rhs) -> BinaryExpr<LhsT, RhsT const&> const {
return { static_cast<bool>(m_lhs ^ rhs), m_lhs, "^", rhs };
}
template<typename RhsT>
auto operator && ( RhsT const& ) -> BinaryExpr<LhsT, RhsT const&> const {
@@ -2685,7 +2708,7 @@ namespace Catch {
CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION \
} INTERNAL_CATCH_CATCH( catchAssertionHandler ) \
INTERNAL_CATCH_REACT( catchAssertionHandler ) \
} while( false )
} while( (void)0, (false) && static_cast<bool>( !!(__VA_ARGS__) ) )
///////////////////////////////////////////////////////////////////////////////
#define INTERNAL_CATCH_IF( macroName, resultDisposition, ... ) \
@@ -3002,6 +3025,9 @@ namespace Catch {
{}
std::string translate( ExceptionTranslators::const_iterator it, ExceptionTranslators::const_iterator itEnd ) const override {
#if defined(CATCH_CONFIG_DISABLE_EXCEPTIONS)
return "";
#else
try {
if( it == itEnd )
std::rethrow_exception(std::current_exception());
@@ -3011,6 +3037,7 @@ namespace Catch {
catch( T& ex ) {
return m_translateFunction( ex );
}
#endif
}
protected:
@@ -3573,12 +3600,12 @@ namespace Catch {
namespace Matchers {
namespace Vector {
template<typename T>
struct ContainsElementMatcher : MatcherBase<std::vector<T>> {
template<typename T, typename Alloc>
struct ContainsElementMatcher : MatcherBase<std::vector<T, Alloc>> {
ContainsElementMatcher(T const &comparator) : m_comparator( comparator) {}
bool match(std::vector<T> const &v) const override {
bool match(std::vector<T, Alloc> const &v) const override {
for (auto const& el : v) {
if (el == m_comparator) {
return true;
@@ -3594,12 +3621,12 @@ namespace Matchers {
T const& m_comparator;
};
template<typename T>
struct ContainsMatcher : MatcherBase<std::vector<T>> {
template<typename T, typename AllocComp, typename AllocMatch>
struct ContainsMatcher : MatcherBase<std::vector<T, AllocMatch>> {
ContainsMatcher(std::vector<T> const &comparator) : m_comparator( comparator ) {}
ContainsMatcher(std::vector<T, AllocComp> const &comparator) : m_comparator( comparator ) {}
bool match(std::vector<T> const &v) const override {
bool match(std::vector<T, AllocMatch> const &v) const override {
// !TBD: see note in EqualsMatcher
if (m_comparator.size() > v.size())
return false;
@@ -3621,18 +3648,18 @@ namespace Matchers {
return "Contains: " + ::Catch::Detail::stringify( m_comparator );
}
std::vector<T> const& m_comparator;
std::vector<T, AllocComp> const& m_comparator;
};
template<typename T>
struct EqualsMatcher : MatcherBase<std::vector<T>> {
template<typename T, typename AllocComp, typename AllocMatch>
struct EqualsMatcher : MatcherBase<std::vector<T, AllocMatch>> {
EqualsMatcher(std::vector<T> const &comparator) : m_comparator( comparator ) {}
EqualsMatcher(std::vector<T, AllocComp> const &comparator) : m_comparator( comparator ) {}
bool match(std::vector<T> const &v) const override {
bool match(std::vector<T, AllocMatch> const &v) const override {
// !TBD: This currently works if all elements can be compared using !=
// - a more general approach would be via a compare template that defaults
// to using !=. but could be specialised for, e.g. std::vector<T> etc
// to using !=. but could be specialised for, e.g. std::vector<T, Alloc> etc
// - then just call that directly
if (m_comparator.size() != v.size())
return false;
@@ -3644,15 +3671,15 @@ namespace Matchers {
std::string describe() const override {
return "Equals: " + ::Catch::Detail::stringify( m_comparator );
}
std::vector<T> const& m_comparator;
std::vector<T, AllocComp> const& m_comparator;
};
template<typename T>
struct ApproxMatcher : MatcherBase<std::vector<T>> {
template<typename T, typename AllocComp, typename AllocMatch>
struct ApproxMatcher : MatcherBase<std::vector<T, AllocMatch>> {
ApproxMatcher(std::vector<T> const& comparator) : m_comparator( comparator ) {}
ApproxMatcher(std::vector<T, AllocComp> const& comparator) : m_comparator( comparator ) {}
bool match(std::vector<T> const &v) const override {
bool match(std::vector<T, AllocMatch> const &v) const override {
if (m_comparator.size() != v.size())
return false;
for (std::size_t i = 0; i < v.size(); ++i)
@@ -3679,14 +3706,14 @@ namespace Matchers {
return *this;
}
std::vector<T> const& m_comparator;
std::vector<T, AllocComp> const& m_comparator;
mutable Catch::Detail::Approx approx = Catch::Detail::Approx::custom();
};
template<typename T>
struct UnorderedEqualsMatcher : MatcherBase<std::vector<T>> {
UnorderedEqualsMatcher(std::vector<T> const& target) : m_target(target) {}
bool match(std::vector<T> const& vec) const override {
template<typename T, typename AllocComp, typename AllocMatch>
struct UnorderedEqualsMatcher : MatcherBase<std::vector<T, AllocMatch>> {
UnorderedEqualsMatcher(std::vector<T, AllocComp> const& target) : m_target(target) {}
bool match(std::vector<T, AllocMatch> const& vec) const override {
// Note: This is a reimplementation of std::is_permutation,
// because I don't want to include <algorithm> inside the common path
if (m_target.size() != vec.size()) {
@@ -3699,7 +3726,7 @@ namespace Matchers {
return "UnorderedEquals: " + ::Catch::Detail::stringify(m_target);
}
private:
std::vector<T> const& m_target;
std::vector<T, AllocComp> const& m_target;
};
} // namespace Vector
@@ -3707,29 +3734,29 @@ namespace Matchers {
// The following functions create the actual matcher objects.
// This allows the types to be inferred
template<typename T>
Vector::ContainsMatcher<T> Contains( std::vector<T> const& comparator ) {
return Vector::ContainsMatcher<T>( comparator );
template<typename T, typename AllocComp = std::allocator<T>, typename AllocMatch = AllocComp>
Vector::ContainsMatcher<T, AllocComp, AllocMatch> Contains( std::vector<T, AllocComp> const& comparator ) {
return Vector::ContainsMatcher<T, AllocComp, AllocMatch>( comparator );
}
template<typename T>
Vector::ContainsElementMatcher<T> VectorContains( T const& comparator ) {
return Vector::ContainsElementMatcher<T>( comparator );
template<typename T, typename Alloc = std::allocator<T>>
Vector::ContainsElementMatcher<T, Alloc> VectorContains( T const& comparator ) {
return Vector::ContainsElementMatcher<T, Alloc>( comparator );
}
template<typename T>
Vector::EqualsMatcher<T> Equals( std::vector<T> const& comparator ) {
return Vector::EqualsMatcher<T>( comparator );
template<typename T, typename AllocComp = std::allocator<T>, typename AllocMatch = AllocComp>
Vector::EqualsMatcher<T, AllocComp, AllocMatch> Equals( std::vector<T, AllocComp> const& comparator ) {
return Vector::EqualsMatcher<T, AllocComp, AllocMatch>( comparator );
}
template<typename T>
Vector::ApproxMatcher<T> Approx( std::vector<T> const& comparator ) {
return Vector::ApproxMatcher<T>( comparator );
template<typename T, typename AllocComp = std::allocator<T>, typename AllocMatch = AllocComp>
Vector::ApproxMatcher<T, AllocComp, AllocMatch> Approx( std::vector<T, AllocComp> const& comparator ) {
return Vector::ApproxMatcher<T, AllocComp, AllocMatch>( comparator );
}
template<typename T>
Vector::UnorderedEqualsMatcher<T> UnorderedEquals(std::vector<T> const& target) {
return Vector::UnorderedEqualsMatcher<T>(target);
template<typename T, typename AllocComp = std::allocator<T>, typename AllocMatch = AllocComp>
Vector::UnorderedEqualsMatcher<T, AllocComp, AllocMatch> UnorderedEquals(std::vector<T, AllocComp> const& target) {
return Vector::UnorderedEqualsMatcher<T, AllocComp, AllocMatch>( target );
}
} // namespace Matchers
@@ -10321,8 +10348,7 @@ namespace Catch {
#if defined(CATCH_PLATFORM_MAC) || defined(CATCH_PLATFORM_IPHONE)
# include <assert.h>
# include <stdbool.h>
# include <cassert>
# include <sys/types.h>
# include <unistd.h>
# include <cstddef>
@@ -13979,27 +14005,77 @@ namespace Catch {
// end catch_test_case_info.cpp
// start catch_test_case_registry_impl.cpp
#include <algorithm>
#include <sstream>
namespace Catch {
namespace {
struct TestHasher {
explicit TestHasher(Catch::SimplePcg32& rng) {
basis = rng();
basis <<= 32;
basis |= rng();
}
uint64_t basis;
uint64_t operator()(TestCase const& t) const {
// Modified FNV-1a hash
static constexpr uint64_t prime = 1099511628211;
uint64_t hash = basis;
for (const char c : t.name) {
hash ^= c;
hash *= prime;
}
return hash;
}
};
} // end unnamed namespace
std::vector<TestCase> sortTests( IConfig const& config, std::vector<TestCase> const& unsortedTestCases ) {
std::vector<TestCase> sorted = unsortedTestCases;
switch( config.runOrder() ) {
case RunTests::InLexicographicalOrder:
std::sort( sorted.begin(), sorted.end() );
break;
case RunTests::InRandomOrder:
seedRng( config );
std::shuffle( sorted.begin(), sorted.end(), rng() );
break;
case RunTests::InDeclarationOrder:
// already in declaration order
break;
case RunTests::InLexicographicalOrder: {
std::vector<TestCase> sorted = unsortedTestCases;
std::sort( sorted.begin(), sorted.end() );
return sorted;
}
case RunTests::InRandomOrder: {
seedRng( config );
TestHasher h( rng() );
using hashedTest = std::pair<uint64_t, TestCase const*>;
std::vector<hashedTest> indexed_tests;
indexed_tests.reserve( unsortedTestCases.size() );
for (auto const& testCase : unsortedTestCases) {
indexed_tests.emplace_back(h(testCase), &testCase);
}
std::sort(indexed_tests.begin(), indexed_tests.end(),
[](hashedTest const& lhs, hashedTest const& rhs) {
if (lhs.first == rhs.first) {
return lhs.second->name < rhs.second->name;
}
return lhs.first < rhs.first;
});
std::vector<TestCase> sorted;
sorted.reserve( indexed_tests.size() );
for (auto const& hashed : indexed_tests) {
sorted.emplace_back(*hashed.second);
}
return sorted;
}
}
return sorted;
return unsortedTestCases;
}
bool isThrowSafe( TestCase const& testCase, IConfig const& config ) {
@@ -14593,6 +14669,7 @@ namespace Catch {
m_pos = m_arg.size();
m_substring.clear();
m_patternName.clear();
m_realPatternPos = 0;
return false;
}
endMode();
@@ -14611,6 +14688,7 @@ namespace Catch {
}
m_patternName.clear();
m_realPatternPos = 0;
return token;
}
@@ -15081,7 +15159,7 @@ namespace Catch {
}
Version const& libraryVersion() {
static Version version( 2, 11, 2, "", 0 );
static Version version( 2, 12, 1, "", 0 );
return version;
}
@@ -16144,7 +16222,7 @@ ConsoleReporter::ConsoleReporter(ReporterConfig const& config)
else
{
return{
{ "benchmark name", CATCH_CONFIG_CONSOLE_WIDTH - 32, ColumnInfo::Left },
{ "benchmark name", CATCH_CONFIG_CONSOLE_WIDTH - 43, ColumnInfo::Left },
{ "samples mean std dev", 14, ColumnInfo::Right },
{ "iterations low mean low std dev", 14, ColumnInfo::Right },
{ "estimated high mean high std dev", 14, ColumnInfo::Right }