mirror of
https://github.com/catchorg/Catch2.git
synced 2026-05-22 08:34:46 +02:00
Compare commits
24 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 69e0473f6e | |||
| 6ee0826dca | |||
| 47ea57d74f | |||
| d838f88b9c | |||
| c267b6eb4d | |||
| 3cdae5faf0 | |||
| 651247c7f4 | |||
| 15b9393f0f | |||
| a18badd10f | |||
| 54af40652a | |||
| 5f47160bb2 | |||
| e83528c6eb | |||
| fd31a62547 | |||
| 4df8fee92d | |||
| 300c5d3eed | |||
| 11a96e186a | |||
| 10f62484bf | |||
| be2dfb45cc | |||
| 47200ddbee | |||
| e51dcdcc59 | |||
| 77eae8bd2a | |||
| 3ab0d7cef3 | |||
| e83218c2df | |||
| 548e14a8c8 |
@@ -32,6 +32,7 @@ Checks: >-
|
||||
-modernize-deprecated-headers,
|
||||
,# There's a lot of these and most of them are probably not useful,
|
||||
-modernize-pass-by-value,
|
||||
-modernize-use-string-view, # We support C++14,
|
||||
|
||||
performance-*,
|
||||
performance-enum-size,
|
||||
@@ -58,6 +59,8 @@ Checks: >-
|
||||
-readability-uppercase-literal-suffix,
|
||||
-readability-use-anyofallof,
|
||||
-readability-avoid-return-with-void-value,
|
||||
,# We prefer if defined(FOO) form because it is easier to extend later,
|
||||
-readability-use-concise-preprocessor-directives,
|
||||
|
||||
,# time hogs,
|
||||
-bugprone-throw-keyword-missing,
|
||||
|
||||
+1
-1
@@ -35,7 +35,7 @@ if(CMAKE_BINARY_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR)
|
||||
endif()
|
||||
|
||||
project(Catch2
|
||||
VERSION 3.14.0 # CML version placeholder, don't delete
|
||||
VERSION 3.15.0 # CML version placeholder, don't delete
|
||||
LANGUAGES CXX
|
||||
HOMEPAGE_URL "https://github.com/catchorg/Catch2"
|
||||
DESCRIPTION "A modern, C++-native, unit test framework."
|
||||
|
||||
@@ -9,8 +9,13 @@ add_executable(AssertionsSlowPath
|
||||
assertion_listener.cpp
|
||||
)
|
||||
|
||||
add_executable(EmptyExecutable
|
||||
only_include.cpp
|
||||
)
|
||||
|
||||
target_link_libraries(AssertionsFastPath PRIVATE Catch2::Catch2WithMain)
|
||||
target_link_libraries(AssertionsSlowPath PRIVATE Catch2::Catch2WithMain)
|
||||
target_link_libraries(EmptyExecutable PRIVATE Catch2::Catch2WithMain)
|
||||
|
||||
list(APPEND CATCH_TEST_TARGETS AssertionsFastPath AssertionsSlowPath)
|
||||
list(APPEND CATCH_TEST_TARGETS AssertionsFastPath AssertionsSlowPath EmptyExecutable)
|
||||
set(CATCH_TEST_TARGETS ${CATCH_TEST_TARGETS} PARENT_SCOPE)
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
|
||||
// Copyright Catch2 Authors
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// (See accompanying file LICENSE.txt or copy at
|
||||
// https://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
// SPDX-License-Identifier: BSL-1.0
|
||||
|
||||
/**\file
|
||||
* "empty" include of catch_test_macros.hpp
|
||||
*
|
||||
* This file does only one thing: include `catch2/catch_test_macros.hpp`,
|
||||
* so that we can measure the compilation cost of the header.
|
||||
*/
|
||||
|
||||
#include <catch2/catch_test_macros.hpp>
|
||||
@@ -0,0 +1,81 @@
|
||||
<a id="top"></a>
|
||||
|
||||
# Benchmarks of Catch2
|
||||
|
||||
This folder holds benchmarks for Catch2. It should not be built for the
|
||||
small(er) test sets, as it is only relevant for running (mainly runtime)
|
||||
benchmarks.
|
||||
|
||||
Below you will find some practical examples using
|
||||
[hyperfine](https://github.com/sharkdp/hyperfine) to determine the
|
||||
performance of various scenarios. They assume two parallel checkouts, one
|
||||
named `Catch2-old` and the other `Catch2-new`. You will need to change
|
||||
the paths to work on your own machine.
|
||||
|
||||
|
||||
## Runtime benchmarks
|
||||
|
||||
The runtime benchmarks currently consist of few different `TEST_CASE`s,
|
||||
each with a simple loop over different assertion type. They are compiled
|
||||
into two binaries, one for assertion slow path and one for assertion fast
|
||||
path.
|
||||
|
||||
|
||||
### Assumptions and notes about real-world usage
|
||||
|
||||
The basic assertion macro, `REQUIRE` (and `CHECK`) is the most common one,
|
||||
by far. Thus, it is the most important one to run quickly. It is probably
|
||||
followed by the matcher macro, `REQUIRE_THAT`.
|
||||
|
||||
The most common result of an assertion is that it passes. Even if it is
|
||||
stringified and reported, that is most likely due to some listener/reporter
|
||||
that wants the string representation, not because it failed.
|
||||
|
||||
The performance of both Debug and Release builds are important; users
|
||||
will run tests in both. LTO runtime performance is not too important,
|
||||
but compile time perf is.
|
||||
|
||||
|
||||
### Examples
|
||||
|
||||
**Compare performance of `REQUIRE` in slow path, debug build**
|
||||
```text
|
||||
hyperfine --warmup 2 --shell none --parameter-list version old,new '/home/xarn/benches/Catch2-{version}/build-debug/benchmarks/AssertionsSlowPath -o /dev/null "REQUIRE"'
|
||||
```
|
||||
|
||||
**Compare performance of `REQUIRE_THAT` in fast path, release build**
|
||||
```text
|
||||
hyperfine --warmup 2 --shell none --parameter-list version old,new '/home/xarn/benches/Catch2-{version}/build-release/benchmarks/AssertionsFastPath -o /dev/null "REQUIRE_THAT"'
|
||||
```
|
||||
|
||||
**Compare performance of `REQUIRE` with stringification enabled, release build**
|
||||
```text
|
||||
hyperfine --warmup 2 --shell none --parameter-list version old,new '/home/xarn/benches/Catch2-{version}/build-release/benchmarks/AssertionsFastPath -s -o /dev/null "REQUIRE"'
|
||||
```
|
||||
_Note that we redirect the output to `/dev/null` to reduce the overhead of the actual output printing, to see just the impact of stringification._
|
||||
|
||||
TODO:
|
||||
* Start empty binary (set up cost base)
|
||||
* Start binary with X (100/1k/10k) tests (test registration cost)
|
||||
* Section tracking
|
||||
|
||||
## Compilation benchmarks
|
||||
|
||||
As tests are often iterated upon and relinked, the compilation cost of
|
||||
Catch2 is also important.
|
||||
|
||||
|
||||
### Examples
|
||||
|
||||
**Compare overhead of including `catch_test_macros.hpp`**
|
||||
```text
|
||||
hyperfine --warmup 2 --shell none --parameter-list version old,new '/usr/bin/c++ -I/home/xarn/benches/Catch2-{version}/src/catch2/.. -I/home/xarn/benches/Catch2-{version}/build-debug/generated-includes -g -o /dev/null -c /home/xarn/benches/Catch2-{version}/benchmarks/only_include.cpp'
|
||||
```
|
||||
|
||||
**Compare build time of Catch2's `SelfTest` test suite, Debug build**
|
||||
```text
|
||||
hyperfine --warmup 2 --parameter-list version old,vas --prepare 'find ~/benches/Catch2-{version}/tests/SelfTest -type f -name "*.cpp" -exec touch {} +' 'ninja -j 1 -C ~/benches/Catch2-{version}/build-debug'
|
||||
```
|
||||
|
||||
TODO:
|
||||
* Link-only recipe
|
||||
@@ -7,21 +7,48 @@
|
||||
// SPDX-License-Identifier: BSL-1.0
|
||||
|
||||
#include <catch2/catch_test_macros.hpp>
|
||||
#include <catch2/matchers/catch_matchers_templated.hpp>
|
||||
|
||||
TEST_CASE("Simple REQUIRE - 10M") {
|
||||
for (size_t i = 0; i < 10'000'000; ++i) {
|
||||
REQUIRE(true);
|
||||
namespace {
|
||||
|
||||
class MatchAllMatcher final : public Catch::Matchers::MatcherGenericBase {
|
||||
public:
|
||||
template <typename Any>
|
||||
bool match( Any&& ) const {
|
||||
return true;
|
||||
}
|
||||
|
||||
std::string describe() const override {
|
||||
using namespace std::string_literals;
|
||||
return "Long string that does not fit into SSO"s;
|
||||
}
|
||||
};
|
||||
|
||||
MatchAllMatcher MatchAll() { return MatchAllMatcher(); }
|
||||
|
||||
|
||||
TEST_CASE( "REQUIRE", "[assertions]" ) {
|
||||
for ( size_t i = 0; i < 10'000'000; ++i ) {
|
||||
REQUIRE( true );
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("Simple NOTHROW - 10M") {
|
||||
for (size_t i = 0; i < 10'000'000; ++i) {
|
||||
REQUIRE_NOTHROW([](){}());
|
||||
TEST_CASE( "REQUIRE_THAT", "[assertions][matchers]" ) {
|
||||
for ( size_t i = 0; i < 10'000'000; ++i ) {
|
||||
REQUIRE_THAT( 1, MatchAll() );
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("Simple THROWS - 10M") {
|
||||
for (size_t i = 0; i < 10'000'000; ++i) {
|
||||
REQUIRE_THROWS([]() { throw 1; }());
|
||||
TEST_CASE( "REQUIRE_NOTHROW", "[assertions][exceptions]" ) {
|
||||
for ( size_t i = 0; i < 10'000'000; ++i ) {
|
||||
REQUIRE_NOTHROW( []() {}() );
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE( "REQUIRE_THROWS", "[assertions][exceptions]" ) {
|
||||
for ( size_t i = 0; i < 10'000'000; ++i ) {
|
||||
REQUIRE_THROWS( []() { throw 1; }() );
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
[Built-in matchers](#built-in-matchers)<br>
|
||||
[Writing custom matchers (old style)](#writing-custom-matchers-old-style)<br>
|
||||
[Writing custom matchers (new style)](#writing-custom-matchers-new-style)<br>
|
||||
[Constexpr matchers](#constexpr-matchers)<br>
|
||||
|
||||
Matchers, as popularized by the [Hamcrest](https://en.wikipedia.org/wiki/Hamcrest)
|
||||
framework are an alternative way to write assertions, useful for tests
|
||||
@@ -471,6 +472,42 @@ and new style matchers arbitrarily.
|
||||
> `MatcherGenericBase` lives in `catch2/matchers/catch_matchers_templated.hpp`
|
||||
|
||||
|
||||
## Constexpr matchers
|
||||
|
||||
> Support for constexpr matchers was introduced in Catch2 3.15.0
|
||||
|
||||
When compiled for C++20, the new-style matchers (can) support `constexpr`
|
||||
matching, albeit not `constexpr` stringification. The matcher combinators
|
||||
require C++26 (or at least P2738) to be `constexpr` compatible.
|
||||
|
||||
This can be used together with the `STATIC_REQUIRE_THAT` macro to write
|
||||
matcher-based static assertions like this:
|
||||
|
||||
```cpp
|
||||
TEST_CASE("Constexpr support for matchers", "[constexpr][matchers]") {
|
||||
STATIC_REQUIRE_THAT( 1, MatchAll() );
|
||||
STATIC_REQUIRE_THAT( 1, MatchAll() || MatchAll() );
|
||||
STATIC_REQUIRE_THAT( 1, !!MatchAll() );
|
||||
}
|
||||
```
|
||||
|
||||
### First party constexpr matchers
|
||||
|
||||
Some (but not all) of Catch2's generic matchers support `constexpr`
|
||||
matching. Currently, this includes:
|
||||
|
||||
* `IsEmpty()`
|
||||
* `SizeIs(size_t target_size)`, `SizeIs(Matcher size_matcher)`
|
||||
* `AllMatch(Matcher element_matcher)`
|
||||
* `AnyMatch(Matcher element_matcher)`
|
||||
* `NoneMatch(Matcher element_matcher)`
|
||||
* `AllTrue()`, `AnyTrue()`, `NoneTrue()`
|
||||
* `Contains(T&& target_element, Comparator = std::equal_to<>{})`
|
||||
* `Contains(Matcher element_matcher)`
|
||||
* `RangeEquals(TargetRangeLike&&, Comparator = std::equal_to<>{})`
|
||||
* `UnorderedRangeEquals(TargetRangeLike&&, Comparator = std::equal_to<>{})`
|
||||
|
||||
|
||||
---
|
||||
|
||||
[Home](Readme.md#top)
|
||||
|
||||
@@ -91,6 +91,30 @@ TEST_CASE("STATIC_CHECK showcase", "[traits]") {
|
||||
}
|
||||
```
|
||||
|
||||
* `STATIC_REQUIRE_THAT` and `STATIC_CHECK_THAT`
|
||||
|
||||
> `STATIC_REQUIRE_THAT` and `STATIC_CHECK_THAT` was introduced in Catch2 3.15.0
|
||||
|
||||
`STATIC_{REQUIRE,CHECK}_THAT` are analogous to `STATIC_{REQUIRE,CHECK}`,
|
||||
but for matchers. They are always defined, even if the current compiler
|
||||
does not support `constexpr` matchers, but in that case the compilation
|
||||
will always fail.
|
||||
|
||||
Just like `STATIC_{REQUIRE,CHECK}`, `STATIC_{REQUIRE,CHECK}_THAT` can be
|
||||
delayed into runtime through the `CATCH_CONFIG_RUNTIME_STATIC_REQUIRE`
|
||||
configuration option.
|
||||
|
||||
Example:
|
||||
```cpp
|
||||
TEST_CASE("Constexpr support for matchers", "[constexpr][matchers]") {
|
||||
STATIC_REQUIRE_THAT( 1, MatchAll() );
|
||||
STATIC_REQUIRE_THAT( 1, MatchAll() && MatchAll() );
|
||||
STATIC_REQUIRE_THAT( 1, MatchAll() || MatchAll() );
|
||||
STATIC_REQUIRE_THAT( 1, !!MatchAll() );
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
## Test case related macros
|
||||
|
||||
* `REGISTER_TEST_CASE`
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
# Release notes
|
||||
**Contents**<br>
|
||||
[3.15.0](#3150)<br>
|
||||
[3.14.0](#3140)<br>
|
||||
[3.13.0](#3130)<br>
|
||||
[3.12.0](#3120)<br>
|
||||
@@ -74,6 +75,22 @@
|
||||
[Even Older versions](#even-older-versions)<br>
|
||||
|
||||
|
||||
## 3.15.0
|
||||
|
||||
### Fixes
|
||||
* Fixed ambiguous overload issue with `std::optional<T>` in C++26. (#3095)
|
||||
* Since `std::optional` was turned into a range, the partial specialization of `StringMaker` for range-like types and for `std::optional<T>` were in conflict.
|
||||
|
||||
### Improvements
|
||||
* Simplified `CATCH_REGISTER_ENUM` internals for faster compilation and retrieval.
|
||||
* Successful assertion are slightly (1-2%) faster.
|
||||
* Generic (new-style) matchers support constexpr matching in C++20.
|
||||
* Combining matchers requires C++26.
|
||||
* Catch2-provided generic matchers are all constexpr enabled.
|
||||
* Added `STATIC_REQUIRE_THAT` for compile-time matcher assertions.
|
||||
* This requires the compiler to support enough `constexpr` for matchers, see above.
|
||||
|
||||
|
||||
## 3.14.0
|
||||
|
||||
### Fixes
|
||||
|
||||
@@ -6,8 +6,8 @@
|
||||
|
||||
// SPDX-License-Identifier: BSL-1.0
|
||||
|
||||
// Catch v3.14.0
|
||||
// Generated: 2026-04-05 15:03:01.631668
|
||||
// Catch v3.15.0
|
||||
// Generated: 2026-05-12 13:08:21.086523
|
||||
// ----------------------------------------------------------
|
||||
// This file is an amalgamation of multiple different files.
|
||||
// You probably shouldn't edit it directly.
|
||||
@@ -74,11 +74,11 @@ namespace Catch {
|
||||
samples.data(), samples.data() + samples.size() );
|
||||
|
||||
auto wrap_estimate = [](Estimate<double> e) {
|
||||
return Estimate<FDuration> {
|
||||
FDuration(e.point),
|
||||
FDuration(e.lower_bound),
|
||||
FDuration(e.upper_bound),
|
||||
e.confidence_interval,
|
||||
return Estimate<FDuration>{
|
||||
FDuration( e.point ),
|
||||
FDuration( e.lower_bound ),
|
||||
FDuration( e.upper_bound ),
|
||||
e.confidence_interval,
|
||||
};
|
||||
};
|
||||
std::vector<FDuration> samples2;
|
||||
@@ -147,7 +147,7 @@ namespace Catch {
|
||||
namespace Catch {
|
||||
namespace Benchmark {
|
||||
namespace Detail {
|
||||
struct optimized_away_error : std::exception {
|
||||
struct optimized_away_error final : std::exception {
|
||||
const char* what() const noexcept override;
|
||||
};
|
||||
|
||||
@@ -995,6 +995,7 @@ namespace Catch {
|
||||
|
||||
|
||||
|
||||
|
||||
#include <cassert>
|
||||
#include <stack>
|
||||
|
||||
@@ -1007,7 +1008,7 @@ namespace Catch {
|
||||
m_messageId( builder.m_info.sequence ) {
|
||||
MessageInfo info( CATCH_MOVE( builder.m_info ) );
|
||||
info.message = builder.m_stream.str();
|
||||
IResultCapture::pushScopedMessage( CATCH_MOVE( info ) );
|
||||
Detail::pushScopedMessage( CATCH_MOVE( info ) );
|
||||
}
|
||||
|
||||
ScopedMessage::ScopedMessage( ScopedMessage&& old ) noexcept:
|
||||
@@ -1016,7 +1017,7 @@ namespace Catch {
|
||||
}
|
||||
|
||||
ScopedMessage::~ScopedMessage() {
|
||||
if ( !m_moved ) { IResultCapture::popScopedMessage( m_messageId ); }
|
||||
if ( !m_moved ) { Detail::popScopedMessage( m_messageId ); }
|
||||
}
|
||||
|
||||
|
||||
@@ -1088,7 +1089,7 @@ namespace Catch {
|
||||
assert( m_captured == m_messages.size() );
|
||||
if ( m_isScoped ) {
|
||||
for ( auto const& message : m_messages ) {
|
||||
IResultCapture::popScopedMessage( message.sequence );
|
||||
Detail::popScopedMessage( message.sequence );
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1097,9 +1098,9 @@ namespace Catch {
|
||||
assert( index < m_messages.size() );
|
||||
m_messages[index].message += value;
|
||||
if ( m_isScoped ) {
|
||||
IResultCapture::pushScopedMessage( CATCH_MOVE( m_messages[index] ) );
|
||||
Detail::pushScopedMessage( CATCH_MOVE( m_messages[index] ) );
|
||||
} else {
|
||||
IResultCapture::addUnscopedMessage( CATCH_MOVE( m_messages[index] ) );
|
||||
Detail::addUnscopedMessage( CATCH_MOVE( m_messages[index] ) );
|
||||
}
|
||||
m_captured++;
|
||||
}
|
||||
@@ -1160,9 +1161,6 @@ namespace Catch {
|
||||
CATCH_INTERNAL_ERROR("Attempted to register active exception under CATCH_CONFIG_DISABLE_EXCEPTIONS!");
|
||||
#endif
|
||||
}
|
||||
IMutableEnumValuesRegistry& getMutableEnumValuesRegistry() override {
|
||||
return m_enumValuesRegistry;
|
||||
}
|
||||
|
||||
private:
|
||||
TestRegistry m_testCaseRegistry;
|
||||
@@ -1170,7 +1168,6 @@ namespace Catch {
|
||||
ExceptionTranslatorRegistry m_exceptionTranslatorRegistry;
|
||||
TagAliasRegistry m_tagAliasRegistry;
|
||||
StartupExceptionRegistry m_exceptionRegistry;
|
||||
Detail::EnumValuesRegistry m_enumValuesRegistry;
|
||||
};
|
||||
}
|
||||
|
||||
@@ -2397,7 +2394,7 @@ namespace Catch {
|
||||
}
|
||||
|
||||
Version const& libraryVersion() {
|
||||
static Version version( 3, 14, 0, "", 0 );
|
||||
static Version version( 3, 15, 0, "", 0 );
|
||||
return version;
|
||||
}
|
||||
|
||||
@@ -2686,13 +2683,17 @@ namespace Catch {
|
||||
|
||||
namespace Catch {
|
||||
|
||||
void AssertionHandler::finishIncomplete() {
|
||||
m_resultCapture.handleIncomplete( m_assertionInfo );
|
||||
}
|
||||
|
||||
AssertionHandler::AssertionHandler
|
||||
( StringRef macroName,
|
||||
SourceLineInfo const& lineInfo,
|
||||
StringRef capturedExpression,
|
||||
ResultDisposition::Flags resultDisposition )
|
||||
: m_assertionInfo{ macroName, lineInfo, capturedExpression, resultDisposition },
|
||||
m_resultCapture( getResultCapture() )
|
||||
m_resultCapture( static_cast<RunContext&>(getResultCapture()) )
|
||||
{
|
||||
m_resultCapture.notifyAssertionStarted( m_assertionInfo );
|
||||
}
|
||||
@@ -4088,12 +4089,11 @@ namespace Catch {
|
||||
|
||||
|
||||
|
||||
|
||||
#include <cassert>
|
||||
|
||||
namespace Catch {
|
||||
|
||||
IMutableEnumValuesRegistry::~IMutableEnumValuesRegistry() = default;
|
||||
|
||||
namespace Detail {
|
||||
|
||||
namespace {
|
||||
@@ -4119,9 +4119,7 @@ namespace Catch {
|
||||
return parsed;
|
||||
}
|
||||
|
||||
EnumInfo::~EnumInfo() = default;
|
||||
|
||||
StringRef EnumInfo::lookup( int value ) const {
|
||||
StringRef EnumInfo::lookup( int64_t value ) const {
|
||||
for( auto const& valueToName : m_values ) {
|
||||
if( valueToName.first == value )
|
||||
return valueToName.second;
|
||||
@@ -4129,25 +4127,20 @@ namespace Catch {
|
||||
return "{** unexpected enum value **}"_sr;
|
||||
}
|
||||
|
||||
Catch::Detail::unique_ptr<EnumInfo> makeEnumInfo( StringRef enumName, StringRef allValueNames, std::vector<int> const& values ) {
|
||||
auto enumInfo = Catch::Detail::make_unique<EnumInfo>();
|
||||
enumInfo->m_name = enumName;
|
||||
enumInfo->m_values.reserve( values.size() );
|
||||
EnumInfo makeEnumInfo( StringRef enumName, StringRef allValueNames, std::vector<int64_t> const& values ) {
|
||||
EnumInfo enumInfo;
|
||||
enumInfo.m_name = enumName;
|
||||
enumInfo.m_values.reserve( values.size() );
|
||||
|
||||
const auto valueNames = Catch::Detail::parseEnums( allValueNames );
|
||||
assert( valueNames.size() == values.size() );
|
||||
std::size_t i = 0;
|
||||
for( auto value : values )
|
||||
enumInfo->m_values.emplace_back(value, valueNames[i++]);
|
||||
for (size_t i = 0; i < values.size(); ++i) {
|
||||
enumInfo.m_values.emplace_back( values[i], valueNames[i] );
|
||||
}
|
||||
|
||||
return enumInfo;
|
||||
}
|
||||
|
||||
EnumInfo const& EnumValuesRegistry::registerEnum( StringRef enumName, StringRef allValueNames, std::vector<int> const& values ) {
|
||||
m_enumInfos.push_back(makeEnumInfo(enumName, allValueNames, values));
|
||||
return *m_enumInfos.back();
|
||||
}
|
||||
|
||||
} // Detail
|
||||
} // Catch
|
||||
|
||||
@@ -5072,7 +5065,7 @@ namespace Catch {
|
||||
namespace {
|
||||
//! A no-op implementation, used if no reporter wants output
|
||||
//! redirection.
|
||||
class NoopRedirect : public OutputRedirect {
|
||||
class NoopRedirect final : public OutputRedirect {
|
||||
void activateImpl() override {}
|
||||
void deactivateImpl() override {}
|
||||
std::string getStdout() override { return {}; }
|
||||
@@ -5109,7 +5102,7 @@ namespace Catch {
|
||||
* Redirects the `std::cout`, `std::cerr`, `std::clog` streams,
|
||||
* but does not touch the actual `stdout`/`stderr` file descriptors.
|
||||
*/
|
||||
class StreamRedirect : public OutputRedirect {
|
||||
class StreamRedirect final : public OutputRedirect {
|
||||
ReusableStringStream m_redirectedOut, m_redirectedErr;
|
||||
RedirectedStreamNew m_cout, m_cerr, m_clog;
|
||||
|
||||
@@ -5220,7 +5213,7 @@ namespace Catch {
|
||||
* Works by replacing the file descriptors numbered 1 and 2
|
||||
* with an open temporary file.
|
||||
*/
|
||||
class FileRedirect : public OutputRedirect {
|
||||
class FileRedirect final : public OutputRedirect {
|
||||
TempFile m_outFile, m_errFile;
|
||||
int m_originalOut = -1;
|
||||
int m_originalErr = -1;
|
||||
@@ -6136,6 +6129,25 @@ namespace Catch {
|
||||
}
|
||||
CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION
|
||||
|
||||
|
||||
void pushScopedMessage( MessageInfo&& message ) {
|
||||
Detail::g_messageHolder().addScopedMessage( CATCH_MOVE( message ) );
|
||||
}
|
||||
|
||||
void popScopedMessage( unsigned int messageId ) {
|
||||
Detail::g_messageHolder().removeMessage( messageId );
|
||||
}
|
||||
|
||||
void emplaceUnscopedMessage( MessageBuilder&& builder ) {
|
||||
Detail::g_messageHolder().addUnscopedMessage( CATCH_MOVE( builder ) );
|
||||
}
|
||||
|
||||
void addUnscopedMessage( MessageInfo&& message ) {
|
||||
Detail::g_messageHolder().addUnscopedMessage( CATCH_MOVE( message ) );
|
||||
}
|
||||
|
||||
bool lastAssertionPassed() { return Detail::g_lastAssertionPassed; }
|
||||
|
||||
} // namespace Detail
|
||||
|
||||
RunContext::RunContext(IConfig const* _config, IEventListenerPtr&& reporter)
|
||||
@@ -6269,14 +6281,13 @@ namespace Catch {
|
||||
Detail::g_lastAssertionPassed = true;
|
||||
} else if (!result.succeeded()) {
|
||||
Detail::g_lastAssertionPassed = false;
|
||||
if (result.isOk()) {
|
||||
}
|
||||
else if( m_activeTestCase->getTestCaseInfo().okToFail() ) // Read from a shared state established before the threads could start, this is fine
|
||||
if (result.isOk()) {}
|
||||
else if( m_activeTestCase->getTestCaseInfo().okToFail() ) { // Read from a shared state established before the threads could start, this is fine
|
||||
m_atomicAssertionCount.failedButOk++;
|
||||
else
|
||||
} else {
|
||||
m_atomicAssertionCount.failed++;
|
||||
}
|
||||
else {
|
||||
}
|
||||
} else {
|
||||
Detail::g_lastAssertionPassed = true;
|
||||
}
|
||||
|
||||
@@ -6458,7 +6469,7 @@ namespace Catch {
|
||||
// and since IResultCapture::getLastResult is deprecated,
|
||||
// we will leave it as is, until it is finally removed.
|
||||
Detail::LockGuard _( m_assertionMutex );
|
||||
return &(*m_lastResult);
|
||||
return &*m_lastResult;
|
||||
}
|
||||
|
||||
void RunContext::exceptionEarlyReported() {
|
||||
@@ -6532,10 +6543,6 @@ namespace Catch {
|
||||
m_reporter->testRunEnded(TestRunStats(m_runInfo, m_totals, false));
|
||||
}
|
||||
|
||||
bool RunContext::lastAssertionPassed() {
|
||||
return Detail::g_lastAssertionPassed;
|
||||
}
|
||||
|
||||
void RunContext::assertionPassedFastPath(SourceLineInfo lineInfo) {
|
||||
// We want to save the line info for better experience with unexpected assertions
|
||||
Detail::g_lastKnownLineInfo = lineInfo;
|
||||
@@ -6714,7 +6721,7 @@ namespace Catch {
|
||||
}
|
||||
|
||||
void RunContext::populateReaction( AssertionReaction& reaction,
|
||||
bool has_normal_disposition ) {
|
||||
bool has_normal_disposition ) const {
|
||||
reaction.shouldDebugBreak = m_shouldDebugBreak;
|
||||
reaction.shouldThrow = aborting() || has_normal_disposition;
|
||||
}
|
||||
@@ -6765,22 +6772,6 @@ namespace Catch {
|
||||
}
|
||||
}
|
||||
|
||||
void IResultCapture::pushScopedMessage( MessageInfo&& message ) {
|
||||
Detail::g_messageHolder().addScopedMessage( CATCH_MOVE( message ) );
|
||||
}
|
||||
|
||||
void IResultCapture::popScopedMessage( unsigned int messageId ) {
|
||||
Detail::g_messageHolder().removeMessage( messageId );
|
||||
}
|
||||
|
||||
void IResultCapture::emplaceUnscopedMessage( MessageBuilder&& builder ) {
|
||||
Detail::g_messageHolder().addUnscopedMessage( CATCH_MOVE( builder ) );
|
||||
}
|
||||
|
||||
void IResultCapture::addUnscopedMessage( MessageInfo&& message ) {
|
||||
Detail::g_messageHolder().addUnscopedMessage( CATCH_MOVE( message ) );
|
||||
}
|
||||
|
||||
void seedRng(IConfig const& config) {
|
||||
sharedRng().seed(config.rngSeed());
|
||||
}
|
||||
@@ -7112,10 +7103,11 @@ namespace Catch {
|
||||
|
||||
TagAlias const* TagAliasRegistry::find( std::string const& alias ) const {
|
||||
auto it = m_registry.find( alias );
|
||||
if( it != m_registry.end() )
|
||||
return &(it->second);
|
||||
else
|
||||
if ( it != m_registry.end() ) {
|
||||
return &it->second;
|
||||
} else {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
std::string TagAliasRegistry::expandAliases( std::string const& unexpandedTestSpec ) const {
|
||||
@@ -7562,7 +7554,7 @@ namespace Catch {
|
||||
|
||||
void throw_test_failure_exception() {
|
||||
#if !defined( CATCH_CONFIG_DISABLE_EXCEPTIONS )
|
||||
throw TestFailureException{};
|
||||
throw TestFailureException{}; //NOLINT(bugprone-std-exception-baseclass)
|
||||
#else
|
||||
CATCH_ERROR( "Test failure requires aborting test!" );
|
||||
#endif
|
||||
@@ -7570,7 +7562,7 @@ namespace Catch {
|
||||
|
||||
void throw_test_skip_exception() {
|
||||
#if !defined( CATCH_CONFIG_DISABLE_EXCEPTIONS )
|
||||
throw Catch::TestSkipException();
|
||||
throw Catch::TestSkipException(); //NOLINT(bugprone-std-exception-baseclass)
|
||||
#else
|
||||
CATCH_ERROR( "Explicitly skipping tests during runtime requires exceptions" );
|
||||
#endif
|
||||
@@ -8674,13 +8666,13 @@ namespace Catch {
|
||||
namespace Matchers {
|
||||
|
||||
std::string MatcherUntypedBase::toString() const {
|
||||
if (m_cachedToString.empty()) {
|
||||
m_cachedToString = describe();
|
||||
}
|
||||
return m_cachedToString;
|
||||
return describe();
|
||||
}
|
||||
|
||||
MatcherUntypedBase::~MatcherUntypedBase() = default;
|
||||
std::string MatcherUntypedBase::describe() const {
|
||||
using namespace std::string_literals;
|
||||
return "Undescribed matcher"s;
|
||||
}
|
||||
|
||||
} // namespace Matchers
|
||||
} // namespace Catch
|
||||
@@ -8701,14 +8693,6 @@ namespace Matchers {
|
||||
return sstr.str();
|
||||
}
|
||||
|
||||
IsEmptyMatcher IsEmpty() {
|
||||
return {};
|
||||
}
|
||||
|
||||
HasSizeMatcher SizeIs(std::size_t sz) {
|
||||
return HasSizeMatcher{ sz };
|
||||
}
|
||||
|
||||
} // end namespace Matchers
|
||||
} // end namespace Catch
|
||||
|
||||
@@ -8962,17 +8946,13 @@ std::string Catch::Matchers::Detail::finalizeDescription(const std::string& desc
|
||||
|
||||
namespace Catch {
|
||||
namespace Matchers {
|
||||
std::string AllTrueMatcher::describe() const { return "contains only true"; }
|
||||
|
||||
AllTrueMatcher AllTrue() { return AllTrueMatcher{}; }
|
||||
std::string AllTrueMatcher::describe() const { return "contains only true"; }
|
||||
|
||||
std::string NoneTrueMatcher::describe() const { return "contains no true"; }
|
||||
|
||||
NoneTrueMatcher NoneTrue() { return NoneTrueMatcher{}; }
|
||||
|
||||
std::string AnyTrueMatcher::describe() const { return "contains at least one true"; }
|
||||
|
||||
AnyTrueMatcher AnyTrue() { return AnyTrueMatcher{}; }
|
||||
} // namespace Matchers
|
||||
} // namespace Catch
|
||||
|
||||
@@ -9085,7 +9065,11 @@ namespace Matchers {
|
||||
|
||||
namespace Catch {
|
||||
namespace Matchers {
|
||||
MatcherGenericBase::~MatcherGenericBase() = default;
|
||||
|
||||
std::string MatcherGenericBase::describe() const {
|
||||
using namespace std::string_literals;
|
||||
return "Undescribed generic matcher"s;
|
||||
}
|
||||
|
||||
namespace Detail {
|
||||
|
||||
@@ -10108,9 +10092,8 @@ namespace Catch {
|
||||
bool operator()(
|
||||
Detail::unique_ptr<CumulativeReporterBase::SectionNode> const&
|
||||
node ) const {
|
||||
return (
|
||||
( node->stats.sectionInfo.name == m_other.name ) &&
|
||||
( node->stats.sectionInfo.lineInfo == m_other.lineInfo ) );
|
||||
return node->stats.sectionInfo.name == m_other.name
|
||||
&& node->stats.sectionInfo.lineInfo == m_other.lineInfo;
|
||||
}
|
||||
void operator=( BySectionInfo const& ) = delete;
|
||||
|
||||
@@ -10464,7 +10447,7 @@ namespace Catch {
|
||||
}
|
||||
|
||||
// minimum whitespace to pad tag counts, possibly overwritten below
|
||||
size_t maxTagCountLen = 2;
|
||||
int maxTagCountLen = 2;
|
||||
|
||||
// determine necessary padding for tag count column
|
||||
if ( ! tags.empty() ) {
|
||||
@@ -10479,7 +10462,7 @@ namespace Catch {
|
||||
// more padding necessary for 3+ digits
|
||||
if (maxTagCount >= 100) {
|
||||
auto numDigits = 1 + std::floor( std::log10( maxTagCount ) );
|
||||
maxTagCountLen = static_cast<size_t>( numDigits );
|
||||
maxTagCountLen = static_cast<int>( numDigits );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+254
-186
@@ -6,8 +6,8 @@
|
||||
|
||||
// SPDX-License-Identifier: BSL-1.0
|
||||
|
||||
// Catch v3.14.0
|
||||
// Generated: 2026-04-05 15:03:01.150393
|
||||
// Catch v3.15.0
|
||||
// Generated: 2026-05-12 13:08:20.543985
|
||||
// ----------------------------------------------------------
|
||||
// This file is an amalgamation of multiple different files.
|
||||
// You probably shouldn't edit it directly.
|
||||
@@ -118,16 +118,24 @@
|
||||
|
||||
#endif // CATCH_PLATFORM_HPP_INCLUDED
|
||||
|
||||
#ifdef __cplusplus
|
||||
#if (__cplusplus >= 201703L) || (defined(_MSVC_LANG) && _MSVC_LANG >= 201703L)
|
||||
# define CATCH_CPP17_OR_GREATER
|
||||
#endif
|
||||
|
||||
# if (__cplusplus >= 201703L) || (defined(_MSVC_LANG) && _MSVC_LANG >= 201703L)
|
||||
# define CATCH_CPP17_OR_GREATER
|
||||
# endif
|
||||
|
||||
# if (__cplusplus >= 202002L) || (defined(_MSVC_LANG) && _MSVC_LANG >= 202002L)
|
||||
# define CATCH_CPP20_OR_GREATER
|
||||
# endif
|
||||
#if (__cplusplus >= 202002L) || (defined(_MSVC_LANG) && _MSVC_LANG >= 202002L)
|
||||
# define CATCH_CPP20_OR_GREATER
|
||||
#endif
|
||||
|
||||
// Matchers are only constexpr-able in C++20
|
||||
#if defined( CATCH_CPP20_OR_GREATER ) && \
|
||||
defined( __cpp_constexpr_dynamic_alloc ) && \
|
||||
__cpp_constexpr_dynamic_alloc >= 201907L && \
|
||||
/* GCC < 13 define the feature macro, but compiler bugs stop us from using it */ \
|
||||
( !defined( __GNUC__ ) || __GNUC__ >= 13 || defined(__clang__) )
|
||||
# define CATCH_INTERNAL_CONSTEXPR_MATCHERS_ENABLED
|
||||
# define CATCH_DESTRUCTOR_CONSTEXPR constexpr
|
||||
#else
|
||||
# define CATCH_DESTRUCTOR_CONSTEXPR
|
||||
#endif
|
||||
|
||||
// Only GCC compiler should be used in this block, so other compilers trying to
|
||||
@@ -1053,8 +1061,6 @@ namespace Catch {
|
||||
struct AssertionInfo;
|
||||
struct SectionInfo;
|
||||
struct SectionEndInfo;
|
||||
struct MessageInfo;
|
||||
struct MessageBuilder;
|
||||
struct Counts;
|
||||
struct AssertionReaction;
|
||||
struct SourceLineInfo;
|
||||
@@ -1094,11 +1100,6 @@ namespace Catch {
|
||||
virtual void benchmarkEnded( BenchmarkStats<> const& stats ) = 0;
|
||||
virtual void benchmarkFailed( StringRef error ) = 0;
|
||||
|
||||
static void pushScopedMessage( MessageInfo&& message );
|
||||
static void popScopedMessage( unsigned int messageId );
|
||||
static void addUnscopedMessage( MessageInfo&& message );
|
||||
static void emplaceUnscopedMessage( MessageBuilder&& builder );
|
||||
|
||||
virtual void handleFatalErrorCondition( StringRef message ) = 0;
|
||||
|
||||
virtual void handleExpr
|
||||
@@ -1124,9 +1125,6 @@ namespace Catch {
|
||||
ResultWas::OfType resultType,
|
||||
AssertionReaction &reaction ) = 0;
|
||||
|
||||
|
||||
virtual bool lastAssertionPassed() = 0;
|
||||
|
||||
// Deprecated, do not use:
|
||||
virtual std::string getCurrentTestName() const = 0;
|
||||
virtual const AssertionResult* getLastResult() const = 0;
|
||||
@@ -1231,7 +1229,7 @@ namespace Catch {
|
||||
class IStream;
|
||||
struct PathFilter;
|
||||
|
||||
class IConfig : public Detail::NonCopyable {
|
||||
class IConfig : Detail::NonCopyable {
|
||||
public:
|
||||
virtual ~IConfig();
|
||||
|
||||
@@ -1319,7 +1317,6 @@ namespace Catch {
|
||||
virtual void registerTranslator( Detail::unique_ptr<IExceptionTranslator>&& translator ) = 0;
|
||||
virtual void registerTagAlias( std::string const& alias, std::string const& tag, SourceLineInfo const& lineInfo ) = 0;
|
||||
virtual void registerStartupException() noexcept = 0;
|
||||
virtual IMutableEnumValuesRegistry& getMutableEnumValuesRegistry() = 0;
|
||||
};
|
||||
|
||||
IRegistryHub const& getRegistryHub();
|
||||
@@ -1681,7 +1678,7 @@ namespace Catch {
|
||||
callable& operator=(callable&&) = default;
|
||||
};
|
||||
template <typename Fun>
|
||||
struct model : public callable {
|
||||
struct model final : public callable {
|
||||
model(Fun&& fun_) : fun(CATCH_MOVE(fun_)) {}
|
||||
model(Fun const& fun_) : fun(fun_) {}
|
||||
|
||||
@@ -2469,45 +2466,46 @@ namespace Catch {
|
||||
#endif // CATCH_VOID_TYPE_HPP_INCLUDED
|
||||
|
||||
|
||||
#ifndef CATCH_INTERFACES_ENUM_VALUES_REGISTRY_HPP_INCLUDED
|
||||
#define CATCH_INTERFACES_ENUM_VALUES_REGISTRY_HPP_INCLUDED
|
||||
#ifndef CATCH_ENUM_INFO_HPP_INCLUDED
|
||||
#define CATCH_ENUM_INFO_HPP_INCLUDED
|
||||
|
||||
|
||||
#include <cstdint>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
namespace Catch {
|
||||
|
||||
namespace Detail {
|
||||
|
||||
struct EnumInfo {
|
||||
StringRef m_name;
|
||||
std::vector<std::pair<int, StringRef>> m_values;
|
||||
std::vector<std::pair<int64_t, StringRef>> m_values;
|
||||
|
||||
~EnumInfo();
|
||||
|
||||
StringRef lookup( int value ) const;
|
||||
StringRef lookup( int64_t value ) const;
|
||||
};
|
||||
} // namespace Detail
|
||||
|
||||
class IMutableEnumValuesRegistry {
|
||||
public:
|
||||
virtual ~IMutableEnumValuesRegistry(); // = default;
|
||||
|
||||
virtual Detail::EnumInfo const& registerEnum( StringRef enumName, StringRef allEnums, std::vector<int> const& values ) = 0;
|
||||
|
||||
template<typename E>
|
||||
Detail::EnumInfo const& registerEnum( StringRef enumName, StringRef allEnums, std::initializer_list<E> values ) {
|
||||
static_assert(sizeof(int) >= sizeof(E), "Cannot serialize enum to int");
|
||||
std::vector<int> intValues;
|
||||
EnumInfo makeEnumInfo( StringRef enumName,
|
||||
StringRef allValueNames,
|
||||
std::vector<int64_t> const& values );
|
||||
template <typename E>
|
||||
Detail::EnumInfo makeEnumInfo( StringRef enumName,
|
||||
StringRef allEnums,
|
||||
std::initializer_list<E> values ) {
|
||||
static_assert( sizeof( int64_t ) >= sizeof( E ),
|
||||
"Cannot serialize enum to int64_t" );
|
||||
std::vector<int64_t> intValues;
|
||||
intValues.reserve( values.size() );
|
||||
for( auto enumValue : values )
|
||||
intValues.push_back( static_cast<int>( enumValue ) );
|
||||
return registerEnum( enumName, allEnums, intValues );
|
||||
for ( auto enumValue : values )
|
||||
intValues.push_back( static_cast<int64_t>( enumValue ) );
|
||||
return makeEnumInfo( enumName, allEnums, intValues );
|
||||
}
|
||||
};
|
||||
|
||||
} // Catch
|
||||
std::vector<StringRef> parseEnums( StringRef enums );
|
||||
|
||||
#endif // CATCH_INTERFACES_ENUM_VALUES_REGISTRY_HPP_INCLUDED
|
||||
} // namespace Detail
|
||||
} // namespace Catch
|
||||
|
||||
#endif // CATCH_ENUM_INFO_HPP_INCLUDED
|
||||
|
||||
#ifdef CATCH_CONFIG_CPP17_STRING_VIEW
|
||||
#include <string_view>
|
||||
@@ -2872,7 +2870,10 @@ namespace Catch {
|
||||
}
|
||||
#endif // CATCH_CONFIG_ENABLE_PAIR_STRINGMAKER
|
||||
|
||||
#if defined(CATCH_CONFIG_ENABLE_OPTIONAL_STRINGMAKER) && defined(CATCH_CONFIG_CPP17_OPTIONAL)
|
||||
#if defined( CATCH_CONFIG_ENABLE_OPTIONAL_STRINGMAKER ) && \
|
||||
defined( CATCH_CONFIG_CPP17_OPTIONAL ) && \
|
||||
/* P3168 turned optional into a range, making this ambigous with the range support */ \
|
||||
!defined( __cpp_lib_optional_range_support )
|
||||
#include <optional>
|
||||
namespace Catch {
|
||||
template<typename T>
|
||||
@@ -3119,16 +3120,21 @@ struct ratio_string<std::milli> {
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
#define INTERNAL_CATCH_REGISTER_ENUM( enumName, ... ) \
|
||||
namespace Catch { \
|
||||
template<> struct StringMaker<enumName> { \
|
||||
static std::string convert( enumName value ) { \
|
||||
static const auto& enumInfo = ::Catch::getMutableRegistryHub().getMutableEnumValuesRegistry().registerEnum( #enumName, #__VA_ARGS__, { __VA_ARGS__ } ); \
|
||||
return static_cast<std::string>(enumInfo.lookup( static_cast<int>( value ) )); \
|
||||
} \
|
||||
}; \
|
||||
}
|
||||
#define INTERNAL_CATCH_REGISTER_ENUM( enumName, ... ) \
|
||||
namespace Catch { \
|
||||
template <> \
|
||||
struct StringMaker<enumName> { \
|
||||
static std::string convert( enumName value ) { \
|
||||
CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \
|
||||
CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
|
||||
static const auto enumInfo = ::Catch::Detail::makeEnumInfo( \
|
||||
#enumName, #__VA_ARGS__, { __VA_ARGS__ } ); \
|
||||
CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION \
|
||||
return static_cast<std::string>( \
|
||||
enumInfo.lookup( static_cast<int64_t>( value ) ) ); \
|
||||
} \
|
||||
}; \
|
||||
}
|
||||
|
||||
#define CATCH_REGISTER_ENUM( enumName, ... ) INTERNAL_CATCH_REGISTER_ENUM( enumName, __VA_ARGS__ )
|
||||
|
||||
@@ -4049,9 +4055,21 @@ namespace Catch {
|
||||
#include <vector>
|
||||
|
||||
namespace Catch {
|
||||
struct MessageInfo;
|
||||
struct MessageBuilder;
|
||||
|
||||
namespace Detail {
|
||||
// The message state affecting functions have to be defined in
|
||||
// the TU where the thread-local message holders are defined.
|
||||
// Currently this is catch_run_context.cpp
|
||||
|
||||
void pushScopedMessage( MessageInfo&& message );
|
||||
void popScopedMessage( unsigned int messageId );
|
||||
void addUnscopedMessage( MessageInfo&& message );
|
||||
void emplaceUnscopedMessage( MessageBuilder&& builder );
|
||||
} // namespace Detail
|
||||
|
||||
struct SourceLineInfo;
|
||||
class IResultCapture;
|
||||
|
||||
struct MessageStream {
|
||||
|
||||
@@ -4141,7 +4159,7 @@ namespace Catch {
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
#define INTERNAL_CATCH_UNSCOPED_INFO( macroName, log ) \
|
||||
Catch::IResultCapture::emplaceUnscopedMessage( Catch::MessageBuilder( macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, Catch::ResultWas::Info ) << log )
|
||||
Catch::Detail::emplaceUnscopedMessage( Catch::MessageBuilder( macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, Catch::ResultWas::Info ) << log )
|
||||
|
||||
|
||||
#if defined(CATCH_CONFIG_PREFIX_MESSAGES) && !defined(CATCH_CONFIG_DISABLE)
|
||||
@@ -5430,7 +5448,7 @@ namespace Catch {
|
||||
void formatReconstructedExpression( std::ostream &os, std::string const& lhs, StringRef op, std::string const& rhs );
|
||||
|
||||
template<typename LhsT, typename RhsT>
|
||||
class BinaryExpr : public ITransientExpression {
|
||||
class BinaryExpr final : public ITransientExpression {
|
||||
LhsT m_lhs;
|
||||
StringRef m_op;
|
||||
RhsT m_rhs;
|
||||
@@ -5506,7 +5524,7 @@ namespace Catch {
|
||||
};
|
||||
|
||||
template<typename LhsT>
|
||||
class UnaryExpr : public ITransientExpression {
|
||||
class UnaryExpr final : public ITransientExpression {
|
||||
LhsT m_lhs;
|
||||
|
||||
void streamReconstructedExpression( std::ostream &os ) const override {
|
||||
@@ -5707,6 +5725,8 @@ namespace Catch {
|
||||
|
||||
namespace Catch {
|
||||
|
||||
class RunContext;
|
||||
|
||||
struct AssertionReaction {
|
||||
bool shouldDebugBreak = false;
|
||||
bool shouldThrow = false;
|
||||
@@ -5717,7 +5737,12 @@ namespace Catch {
|
||||
AssertionInfo m_assertionInfo;
|
||||
AssertionReaction m_reaction;
|
||||
bool m_completed = false;
|
||||
IResultCapture& m_resultCapture;
|
||||
// Since all uses are hidden in the .cpp file, we can directly use
|
||||
// the final type and avoid going through virtual dispatch, without
|
||||
// massive compilation time overhead.
|
||||
RunContext& m_resultCapture;
|
||||
|
||||
void finishIncomplete();
|
||||
|
||||
public:
|
||||
AssertionHandler
|
||||
@@ -5726,9 +5751,9 @@ namespace Catch {
|
||||
StringRef capturedExpression,
|
||||
ResultDisposition::Flags resultDisposition );
|
||||
~AssertionHandler() {
|
||||
if ( !m_completed ) {
|
||||
m_resultCapture.handleIncomplete( m_assertionInfo );
|
||||
}
|
||||
// We want the common fast path inlinable, and the virtual
|
||||
// dispatch in a function in single TU.
|
||||
if ( !m_completed ) { finishIncomplete(); }
|
||||
}
|
||||
|
||||
|
||||
@@ -5771,6 +5796,13 @@ namespace Catch {
|
||||
|
||||
#endif // CATCH_PREPROCESSOR_INTERNAL_STRINGIFY_HPP_INCLUDED
|
||||
|
||||
namespace Catch {
|
||||
namespace Detail {
|
||||
// Defined in catch_run_context.cpp, where the thread-local data lives.
|
||||
bool lastAssertionPassed();
|
||||
}
|
||||
}
|
||||
|
||||
// We need this suppression to leak, because it took until GCC 10
|
||||
// for the front end to handle local suppression via _Pragma properly
|
||||
#if defined(__GNUC__) && !defined(__clang__) && !defined(__ICC) && __GNUC__ <= 9
|
||||
@@ -5813,12 +5845,12 @@ namespace Catch {
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
#define INTERNAL_CATCH_IF( macroName, resultDisposition, ... ) \
|
||||
INTERNAL_CATCH_TEST( macroName, resultDisposition, __VA_ARGS__ ); \
|
||||
if( Catch::getResultCapture().lastAssertionPassed() )
|
||||
if( Catch::Detail::lastAssertionPassed() )
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
#define INTERNAL_CATCH_ELSE( macroName, resultDisposition, ... ) \
|
||||
INTERNAL_CATCH_TEST( macroName, resultDisposition, __VA_ARGS__ ); \
|
||||
if( !Catch::getResultCapture().lastAssertionPassed() )
|
||||
if( !Catch::Detail::lastAssertionPassed() )
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
#define INTERNAL_CATCH_NO_THROW( macroName, resultDisposition, ... ) \
|
||||
@@ -6101,7 +6133,7 @@ namespace Catch {
|
||||
namespace Catch {
|
||||
|
||||
template<typename C>
|
||||
class TestInvokerAsMethod : public ITestInvoker {
|
||||
class TestInvokerAsMethod final : public ITestInvoker {
|
||||
void (C::*m_testAsMethod)();
|
||||
public:
|
||||
constexpr TestInvokerAsMethod( void ( C::*testAsMethod )() ) noexcept:
|
||||
@@ -6121,7 +6153,7 @@ Detail::unique_ptr<ITestInvoker> makeTestInvoker( void (C::*testAsMethod)() ) {
|
||||
}
|
||||
|
||||
template <typename C>
|
||||
class TestInvokerFixture : public ITestInvoker {
|
||||
class TestInvokerFixture final : public ITestInvoker {
|
||||
void ( C::*m_testAsMethod )() const;
|
||||
Detail::unique_ptr<C> m_fixture = nullptr;
|
||||
|
||||
@@ -6196,7 +6228,7 @@ struct AutoReg : Detail::NonCopyable {
|
||||
namespace Catch {
|
||||
namespace Detail {
|
||||
struct DummyUse {
|
||||
DummyUse( void ( * )( int ), Catch::NameAndTags const& );
|
||||
DummyUse( void ( * )( int ), Catch::NameAndTags const& ) noexcept;
|
||||
};
|
||||
} // namespace Detail
|
||||
} // namespace Catch
|
||||
@@ -7433,7 +7465,7 @@ namespace Catch {
|
||||
|
||||
class ExceptionTranslatorRegistrar {
|
||||
template<typename T>
|
||||
class ExceptionTranslator : public IExceptionTranslator {
|
||||
class ExceptionTranslator final : public IExceptionTranslator {
|
||||
public:
|
||||
|
||||
constexpr ExceptionTranslator( std::string(*translateFunction)( T const& ) )
|
||||
@@ -7537,7 +7569,7 @@ namespace Catch {
|
||||
#define CATCH_VERSION_MACROS_HPP_INCLUDED
|
||||
|
||||
#define CATCH_VERSION_MAJOR 3
|
||||
#define CATCH_VERSION_MINOR 14
|
||||
#define CATCH_VERSION_MINOR 15
|
||||
#define CATCH_VERSION_PATCH 0
|
||||
|
||||
#endif // CATCH_VERSION_MACROS_HPP_INCLUDED
|
||||
@@ -9842,34 +9874,6 @@ namespace Catch {
|
||||
#endif // CATCH_ENFORCE_HPP_INCLUDED
|
||||
|
||||
|
||||
#ifndef CATCH_ENUM_VALUES_REGISTRY_HPP_INCLUDED
|
||||
#define CATCH_ENUM_VALUES_REGISTRY_HPP_INCLUDED
|
||||
|
||||
|
||||
#include <vector>
|
||||
|
||||
namespace Catch {
|
||||
|
||||
namespace Detail {
|
||||
|
||||
Catch::Detail::unique_ptr<EnumInfo> makeEnumInfo( StringRef enumName, StringRef allValueNames, std::vector<int> const& values );
|
||||
|
||||
class EnumValuesRegistry : public IMutableEnumValuesRegistry {
|
||||
|
||||
std::vector<Catch::Detail::unique_ptr<EnumInfo>> m_enumInfos;
|
||||
|
||||
EnumInfo const& registerEnum( StringRef enumName, StringRef allValueNames, std::vector<int> const& values) override;
|
||||
};
|
||||
|
||||
std::vector<StringRef> parseEnums( StringRef enums );
|
||||
|
||||
} // Detail
|
||||
|
||||
} // Catch
|
||||
|
||||
#endif // CATCH_ENUM_VALUES_REGISTRY_HPP_INCLUDED
|
||||
|
||||
|
||||
#ifndef CATCH_ERRNO_GUARD_HPP_INCLUDED
|
||||
#define CATCH_ERRNO_GUARD_HPP_INCLUDED
|
||||
|
||||
@@ -9900,7 +9904,7 @@ namespace Catch {
|
||||
|
||||
namespace Catch {
|
||||
|
||||
class ExceptionTranslatorRegistry : public IExceptionTranslatorRegistry {
|
||||
class ExceptionTranslatorRegistry final : public IExceptionTranslatorRegistry {
|
||||
public:
|
||||
~ExceptionTranslatorRegistry() override;
|
||||
void registerTranslator( Detail::unique_ptr<IExceptionTranslator>&& translator );
|
||||
@@ -10952,8 +10956,6 @@ namespace Catch {
|
||||
|
||||
void handleFatalErrorCondition( StringRef message ) override;
|
||||
|
||||
bool lastAssertionPassed() override;
|
||||
|
||||
public:
|
||||
// !TBD We need to do this another way!
|
||||
bool aborting() const;
|
||||
@@ -10975,7 +10977,7 @@ namespace Catch {
|
||||
ITransientExpression const *expr,
|
||||
bool negated );
|
||||
|
||||
void populateReaction( AssertionReaction& reaction, bool has_normal_disposition );
|
||||
void populateReaction( AssertionReaction& reaction, bool has_normal_disposition ) const;
|
||||
|
||||
// Creates dummy info for unexpected exceptions/fatal errors,
|
||||
// where we do not have the access to one, but we still need
|
||||
@@ -11067,7 +11069,7 @@ namespace Catch {
|
||||
|
||||
|
||||
template<typename SingletonImplT, typename InterfaceT = SingletonImplT, typename MutableInterfaceT = InterfaceT>
|
||||
class Singleton : SingletonImplT, public ISingleton {
|
||||
class Singleton final : SingletonImplT, public ISingleton {
|
||||
|
||||
static auto getInternal() -> Singleton* {
|
||||
static Singleton* s_instance = nullptr;
|
||||
@@ -11198,7 +11200,7 @@ namespace Catch {
|
||||
namespace Catch {
|
||||
struct SourceLineInfo;
|
||||
|
||||
class TagAliasRegistry : public ITagAliasRegistry {
|
||||
class TagAliasRegistry final : public ITagAliasRegistry {
|
||||
public:
|
||||
~TagAliasRegistry() override;
|
||||
TagAlias const* find( std::string const& alias ) const override;
|
||||
@@ -11258,7 +11260,7 @@ namespace Catch {
|
||||
std::vector<TestCaseHandle> filterTests( std::vector<TestCaseHandle> const& testCases, TestSpec const& testSpec, IConfig const& config );
|
||||
std::vector<TestCaseHandle> const& getAllTestCasesSorted( IConfig const& config );
|
||||
|
||||
class TestRegistry : public ITestCaseRegistry {
|
||||
class TestRegistry final : public ITestCaseRegistry {
|
||||
public:
|
||||
void registerTest( Detail::unique_ptr<TestCaseInfo> testInfo, Detail::unique_ptr<ITestInvoker> testInvoker );
|
||||
|
||||
@@ -11897,7 +11899,7 @@ namespace Catch {
|
||||
#endif
|
||||
|
||||
template<typename ArgT, typename MatcherT>
|
||||
class MatchExpr : public ITransientExpression {
|
||||
class MatchExpr final : public ITransientExpression {
|
||||
ArgT && m_arg;
|
||||
MatcherT const& m_matcher;
|
||||
public:
|
||||
@@ -11984,10 +11986,10 @@ namespace Matchers {
|
||||
|
||||
class MatcherUntypedBase {
|
||||
public:
|
||||
MatcherUntypedBase() = default;
|
||||
constexpr MatcherUntypedBase() = default;
|
||||
|
||||
MatcherUntypedBase(MatcherUntypedBase const&) = default;
|
||||
MatcherUntypedBase(MatcherUntypedBase&&) = default;
|
||||
constexpr MatcherUntypedBase(MatcherUntypedBase const&) = default;
|
||||
constexpr MatcherUntypedBase(MatcherUntypedBase&&) = default;
|
||||
|
||||
MatcherUntypedBase& operator = (MatcherUntypedBase const&) = delete;
|
||||
MatcherUntypedBase& operator = (MatcherUntypedBase&&) = delete;
|
||||
@@ -11995,9 +11997,9 @@ namespace Matchers {
|
||||
std::string toString() const;
|
||||
|
||||
protected:
|
||||
virtual ~MatcherUntypedBase(); // = default;
|
||||
virtual std::string describe() const = 0;
|
||||
mutable std::string m_cachedToString;
|
||||
CATCH_DESTRUCTOR_CONSTEXPR virtual ~MatcherUntypedBase() = default;
|
||||
//! Should be overridden, but we provide default "undescribed" impl
|
||||
virtual std::string describe() const;
|
||||
};
|
||||
|
||||
|
||||
@@ -12179,6 +12181,19 @@ namespace Matchers {
|
||||
#define CATCH_CHECK_THAT( arg, matcher ) INTERNAL_CHECK_THAT( "CATCH_CHECK_THAT", matcher, Catch::ResultDisposition::ContinueOnFailure, arg )
|
||||
#define CATCH_REQUIRE_THAT( arg, matcher ) INTERNAL_CHECK_THAT( "CATCH_REQUIRE_THAT", matcher, Catch::ResultDisposition::Normal, arg )
|
||||
|
||||
#if !defined(CATCH_CONFIG_RUNTIME_STATIC_REQUIRE)
|
||||
#define CATCH_STATIC_REQUIRE_THAT( arg, matcher ) \
|
||||
static_assert( ( matcher ).match( arg ), #matcher ".match( " #arg " )"); \
|
||||
CATCH_SUCCEED( #matcher ".match( " #arg " )" )
|
||||
#define CATCH_STATIC_CHECK_THAT( arg, matcher ) \
|
||||
static_assert( ( matcher ).match( arg ), #matcher ".match( " #arg " )"); \
|
||||
CATCH_SUCCEED( #matcher ".match( " #arg " )" )
|
||||
#else
|
||||
#define CATCH_STATIC_REQUIRE_THAT( arg, matcher ) CATCH_REQUIRE_THAT( arg, matcher )
|
||||
#define CATCH_STATIC_CHECK_THAT( arg, matcher ) CATCH_CHECK_THAT( arg, matcher )
|
||||
#endif
|
||||
|
||||
|
||||
#elif defined(CATCH_CONFIG_PREFIX_ALL) && defined(CATCH_CONFIG_DISABLE)
|
||||
|
||||
#define CATCH_REQUIRE_THROWS_WITH( expr, matcher ) (void)(0)
|
||||
@@ -12190,6 +12205,9 @@ namespace Matchers {
|
||||
#define CATCH_CHECK_THAT( arg, matcher ) (void)(0)
|
||||
#define CATCH_REQUIRE_THAT( arg, matcher ) (void)(0)
|
||||
|
||||
#define CATCH_STATIC_REQUIRE_THAT( arg, matcher ) (void)(0)
|
||||
#define CATCH_STATIC_CHECK_THAT( arg, matcher ) (void)(0)
|
||||
|
||||
#elif !defined(CATCH_CONFIG_PREFIX_ALL) && !defined(CATCH_CONFIG_DISABLE)
|
||||
|
||||
#define REQUIRE_THROWS_WITH( expr, matcher ) INTERNAL_CATCH_THROWS_STR_MATCHES( "REQUIRE_THROWS_WITH", Catch::ResultDisposition::Normal, matcher, expr )
|
||||
@@ -12201,6 +12219,19 @@ namespace Matchers {
|
||||
#define CHECK_THAT( arg, matcher ) INTERNAL_CHECK_THAT( "CHECK_THAT", matcher, Catch::ResultDisposition::ContinueOnFailure, arg )
|
||||
#define REQUIRE_THAT( arg, matcher ) INTERNAL_CHECK_THAT( "REQUIRE_THAT", matcher, Catch::ResultDisposition::Normal, arg )
|
||||
|
||||
#if !defined(CATCH_CONFIG_RUNTIME_STATIC_REQUIRE)
|
||||
#define STATIC_REQUIRE_THAT( arg, matcher ) \
|
||||
static_assert( ( matcher ).match( arg ), #matcher ".match( " #arg " )"); \
|
||||
SUCCEED( #matcher ".match( " #arg " )" )
|
||||
#define STATIC_CHECK_THAT( arg, matcher ) \
|
||||
static_assert( ( matcher ).match( arg ), #matcher ".match( " #arg " )"); \
|
||||
SUCCEED( #matcher ".match( " #arg " )" )
|
||||
#else
|
||||
#define STATIC_REQUIRE_THAT( arg, matcher ) REQUIRE_THAT( arg, matcher )
|
||||
#define STATIC_CHECK_THAT( arg, matcher ) CHECK_THAT( arg, matcher )
|
||||
#endif
|
||||
|
||||
|
||||
#elif !defined(CATCH_CONFIG_PREFIX_ALL) && defined(CATCH_CONFIG_DISABLE)
|
||||
|
||||
#define REQUIRE_THROWS_WITH( expr, matcher ) (void)(0)
|
||||
@@ -12212,6 +12243,9 @@ namespace Matchers {
|
||||
#define CHECK_THAT( arg, matcher ) (void)(0)
|
||||
#define REQUIRE_THAT( arg, matcher ) (void)(0)
|
||||
|
||||
#define STATIC_REQUIRE_THAT( arg, matcher ) (void)(0)
|
||||
#define STATIC_CHECK_THAT( arg, matcher ) (void)(0)
|
||||
|
||||
#endif // end of user facing macro declarations
|
||||
|
||||
#endif // CATCH_MATCHERS_HPP_INCLUDED
|
||||
@@ -12234,12 +12268,12 @@ namespace Matchers {
|
||||
namespace Catch {
|
||||
namespace Matchers {
|
||||
class MatcherGenericBase : public MatcherUntypedBase {
|
||||
std::string describe() const override;
|
||||
public:
|
||||
MatcherGenericBase() = default;
|
||||
~MatcherGenericBase() override; // = default;
|
||||
constexpr MatcherGenericBase() = default;
|
||||
|
||||
MatcherGenericBase(MatcherGenericBase const&) = default;
|
||||
MatcherGenericBase(MatcherGenericBase&&) = default;
|
||||
constexpr MatcherGenericBase(MatcherGenericBase const&) = default;
|
||||
constexpr MatcherGenericBase(MatcherGenericBase&&) = default;
|
||||
|
||||
MatcherGenericBase& operator=(MatcherGenericBase const&) = delete;
|
||||
MatcherGenericBase& operator=(MatcherGenericBase&&) = delete;
|
||||
@@ -12248,7 +12282,9 @@ namespace Matchers {
|
||||
|
||||
namespace Detail {
|
||||
template<std::size_t N, std::size_t M>
|
||||
std::array<void const*, N + M> array_cat(std::array<void const*, N> && lhs, std::array<void const*, M> && rhs) {
|
||||
constexpr std::array<void const*, N + M>
|
||||
array_cat( std::array<void const*, N>&& lhs,
|
||||
std::array<void const*, M>&& rhs ) {
|
||||
std::array<void const*, N + M> arr{};
|
||||
std::copy_n(lhs.begin(), N, arr.begin());
|
||||
std::copy_n(rhs.begin(), M, arr.begin() + N);
|
||||
@@ -12256,7 +12292,8 @@ namespace Matchers {
|
||||
}
|
||||
|
||||
template<std::size_t N>
|
||||
std::array<void const*, N+1> array_cat(std::array<void const*, N> && lhs, void const* rhs) {
|
||||
constexpr std::array<void const*, N + 1>
|
||||
array_cat( std::array<void const*, N>&& lhs, void const* rhs ) {
|
||||
std::array<void const*, N+1> arr{};
|
||||
std::copy_n(lhs.begin(), N, arr.begin());
|
||||
arr[N] = rhs;
|
||||
@@ -12264,7 +12301,8 @@ namespace Matchers {
|
||||
}
|
||||
|
||||
template<std::size_t N>
|
||||
std::array<void const*, N+1> array_cat(void const* lhs, std::array<void const*, N> && rhs) {
|
||||
constexpr std::array<void const*, N + 1>
|
||||
array_cat( void const* lhs, std::array<void const*, N>&& rhs ) {
|
||||
std::array<void const*, N + 1> arr{ {lhs} };
|
||||
std::copy_n(rhs.begin(), N, arr.begin() + 1);
|
||||
return arr;
|
||||
@@ -12287,23 +12325,31 @@ namespace Matchers {
|
||||
|
||||
|
||||
template<std::size_t N, typename Arg>
|
||||
bool match_all_of(Arg&&, std::array<void const*, N> const&, std::index_sequence<>) {
|
||||
constexpr bool match_all_of( Arg&&,
|
||||
std::array<void const*, N> const&,
|
||||
std::index_sequence<> ) {
|
||||
return true;
|
||||
}
|
||||
|
||||
template<typename T, typename... MatcherTs, std::size_t N, typename Arg, std::size_t Idx, std::size_t... Indices>
|
||||
bool match_all_of(Arg&& arg, std::array<void const*, N> const& matchers, std::index_sequence<Idx, Indices...>) {
|
||||
constexpr bool match_all_of( Arg&& arg,
|
||||
std::array<void const*, N> const& matchers,
|
||||
std::index_sequence<Idx, Indices...> ) {
|
||||
return static_cast<T const*>(matchers[Idx])->match(arg) && match_all_of<MatcherTs...>(arg, matchers, std::index_sequence<Indices...>{});
|
||||
}
|
||||
|
||||
|
||||
template<std::size_t N, typename Arg>
|
||||
bool match_any_of(Arg&&, std::array<void const*, N> const&, std::index_sequence<>) {
|
||||
constexpr bool match_any_of( Arg&&,
|
||||
std::array<void const*, N> const&,
|
||||
std::index_sequence<> ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
template<typename T, typename... MatcherTs, std::size_t N, typename Arg, std::size_t Idx, std::size_t... Indices>
|
||||
bool match_any_of(Arg&& arg, std::array<void const*, N> const& matchers, std::index_sequence<Idx, Indices...>) {
|
||||
constexpr bool match_any_of( Arg&& arg,
|
||||
std::array<void const*, N> const& matchers,
|
||||
std::index_sequence<Idx, Indices...> ) {
|
||||
return static_cast<T const*>(matchers[Idx])->match(arg) || match_any_of<MatcherTs...>(arg, matchers, std::index_sequence<Indices...>{});
|
||||
}
|
||||
|
||||
@@ -12324,15 +12370,18 @@ namespace Matchers {
|
||||
public:
|
||||
MatchAllOfGeneric(MatchAllOfGeneric const&) = delete;
|
||||
MatchAllOfGeneric& operator=(MatchAllOfGeneric const&) = delete;
|
||||
MatchAllOfGeneric(MatchAllOfGeneric&&) = default;
|
||||
MatchAllOfGeneric& operator=(MatchAllOfGeneric&&) = default;
|
||||
constexpr MatchAllOfGeneric( MatchAllOfGeneric&& ) = default;
|
||||
constexpr MatchAllOfGeneric& operator=(MatchAllOfGeneric&&) = default;
|
||||
|
||||
MatchAllOfGeneric(MatcherTs const&... matchers CATCH_ATTR_LIFETIMEBOUND)
|
||||
constexpr MatchAllOfGeneric(
|
||||
MatcherTs const&... matchers CATCH_ATTR_LIFETIMEBOUND )
|
||||
: m_matchers{ {std::addressof(matchers)...} } {}
|
||||
explicit MatchAllOfGeneric(std::array<void const*, sizeof...(MatcherTs)> matchers) : m_matchers{matchers} {}
|
||||
constexpr explicit MatchAllOfGeneric(
|
||||
std::array<void const*, sizeof...( MatcherTs )> matchers ):
|
||||
m_matchers{ matchers } {}
|
||||
|
||||
template<typename Arg>
|
||||
bool match(Arg&& arg) const {
|
||||
constexpr bool match( Arg&& arg ) const {
|
||||
return match_all_of<MatcherTs...>(arg, m_matchers, std::index_sequence_for<MatcherTs...>{});
|
||||
}
|
||||
|
||||
@@ -12348,7 +12397,7 @@ namespace Matchers {
|
||||
|
||||
//! Avoids type nesting for `GenericAllOf && GenericAllOf` case
|
||||
template<typename... MatchersRHS>
|
||||
friend
|
||||
constexpr friend
|
||||
MatchAllOfGeneric<MatcherTs..., MatchersRHS...> operator && (
|
||||
MatchAllOfGeneric<MatcherTs...>&& lhs CATCH_ATTR_LIFETIMEBOUND,
|
||||
MatchAllOfGeneric<MatchersRHS...>&& rhs CATCH_ATTR_LIFETIMEBOUND ) {
|
||||
@@ -12357,7 +12406,8 @@ namespace Matchers {
|
||||
|
||||
//! Avoids type nesting for `GenericAllOf && some matcher` case
|
||||
template<typename MatcherRHS>
|
||||
friend std::enable_if_t<is_matcher_v<MatcherRHS>,
|
||||
constexpr friend std::enable_if_t<
|
||||
is_matcher_v<MatcherRHS>,
|
||||
MatchAllOfGeneric<MatcherTs..., MatcherRHS>> operator && (
|
||||
MatchAllOfGeneric<MatcherTs...>&& lhs CATCH_ATTR_LIFETIMEBOUND,
|
||||
MatcherRHS const& rhs CATCH_ATTR_LIFETIMEBOUND ) {
|
||||
@@ -12366,7 +12416,8 @@ namespace Matchers {
|
||||
|
||||
//! Avoids type nesting for `some matcher && GenericAllOf` case
|
||||
template<typename MatcherLHS>
|
||||
friend std::enable_if_t<is_matcher_v<MatcherLHS>,
|
||||
constexpr friend std::enable_if_t<
|
||||
is_matcher_v<MatcherLHS>,
|
||||
MatchAllOfGeneric<MatcherLHS, MatcherTs...>> operator && (
|
||||
MatcherLHS const& lhs CATCH_ATTR_LIFETIMEBOUND,
|
||||
MatchAllOfGeneric<MatcherTs...>&& rhs CATCH_ATTR_LIFETIMEBOUND ) {
|
||||
@@ -12380,15 +12431,18 @@ namespace Matchers {
|
||||
public:
|
||||
MatchAnyOfGeneric(MatchAnyOfGeneric const&) = delete;
|
||||
MatchAnyOfGeneric& operator=(MatchAnyOfGeneric const&) = delete;
|
||||
MatchAnyOfGeneric(MatchAnyOfGeneric&&) = default;
|
||||
MatchAnyOfGeneric& operator=(MatchAnyOfGeneric&&) = default;
|
||||
constexpr MatchAnyOfGeneric( MatchAnyOfGeneric&& ) = default;
|
||||
constexpr MatchAnyOfGeneric& operator=(MatchAnyOfGeneric&&) = default;
|
||||
|
||||
MatchAnyOfGeneric(MatcherTs const&... matchers CATCH_ATTR_LIFETIMEBOUND)
|
||||
constexpr MatchAnyOfGeneric(
|
||||
MatcherTs const&... matchers CATCH_ATTR_LIFETIMEBOUND )
|
||||
: m_matchers{ {std::addressof(matchers)...} } {}
|
||||
explicit MatchAnyOfGeneric(std::array<void const*, sizeof...(MatcherTs)> matchers) : m_matchers{matchers} {}
|
||||
constexpr explicit MatchAnyOfGeneric(
|
||||
std::array<void const*, sizeof...( MatcherTs )> matchers ):
|
||||
m_matchers{ matchers } {}
|
||||
|
||||
template<typename Arg>
|
||||
bool match(Arg&& arg) const {
|
||||
constexpr bool match( Arg&& arg ) const {
|
||||
return match_any_of<MatcherTs...>(arg, m_matchers, std::index_sequence_for<MatcherTs...>{});
|
||||
}
|
||||
|
||||
@@ -12404,7 +12458,8 @@ namespace Matchers {
|
||||
|
||||
//! Avoids type nesting for `GenericAnyOf || GenericAnyOf` case
|
||||
template<typename... MatchersRHS>
|
||||
friend MatchAnyOfGeneric<MatcherTs..., MatchersRHS...> operator || (
|
||||
constexpr friend MatchAnyOfGeneric<MatcherTs..., MatchersRHS...>
|
||||
operator||(
|
||||
MatchAnyOfGeneric<MatcherTs...>&& lhs CATCH_ATTR_LIFETIMEBOUND,
|
||||
MatchAnyOfGeneric<MatchersRHS...>&& rhs CATCH_ATTR_LIFETIMEBOUND ) {
|
||||
return MatchAnyOfGeneric<MatcherTs..., MatchersRHS...>{array_cat(CATCH_MOVE(lhs.m_matchers), CATCH_MOVE(rhs.m_matchers))};
|
||||
@@ -12412,7 +12467,8 @@ namespace Matchers {
|
||||
|
||||
//! Avoids type nesting for `GenericAnyOf || some matcher` case
|
||||
template<typename MatcherRHS>
|
||||
friend std::enable_if_t<is_matcher_v<MatcherRHS>,
|
||||
constexpr friend std::enable_if_t<
|
||||
is_matcher_v<MatcherRHS>,
|
||||
MatchAnyOfGeneric<MatcherTs..., MatcherRHS>> operator || (
|
||||
MatchAnyOfGeneric<MatcherTs...>&& lhs CATCH_ATTR_LIFETIMEBOUND,
|
||||
MatcherRHS const& rhs CATCH_ATTR_LIFETIMEBOUND ) {
|
||||
@@ -12421,7 +12477,8 @@ namespace Matchers {
|
||||
|
||||
//! Avoids type nesting for `some matcher || GenericAnyOf` case
|
||||
template<typename MatcherLHS>
|
||||
friend std::enable_if_t<is_matcher_v<MatcherLHS>,
|
||||
constexpr friend std::enable_if_t<
|
||||
is_matcher_v<MatcherLHS>,
|
||||
MatchAnyOfGeneric<MatcherLHS, MatcherTs...>> operator || (
|
||||
MatcherLHS const& lhs CATCH_ATTR_LIFETIMEBOUND,
|
||||
MatchAnyOfGeneric<MatcherTs...>&& rhs CATCH_ATTR_LIFETIMEBOUND) {
|
||||
@@ -12437,14 +12494,15 @@ namespace Matchers {
|
||||
public:
|
||||
MatchNotOfGeneric(MatchNotOfGeneric const&) = delete;
|
||||
MatchNotOfGeneric& operator=(MatchNotOfGeneric const&) = delete;
|
||||
MatchNotOfGeneric(MatchNotOfGeneric&&) = default;
|
||||
MatchNotOfGeneric& operator=(MatchNotOfGeneric&&) = default;
|
||||
constexpr MatchNotOfGeneric( MatchNotOfGeneric&& ) = default;
|
||||
constexpr MatchNotOfGeneric& operator=(MatchNotOfGeneric&&) = default;
|
||||
|
||||
explicit MatchNotOfGeneric(MatcherT const& matcher CATCH_ATTR_LIFETIMEBOUND)
|
||||
constexpr explicit MatchNotOfGeneric(
|
||||
MatcherT const& matcher CATCH_ATTR_LIFETIMEBOUND )
|
||||
: m_matcher{matcher} {}
|
||||
|
||||
template<typename Arg>
|
||||
bool match(Arg&& arg) const {
|
||||
constexpr bool match( Arg&& arg ) const {
|
||||
return !m_matcher.match(arg);
|
||||
}
|
||||
|
||||
@@ -12453,7 +12511,7 @@ namespace Matchers {
|
||||
}
|
||||
|
||||
//! Negating negation can just unwrap and return underlying matcher
|
||||
friend MatcherT const&
|
||||
constexpr friend MatcherT const&
|
||||
operator!( MatchNotOfGeneric<MatcherT> const& matcher
|
||||
CATCH_ATTR_LIFETIMEBOUND ) {
|
||||
return matcher.m_matcher;
|
||||
@@ -12464,14 +12522,18 @@ namespace Matchers {
|
||||
|
||||
// compose only generic matchers
|
||||
template<typename MatcherLHS, typename MatcherRHS>
|
||||
std::enable_if_t<Detail::are_generic_matchers_v<MatcherLHS, MatcherRHS>, Detail::MatchAllOfGeneric<MatcherLHS, MatcherRHS>>
|
||||
constexpr std::enable_if_t<
|
||||
Detail::are_generic_matchers_v<MatcherLHS, MatcherRHS>,
|
||||
Detail::MatchAllOfGeneric<MatcherLHS, MatcherRHS>>
|
||||
operator&&( MatcherLHS const& lhs CATCH_ATTR_LIFETIMEBOUND,
|
||||
MatcherRHS const& rhs CATCH_ATTR_LIFETIMEBOUND ) {
|
||||
return { lhs, rhs };
|
||||
}
|
||||
|
||||
template<typename MatcherLHS, typename MatcherRHS>
|
||||
std::enable_if_t<Detail::are_generic_matchers_v<MatcherLHS, MatcherRHS>, Detail::MatchAnyOfGeneric<MatcherLHS, MatcherRHS>>
|
||||
constexpr std::enable_if_t<
|
||||
Detail::are_generic_matchers_v<MatcherLHS, MatcherRHS>,
|
||||
Detail::MatchAnyOfGeneric<MatcherLHS, MatcherRHS>>
|
||||
operator||( MatcherLHS const& lhs CATCH_ATTR_LIFETIMEBOUND,
|
||||
MatcherRHS const& rhs CATCH_ATTR_LIFETIMEBOUND ) {
|
||||
return { lhs, rhs };
|
||||
@@ -12479,7 +12541,8 @@ namespace Matchers {
|
||||
|
||||
//! Wrap provided generic matcher in generic negator
|
||||
template<typename MatcherT>
|
||||
std::enable_if_t<Detail::is_generic_matcher_v<MatcherT>, Detail::MatchNotOfGeneric<MatcherT>>
|
||||
constexpr std::enable_if_t<Detail::is_generic_matcher_v<MatcherT>,
|
||||
Detail::MatchNotOfGeneric<MatcherT>>
|
||||
operator!( MatcherT const& matcher CATCH_ATTR_LIFETIMEBOUND ) {
|
||||
return Detail::MatchNotOfGeneric<MatcherT>{matcher};
|
||||
}
|
||||
@@ -12525,7 +12588,7 @@ namespace Catch {
|
||||
class IsEmptyMatcher final : public MatcherGenericBase {
|
||||
public:
|
||||
template <typename RangeLike>
|
||||
bool match(RangeLike&& rng) const {
|
||||
constexpr bool match(RangeLike&& rng) const {
|
||||
#if defined(CATCH_CONFIG_POLYFILL_NONMEMBER_CONTAINER_ACCESS)
|
||||
using Catch::Detail::empty;
|
||||
#else
|
||||
@@ -12540,12 +12603,12 @@ namespace Catch {
|
||||
class HasSizeMatcher final : public MatcherGenericBase {
|
||||
std::size_t m_target_size;
|
||||
public:
|
||||
explicit HasSizeMatcher(std::size_t target_size):
|
||||
constexpr explicit HasSizeMatcher(std::size_t target_size):
|
||||
m_target_size(target_size)
|
||||
{}
|
||||
|
||||
template <typename RangeLike>
|
||||
bool match(RangeLike&& rng) const {
|
||||
constexpr bool match(RangeLike&& rng) const {
|
||||
#if defined(CATCH_CONFIG_POLYFILL_NONMEMBER_CONTAINER_ACCESS)
|
||||
using Catch::Detail::size;
|
||||
#else
|
||||
@@ -12561,12 +12624,12 @@ namespace Catch {
|
||||
class SizeMatchesMatcher final : public MatcherGenericBase {
|
||||
Matcher m_matcher;
|
||||
public:
|
||||
explicit SizeMatchesMatcher(Matcher m):
|
||||
constexpr explicit SizeMatchesMatcher(Matcher m):
|
||||
m_matcher(CATCH_MOVE(m))
|
||||
{}
|
||||
|
||||
template <typename RangeLike>
|
||||
bool match(RangeLike&& rng) const {
|
||||
constexpr bool match(RangeLike&& rng) const {
|
||||
#if defined(CATCH_CONFIG_POLYFILL_NONMEMBER_CONTAINER_ACCESS)
|
||||
using Catch::Detail::size;
|
||||
#else
|
||||
@@ -12582,11 +12645,13 @@ namespace Catch {
|
||||
|
||||
|
||||
//! Creates a matcher that accepts empty ranges/containers
|
||||
IsEmptyMatcher IsEmpty();
|
||||
inline CATCH_DESTRUCTOR_CONSTEXPR IsEmptyMatcher IsEmpty() { return {}; }
|
||||
//! Creates a matcher that accepts ranges/containers with specific size
|
||||
HasSizeMatcher SizeIs(std::size_t sz);
|
||||
inline CATCH_DESTRUCTOR_CONSTEXPR HasSizeMatcher SizeIs( std::size_t sz ) {
|
||||
return HasSizeMatcher{ sz };
|
||||
}
|
||||
template <typename Matcher>
|
||||
std::enable_if_t<Detail::is_matcher_v<Matcher>,
|
||||
constexpr std::enable_if_t<Detail::is_matcher_v<Matcher>,
|
||||
SizeMatchesMatcher<Matcher>> SizeIs(Matcher&& m) {
|
||||
return SizeMatchesMatcher<Matcher>{CATCH_FORWARD(m)};
|
||||
}
|
||||
@@ -12613,7 +12678,7 @@ namespace Catch {
|
||||
Equality m_eq;
|
||||
public:
|
||||
template <typename T2, typename Equality2>
|
||||
ContainsElementMatcher(T2&& target, Equality2&& predicate):
|
||||
constexpr ContainsElementMatcher(T2&& target, Equality2&& predicate):
|
||||
m_desired(CATCH_FORWARD(target)),
|
||||
m_eq(CATCH_FORWARD(predicate))
|
||||
{}
|
||||
@@ -12623,7 +12688,7 @@ namespace Catch {
|
||||
}
|
||||
|
||||
template <typename RangeLike>
|
||||
bool match( RangeLike&& rng ) const {
|
||||
constexpr bool match( RangeLike&& rng ) const {
|
||||
for ( auto&& elem : rng ) {
|
||||
if ( m_eq( elem, m_desired ) ) { return true; }
|
||||
}
|
||||
@@ -12639,12 +12704,12 @@ namespace Catch {
|
||||
// Note that we do a copy+move to avoid having to SFINAE this
|
||||
// constructor (and also avoid some perfect forwarding failure
|
||||
// cases)
|
||||
ContainsMatcherMatcher(Matcher matcher):
|
||||
constexpr ContainsMatcherMatcher(Matcher matcher):
|
||||
m_matcher(CATCH_MOVE(matcher))
|
||||
{}
|
||||
|
||||
template <typename RangeLike>
|
||||
bool match(RangeLike&& rng) const {
|
||||
constexpr bool match(RangeLike&& rng) const {
|
||||
for (auto&& elem : rng) {
|
||||
if (m_matcher.match(elem)) {
|
||||
return true;
|
||||
@@ -12664,14 +12729,14 @@ namespace Catch {
|
||||
* Uses `std::equal_to` to do the comparison
|
||||
*/
|
||||
template <typename T>
|
||||
std::enable_if_t<!Detail::is_matcher_v<T>,
|
||||
constexpr std::enable_if_t<!Detail::is_matcher_v<T>,
|
||||
ContainsElementMatcher<T, std::equal_to<>>> Contains(T&& elem) {
|
||||
return { CATCH_FORWARD(elem), std::equal_to<>{} };
|
||||
}
|
||||
|
||||
//! Creates a matcher that checks whether a range contains element matching a matcher
|
||||
template <typename Matcher>
|
||||
std::enable_if_t<Detail::is_matcher_v<Matcher>,
|
||||
constexpr std::enable_if_t<Detail::is_matcher_v<Matcher>,
|
||||
ContainsMatcherMatcher<Matcher>> Contains(Matcher&& matcher) {
|
||||
return { CATCH_FORWARD(matcher) };
|
||||
}
|
||||
@@ -12682,7 +12747,7 @@ namespace Catch {
|
||||
* Uses `eq` to do the comparisons, the element is provided on the rhs
|
||||
*/
|
||||
template <typename T, typename Equality>
|
||||
ContainsElementMatcher<T, Equality> Contains(T&& elem, Equality&& eq) {
|
||||
constexpr ContainsElementMatcher<T, Equality> Contains(T&& elem, Equality&& eq) {
|
||||
return { CATCH_FORWARD(elem), CATCH_FORWARD(eq) };
|
||||
}
|
||||
|
||||
@@ -12897,7 +12962,7 @@ namespace Catch {
|
||||
class AllMatchMatcher final : public MatcherGenericBase {
|
||||
Matcher m_matcher;
|
||||
public:
|
||||
AllMatchMatcher(Matcher matcher):
|
||||
constexpr AllMatchMatcher(Matcher matcher):
|
||||
m_matcher(CATCH_MOVE(matcher))
|
||||
{}
|
||||
|
||||
@@ -12906,7 +12971,7 @@ namespace Catch {
|
||||
}
|
||||
|
||||
template <typename RangeLike>
|
||||
bool match(RangeLike&& rng) const {
|
||||
constexpr bool match(RangeLike&& rng) const {
|
||||
for (auto&& elem : rng) {
|
||||
if (!m_matcher.match(elem)) {
|
||||
return false;
|
||||
@@ -12921,7 +12986,7 @@ namespace Catch {
|
||||
class NoneMatchMatcher final : public MatcherGenericBase {
|
||||
Matcher m_matcher;
|
||||
public:
|
||||
NoneMatchMatcher(Matcher matcher):
|
||||
constexpr NoneMatchMatcher(Matcher matcher):
|
||||
m_matcher(CATCH_MOVE(matcher))
|
||||
{}
|
||||
|
||||
@@ -12930,7 +12995,7 @@ namespace Catch {
|
||||
}
|
||||
|
||||
template <typename RangeLike>
|
||||
bool match(RangeLike&& rng) const {
|
||||
constexpr bool match(RangeLike&& rng) const {
|
||||
for (auto&& elem : rng) {
|
||||
if (m_matcher.match(elem)) {
|
||||
return false;
|
||||
@@ -12945,7 +13010,7 @@ namespace Catch {
|
||||
class AnyMatchMatcher final : public MatcherGenericBase {
|
||||
Matcher m_matcher;
|
||||
public:
|
||||
AnyMatchMatcher(Matcher matcher):
|
||||
constexpr AnyMatchMatcher(Matcher matcher):
|
||||
m_matcher(CATCH_MOVE(matcher))
|
||||
{}
|
||||
|
||||
@@ -12954,7 +13019,7 @@ namespace Catch {
|
||||
}
|
||||
|
||||
template <typename RangeLike>
|
||||
bool match(RangeLike&& rng) const {
|
||||
constexpr bool match(RangeLike&& rng) const {
|
||||
for (auto&& elem : rng) {
|
||||
if (m_matcher.match(elem)) {
|
||||
return true;
|
||||
@@ -12970,7 +13035,7 @@ namespace Catch {
|
||||
std::string describe() const override;
|
||||
|
||||
template <typename RangeLike>
|
||||
bool match(RangeLike&& rng) const {
|
||||
constexpr bool match(RangeLike&& rng) const {
|
||||
for (auto&& elem : rng) {
|
||||
if (!elem) {
|
||||
return false;
|
||||
@@ -12986,7 +13051,7 @@ namespace Catch {
|
||||
std::string describe() const override;
|
||||
|
||||
template <typename RangeLike>
|
||||
bool match(RangeLike&& rng) const {
|
||||
constexpr bool match(RangeLike&& rng) const {
|
||||
for (auto&& elem : rng) {
|
||||
if (elem) {
|
||||
return false;
|
||||
@@ -13002,7 +13067,7 @@ namespace Catch {
|
||||
std::string describe() const override;
|
||||
|
||||
template <typename RangeLike>
|
||||
bool match(RangeLike&& rng) const {
|
||||
constexpr bool match(RangeLike&& rng) const {
|
||||
for (auto&& elem : rng) {
|
||||
if (elem) {
|
||||
return true;
|
||||
@@ -13012,32 +13077,35 @@ namespace Catch {
|
||||
}
|
||||
};
|
||||
|
||||
// Creates a matcher that checks whether all elements in a range match a matcher
|
||||
//! Creates a matcher that checks whether all elements in a range match a matcher
|
||||
template <typename Matcher>
|
||||
AllMatchMatcher<Matcher> AllMatch(Matcher&& matcher) {
|
||||
constexpr AllMatchMatcher<Matcher> AllMatch(Matcher&& matcher) {
|
||||
return { CATCH_FORWARD(matcher) };
|
||||
}
|
||||
|
||||
// Creates a matcher that checks whether no element in a range matches a matcher.
|
||||
//! Creates a matcher that checks whether no element in a range matches a matcher.
|
||||
template <typename Matcher>
|
||||
NoneMatchMatcher<Matcher> NoneMatch(Matcher&& matcher) {
|
||||
constexpr NoneMatchMatcher<Matcher> NoneMatch(Matcher&& matcher) {
|
||||
return { CATCH_FORWARD(matcher) };
|
||||
}
|
||||
|
||||
// Creates a matcher that checks whether any element in a range matches a matcher.
|
||||
//! Creates a matcher that checks whether any element in a range matches a matcher.
|
||||
template <typename Matcher>
|
||||
AnyMatchMatcher<Matcher> AnyMatch(Matcher&& matcher) {
|
||||
constexpr AnyMatchMatcher<Matcher> AnyMatch(Matcher&& matcher) {
|
||||
return { CATCH_FORWARD(matcher) };
|
||||
}
|
||||
|
||||
// Creates a matcher that checks whether all elements in a range are true
|
||||
AllTrueMatcher AllTrue();
|
||||
//! Creates a matcher that checks whether all elements in a range are true
|
||||
inline CATCH_DESTRUCTOR_CONSTEXPR
|
||||
AllTrueMatcher AllTrue() { return AllTrueMatcher{}; }
|
||||
|
||||
// Creates a matcher that checks whether no element in a range is true
|
||||
NoneTrueMatcher NoneTrue();
|
||||
//! Creates a matcher that checks whether no element in a range is true
|
||||
inline CATCH_DESTRUCTOR_CONSTEXPR
|
||||
NoneTrueMatcher NoneTrue() { return NoneTrueMatcher{}; }
|
||||
|
||||
// Creates a matcher that checks whether any element in a range is true
|
||||
AnyTrueMatcher AnyTrue();
|
||||
//! Creates a matcher that checks whether any element in a range is true
|
||||
inline CATCH_DESTRUCTOR_CONSTEXPR
|
||||
AnyTrueMatcher AnyTrue() { return AnyTrueMatcher{}; }
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -8,7 +8,7 @@
|
||||
project(
|
||||
'catch2',
|
||||
'cpp',
|
||||
version: '3.14.0', # CML version placeholder, don't delete
|
||||
version: '3.15.0', # CML version placeholder, don't delete
|
||||
license: 'BSL-1.0',
|
||||
meson_version: '>=0.54.1',
|
||||
)
|
||||
|
||||
+2
-3
@@ -87,7 +87,7 @@ set(IMPL_HEADERS
|
||||
${SOURCES_DIR}/internal/catch_decomposer.hpp
|
||||
${SOURCES_DIR}/internal/catch_deprecation_macro.hpp
|
||||
${SOURCES_DIR}/internal/catch_enforce.hpp
|
||||
${SOURCES_DIR}/internal/catch_enum_values_registry.hpp
|
||||
${SOURCES_DIR}/internal/catch_enum_info.hpp
|
||||
${SOURCES_DIR}/internal/catch_errno_guard.hpp
|
||||
${SOURCES_DIR}/internal/catch_exception_translator_registry.hpp
|
||||
${SOURCES_DIR}/internal/catch_fatal_condition_handler.hpp
|
||||
@@ -181,7 +181,7 @@ set(IMPL_SOURCES
|
||||
${SOURCES_DIR}/internal/catch_debugger.cpp
|
||||
${SOURCES_DIR}/internal/catch_decomposer.cpp
|
||||
${SOURCES_DIR}/internal/catch_enforce.cpp
|
||||
${SOURCES_DIR}/internal/catch_enum_values_registry.cpp
|
||||
${SOURCES_DIR}/internal/catch_enum_info.cpp
|
||||
${SOURCES_DIR}/internal/catch_errno_guard.cpp
|
||||
${SOURCES_DIR}/internal/catch_exception_translator_registry.cpp
|
||||
${SOURCES_DIR}/internal/catch_fatal_condition_handler.cpp
|
||||
@@ -227,7 +227,6 @@ set(INTERFACE_HEADERS
|
||||
${SOURCES_DIR}/interfaces/catch_interfaces_all.hpp
|
||||
${SOURCES_DIR}/interfaces/catch_interfaces_capture.hpp
|
||||
${SOURCES_DIR}/interfaces/catch_interfaces_config.hpp
|
||||
${SOURCES_DIR}/interfaces/catch_interfaces_enum_values_registry.hpp
|
||||
${SOURCES_DIR}/interfaces/catch_interfaces_exception.hpp
|
||||
${SOURCES_DIR}/interfaces/catch_interfaces_generatortracker.hpp
|
||||
${SOURCES_DIR}/interfaces/catch_interfaces_registry_hub.hpp
|
||||
|
||||
@@ -36,11 +36,11 @@ namespace Catch {
|
||||
samples.data(), samples.data() + samples.size() );
|
||||
|
||||
auto wrap_estimate = [](Estimate<double> e) {
|
||||
return Estimate<FDuration> {
|
||||
FDuration(e.point),
|
||||
FDuration(e.lower_bound),
|
||||
FDuration(e.upper_bound),
|
||||
e.confidence_interval,
|
||||
return Estimate<FDuration>{
|
||||
FDuration( e.point ),
|
||||
FDuration( e.lower_bound ),
|
||||
FDuration( e.upper_bound ),
|
||||
e.confidence_interval,
|
||||
};
|
||||
};
|
||||
std::vector<FDuration> samples2;
|
||||
|
||||
@@ -41,7 +41,7 @@ namespace Catch {
|
||||
callable& operator=(callable&&) = default;
|
||||
};
|
||||
template <typename Fun>
|
||||
struct model : public callable {
|
||||
struct model final : public callable {
|
||||
model(Fun&& fun_) : fun(CATCH_MOVE(fun_)) {}
|
||||
model(Fun const& fun_) : fun(fun_) {}
|
||||
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
namespace Catch {
|
||||
namespace Benchmark {
|
||||
namespace Detail {
|
||||
struct optimized_away_error : std::exception {
|
||||
struct optimized_away_error final : std::exception {
|
||||
const char* what() const noexcept override;
|
||||
};
|
||||
|
||||
|
||||
@@ -68,7 +68,7 @@
|
||||
#include <catch2/internal/catch_decomposer.hpp>
|
||||
#include <catch2/internal/catch_deprecation_macro.hpp>
|
||||
#include <catch2/internal/catch_enforce.hpp>
|
||||
#include <catch2/internal/catch_enum_values_registry.hpp>
|
||||
#include <catch2/internal/catch_enum_info.hpp>
|
||||
#include <catch2/internal/catch_errno_guard.hpp>
|
||||
#include <catch2/internal/catch_exception_translator_registry.hpp>
|
||||
#include <catch2/internal/catch_fatal_condition_handler.hpp>
|
||||
|
||||
@@ -5,8 +5,8 @@
|
||||
// https://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
// SPDX-License-Identifier: BSL-1.0
|
||||
|
||||
#include <catch2/catch_message.hpp>
|
||||
#include <catch2/interfaces/catch_interfaces_capture.hpp>
|
||||
#include <catch2/internal/catch_enforce.hpp>
|
||||
#include <catch2/internal/catch_move_and_forward.hpp>
|
||||
|
||||
@@ -22,7 +22,7 @@ namespace Catch {
|
||||
m_messageId( builder.m_info.sequence ) {
|
||||
MessageInfo info( CATCH_MOVE( builder.m_info ) );
|
||||
info.message = builder.m_stream.str();
|
||||
IResultCapture::pushScopedMessage( CATCH_MOVE( info ) );
|
||||
Detail::pushScopedMessage( CATCH_MOVE( info ) );
|
||||
}
|
||||
|
||||
ScopedMessage::ScopedMessage( ScopedMessage&& old ) noexcept:
|
||||
@@ -31,7 +31,7 @@ namespace Catch {
|
||||
}
|
||||
|
||||
ScopedMessage::~ScopedMessage() {
|
||||
if ( !m_moved ) { IResultCapture::popScopedMessage( m_messageId ); }
|
||||
if ( !m_moved ) { Detail::popScopedMessage( m_messageId ); }
|
||||
}
|
||||
|
||||
|
||||
@@ -103,7 +103,7 @@ namespace Catch {
|
||||
assert( m_captured == m_messages.size() );
|
||||
if ( m_isScoped ) {
|
||||
for ( auto const& message : m_messages ) {
|
||||
IResultCapture::popScopedMessage( message.sequence );
|
||||
Detail::popScopedMessage( message.sequence );
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -112,9 +112,9 @@ namespace Catch {
|
||||
assert( index < m_messages.size() );
|
||||
m_messages[index].message += value;
|
||||
if ( m_isScoped ) {
|
||||
IResultCapture::pushScopedMessage( CATCH_MOVE( m_messages[index] ) );
|
||||
Detail::pushScopedMessage( CATCH_MOVE( m_messages[index] ) );
|
||||
} else {
|
||||
IResultCapture::addUnscopedMessage( CATCH_MOVE( m_messages[index] ) );
|
||||
Detail::addUnscopedMessage( CATCH_MOVE( m_messages[index] ) );
|
||||
}
|
||||
m_captured++;
|
||||
}
|
||||
|
||||
@@ -13,16 +13,28 @@
|
||||
#include <catch2/internal/catch_reusable_string_stream.hpp>
|
||||
#include <catch2/internal/catch_stream_end_stop.hpp>
|
||||
#include <catch2/internal/catch_message_info.hpp>
|
||||
#include <catch2/internal/catch_move_and_forward.hpp>
|
||||
#include <catch2/catch_tostring.hpp>
|
||||
#include <catch2/interfaces/catch_interfaces_capture.hpp>
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace Catch {
|
||||
struct MessageInfo;
|
||||
struct MessageBuilder;
|
||||
|
||||
namespace Detail {
|
||||
// The message state affecting functions have to be defined in
|
||||
// the TU where the thread-local message holders are defined.
|
||||
// Currently this is catch_run_context.cpp
|
||||
|
||||
void pushScopedMessage( MessageInfo&& message );
|
||||
void popScopedMessage( unsigned int messageId );
|
||||
void addUnscopedMessage( MessageInfo&& message );
|
||||
void emplaceUnscopedMessage( MessageBuilder&& builder );
|
||||
} // namespace Detail
|
||||
|
||||
struct SourceLineInfo;
|
||||
class IResultCapture;
|
||||
|
||||
struct MessageStream {
|
||||
|
||||
@@ -112,7 +124,7 @@ namespace Catch {
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
#define INTERNAL_CATCH_UNSCOPED_INFO( macroName, log ) \
|
||||
Catch::IResultCapture::emplaceUnscopedMessage( Catch::MessageBuilder( macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, Catch::ResultWas::Info ) << log )
|
||||
Catch::Detail::emplaceUnscopedMessage( Catch::MessageBuilder( macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, Catch::ResultWas::Info ) << log )
|
||||
|
||||
|
||||
#if defined(CATCH_CONFIG_PREFIX_MESSAGES) && !defined(CATCH_CONFIG_DISABLE)
|
||||
|
||||
@@ -15,7 +15,6 @@
|
||||
#include <catch2/internal/catch_tag_alias_registry.hpp>
|
||||
#include <catch2/internal/catch_startup_exception_registry.hpp>
|
||||
#include <catch2/internal/catch_singletons.hpp>
|
||||
#include <catch2/internal/catch_enum_values_registry.hpp>
|
||||
#include <catch2/catch_test_case_info.hpp>
|
||||
#include <catch2/internal/catch_noncopyable.hpp>
|
||||
#include <catch2/interfaces/catch_interfaces_reporter_factory.hpp>
|
||||
@@ -72,9 +71,6 @@ namespace Catch {
|
||||
CATCH_INTERNAL_ERROR("Attempted to register active exception under CATCH_CONFIG_DISABLE_EXCEPTIONS!");
|
||||
#endif
|
||||
}
|
||||
IMutableEnumValuesRegistry& getMutableEnumValuesRegistry() override {
|
||||
return m_enumValuesRegistry;
|
||||
}
|
||||
|
||||
private:
|
||||
TestRegistry m_testCaseRegistry;
|
||||
@@ -82,7 +78,6 @@ namespace Catch {
|
||||
ExceptionTranslatorRegistry m_exceptionTranslatorRegistry;
|
||||
TagAliasRegistry m_tagAliasRegistry;
|
||||
StartupExceptionRegistry m_exceptionRegistry;
|
||||
Detail::EnumValuesRegistry m_enumValuesRegistry;
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
#include <catch2/reporters/catch_reporter_multi.hpp>
|
||||
#include <catch2/internal/catch_reporter_registry.hpp>
|
||||
#include <catch2/interfaces/catch_interfaces_reporter_factory.hpp>
|
||||
#include <catch2/interfaces/catch_interfaces_registry_hub.hpp>
|
||||
#include <catch2/internal/catch_move_and_forward.hpp>
|
||||
#include <catch2/internal/catch_stdstreams.hpp>
|
||||
#include <catch2/internal/catch_istream.hpp>
|
||||
|
||||
@@ -18,7 +18,8 @@
|
||||
#include <catch2/internal/catch_config_wchar.hpp>
|
||||
#include <catch2/internal/catch_reusable_string_stream.hpp>
|
||||
#include <catch2/internal/catch_void_type.hpp>
|
||||
#include <catch2/interfaces/catch_interfaces_enum_values_registry.hpp>
|
||||
#include <catch2/internal/catch_enum_info.hpp>
|
||||
#include <catch2/internal/catch_stringref.hpp>
|
||||
|
||||
#ifdef CATCH_CONFIG_CPP17_STRING_VIEW
|
||||
#include <string_view>
|
||||
@@ -383,7 +384,10 @@ namespace Catch {
|
||||
}
|
||||
#endif // CATCH_CONFIG_ENABLE_PAIR_STRINGMAKER
|
||||
|
||||
#if defined(CATCH_CONFIG_ENABLE_OPTIONAL_STRINGMAKER) && defined(CATCH_CONFIG_CPP17_OPTIONAL)
|
||||
#if defined( CATCH_CONFIG_ENABLE_OPTIONAL_STRINGMAKER ) && \
|
||||
defined( CATCH_CONFIG_CPP17_OPTIONAL ) && \
|
||||
/* P3168 turned optional into a range, making this ambigous with the range support */ \
|
||||
!defined( __cpp_lib_optional_range_support )
|
||||
#include <optional>
|
||||
namespace Catch {
|
||||
template<typename T>
|
||||
@@ -630,17 +634,21 @@ struct ratio_string<std::milli> {
|
||||
};
|
||||
}
|
||||
|
||||
#include <catch2/interfaces/catch_interfaces_registry_hub.hpp>
|
||||
|
||||
#define INTERNAL_CATCH_REGISTER_ENUM( enumName, ... ) \
|
||||
namespace Catch { \
|
||||
template<> struct StringMaker<enumName> { \
|
||||
static std::string convert( enumName value ) { \
|
||||
static const auto& enumInfo = ::Catch::getMutableRegistryHub().getMutableEnumValuesRegistry().registerEnum( #enumName, #__VA_ARGS__, { __VA_ARGS__ } ); \
|
||||
return static_cast<std::string>(enumInfo.lookup( static_cast<int>( value ) )); \
|
||||
} \
|
||||
}; \
|
||||
}
|
||||
#define INTERNAL_CATCH_REGISTER_ENUM( enumName, ... ) \
|
||||
namespace Catch { \
|
||||
template <> \
|
||||
struct StringMaker<enumName> { \
|
||||
static std::string convert( enumName value ) { \
|
||||
CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \
|
||||
CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
|
||||
static const auto enumInfo = ::Catch::Detail::makeEnumInfo( \
|
||||
#enumName, #__VA_ARGS__, { __VA_ARGS__ } ); \
|
||||
CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION \
|
||||
return static_cast<std::string>( \
|
||||
enumInfo.lookup( static_cast<int64_t>( value ) ) ); \
|
||||
} \
|
||||
}; \
|
||||
}
|
||||
|
||||
#define CATCH_REGISTER_ENUM( enumName, ... ) INTERNAL_CATCH_REGISTER_ENUM( enumName, __VA_ARGS__ )
|
||||
|
||||
|
||||
@@ -22,7 +22,7 @@ namespace Catch {
|
||||
|
||||
class ExceptionTranslatorRegistrar {
|
||||
template<typename T>
|
||||
class ExceptionTranslator : public IExceptionTranslator {
|
||||
class ExceptionTranslator final : public IExceptionTranslator {
|
||||
public:
|
||||
|
||||
constexpr ExceptionTranslator( std::string(*translateFunction)( T const& ) )
|
||||
|
||||
@@ -36,7 +36,7 @@ namespace Catch {
|
||||
}
|
||||
|
||||
Version const& libraryVersion() {
|
||||
static Version version( 3, 14, 0, "", 0 );
|
||||
static Version version( 3, 15, 0, "", 0 );
|
||||
return version;
|
||||
}
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
#define CATCH_VERSION_MACROS_HPP_INCLUDED
|
||||
|
||||
#define CATCH_VERSION_MAJOR 3
|
||||
#define CATCH_VERSION_MINOR 14
|
||||
#define CATCH_VERSION_MINOR 15
|
||||
#define CATCH_VERSION_PATCH 0
|
||||
|
||||
#endif // CATCH_VERSION_MACROS_HPP_INCLUDED
|
||||
|
||||
@@ -24,7 +24,6 @@
|
||||
|
||||
#include <catch2/interfaces/catch_interfaces_capture.hpp>
|
||||
#include <catch2/interfaces/catch_interfaces_config.hpp>
|
||||
#include <catch2/interfaces/catch_interfaces_enum_values_registry.hpp>
|
||||
#include <catch2/interfaces/catch_interfaces_exception.hpp>
|
||||
#include <catch2/interfaces/catch_interfaces_generatortracker.hpp>
|
||||
#include <catch2/interfaces/catch_interfaces_registry_hub.hpp>
|
||||
|
||||
@@ -22,8 +22,6 @@ namespace Catch {
|
||||
struct AssertionInfo;
|
||||
struct SectionInfo;
|
||||
struct SectionEndInfo;
|
||||
struct MessageInfo;
|
||||
struct MessageBuilder;
|
||||
struct Counts;
|
||||
struct AssertionReaction;
|
||||
struct SourceLineInfo;
|
||||
@@ -63,11 +61,6 @@ namespace Catch {
|
||||
virtual void benchmarkEnded( BenchmarkStats<> const& stats ) = 0;
|
||||
virtual void benchmarkFailed( StringRef error ) = 0;
|
||||
|
||||
static void pushScopedMessage( MessageInfo&& message );
|
||||
static void popScopedMessage( unsigned int messageId );
|
||||
static void addUnscopedMessage( MessageInfo&& message );
|
||||
static void emplaceUnscopedMessage( MessageBuilder&& builder );
|
||||
|
||||
virtual void handleFatalErrorCondition( StringRef message ) = 0;
|
||||
|
||||
virtual void handleExpr
|
||||
@@ -93,9 +86,6 @@ namespace Catch {
|
||||
ResultWas::OfType resultType,
|
||||
AssertionReaction &reaction ) = 0;
|
||||
|
||||
|
||||
virtual bool lastAssertionPassed() = 0;
|
||||
|
||||
// Deprecated, do not use:
|
||||
virtual std::string getCurrentTestName() const = 0;
|
||||
virtual const AssertionResult* getLastResult() const = 0;
|
||||
|
||||
@@ -64,7 +64,7 @@ namespace Catch {
|
||||
class IStream;
|
||||
struct PathFilter;
|
||||
|
||||
class IConfig : public Detail::NonCopyable {
|
||||
class IConfig : Detail::NonCopyable {
|
||||
public:
|
||||
virtual ~IConfig();
|
||||
|
||||
|
||||
@@ -1,47 +0,0 @@
|
||||
|
||||
// Copyright Catch2 Authors
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// (See accompanying file LICENSE.txt or copy at
|
||||
// https://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
// SPDX-License-Identifier: BSL-1.0
|
||||
#ifndef CATCH_INTERFACES_ENUM_VALUES_REGISTRY_HPP_INCLUDED
|
||||
#define CATCH_INTERFACES_ENUM_VALUES_REGISTRY_HPP_INCLUDED
|
||||
|
||||
#include <catch2/internal/catch_stringref.hpp>
|
||||
|
||||
#include <vector>
|
||||
|
||||
namespace Catch {
|
||||
|
||||
namespace Detail {
|
||||
struct EnumInfo {
|
||||
StringRef m_name;
|
||||
std::vector<std::pair<int, StringRef>> m_values;
|
||||
|
||||
~EnumInfo();
|
||||
|
||||
StringRef lookup( int value ) const;
|
||||
};
|
||||
} // namespace Detail
|
||||
|
||||
class IMutableEnumValuesRegistry {
|
||||
public:
|
||||
virtual ~IMutableEnumValuesRegistry(); // = default;
|
||||
|
||||
virtual Detail::EnumInfo const& registerEnum( StringRef enumName, StringRef allEnums, std::vector<int> const& values ) = 0;
|
||||
|
||||
template<typename E>
|
||||
Detail::EnumInfo const& registerEnum( StringRef enumName, StringRef allEnums, std::initializer_list<E> values ) {
|
||||
static_assert(sizeof(int) >= sizeof(E), "Cannot serialize enum to int");
|
||||
std::vector<int> intValues;
|
||||
intValues.reserve( values.size() );
|
||||
for( auto enumValue : values )
|
||||
intValues.push_back( static_cast<int>( enumValue ) );
|
||||
return registerEnum( enumName, allEnums, intValues );
|
||||
}
|
||||
};
|
||||
|
||||
} // Catch
|
||||
|
||||
#endif // CATCH_INTERFACES_ENUM_VALUES_REGISTRY_HPP_INCLUDED
|
||||
@@ -53,7 +53,6 @@ namespace Catch {
|
||||
virtual void registerTranslator( Detail::unique_ptr<IExceptionTranslator>&& translator ) = 0;
|
||||
virtual void registerTagAlias( std::string const& alias, std::string const& tag, SourceLineInfo const& lineInfo ) = 0;
|
||||
virtual void registerStartupException() noexcept = 0;
|
||||
virtual IMutableEnumValuesRegistry& getMutableEnumValuesRegistry() = 0;
|
||||
};
|
||||
|
||||
IRegistryHub const& getRegistryHub();
|
||||
|
||||
@@ -6,21 +6,28 @@
|
||||
|
||||
// SPDX-License-Identifier: BSL-1.0
|
||||
#include <catch2/internal/catch_assertion_handler.hpp>
|
||||
#include <catch2/interfaces/catch_interfaces_capture.hpp>
|
||||
#include <catch2/interfaces/catch_interfaces_config.hpp>
|
||||
#include <catch2/interfaces/catch_interfaces_registry_hub.hpp>
|
||||
#include <catch2/internal/catch_context.hpp>
|
||||
#include <catch2/internal/catch_debugger.hpp>
|
||||
#include <catch2/internal/catch_run_context.hpp>
|
||||
#include <catch2/internal/catch_test_failure_exception.hpp>
|
||||
#include <catch2/matchers/catch_matchers_string.hpp>
|
||||
|
||||
namespace Catch {
|
||||
|
||||
void AssertionHandler::finishIncomplete() {
|
||||
m_resultCapture.handleIncomplete( m_assertionInfo );
|
||||
}
|
||||
|
||||
AssertionHandler::AssertionHandler
|
||||
( StringRef macroName,
|
||||
SourceLineInfo const& lineInfo,
|
||||
StringRef capturedExpression,
|
||||
ResultDisposition::Flags resultDisposition )
|
||||
: m_assertionInfo{ macroName, lineInfo, capturedExpression, resultDisposition },
|
||||
m_resultCapture( getResultCapture() )
|
||||
m_resultCapture( static_cast<RunContext&>(getResultCapture()) )
|
||||
{
|
||||
m_resultCapture.notifyAssertionStarted( m_assertionInfo );
|
||||
}
|
||||
|
||||
@@ -10,12 +10,13 @@
|
||||
|
||||
#include <catch2/catch_assertion_info.hpp>
|
||||
#include <catch2/internal/catch_decomposer.hpp>
|
||||
#include <catch2/interfaces/catch_interfaces_capture.hpp>
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace Catch {
|
||||
|
||||
class RunContext;
|
||||
|
||||
struct AssertionReaction {
|
||||
bool shouldDebugBreak = false;
|
||||
bool shouldThrow = false;
|
||||
@@ -26,7 +27,12 @@ namespace Catch {
|
||||
AssertionInfo m_assertionInfo;
|
||||
AssertionReaction m_reaction;
|
||||
bool m_completed = false;
|
||||
IResultCapture& m_resultCapture;
|
||||
// Since all uses are hidden in the .cpp file, we can directly use
|
||||
// the final type and avoid going through virtual dispatch, without
|
||||
// massive compilation time overhead.
|
||||
RunContext& m_resultCapture;
|
||||
|
||||
void finishIncomplete();
|
||||
|
||||
public:
|
||||
AssertionHandler
|
||||
@@ -35,9 +41,9 @@ namespace Catch {
|
||||
StringRef capturedExpression,
|
||||
ResultDisposition::Flags resultDisposition );
|
||||
~AssertionHandler() {
|
||||
if ( !m_completed ) {
|
||||
m_resultCapture.handleIncomplete( m_assertionInfo );
|
||||
}
|
||||
// We want the common fast path inlinable, and the virtual
|
||||
// dispatch in a function in single TU.
|
||||
if ( !m_completed ) { finishIncomplete(); }
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -27,16 +27,24 @@
|
||||
#include <catch2/internal/catch_platform.hpp>
|
||||
#include <catch2/catch_user_config.hpp>
|
||||
|
||||
#ifdef __cplusplus
|
||||
#if (__cplusplus >= 201703L) || (defined(_MSVC_LANG) && _MSVC_LANG >= 201703L)
|
||||
# define CATCH_CPP17_OR_GREATER
|
||||
#endif
|
||||
|
||||
# if (__cplusplus >= 201703L) || (defined(_MSVC_LANG) && _MSVC_LANG >= 201703L)
|
||||
# define CATCH_CPP17_OR_GREATER
|
||||
# endif
|
||||
|
||||
# if (__cplusplus >= 202002L) || (defined(_MSVC_LANG) && _MSVC_LANG >= 202002L)
|
||||
# define CATCH_CPP20_OR_GREATER
|
||||
# endif
|
||||
#if (__cplusplus >= 202002L) || (defined(_MSVC_LANG) && _MSVC_LANG >= 202002L)
|
||||
# define CATCH_CPP20_OR_GREATER
|
||||
#endif
|
||||
|
||||
// Matchers are only constexpr-able in C++20
|
||||
#if defined( CATCH_CPP20_OR_GREATER ) && \
|
||||
defined( __cpp_constexpr_dynamic_alloc ) && \
|
||||
__cpp_constexpr_dynamic_alloc >= 201907L && \
|
||||
/* GCC < 13 define the feature macro, but compiler bugs stop us from using it */ \
|
||||
( !defined( __GNUC__ ) || __GNUC__ >= 13 || defined(__clang__) )
|
||||
# define CATCH_INTERNAL_CONSTEXPR_MATCHERS_ENABLED
|
||||
# define CATCH_DESTRUCTOR_CONSTEXPR constexpr
|
||||
#else
|
||||
# define CATCH_DESTRUCTOR_CONSTEXPR
|
||||
#endif
|
||||
|
||||
// Only GCC compiler should be used in this block, so other compilers trying to
|
||||
|
||||
@@ -193,7 +193,7 @@ namespace Catch {
|
||||
void formatReconstructedExpression( std::ostream &os, std::string const& lhs, StringRef op, std::string const& rhs );
|
||||
|
||||
template<typename LhsT, typename RhsT>
|
||||
class BinaryExpr : public ITransientExpression {
|
||||
class BinaryExpr final : public ITransientExpression {
|
||||
LhsT m_lhs;
|
||||
StringRef m_op;
|
||||
RhsT m_rhs;
|
||||
@@ -269,7 +269,7 @@ namespace Catch {
|
||||
};
|
||||
|
||||
template<typename LhsT>
|
||||
class UnaryExpr : public ITransientExpression {
|
||||
class UnaryExpr final : public ITransientExpression {
|
||||
LhsT m_lhs;
|
||||
|
||||
void streamReconstructedExpression( std::ostream &os ) const override {
|
||||
|
||||
+10
-18
@@ -5,15 +5,14 @@
|
||||
// https://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
// SPDX-License-Identifier: BSL-1.0
|
||||
#include <catch2/internal/catch_enum_values_registry.hpp>
|
||||
|
||||
#include <catch2/internal/catch_enum_info.hpp>
|
||||
#include <catch2/internal/catch_string_manip.hpp>
|
||||
|
||||
#include <cassert>
|
||||
|
||||
namespace Catch {
|
||||
|
||||
IMutableEnumValuesRegistry::~IMutableEnumValuesRegistry() = default;
|
||||
|
||||
namespace Detail {
|
||||
|
||||
namespace {
|
||||
@@ -39,9 +38,7 @@ namespace Catch {
|
||||
return parsed;
|
||||
}
|
||||
|
||||
EnumInfo::~EnumInfo() = default;
|
||||
|
||||
StringRef EnumInfo::lookup( int value ) const {
|
||||
StringRef EnumInfo::lookup( int64_t value ) const {
|
||||
for( auto const& valueToName : m_values ) {
|
||||
if( valueToName.first == value )
|
||||
return valueToName.second;
|
||||
@@ -49,25 +46,20 @@ namespace Catch {
|
||||
return "{** unexpected enum value **}"_sr;
|
||||
}
|
||||
|
||||
Catch::Detail::unique_ptr<EnumInfo> makeEnumInfo( StringRef enumName, StringRef allValueNames, std::vector<int> const& values ) {
|
||||
auto enumInfo = Catch::Detail::make_unique<EnumInfo>();
|
||||
enumInfo->m_name = enumName;
|
||||
enumInfo->m_values.reserve( values.size() );
|
||||
EnumInfo makeEnumInfo( StringRef enumName, StringRef allValueNames, std::vector<int64_t> const& values ) {
|
||||
EnumInfo enumInfo;
|
||||
enumInfo.m_name = enumName;
|
||||
enumInfo.m_values.reserve( values.size() );
|
||||
|
||||
const auto valueNames = Catch::Detail::parseEnums( allValueNames );
|
||||
assert( valueNames.size() == values.size() );
|
||||
std::size_t i = 0;
|
||||
for( auto value : values )
|
||||
enumInfo->m_values.emplace_back(value, valueNames[i++]);
|
||||
for (size_t i = 0; i < values.size(); ++i) {
|
||||
enumInfo.m_values.emplace_back( values[i], valueNames[i] );
|
||||
}
|
||||
|
||||
return enumInfo;
|
||||
}
|
||||
|
||||
EnumInfo const& EnumValuesRegistry::registerEnum( StringRef enumName, StringRef allValueNames, std::vector<int> const& values ) {
|
||||
m_enumInfos.push_back(makeEnumInfo(enumName, allValueNames, values));
|
||||
return *m_enumInfos.back();
|
||||
}
|
||||
|
||||
} // Detail
|
||||
} // Catch
|
||||
|
||||
@@ -0,0 +1,48 @@
|
||||
|
||||
// Copyright Catch2 Authors
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// (See accompanying file LICENSE.txt or copy at
|
||||
// https://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
// SPDX-License-Identifier: BSL-1.0
|
||||
#ifndef CATCH_ENUM_INFO_HPP_INCLUDED
|
||||
#define CATCH_ENUM_INFO_HPP_INCLUDED
|
||||
|
||||
#include <catch2/internal/catch_stringref.hpp>
|
||||
|
||||
#include <cstdint>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
namespace Catch {
|
||||
namespace Detail {
|
||||
|
||||
struct EnumInfo {
|
||||
StringRef m_name;
|
||||
std::vector<std::pair<int64_t, StringRef>> m_values;
|
||||
|
||||
StringRef lookup( int64_t value ) const;
|
||||
};
|
||||
|
||||
EnumInfo makeEnumInfo( StringRef enumName,
|
||||
StringRef allValueNames,
|
||||
std::vector<int64_t> const& values );
|
||||
template <typename E>
|
||||
Detail::EnumInfo makeEnumInfo( StringRef enumName,
|
||||
StringRef allEnums,
|
||||
std::initializer_list<E> values ) {
|
||||
static_assert( sizeof( int64_t ) >= sizeof( E ),
|
||||
"Cannot serialize enum to int64_t" );
|
||||
std::vector<int64_t> intValues;
|
||||
intValues.reserve( values.size() );
|
||||
for ( auto enumValue : values )
|
||||
intValues.push_back( static_cast<int64_t>( enumValue ) );
|
||||
return makeEnumInfo( enumName, allEnums, intValues );
|
||||
}
|
||||
|
||||
std::vector<StringRef> parseEnums( StringRef enums );
|
||||
|
||||
} // namespace Detail
|
||||
} // namespace Catch
|
||||
|
||||
#endif // CATCH_ENUM_INFO_HPP_INCLUDED
|
||||
@@ -1,36 +0,0 @@
|
||||
|
||||
// Copyright Catch2 Authors
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// (See accompanying file LICENSE.txt or copy at
|
||||
// https://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
// SPDX-License-Identifier: BSL-1.0
|
||||
#ifndef CATCH_ENUM_VALUES_REGISTRY_HPP_INCLUDED
|
||||
#define CATCH_ENUM_VALUES_REGISTRY_HPP_INCLUDED
|
||||
|
||||
#include <catch2/interfaces/catch_interfaces_enum_values_registry.hpp>
|
||||
#include <catch2/internal/catch_unique_ptr.hpp>
|
||||
#include <catch2/internal/catch_stringref.hpp>
|
||||
|
||||
#include <vector>
|
||||
|
||||
namespace Catch {
|
||||
|
||||
namespace Detail {
|
||||
|
||||
Catch::Detail::unique_ptr<EnumInfo> makeEnumInfo( StringRef enumName, StringRef allValueNames, std::vector<int> const& values );
|
||||
|
||||
class EnumValuesRegistry : public IMutableEnumValuesRegistry {
|
||||
|
||||
std::vector<Catch::Detail::unique_ptr<EnumInfo>> m_enumInfos;
|
||||
|
||||
EnumInfo const& registerEnum( StringRef enumName, StringRef allValueNames, std::vector<int> const& values) override;
|
||||
};
|
||||
|
||||
std::vector<StringRef> parseEnums( StringRef enums );
|
||||
|
||||
} // Detail
|
||||
|
||||
} // Catch
|
||||
|
||||
#endif // CATCH_ENUM_VALUES_REGISTRY_HPP_INCLUDED
|
||||
@@ -15,7 +15,7 @@
|
||||
|
||||
namespace Catch {
|
||||
|
||||
class ExceptionTranslatorRegistry : public IExceptionTranslatorRegistry {
|
||||
class ExceptionTranslatorRegistry final : public IExceptionTranslatorRegistry {
|
||||
public:
|
||||
~ExceptionTranslatorRegistry() override;
|
||||
void registerTranslator( Detail::unique_ptr<IExceptionTranslator>&& translator );
|
||||
|
||||
@@ -33,7 +33,7 @@ namespace Catch {
|
||||
namespace {
|
||||
//! A no-op implementation, used if no reporter wants output
|
||||
//! redirection.
|
||||
class NoopRedirect : public OutputRedirect {
|
||||
class NoopRedirect final : public OutputRedirect {
|
||||
void activateImpl() override {}
|
||||
void deactivateImpl() override {}
|
||||
std::string getStdout() override { return {}; }
|
||||
@@ -70,7 +70,7 @@ namespace Catch {
|
||||
* Redirects the `std::cout`, `std::cerr`, `std::clog` streams,
|
||||
* but does not touch the actual `stdout`/`stderr` file descriptors.
|
||||
*/
|
||||
class StreamRedirect : public OutputRedirect {
|
||||
class StreamRedirect final : public OutputRedirect {
|
||||
ReusableStringStream m_redirectedOut, m_redirectedErr;
|
||||
RedirectedStreamNew m_cout, m_cerr, m_clog;
|
||||
|
||||
@@ -181,7 +181,7 @@ namespace Catch {
|
||||
* Works by replacing the file descriptors numbered 1 and 2
|
||||
* with an open temporary file.
|
||||
*/
|
||||
class FileRedirect : public OutputRedirect {
|
||||
class FileRedirect final : public OutputRedirect {
|
||||
TempFile m_outFile, m_errFile;
|
||||
int m_originalOut = -1;
|
||||
int m_originalErr = -1;
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
#include <catch2/generators/catch_generators_throw.hpp>
|
||||
#include <catch2/interfaces/catch_interfaces_config.hpp>
|
||||
#include <catch2/interfaces/catch_interfaces_generatortracker.hpp>
|
||||
#include <catch2/interfaces/catch_interfaces_registry_hub.hpp>
|
||||
#include <catch2/interfaces/catch_interfaces_reporter.hpp>
|
||||
#include <catch2/internal/catch_compiler_capabilities.hpp>
|
||||
#include <catch2/internal/catch_context.hpp>
|
||||
@@ -308,6 +309,25 @@ namespace Catch {
|
||||
}
|
||||
CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION
|
||||
|
||||
|
||||
void pushScopedMessage( MessageInfo&& message ) {
|
||||
Detail::g_messageHolder().addScopedMessage( CATCH_MOVE( message ) );
|
||||
}
|
||||
|
||||
void popScopedMessage( unsigned int messageId ) {
|
||||
Detail::g_messageHolder().removeMessage( messageId );
|
||||
}
|
||||
|
||||
void emplaceUnscopedMessage( MessageBuilder&& builder ) {
|
||||
Detail::g_messageHolder().addUnscopedMessage( CATCH_MOVE( builder ) );
|
||||
}
|
||||
|
||||
void addUnscopedMessage( MessageInfo&& message ) {
|
||||
Detail::g_messageHolder().addUnscopedMessage( CATCH_MOVE( message ) );
|
||||
}
|
||||
|
||||
bool lastAssertionPassed() { return Detail::g_lastAssertionPassed; }
|
||||
|
||||
} // namespace Detail
|
||||
|
||||
RunContext::RunContext(IConfig const* _config, IEventListenerPtr&& reporter)
|
||||
@@ -441,14 +461,13 @@ namespace Catch {
|
||||
Detail::g_lastAssertionPassed = true;
|
||||
} else if (!result.succeeded()) {
|
||||
Detail::g_lastAssertionPassed = false;
|
||||
if (result.isOk()) {
|
||||
}
|
||||
else if( m_activeTestCase->getTestCaseInfo().okToFail() ) // Read from a shared state established before the threads could start, this is fine
|
||||
if (result.isOk()) {}
|
||||
else if( m_activeTestCase->getTestCaseInfo().okToFail() ) { // Read from a shared state established before the threads could start, this is fine
|
||||
m_atomicAssertionCount.failedButOk++;
|
||||
else
|
||||
} else {
|
||||
m_atomicAssertionCount.failed++;
|
||||
}
|
||||
else {
|
||||
}
|
||||
} else {
|
||||
Detail::g_lastAssertionPassed = true;
|
||||
}
|
||||
|
||||
@@ -630,7 +649,7 @@ namespace Catch {
|
||||
// and since IResultCapture::getLastResult is deprecated,
|
||||
// we will leave it as is, until it is finally removed.
|
||||
Detail::LockGuard _( m_assertionMutex );
|
||||
return &(*m_lastResult);
|
||||
return &*m_lastResult;
|
||||
}
|
||||
|
||||
void RunContext::exceptionEarlyReported() {
|
||||
@@ -704,10 +723,6 @@ namespace Catch {
|
||||
m_reporter->testRunEnded(TestRunStats(m_runInfo, m_totals, false));
|
||||
}
|
||||
|
||||
bool RunContext::lastAssertionPassed() {
|
||||
return Detail::g_lastAssertionPassed;
|
||||
}
|
||||
|
||||
void RunContext::assertionPassedFastPath(SourceLineInfo lineInfo) {
|
||||
// We want to save the line info for better experience with unexpected assertions
|
||||
Detail::g_lastKnownLineInfo = lineInfo;
|
||||
@@ -886,7 +901,7 @@ namespace Catch {
|
||||
}
|
||||
|
||||
void RunContext::populateReaction( AssertionReaction& reaction,
|
||||
bool has_normal_disposition ) {
|
||||
bool has_normal_disposition ) const {
|
||||
reaction.shouldDebugBreak = m_shouldDebugBreak;
|
||||
reaction.shouldThrow = aborting() || has_normal_disposition;
|
||||
}
|
||||
@@ -937,22 +952,6 @@ namespace Catch {
|
||||
}
|
||||
}
|
||||
|
||||
void IResultCapture::pushScopedMessage( MessageInfo&& message ) {
|
||||
Detail::g_messageHolder().addScopedMessage( CATCH_MOVE( message ) );
|
||||
}
|
||||
|
||||
void IResultCapture::popScopedMessage( unsigned int messageId ) {
|
||||
Detail::g_messageHolder().removeMessage( messageId );
|
||||
}
|
||||
|
||||
void IResultCapture::emplaceUnscopedMessage( MessageBuilder&& builder ) {
|
||||
Detail::g_messageHolder().addUnscopedMessage( CATCH_MOVE( builder ) );
|
||||
}
|
||||
|
||||
void IResultCapture::addUnscopedMessage( MessageInfo&& message ) {
|
||||
Detail::g_messageHolder().addUnscopedMessage( CATCH_MOVE( message ) );
|
||||
}
|
||||
|
||||
void seedRng(IConfig const& config) {
|
||||
sharedRng().seed(config.rngSeed());
|
||||
}
|
||||
|
||||
@@ -102,8 +102,6 @@ namespace Catch {
|
||||
|
||||
void handleFatalErrorCondition( StringRef message ) override;
|
||||
|
||||
bool lastAssertionPassed() override;
|
||||
|
||||
public:
|
||||
// !TBD We need to do this another way!
|
||||
bool aborting() const;
|
||||
@@ -125,7 +123,7 @@ namespace Catch {
|
||||
ITransientExpression const *expr,
|
||||
bool negated );
|
||||
|
||||
void populateReaction( AssertionReaction& reaction, bool has_normal_disposition );
|
||||
void populateReaction( AssertionReaction& reaction, bool has_normal_disposition ) const;
|
||||
|
||||
// Creates dummy info for unexpected exceptions/fatal errors,
|
||||
// where we do not have the access to one, but we still need
|
||||
|
||||
@@ -20,7 +20,7 @@ namespace Catch {
|
||||
|
||||
|
||||
template<typename SingletonImplT, typename InterfaceT = SingletonImplT, typename MutableInterfaceT = InterfaceT>
|
||||
class Singleton : SingletonImplT, public ISingleton {
|
||||
class Singleton final : SingletonImplT, public ISingleton {
|
||||
|
||||
static auto getInternal() -> Singleton* {
|
||||
static Singleton* s_instance = nullptr;
|
||||
|
||||
@@ -16,10 +16,11 @@ namespace Catch {
|
||||
|
||||
TagAlias const* TagAliasRegistry::find( std::string const& alias ) const {
|
||||
auto it = m_registry.find( alias );
|
||||
if( it != m_registry.end() )
|
||||
return &(it->second);
|
||||
else
|
||||
if ( it != m_registry.end() ) {
|
||||
return &it->second;
|
||||
} else {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
std::string TagAliasRegistry::expandAliases( std::string const& unexpandedTestSpec ) const {
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
namespace Catch {
|
||||
struct SourceLineInfo;
|
||||
|
||||
class TagAliasRegistry : public ITagAliasRegistry {
|
||||
class TagAliasRegistry final : public ITagAliasRegistry {
|
||||
public:
|
||||
~TagAliasRegistry() override;
|
||||
TagAlias const* find( std::string const& alias ) const override;
|
||||
|
||||
@@ -28,7 +28,7 @@ namespace Catch {
|
||||
std::vector<TestCaseHandle> filterTests( std::vector<TestCaseHandle> const& testCases, TestSpec const& testSpec, IConfig const& config );
|
||||
std::vector<TestCaseHandle> const& getAllTestCasesSorted( IConfig const& config );
|
||||
|
||||
class TestRegistry : public ITestCaseRegistry {
|
||||
class TestRegistry final : public ITestCaseRegistry {
|
||||
public:
|
||||
void registerTest( Detail::unique_ptr<TestCaseInfo> testInfo, Detail::unique_ptr<ITestInvoker> testInvoker );
|
||||
|
||||
|
||||
@@ -14,7 +14,7 @@ namespace Catch {
|
||||
|
||||
void throw_test_failure_exception() {
|
||||
#if !defined( CATCH_CONFIG_DISABLE_EXCEPTIONS )
|
||||
throw TestFailureException{};
|
||||
throw TestFailureException{}; //NOLINT(bugprone-std-exception-baseclass)
|
||||
#else
|
||||
CATCH_ERROR( "Test failure requires aborting test!" );
|
||||
#endif
|
||||
@@ -22,7 +22,7 @@ namespace Catch {
|
||||
|
||||
void throw_test_skip_exception() {
|
||||
#if !defined( CATCH_CONFIG_DISABLE_EXCEPTIONS )
|
||||
throw Catch::TestSkipException();
|
||||
throw Catch::TestSkipException(); //NOLINT(bugprone-std-exception-baseclass)
|
||||
#else
|
||||
CATCH_ERROR( "Explicitly skipping tests during runtime requires exceptions" );
|
||||
#endif
|
||||
|
||||
@@ -11,10 +11,16 @@
|
||||
#include <catch2/catch_user_config.hpp>
|
||||
#include <catch2/internal/catch_assertion_handler.hpp>
|
||||
#include <catch2/internal/catch_preprocessor_internal_stringify.hpp>
|
||||
#include <catch2/interfaces/catch_interfaces_capture.hpp>
|
||||
#include <catch2/internal/catch_stringref.hpp>
|
||||
#include <catch2/internal/catch_source_line_info.hpp>
|
||||
|
||||
namespace Catch {
|
||||
namespace Detail {
|
||||
// Defined in catch_run_context.cpp, where the thread-local data lives.
|
||||
bool lastAssertionPassed();
|
||||
}
|
||||
}
|
||||
|
||||
// We need this suppression to leak, because it took until GCC 10
|
||||
// for the front end to handle local suppression via _Pragma properly
|
||||
#if defined(__GNUC__) && !defined(__clang__) && !defined(__ICC) && __GNUC__ <= 9
|
||||
@@ -57,12 +63,12 @@
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
#define INTERNAL_CATCH_IF( macroName, resultDisposition, ... ) \
|
||||
INTERNAL_CATCH_TEST( macroName, resultDisposition, __VA_ARGS__ ); \
|
||||
if( Catch::getResultCapture().lastAssertionPassed() )
|
||||
if( Catch::Detail::lastAssertionPassed() )
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
#define INTERNAL_CATCH_ELSE( macroName, resultDisposition, ... ) \
|
||||
INTERNAL_CATCH_TEST( macroName, resultDisposition, __VA_ARGS__ ); \
|
||||
if( !Catch::getResultCapture().lastAssertionPassed() )
|
||||
if( !Catch::Detail::lastAssertionPassed() )
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
#define INTERNAL_CATCH_NO_THROW( macroName, resultDisposition, ... ) \
|
||||
|
||||
@@ -29,7 +29,7 @@
|
||||
namespace Catch {
|
||||
|
||||
template<typename C>
|
||||
class TestInvokerAsMethod : public ITestInvoker {
|
||||
class TestInvokerAsMethod final : public ITestInvoker {
|
||||
void (C::*m_testAsMethod)();
|
||||
public:
|
||||
constexpr TestInvokerAsMethod( void ( C::*testAsMethod )() ) noexcept:
|
||||
@@ -49,7 +49,7 @@ Detail::unique_ptr<ITestInvoker> makeTestInvoker( void (C::*testAsMethod)() ) {
|
||||
}
|
||||
|
||||
template <typename C>
|
||||
class TestInvokerFixture : public ITestInvoker {
|
||||
class TestInvokerFixture final : public ITestInvoker {
|
||||
void ( C::*m_testAsMethod )() const;
|
||||
Detail::unique_ptr<C> m_fixture = nullptr;
|
||||
|
||||
@@ -124,7 +124,7 @@ struct AutoReg : Detail::NonCopyable {
|
||||
namespace Catch {
|
||||
namespace Detail {
|
||||
struct DummyUse {
|
||||
DummyUse( void ( * )( int ), Catch::NameAndTags const& );
|
||||
DummyUse( void ( * )( int ), Catch::NameAndTags const& ) noexcept;
|
||||
};
|
||||
} // namespace Detail
|
||||
} // namespace Catch
|
||||
|
||||
@@ -148,8 +148,8 @@ namespace Catch {
|
||||
m_it--;
|
||||
}
|
||||
// Skip back over UTF-8 continuation bytes to the leading byte
|
||||
while ( isUtf8ContinuationByte( *m_it ) ) {
|
||||
assert( m_it != m_string->begin() );
|
||||
while ( m_it != m_string->begin() &&
|
||||
isUtf8ContinuationByte( *m_it ) ) {
|
||||
m_it--;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,13 +13,13 @@ namespace Catch {
|
||||
namespace Matchers {
|
||||
|
||||
std::string MatcherUntypedBase::toString() const {
|
||||
if (m_cachedToString.empty()) {
|
||||
m_cachedToString = describe();
|
||||
}
|
||||
return m_cachedToString;
|
||||
return describe();
|
||||
}
|
||||
|
||||
MatcherUntypedBase::~MatcherUntypedBase() = default;
|
||||
std::string MatcherUntypedBase::describe() const {
|
||||
using namespace std::string_literals;
|
||||
return "Undescribed matcher"s;
|
||||
}
|
||||
|
||||
} // namespace Matchers
|
||||
} // namespace Catch
|
||||
|
||||
@@ -20,10 +20,10 @@ namespace Matchers {
|
||||
|
||||
class MatcherUntypedBase {
|
||||
public:
|
||||
MatcherUntypedBase() = default;
|
||||
constexpr MatcherUntypedBase() = default;
|
||||
|
||||
MatcherUntypedBase(MatcherUntypedBase const&) = default;
|
||||
MatcherUntypedBase(MatcherUntypedBase&&) = default;
|
||||
constexpr MatcherUntypedBase(MatcherUntypedBase const&) = default;
|
||||
constexpr MatcherUntypedBase(MatcherUntypedBase&&) = default;
|
||||
|
||||
MatcherUntypedBase& operator = (MatcherUntypedBase const&) = delete;
|
||||
MatcherUntypedBase& operator = (MatcherUntypedBase&&) = delete;
|
||||
@@ -31,9 +31,9 @@ namespace Matchers {
|
||||
std::string toString() const;
|
||||
|
||||
protected:
|
||||
virtual ~MatcherUntypedBase(); // = default;
|
||||
virtual std::string describe() const = 0;
|
||||
mutable std::string m_cachedToString;
|
||||
CATCH_DESTRUCTOR_CONSTEXPR virtual ~MatcherUntypedBase() = default;
|
||||
//! Should be overridden, but we provide default "undescribed" impl
|
||||
virtual std::string describe() const;
|
||||
};
|
||||
|
||||
|
||||
@@ -215,6 +215,19 @@ namespace Matchers {
|
||||
#define CATCH_CHECK_THAT( arg, matcher ) INTERNAL_CHECK_THAT( "CATCH_CHECK_THAT", matcher, Catch::ResultDisposition::ContinueOnFailure, arg )
|
||||
#define CATCH_REQUIRE_THAT( arg, matcher ) INTERNAL_CHECK_THAT( "CATCH_REQUIRE_THAT", matcher, Catch::ResultDisposition::Normal, arg )
|
||||
|
||||
#if !defined(CATCH_CONFIG_RUNTIME_STATIC_REQUIRE)
|
||||
#define CATCH_STATIC_REQUIRE_THAT( arg, matcher ) \
|
||||
static_assert( ( matcher ).match( arg ), #matcher ".match( " #arg " )"); \
|
||||
CATCH_SUCCEED( #matcher ".match( " #arg " )" )
|
||||
#define CATCH_STATIC_CHECK_THAT( arg, matcher ) \
|
||||
static_assert( ( matcher ).match( arg ), #matcher ".match( " #arg " )"); \
|
||||
CATCH_SUCCEED( #matcher ".match( " #arg " )" )
|
||||
#else
|
||||
#define CATCH_STATIC_REQUIRE_THAT( arg, matcher ) CATCH_REQUIRE_THAT( arg, matcher )
|
||||
#define CATCH_STATIC_CHECK_THAT( arg, matcher ) CATCH_CHECK_THAT( arg, matcher )
|
||||
#endif
|
||||
|
||||
|
||||
#elif defined(CATCH_CONFIG_PREFIX_ALL) && defined(CATCH_CONFIG_DISABLE)
|
||||
|
||||
#define CATCH_REQUIRE_THROWS_WITH( expr, matcher ) (void)(0)
|
||||
@@ -226,6 +239,9 @@ namespace Matchers {
|
||||
#define CATCH_CHECK_THAT( arg, matcher ) (void)(0)
|
||||
#define CATCH_REQUIRE_THAT( arg, matcher ) (void)(0)
|
||||
|
||||
#define CATCH_STATIC_REQUIRE_THAT( arg, matcher ) (void)(0)
|
||||
#define CATCH_STATIC_CHECK_THAT( arg, matcher ) (void)(0)
|
||||
|
||||
#elif !defined(CATCH_CONFIG_PREFIX_ALL) && !defined(CATCH_CONFIG_DISABLE)
|
||||
|
||||
#define REQUIRE_THROWS_WITH( expr, matcher ) INTERNAL_CATCH_THROWS_STR_MATCHES( "REQUIRE_THROWS_WITH", Catch::ResultDisposition::Normal, matcher, expr )
|
||||
@@ -237,6 +253,19 @@ namespace Matchers {
|
||||
#define CHECK_THAT( arg, matcher ) INTERNAL_CHECK_THAT( "CHECK_THAT", matcher, Catch::ResultDisposition::ContinueOnFailure, arg )
|
||||
#define REQUIRE_THAT( arg, matcher ) INTERNAL_CHECK_THAT( "REQUIRE_THAT", matcher, Catch::ResultDisposition::Normal, arg )
|
||||
|
||||
#if !defined(CATCH_CONFIG_RUNTIME_STATIC_REQUIRE)
|
||||
#define STATIC_REQUIRE_THAT( arg, matcher ) \
|
||||
static_assert( ( matcher ).match( arg ), #matcher ".match( " #arg " )"); \
|
||||
SUCCEED( #matcher ".match( " #arg " )" )
|
||||
#define STATIC_CHECK_THAT( arg, matcher ) \
|
||||
static_assert( ( matcher ).match( arg ), #matcher ".match( " #arg " )"); \
|
||||
SUCCEED( #matcher ".match( " #arg " )" )
|
||||
#else
|
||||
#define STATIC_REQUIRE_THAT( arg, matcher ) REQUIRE_THAT( arg, matcher )
|
||||
#define STATIC_CHECK_THAT( arg, matcher ) CHECK_THAT( arg, matcher )
|
||||
#endif
|
||||
|
||||
|
||||
#elif !defined(CATCH_CONFIG_PREFIX_ALL) && defined(CATCH_CONFIG_DISABLE)
|
||||
|
||||
#define REQUIRE_THROWS_WITH( expr, matcher ) (void)(0)
|
||||
@@ -248,6 +277,9 @@ namespace Matchers {
|
||||
#define CHECK_THAT( arg, matcher ) (void)(0)
|
||||
#define REQUIRE_THAT( arg, matcher ) (void)(0)
|
||||
|
||||
#define STATIC_REQUIRE_THAT( arg, matcher ) (void)(0)
|
||||
#define STATIC_CHECK_THAT( arg, matcher ) (void)(0)
|
||||
|
||||
#endif // end of user facing macro declarations
|
||||
|
||||
#endif // CATCH_MATCHERS_HPP_INCLUDED
|
||||
|
||||
@@ -22,13 +22,5 @@ namespace Matchers {
|
||||
return sstr.str();
|
||||
}
|
||||
|
||||
IsEmptyMatcher IsEmpty() {
|
||||
return {};
|
||||
}
|
||||
|
||||
HasSizeMatcher SizeIs(std::size_t sz) {
|
||||
return HasSizeMatcher{ sz };
|
||||
}
|
||||
|
||||
} // end namespace Matchers
|
||||
} // end namespace Catch
|
||||
|
||||
@@ -18,7 +18,7 @@ namespace Catch {
|
||||
class IsEmptyMatcher final : public MatcherGenericBase {
|
||||
public:
|
||||
template <typename RangeLike>
|
||||
bool match(RangeLike&& rng) const {
|
||||
constexpr bool match(RangeLike&& rng) const {
|
||||
#if defined(CATCH_CONFIG_POLYFILL_NONMEMBER_CONTAINER_ACCESS)
|
||||
using Catch::Detail::empty;
|
||||
#else
|
||||
@@ -33,12 +33,12 @@ namespace Catch {
|
||||
class HasSizeMatcher final : public MatcherGenericBase {
|
||||
std::size_t m_target_size;
|
||||
public:
|
||||
explicit HasSizeMatcher(std::size_t target_size):
|
||||
constexpr explicit HasSizeMatcher(std::size_t target_size):
|
||||
m_target_size(target_size)
|
||||
{}
|
||||
|
||||
template <typename RangeLike>
|
||||
bool match(RangeLike&& rng) const {
|
||||
constexpr bool match(RangeLike&& rng) const {
|
||||
#if defined(CATCH_CONFIG_POLYFILL_NONMEMBER_CONTAINER_ACCESS)
|
||||
using Catch::Detail::size;
|
||||
#else
|
||||
@@ -54,12 +54,12 @@ namespace Catch {
|
||||
class SizeMatchesMatcher final : public MatcherGenericBase {
|
||||
Matcher m_matcher;
|
||||
public:
|
||||
explicit SizeMatchesMatcher(Matcher m):
|
||||
constexpr explicit SizeMatchesMatcher(Matcher m):
|
||||
m_matcher(CATCH_MOVE(m))
|
||||
{}
|
||||
|
||||
template <typename RangeLike>
|
||||
bool match(RangeLike&& rng) const {
|
||||
constexpr bool match(RangeLike&& rng) const {
|
||||
#if defined(CATCH_CONFIG_POLYFILL_NONMEMBER_CONTAINER_ACCESS)
|
||||
using Catch::Detail::size;
|
||||
#else
|
||||
@@ -75,11 +75,13 @@ namespace Catch {
|
||||
|
||||
|
||||
//! Creates a matcher that accepts empty ranges/containers
|
||||
IsEmptyMatcher IsEmpty();
|
||||
inline CATCH_DESTRUCTOR_CONSTEXPR IsEmptyMatcher IsEmpty() { return {}; }
|
||||
//! Creates a matcher that accepts ranges/containers with specific size
|
||||
HasSizeMatcher SizeIs(std::size_t sz);
|
||||
inline CATCH_DESTRUCTOR_CONSTEXPR HasSizeMatcher SizeIs( std::size_t sz ) {
|
||||
return HasSizeMatcher{ sz };
|
||||
}
|
||||
template <typename Matcher>
|
||||
std::enable_if_t<Detail::is_matcher_v<Matcher>,
|
||||
constexpr std::enable_if_t<Detail::is_matcher_v<Matcher>,
|
||||
SizeMatchesMatcher<Matcher>> SizeIs(Matcher&& m) {
|
||||
return SizeMatchesMatcher<Matcher>{CATCH_FORWARD(m)};
|
||||
}
|
||||
|
||||
@@ -23,7 +23,7 @@ namespace Catch {
|
||||
Equality m_eq;
|
||||
public:
|
||||
template <typename T2, typename Equality2>
|
||||
ContainsElementMatcher(T2&& target, Equality2&& predicate):
|
||||
constexpr ContainsElementMatcher(T2&& target, Equality2&& predicate):
|
||||
m_desired(CATCH_FORWARD(target)),
|
||||
m_eq(CATCH_FORWARD(predicate))
|
||||
{}
|
||||
@@ -33,7 +33,7 @@ namespace Catch {
|
||||
}
|
||||
|
||||
template <typename RangeLike>
|
||||
bool match( RangeLike&& rng ) const {
|
||||
constexpr bool match( RangeLike&& rng ) const {
|
||||
for ( auto&& elem : rng ) {
|
||||
if ( m_eq( elem, m_desired ) ) { return true; }
|
||||
}
|
||||
@@ -49,12 +49,12 @@ namespace Catch {
|
||||
// Note that we do a copy+move to avoid having to SFINAE this
|
||||
// constructor (and also avoid some perfect forwarding failure
|
||||
// cases)
|
||||
ContainsMatcherMatcher(Matcher matcher):
|
||||
constexpr ContainsMatcherMatcher(Matcher matcher):
|
||||
m_matcher(CATCH_MOVE(matcher))
|
||||
{}
|
||||
|
||||
template <typename RangeLike>
|
||||
bool match(RangeLike&& rng) const {
|
||||
constexpr bool match(RangeLike&& rng) const {
|
||||
for (auto&& elem : rng) {
|
||||
if (m_matcher.match(elem)) {
|
||||
return true;
|
||||
@@ -74,14 +74,14 @@ namespace Catch {
|
||||
* Uses `std::equal_to` to do the comparison
|
||||
*/
|
||||
template <typename T>
|
||||
std::enable_if_t<!Detail::is_matcher_v<T>,
|
||||
constexpr std::enable_if_t<!Detail::is_matcher_v<T>,
|
||||
ContainsElementMatcher<T, std::equal_to<>>> Contains(T&& elem) {
|
||||
return { CATCH_FORWARD(elem), std::equal_to<>{} };
|
||||
}
|
||||
|
||||
//! Creates a matcher that checks whether a range contains element matching a matcher
|
||||
template <typename Matcher>
|
||||
std::enable_if_t<Detail::is_matcher_v<Matcher>,
|
||||
constexpr std::enable_if_t<Detail::is_matcher_v<Matcher>,
|
||||
ContainsMatcherMatcher<Matcher>> Contains(Matcher&& matcher) {
|
||||
return { CATCH_FORWARD(matcher) };
|
||||
}
|
||||
@@ -92,7 +92,7 @@ namespace Catch {
|
||||
* Uses `eq` to do the comparisons, the element is provided on the rhs
|
||||
*/
|
||||
template <typename T, typename Equality>
|
||||
ContainsElementMatcher<T, Equality> Contains(T&& elem, Equality&& eq) {
|
||||
constexpr ContainsElementMatcher<T, Equality> Contains(T&& elem, Equality&& eq) {
|
||||
return { CATCH_FORWARD(elem), CATCH_FORWARD(eq) };
|
||||
}
|
||||
|
||||
|
||||
@@ -9,16 +9,12 @@
|
||||
|
||||
namespace Catch {
|
||||
namespace Matchers {
|
||||
std::string AllTrueMatcher::describe() const { return "contains only true"; }
|
||||
|
||||
AllTrueMatcher AllTrue() { return AllTrueMatcher{}; }
|
||||
std::string AllTrueMatcher::describe() const { return "contains only true"; }
|
||||
|
||||
std::string NoneTrueMatcher::describe() const { return "contains no true"; }
|
||||
|
||||
NoneTrueMatcher NoneTrue() { return NoneTrueMatcher{}; }
|
||||
|
||||
std::string AnyTrueMatcher::describe() const { return "contains at least one true"; }
|
||||
|
||||
AnyTrueMatcher AnyTrue() { return AnyTrueMatcher{}; }
|
||||
} // namespace Matchers
|
||||
} // namespace Catch
|
||||
|
||||
@@ -18,7 +18,7 @@ namespace Catch {
|
||||
class AllMatchMatcher final : public MatcherGenericBase {
|
||||
Matcher m_matcher;
|
||||
public:
|
||||
AllMatchMatcher(Matcher matcher):
|
||||
constexpr AllMatchMatcher(Matcher matcher):
|
||||
m_matcher(CATCH_MOVE(matcher))
|
||||
{}
|
||||
|
||||
@@ -27,7 +27,7 @@ namespace Catch {
|
||||
}
|
||||
|
||||
template <typename RangeLike>
|
||||
bool match(RangeLike&& rng) const {
|
||||
constexpr bool match(RangeLike&& rng) const {
|
||||
for (auto&& elem : rng) {
|
||||
if (!m_matcher.match(elem)) {
|
||||
return false;
|
||||
@@ -42,7 +42,7 @@ namespace Catch {
|
||||
class NoneMatchMatcher final : public MatcherGenericBase {
|
||||
Matcher m_matcher;
|
||||
public:
|
||||
NoneMatchMatcher(Matcher matcher):
|
||||
constexpr NoneMatchMatcher(Matcher matcher):
|
||||
m_matcher(CATCH_MOVE(matcher))
|
||||
{}
|
||||
|
||||
@@ -51,7 +51,7 @@ namespace Catch {
|
||||
}
|
||||
|
||||
template <typename RangeLike>
|
||||
bool match(RangeLike&& rng) const {
|
||||
constexpr bool match(RangeLike&& rng) const {
|
||||
for (auto&& elem : rng) {
|
||||
if (m_matcher.match(elem)) {
|
||||
return false;
|
||||
@@ -66,7 +66,7 @@ namespace Catch {
|
||||
class AnyMatchMatcher final : public MatcherGenericBase {
|
||||
Matcher m_matcher;
|
||||
public:
|
||||
AnyMatchMatcher(Matcher matcher):
|
||||
constexpr AnyMatchMatcher(Matcher matcher):
|
||||
m_matcher(CATCH_MOVE(matcher))
|
||||
{}
|
||||
|
||||
@@ -75,7 +75,7 @@ namespace Catch {
|
||||
}
|
||||
|
||||
template <typename RangeLike>
|
||||
bool match(RangeLike&& rng) const {
|
||||
constexpr bool match(RangeLike&& rng) const {
|
||||
for (auto&& elem : rng) {
|
||||
if (m_matcher.match(elem)) {
|
||||
return true;
|
||||
@@ -91,7 +91,7 @@ namespace Catch {
|
||||
std::string describe() const override;
|
||||
|
||||
template <typename RangeLike>
|
||||
bool match(RangeLike&& rng) const {
|
||||
constexpr bool match(RangeLike&& rng) const {
|
||||
for (auto&& elem : rng) {
|
||||
if (!elem) {
|
||||
return false;
|
||||
@@ -107,7 +107,7 @@ namespace Catch {
|
||||
std::string describe() const override;
|
||||
|
||||
template <typename RangeLike>
|
||||
bool match(RangeLike&& rng) const {
|
||||
constexpr bool match(RangeLike&& rng) const {
|
||||
for (auto&& elem : rng) {
|
||||
if (elem) {
|
||||
return false;
|
||||
@@ -123,7 +123,7 @@ namespace Catch {
|
||||
std::string describe() const override;
|
||||
|
||||
template <typename RangeLike>
|
||||
bool match(RangeLike&& rng) const {
|
||||
constexpr bool match(RangeLike&& rng) const {
|
||||
for (auto&& elem : rng) {
|
||||
if (elem) {
|
||||
return true;
|
||||
@@ -133,32 +133,35 @@ namespace Catch {
|
||||
}
|
||||
};
|
||||
|
||||
// Creates a matcher that checks whether all elements in a range match a matcher
|
||||
//! Creates a matcher that checks whether all elements in a range match a matcher
|
||||
template <typename Matcher>
|
||||
AllMatchMatcher<Matcher> AllMatch(Matcher&& matcher) {
|
||||
constexpr AllMatchMatcher<Matcher> AllMatch(Matcher&& matcher) {
|
||||
return { CATCH_FORWARD(matcher) };
|
||||
}
|
||||
|
||||
// Creates a matcher that checks whether no element in a range matches a matcher.
|
||||
//! Creates a matcher that checks whether no element in a range matches a matcher.
|
||||
template <typename Matcher>
|
||||
NoneMatchMatcher<Matcher> NoneMatch(Matcher&& matcher) {
|
||||
constexpr NoneMatchMatcher<Matcher> NoneMatch(Matcher&& matcher) {
|
||||
return { CATCH_FORWARD(matcher) };
|
||||
}
|
||||
|
||||
// Creates a matcher that checks whether any element in a range matches a matcher.
|
||||
//! Creates a matcher that checks whether any element in a range matches a matcher.
|
||||
template <typename Matcher>
|
||||
AnyMatchMatcher<Matcher> AnyMatch(Matcher&& matcher) {
|
||||
constexpr AnyMatchMatcher<Matcher> AnyMatch(Matcher&& matcher) {
|
||||
return { CATCH_FORWARD(matcher) };
|
||||
}
|
||||
|
||||
// Creates a matcher that checks whether all elements in a range are true
|
||||
AllTrueMatcher AllTrue();
|
||||
//! Creates a matcher that checks whether all elements in a range are true
|
||||
inline CATCH_DESTRUCTOR_CONSTEXPR
|
||||
AllTrueMatcher AllTrue() { return AllTrueMatcher{}; }
|
||||
|
||||
// Creates a matcher that checks whether no element in a range is true
|
||||
NoneTrueMatcher NoneTrue();
|
||||
//! Creates a matcher that checks whether no element in a range is true
|
||||
inline CATCH_DESTRUCTOR_CONSTEXPR
|
||||
NoneTrueMatcher NoneTrue() { return NoneTrueMatcher{}; }
|
||||
|
||||
// Creates a matcher that checks whether any element in a range is true
|
||||
AnyTrueMatcher AnyTrue();
|
||||
//! Creates a matcher that checks whether any element in a range is true
|
||||
inline CATCH_DESTRUCTOR_CONSTEXPR
|
||||
AnyTrueMatcher AnyTrue() { return AnyTrueMatcher{}; }
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -9,7 +9,11 @@
|
||||
|
||||
namespace Catch {
|
||||
namespace Matchers {
|
||||
MatcherGenericBase::~MatcherGenericBase() = default;
|
||||
|
||||
std::string MatcherGenericBase::describe() const {
|
||||
using namespace std::string_literals;
|
||||
return "Undescribed generic matcher"s;
|
||||
}
|
||||
|
||||
namespace Detail {
|
||||
|
||||
|
||||
@@ -22,12 +22,12 @@
|
||||
namespace Catch {
|
||||
namespace Matchers {
|
||||
class MatcherGenericBase : public MatcherUntypedBase {
|
||||
std::string describe() const override;
|
||||
public:
|
||||
MatcherGenericBase() = default;
|
||||
~MatcherGenericBase() override; // = default;
|
||||
constexpr MatcherGenericBase() = default;
|
||||
|
||||
MatcherGenericBase(MatcherGenericBase const&) = default;
|
||||
MatcherGenericBase(MatcherGenericBase&&) = default;
|
||||
constexpr MatcherGenericBase(MatcherGenericBase const&) = default;
|
||||
constexpr MatcherGenericBase(MatcherGenericBase&&) = default;
|
||||
|
||||
MatcherGenericBase& operator=(MatcherGenericBase const&) = delete;
|
||||
MatcherGenericBase& operator=(MatcherGenericBase&&) = delete;
|
||||
@@ -36,7 +36,9 @@ namespace Matchers {
|
||||
|
||||
namespace Detail {
|
||||
template<std::size_t N, std::size_t M>
|
||||
std::array<void const*, N + M> array_cat(std::array<void const*, N> && lhs, std::array<void const*, M> && rhs) {
|
||||
constexpr std::array<void const*, N + M>
|
||||
array_cat( std::array<void const*, N>&& lhs,
|
||||
std::array<void const*, M>&& rhs ) {
|
||||
std::array<void const*, N + M> arr{};
|
||||
std::copy_n(lhs.begin(), N, arr.begin());
|
||||
std::copy_n(rhs.begin(), M, arr.begin() + N);
|
||||
@@ -44,7 +46,8 @@ namespace Matchers {
|
||||
}
|
||||
|
||||
template<std::size_t N>
|
||||
std::array<void const*, N+1> array_cat(std::array<void const*, N> && lhs, void const* rhs) {
|
||||
constexpr std::array<void const*, N + 1>
|
||||
array_cat( std::array<void const*, N>&& lhs, void const* rhs ) {
|
||||
std::array<void const*, N+1> arr{};
|
||||
std::copy_n(lhs.begin(), N, arr.begin());
|
||||
arr[N] = rhs;
|
||||
@@ -52,7 +55,8 @@ namespace Matchers {
|
||||
}
|
||||
|
||||
template<std::size_t N>
|
||||
std::array<void const*, N+1> array_cat(void const* lhs, std::array<void const*, N> && rhs) {
|
||||
constexpr std::array<void const*, N + 1>
|
||||
array_cat( void const* lhs, std::array<void const*, N>&& rhs ) {
|
||||
std::array<void const*, N + 1> arr{ {lhs} };
|
||||
std::copy_n(rhs.begin(), N, arr.begin() + 1);
|
||||
return arr;
|
||||
@@ -75,23 +79,31 @@ namespace Matchers {
|
||||
|
||||
|
||||
template<std::size_t N, typename Arg>
|
||||
bool match_all_of(Arg&&, std::array<void const*, N> const&, std::index_sequence<>) {
|
||||
constexpr bool match_all_of( Arg&&,
|
||||
std::array<void const*, N> const&,
|
||||
std::index_sequence<> ) {
|
||||
return true;
|
||||
}
|
||||
|
||||
template<typename T, typename... MatcherTs, std::size_t N, typename Arg, std::size_t Idx, std::size_t... Indices>
|
||||
bool match_all_of(Arg&& arg, std::array<void const*, N> const& matchers, std::index_sequence<Idx, Indices...>) {
|
||||
constexpr bool match_all_of( Arg&& arg,
|
||||
std::array<void const*, N> const& matchers,
|
||||
std::index_sequence<Idx, Indices...> ) {
|
||||
return static_cast<T const*>(matchers[Idx])->match(arg) && match_all_of<MatcherTs...>(arg, matchers, std::index_sequence<Indices...>{});
|
||||
}
|
||||
|
||||
|
||||
template<std::size_t N, typename Arg>
|
||||
bool match_any_of(Arg&&, std::array<void const*, N> const&, std::index_sequence<>) {
|
||||
constexpr bool match_any_of( Arg&&,
|
||||
std::array<void const*, N> const&,
|
||||
std::index_sequence<> ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
template<typename T, typename... MatcherTs, std::size_t N, typename Arg, std::size_t Idx, std::size_t... Indices>
|
||||
bool match_any_of(Arg&& arg, std::array<void const*, N> const& matchers, std::index_sequence<Idx, Indices...>) {
|
||||
constexpr bool match_any_of( Arg&& arg,
|
||||
std::array<void const*, N> const& matchers,
|
||||
std::index_sequence<Idx, Indices...> ) {
|
||||
return static_cast<T const*>(matchers[Idx])->match(arg) || match_any_of<MatcherTs...>(arg, matchers, std::index_sequence<Indices...>{});
|
||||
}
|
||||
|
||||
@@ -112,15 +124,18 @@ namespace Matchers {
|
||||
public:
|
||||
MatchAllOfGeneric(MatchAllOfGeneric const&) = delete;
|
||||
MatchAllOfGeneric& operator=(MatchAllOfGeneric const&) = delete;
|
||||
MatchAllOfGeneric(MatchAllOfGeneric&&) = default;
|
||||
MatchAllOfGeneric& operator=(MatchAllOfGeneric&&) = default;
|
||||
constexpr MatchAllOfGeneric( MatchAllOfGeneric&& ) = default;
|
||||
constexpr MatchAllOfGeneric& operator=(MatchAllOfGeneric&&) = default;
|
||||
|
||||
MatchAllOfGeneric(MatcherTs const&... matchers CATCH_ATTR_LIFETIMEBOUND)
|
||||
constexpr MatchAllOfGeneric(
|
||||
MatcherTs const&... matchers CATCH_ATTR_LIFETIMEBOUND )
|
||||
: m_matchers{ {std::addressof(matchers)...} } {}
|
||||
explicit MatchAllOfGeneric(std::array<void const*, sizeof...(MatcherTs)> matchers) : m_matchers{matchers} {}
|
||||
constexpr explicit MatchAllOfGeneric(
|
||||
std::array<void const*, sizeof...( MatcherTs )> matchers ):
|
||||
m_matchers{ matchers } {}
|
||||
|
||||
template<typename Arg>
|
||||
bool match(Arg&& arg) const {
|
||||
constexpr bool match( Arg&& arg ) const {
|
||||
return match_all_of<MatcherTs...>(arg, m_matchers, std::index_sequence_for<MatcherTs...>{});
|
||||
}
|
||||
|
||||
@@ -136,7 +151,7 @@ namespace Matchers {
|
||||
|
||||
//! Avoids type nesting for `GenericAllOf && GenericAllOf` case
|
||||
template<typename... MatchersRHS>
|
||||
friend
|
||||
constexpr friend
|
||||
MatchAllOfGeneric<MatcherTs..., MatchersRHS...> operator && (
|
||||
MatchAllOfGeneric<MatcherTs...>&& lhs CATCH_ATTR_LIFETIMEBOUND,
|
||||
MatchAllOfGeneric<MatchersRHS...>&& rhs CATCH_ATTR_LIFETIMEBOUND ) {
|
||||
@@ -145,7 +160,8 @@ namespace Matchers {
|
||||
|
||||
//! Avoids type nesting for `GenericAllOf && some matcher` case
|
||||
template<typename MatcherRHS>
|
||||
friend std::enable_if_t<is_matcher_v<MatcherRHS>,
|
||||
constexpr friend std::enable_if_t<
|
||||
is_matcher_v<MatcherRHS>,
|
||||
MatchAllOfGeneric<MatcherTs..., MatcherRHS>> operator && (
|
||||
MatchAllOfGeneric<MatcherTs...>&& lhs CATCH_ATTR_LIFETIMEBOUND,
|
||||
MatcherRHS const& rhs CATCH_ATTR_LIFETIMEBOUND ) {
|
||||
@@ -154,7 +170,8 @@ namespace Matchers {
|
||||
|
||||
//! Avoids type nesting for `some matcher && GenericAllOf` case
|
||||
template<typename MatcherLHS>
|
||||
friend std::enable_if_t<is_matcher_v<MatcherLHS>,
|
||||
constexpr friend std::enable_if_t<
|
||||
is_matcher_v<MatcherLHS>,
|
||||
MatchAllOfGeneric<MatcherLHS, MatcherTs...>> operator && (
|
||||
MatcherLHS const& lhs CATCH_ATTR_LIFETIMEBOUND,
|
||||
MatchAllOfGeneric<MatcherTs...>&& rhs CATCH_ATTR_LIFETIMEBOUND ) {
|
||||
@@ -168,15 +185,18 @@ namespace Matchers {
|
||||
public:
|
||||
MatchAnyOfGeneric(MatchAnyOfGeneric const&) = delete;
|
||||
MatchAnyOfGeneric& operator=(MatchAnyOfGeneric const&) = delete;
|
||||
MatchAnyOfGeneric(MatchAnyOfGeneric&&) = default;
|
||||
MatchAnyOfGeneric& operator=(MatchAnyOfGeneric&&) = default;
|
||||
constexpr MatchAnyOfGeneric( MatchAnyOfGeneric&& ) = default;
|
||||
constexpr MatchAnyOfGeneric& operator=(MatchAnyOfGeneric&&) = default;
|
||||
|
||||
MatchAnyOfGeneric(MatcherTs const&... matchers CATCH_ATTR_LIFETIMEBOUND)
|
||||
constexpr MatchAnyOfGeneric(
|
||||
MatcherTs const&... matchers CATCH_ATTR_LIFETIMEBOUND )
|
||||
: m_matchers{ {std::addressof(matchers)...} } {}
|
||||
explicit MatchAnyOfGeneric(std::array<void const*, sizeof...(MatcherTs)> matchers) : m_matchers{matchers} {}
|
||||
constexpr explicit MatchAnyOfGeneric(
|
||||
std::array<void const*, sizeof...( MatcherTs )> matchers ):
|
||||
m_matchers{ matchers } {}
|
||||
|
||||
template<typename Arg>
|
||||
bool match(Arg&& arg) const {
|
||||
constexpr bool match( Arg&& arg ) const {
|
||||
return match_any_of<MatcherTs...>(arg, m_matchers, std::index_sequence_for<MatcherTs...>{});
|
||||
}
|
||||
|
||||
@@ -192,7 +212,8 @@ namespace Matchers {
|
||||
|
||||
//! Avoids type nesting for `GenericAnyOf || GenericAnyOf` case
|
||||
template<typename... MatchersRHS>
|
||||
friend MatchAnyOfGeneric<MatcherTs..., MatchersRHS...> operator || (
|
||||
constexpr friend MatchAnyOfGeneric<MatcherTs..., MatchersRHS...>
|
||||
operator||(
|
||||
MatchAnyOfGeneric<MatcherTs...>&& lhs CATCH_ATTR_LIFETIMEBOUND,
|
||||
MatchAnyOfGeneric<MatchersRHS...>&& rhs CATCH_ATTR_LIFETIMEBOUND ) {
|
||||
return MatchAnyOfGeneric<MatcherTs..., MatchersRHS...>{array_cat(CATCH_MOVE(lhs.m_matchers), CATCH_MOVE(rhs.m_matchers))};
|
||||
@@ -200,7 +221,8 @@ namespace Matchers {
|
||||
|
||||
//! Avoids type nesting for `GenericAnyOf || some matcher` case
|
||||
template<typename MatcherRHS>
|
||||
friend std::enable_if_t<is_matcher_v<MatcherRHS>,
|
||||
constexpr friend std::enable_if_t<
|
||||
is_matcher_v<MatcherRHS>,
|
||||
MatchAnyOfGeneric<MatcherTs..., MatcherRHS>> operator || (
|
||||
MatchAnyOfGeneric<MatcherTs...>&& lhs CATCH_ATTR_LIFETIMEBOUND,
|
||||
MatcherRHS const& rhs CATCH_ATTR_LIFETIMEBOUND ) {
|
||||
@@ -209,7 +231,8 @@ namespace Matchers {
|
||||
|
||||
//! Avoids type nesting for `some matcher || GenericAnyOf` case
|
||||
template<typename MatcherLHS>
|
||||
friend std::enable_if_t<is_matcher_v<MatcherLHS>,
|
||||
constexpr friend std::enable_if_t<
|
||||
is_matcher_v<MatcherLHS>,
|
||||
MatchAnyOfGeneric<MatcherLHS, MatcherTs...>> operator || (
|
||||
MatcherLHS const& lhs CATCH_ATTR_LIFETIMEBOUND,
|
||||
MatchAnyOfGeneric<MatcherTs...>&& rhs CATCH_ATTR_LIFETIMEBOUND) {
|
||||
@@ -225,14 +248,15 @@ namespace Matchers {
|
||||
public:
|
||||
MatchNotOfGeneric(MatchNotOfGeneric const&) = delete;
|
||||
MatchNotOfGeneric& operator=(MatchNotOfGeneric const&) = delete;
|
||||
MatchNotOfGeneric(MatchNotOfGeneric&&) = default;
|
||||
MatchNotOfGeneric& operator=(MatchNotOfGeneric&&) = default;
|
||||
constexpr MatchNotOfGeneric( MatchNotOfGeneric&& ) = default;
|
||||
constexpr MatchNotOfGeneric& operator=(MatchNotOfGeneric&&) = default;
|
||||
|
||||
explicit MatchNotOfGeneric(MatcherT const& matcher CATCH_ATTR_LIFETIMEBOUND)
|
||||
constexpr explicit MatchNotOfGeneric(
|
||||
MatcherT const& matcher CATCH_ATTR_LIFETIMEBOUND )
|
||||
: m_matcher{matcher} {}
|
||||
|
||||
template<typename Arg>
|
||||
bool match(Arg&& arg) const {
|
||||
constexpr bool match( Arg&& arg ) const {
|
||||
return !m_matcher.match(arg);
|
||||
}
|
||||
|
||||
@@ -241,7 +265,7 @@ namespace Matchers {
|
||||
}
|
||||
|
||||
//! Negating negation can just unwrap and return underlying matcher
|
||||
friend MatcherT const&
|
||||
constexpr friend MatcherT const&
|
||||
operator!( MatchNotOfGeneric<MatcherT> const& matcher
|
||||
CATCH_ATTR_LIFETIMEBOUND ) {
|
||||
return matcher.m_matcher;
|
||||
@@ -252,14 +276,18 @@ namespace Matchers {
|
||||
|
||||
// compose only generic matchers
|
||||
template<typename MatcherLHS, typename MatcherRHS>
|
||||
std::enable_if_t<Detail::are_generic_matchers_v<MatcherLHS, MatcherRHS>, Detail::MatchAllOfGeneric<MatcherLHS, MatcherRHS>>
|
||||
constexpr std::enable_if_t<
|
||||
Detail::are_generic_matchers_v<MatcherLHS, MatcherRHS>,
|
||||
Detail::MatchAllOfGeneric<MatcherLHS, MatcherRHS>>
|
||||
operator&&( MatcherLHS const& lhs CATCH_ATTR_LIFETIMEBOUND,
|
||||
MatcherRHS const& rhs CATCH_ATTR_LIFETIMEBOUND ) {
|
||||
return { lhs, rhs };
|
||||
}
|
||||
|
||||
template<typename MatcherLHS, typename MatcherRHS>
|
||||
std::enable_if_t<Detail::are_generic_matchers_v<MatcherLHS, MatcherRHS>, Detail::MatchAnyOfGeneric<MatcherLHS, MatcherRHS>>
|
||||
constexpr std::enable_if_t<
|
||||
Detail::are_generic_matchers_v<MatcherLHS, MatcherRHS>,
|
||||
Detail::MatchAnyOfGeneric<MatcherLHS, MatcherRHS>>
|
||||
operator||( MatcherLHS const& lhs CATCH_ATTR_LIFETIMEBOUND,
|
||||
MatcherRHS const& rhs CATCH_ATTR_LIFETIMEBOUND ) {
|
||||
return { lhs, rhs };
|
||||
@@ -267,7 +295,8 @@ namespace Matchers {
|
||||
|
||||
//! Wrap provided generic matcher in generic negator
|
||||
template<typename MatcherT>
|
||||
std::enable_if_t<Detail::is_generic_matcher_v<MatcherT>, Detail::MatchNotOfGeneric<MatcherT>>
|
||||
constexpr std::enable_if_t<Detail::is_generic_matcher_v<MatcherT>,
|
||||
Detail::MatchNotOfGeneric<MatcherT>>
|
||||
operator!( MatcherT const& matcher CATCH_ATTR_LIFETIMEBOUND ) {
|
||||
return Detail::MatchNotOfGeneric<MatcherT>{matcher};
|
||||
}
|
||||
|
||||
@@ -29,7 +29,7 @@ namespace Catch {
|
||||
#endif
|
||||
|
||||
template<typename ArgT, typename MatcherT>
|
||||
class MatchExpr : public ITransientExpression {
|
||||
class MatchExpr final : public ITransientExpression {
|
||||
ArgT && m_arg;
|
||||
MatcherT const& m_matcher;
|
||||
public:
|
||||
|
||||
@@ -65,7 +65,6 @@ internal_headers = [
|
||||
'interfaces/catch_interfaces_all.hpp',
|
||||
'interfaces/catch_interfaces_capture.hpp',
|
||||
'interfaces/catch_interfaces_config.hpp',
|
||||
'interfaces/catch_interfaces_enum_values_registry.hpp',
|
||||
'interfaces/catch_interfaces_exception.hpp',
|
||||
'interfaces/catch_interfaces_generatortracker.hpp',
|
||||
'interfaces/catch_interfaces_registry_hub.hpp',
|
||||
@@ -95,7 +94,7 @@ internal_headers = [
|
||||
'internal/catch_decomposer.hpp',
|
||||
'internal/catch_deprecation_macro.hpp',
|
||||
'internal/catch_enforce.hpp',
|
||||
'internal/catch_enum_values_registry.hpp',
|
||||
'internal/catch_enum_info.hpp',
|
||||
'internal/catch_errno_guard.hpp',
|
||||
'internal/catch_exception_translator_registry.hpp',
|
||||
'internal/catch_fatal_condition_handler.hpp',
|
||||
@@ -224,7 +223,7 @@ internal_sources = files(
|
||||
'internal/catch_debugger.cpp',
|
||||
'internal/catch_decomposer.cpp',
|
||||
'internal/catch_enforce.cpp',
|
||||
'internal/catch_enum_values_registry.cpp',
|
||||
'internal/catch_enum_info.cpp',
|
||||
'internal/catch_errno_guard.cpp',
|
||||
'internal/catch_exception_translator_registry.cpp',
|
||||
'internal/catch_fatal_condition_handler.cpp',
|
||||
|
||||
@@ -20,9 +20,8 @@ namespace Catch {
|
||||
bool operator()(
|
||||
Detail::unique_ptr<CumulativeReporterBase::SectionNode> const&
|
||||
node ) const {
|
||||
return (
|
||||
( node->stats.sectionInfo.name == m_other.name ) &&
|
||||
( node->stats.sectionInfo.lineInfo == m_other.lineInfo ) );
|
||||
return node->stats.sectionInfo.name == m_other.name
|
||||
&& node->stats.sectionInfo.lineInfo == m_other.lineInfo;
|
||||
}
|
||||
void operator=( BySectionInfo const& ) = delete;
|
||||
|
||||
|
||||
@@ -199,7 +199,7 @@ namespace Catch {
|
||||
}
|
||||
|
||||
// minimum whitespace to pad tag counts, possibly overwritten below
|
||||
size_t maxTagCountLen = 2;
|
||||
int maxTagCountLen = 2;
|
||||
|
||||
// determine necessary padding for tag count column
|
||||
if ( ! tags.empty() ) {
|
||||
@@ -214,7 +214,7 @@ namespace Catch {
|
||||
// more padding necessary for 3+ digits
|
||||
if (maxTagCount >= 100) {
|
||||
auto numDigits = 1 + std::floor( std::log10( maxTagCount ) );
|
||||
maxTagCountLen = static_cast<size_t>( numDigits );
|
||||
maxTagCountLen = static_cast<int>( numDigits );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -62,6 +62,7 @@ cc_test(
|
||||
"SelfTest/UsageTests/Exception.tests.cpp",
|
||||
"SelfTest/UsageTests/Generators.tests.cpp",
|
||||
"SelfTest/UsageTests/Matchers.tests.cpp",
|
||||
"SelfTest/UsageTests/MatchersConstexpr.tests.cpp",
|
||||
"SelfTest/UsageTests/MatchersRanges.tests.cpp",
|
||||
"SelfTest/UsageTests/Message.tests.cpp",
|
||||
"SelfTest/UsageTests/Misc.tests.cpp",
|
||||
|
||||
@@ -124,8 +124,9 @@ set(TEST_SOURCES
|
||||
${SELF_TEST_DIR}/UsageTests/ToStringWhich.tests.cpp
|
||||
${SELF_TEST_DIR}/UsageTests/Tricky.tests.cpp
|
||||
${SELF_TEST_DIR}/UsageTests/VariadicMacros.tests.cpp
|
||||
${SELF_TEST_DIR}/UsageTests/MatchersRanges.tests.cpp
|
||||
${SELF_TEST_DIR}/UsageTests/Matchers.tests.cpp
|
||||
${SELF_TEST_DIR}/UsageTests/MatchersConstexpr.tests.cpp
|
||||
${SELF_TEST_DIR}/UsageTests/MatchersRanges.tests.cpp
|
||||
)
|
||||
|
||||
set(TEST_HEADERS
|
||||
|
||||
@@ -174,7 +174,7 @@ target_compile_definitions(DeferredStaticChecks PRIVATE "CATCH_CONFIG_RUNTIME_ST
|
||||
add_test(NAME DeferredStaticChecks COMMAND DeferredStaticChecks -r compact)
|
||||
set_tests_properties(DeferredStaticChecks
|
||||
PROPERTIES
|
||||
PASS_REGULAR_EXPRESSION "test cases: 1 \\| 1 failed\nassertions: 3 \\| 3 failed"
|
||||
PASS_REGULAR_EXPRESSION "test cases: 1 \\| 1 failed\nassertions: 3 \\| 3 failed;test cases: 1 \\| 1 failed\nassertions: 4 \\| 4 failed"
|
||||
)
|
||||
|
||||
add_executable(MixingClearedAndUnclearedMessages ${TESTS_DIR}/X06-MixingClearedAndUnclearedMessages.cpp)
|
||||
|
||||
@@ -53,6 +53,8 @@ TEST_CASE( "Disabled Macros" ) {
|
||||
REQUIRE_THAT( 1,
|
||||
Catch::Matchers::Predicate( []( int ) { return false; } ) );
|
||||
BENCHMARK( "Disabled benchmark" ) { REQUIRE( 1 == 2 ); };
|
||||
|
||||
STATIC_REQUIRE_THAT( 1, Catch::Matchers::Predicate( []( int ) { return false; } ) );
|
||||
}
|
||||
|
||||
struct DisabledFixture {};
|
||||
|
||||
@@ -12,10 +12,36 @@
|
||||
*/
|
||||
|
||||
#include <catch2/catch_test_macros.hpp>
|
||||
#include <catch2/matchers/catch_matchers_templated.hpp>
|
||||
|
||||
#if defined( CATCH_INTERNAL_CONSTEXPR_MATCHERS_ENABLED )
|
||||
|
||||
namespace {
|
||||
struct MatchNoneMatcher final : public Catch::Matchers::MatcherGenericBase {
|
||||
public:
|
||||
template <typename Any>
|
||||
constexpr bool match( Any&& ) const {
|
||||
return false;
|
||||
}
|
||||
|
||||
std::string describe() const override {
|
||||
using namespace std::string_literals;
|
||||
return "Matches anything"s;
|
||||
}
|
||||
};
|
||||
|
||||
constexpr MatchNoneMatcher MatchNone() { return MatchNoneMatcher(); }
|
||||
|
||||
} // namespace
|
||||
|
||||
#endif
|
||||
|
||||
TEST_CASE("Deferred static checks") {
|
||||
STATIC_CHECK(1 == 2);
|
||||
STATIC_CHECK_FALSE(1 != 2);
|
||||
#if defined(CATCH_INTERNAL_CONSTEXPR_MATCHERS_ENABLED)
|
||||
STATIC_CHECK_THAT(1, MatchNone());
|
||||
#endif
|
||||
// This last assertion must be executed too
|
||||
CHECK(1 == 2);
|
||||
}
|
||||
|
||||
@@ -144,6 +144,7 @@ Nor would this
|
||||
:test-result: SKIP Empty generators can SKIP in constructor
|
||||
:test-result: PASS Empty stream name opens cout stream
|
||||
:test-result: FAIL EndsWith string matcher
|
||||
:test-result: PASS Enum backed by larger underlying type
|
||||
:test-result: PASS Enums can quickly have stringification enabled using CATCH_REGISTER_ENUM
|
||||
:test-result: PASS Enums in namespaces can quickly have stringification enabled using CATCH_REGISTER_ENUM
|
||||
:test-result: PASS Epsilon only applies to Approx's value
|
||||
|
||||
@@ -142,6 +142,7 @@
|
||||
:test-result: SKIP Empty generators can SKIP in constructor
|
||||
:test-result: PASS Empty stream name opens cout stream
|
||||
:test-result: FAIL EndsWith string matcher
|
||||
:test-result: PASS Enum backed by larger underlying type
|
||||
:test-result: PASS Enums can quickly have stringification enabled using CATCH_REGISTER_ENUM
|
||||
:test-result: PASS Enums in namespaces can quickly have stringification enabled using CATCH_REGISTER_ENUM
|
||||
:test-result: PASS Epsilon only applies to Approx's value
|
||||
|
||||
@@ -576,15 +576,18 @@ Approx.tests.cpp:<line number>: passed: 101.000001 != Approx(100).epsilon(0.01)
|
||||
Approx.tests.cpp:<line number>: passed: std::pow(10, -5) != Approx(std::pow(10, -7)) for: 0.00001 != Approx( 0.0000001 )
|
||||
Message.tests.cpp:<line number>: passed: true with 1 message: 'a'
|
||||
Message.tests.cpp:<line number>: failed: false with 1 message: 'b'
|
||||
ToString.tests.cpp:<line number>: passed: enumInfo->lookup(0) == "Value1" for: Value1 == "Value1"
|
||||
ToString.tests.cpp:<line number>: passed: enumInfo->lookup(1) == "Value2" for: Value2 == "Value2"
|
||||
ToString.tests.cpp:<line number>: passed: enumInfo->lookup(3) == "{** unexpected enum value **}" for: {** unexpected enum value **}
|
||||
EnumToString.tests.cpp:<line number>: passed: enumInfo.lookup(0) == "Value1" for: Value1 == "Value1"
|
||||
EnumToString.tests.cpp:<line number>: passed: enumInfo.lookup(1) == "Value2" for: Value2 == "Value2"
|
||||
EnumToString.tests.cpp:<line number>: passed: enumInfo.lookup(3) == "{** unexpected enum value **}" for: {** unexpected enum value **}
|
||||
==
|
||||
"{** unexpected enum value **}"
|
||||
Skip.tests.cpp:<line number>: skipped: 'This generator is empty'
|
||||
Stream.tests.cpp:<line number>: passed: Catch::makeStream( "" )->isConsole() for: true
|
||||
Matchers.tests.cpp:<line number>: failed: testStringForMatching(), EndsWith( "Substring" ) for: "this string contains 'abc' as a substring" ends with: "Substring"
|
||||
Matchers.tests.cpp:<line number>: failed: testStringForMatching(), EndsWith( "this", Catch::CaseSensitive::No ) for: "this string contains 'abc' as a substring" ends with: "this" (case insensitive)
|
||||
EnumToString.tests.cpp:<line number>: passed: stringify( LargeEnum::Flag1 ) == "Flag1" for: "Flag1" == "Flag1"
|
||||
EnumToString.tests.cpp:<line number>: passed: stringify( LargeEnum::Flag2 ) == "Flag2" for: "Flag2" == "Flag2"
|
||||
EnumToString.tests.cpp:<line number>: passed: stringify( LargeEnum::Flag5 ) == "Flag5" for: "Flag5" == "Flag5"
|
||||
EnumToString.tests.cpp:<line number>: passed: stringify( EnumClass3::Value1 ) == "Value1" for: "Value1" == "Value1"
|
||||
EnumToString.tests.cpp:<line number>: passed: stringify( EnumClass3::Value2 ) == "Value2" for: "Value2" == "Value2"
|
||||
EnumToString.tests.cpp:<line number>: passed: stringify( EnumClass3::Value3 ) == "Value3" for: "Value3" == "Value3"
|
||||
@@ -2755,13 +2758,13 @@ Tricky.tests.cpp:<line number>: passed: ptr.get() == 0 for: 0 == 0
|
||||
ToStringPair.tests.cpp:<line number>: passed: ::Catch::Detail::stringify( pair ) == "{ { 42, \"Arthur\" }, { \"Ford\", 24 } }" for: "{ { 42, "Arthur" }, { "Ford", 24 } }"
|
||||
==
|
||||
"{ { 42, "Arthur" }, { "Ford", 24 } }"
|
||||
ToString.tests.cpp:<line number>: passed: parseEnums( "" ), Equals( std::vector<Catch::StringRef>{} ) for: { } Equals: { }
|
||||
ToString.tests.cpp:<line number>: passed: parseEnums( "ClassName::EnumName::Value1" ), Equals(std::vector<Catch::StringRef>{"Value1"} ) for: { Value1 } Equals: { Value1 }
|
||||
ToString.tests.cpp:<line number>: passed: parseEnums( "Value1" ), Equals( std::vector<Catch::StringRef>{"Value1"} ) for: { Value1 } Equals: { Value1 }
|
||||
ToString.tests.cpp:<line number>: passed: parseEnums( "EnumName::Value1" ), Equals(std::vector<Catch::StringRef>{"Value1"} ) for: { Value1 } Equals: { Value1 }
|
||||
ToString.tests.cpp:<line number>: passed: parseEnums( "ClassName::EnumName::Value1, ClassName::EnumName::Value2" ), Equals( std::vector<Catch::StringRef>{"Value1", "Value2"} ) for: { Value1, Value2 } Equals: { Value1, Value2 }
|
||||
ToString.tests.cpp:<line number>: passed: parseEnums( "ClassName::EnumName::Value1, ClassName::EnumName::Value2, ClassName::EnumName::Value3" ), Equals( std::vector<Catch::StringRef>{"Value1", "Value2", "Value3"} ) for: { Value1, Value2, Value3 } Equals: { Value1, Value2, Value3 }
|
||||
ToString.tests.cpp:<line number>: passed: parseEnums( "ClassName::EnumName::Value1,ClassName::EnumName::Value2 , ClassName::EnumName::Value3" ), Equals( std::vector<Catch::StringRef>{"Value1", "Value2", "Value3"} ) for: { Value1, Value2, Value3 } Equals: { Value1, Value2, Value3 }
|
||||
EnumToString.tests.cpp:<line number>: passed: parseEnums( "" ), Equals( std::vector<Catch::StringRef>{} ) for: { } Equals: { }
|
||||
EnumToString.tests.cpp:<line number>: passed: parseEnums( "ClassName::EnumName::Value1" ), Equals(std::vector<Catch::StringRef>{"Value1"} ) for: { Value1 } Equals: { Value1 }
|
||||
EnumToString.tests.cpp:<line number>: passed: parseEnums( "Value1" ), Equals( std::vector<Catch::StringRef>{"Value1"} ) for: { Value1 } Equals: { Value1 }
|
||||
EnumToString.tests.cpp:<line number>: passed: parseEnums( "EnumName::Value1" ), Equals(std::vector<Catch::StringRef>{"Value1"} ) for: { Value1 } Equals: { Value1 }
|
||||
EnumToString.tests.cpp:<line number>: passed: parseEnums( "ClassName::EnumName::Value1, ClassName::EnumName::Value2" ), Equals( std::vector<Catch::StringRef>{"Value1", "Value2"} ) for: { Value1, Value2 } Equals: { Value1, Value2 }
|
||||
EnumToString.tests.cpp:<line number>: passed: parseEnums( "ClassName::EnumName::Value1, ClassName::EnumName::Value2, ClassName::EnumName::Value3" ), Equals( std::vector<Catch::StringRef>{"Value1", "Value2", "Value3"} ) for: { Value1, Value2, Value3 } Equals: { Value1, Value2, Value3 }
|
||||
EnumToString.tests.cpp:<line number>: passed: parseEnums( "ClassName::EnumName::Value1,ClassName::EnumName::Value2 , ClassName::EnumName::Value3" ), Equals( std::vector<Catch::StringRef>{"Value1", "Value2", "Value3"} ) for: { Value1, Value2, Value3 } Equals: { Value1, Value2, Value3 }
|
||||
Tricky.tests.cpp:<line number>: passed: p == 0 for: 0 == 0
|
||||
Message.tests.cpp:<line number>: passed: true with 1 message: 'this MAY be seen IF info is printed for passing assertions'
|
||||
Message.tests.cpp:<line number>: failed: false with 2 messages: 'this SHOULD be seen' and 'this SHOULD also be seen'
|
||||
@@ -2997,7 +3000,7 @@ InternalBenchmark.tests.cpp:<line number>: passed: med == 18. for: 18.0 == 18.0
|
||||
InternalBenchmark.tests.cpp:<line number>: passed: q3 == 23. for: 23.0 == 23.0
|
||||
Misc.tests.cpp:<line number>: passed:
|
||||
Misc.tests.cpp:<line number>: passed:
|
||||
test cases: 450 | 330 passed | 96 failed | 6 skipped | 18 failed as expected
|
||||
assertions: 2413 | 2212 passed | 158 failed | 43 failed as expected
|
||||
test cases: 451 | 331 passed | 96 failed | 6 skipped | 18 failed as expected
|
||||
assertions: 2416 | 2215 passed | 158 failed | 43 failed as expected
|
||||
|
||||
|
||||
|
||||
@@ -574,15 +574,18 @@ Approx.tests.cpp:<line number>: passed: 101.000001 != Approx(100).epsilon(0.01)
|
||||
Approx.tests.cpp:<line number>: passed: std::pow(10, -5) != Approx(std::pow(10, -7)) for: 0.00001 != Approx( 0.0000001 )
|
||||
Message.tests.cpp:<line number>: passed: true with 1 message: 'a'
|
||||
Message.tests.cpp:<line number>: failed: false with 1 message: 'b'
|
||||
ToString.tests.cpp:<line number>: passed: enumInfo->lookup(0) == "Value1" for: Value1 == "Value1"
|
||||
ToString.tests.cpp:<line number>: passed: enumInfo->lookup(1) == "Value2" for: Value2 == "Value2"
|
||||
ToString.tests.cpp:<line number>: passed: enumInfo->lookup(3) == "{** unexpected enum value **}" for: {** unexpected enum value **}
|
||||
EnumToString.tests.cpp:<line number>: passed: enumInfo.lookup(0) == "Value1" for: Value1 == "Value1"
|
||||
EnumToString.tests.cpp:<line number>: passed: enumInfo.lookup(1) == "Value2" for: Value2 == "Value2"
|
||||
EnumToString.tests.cpp:<line number>: passed: enumInfo.lookup(3) == "{** unexpected enum value **}" for: {** unexpected enum value **}
|
||||
==
|
||||
"{** unexpected enum value **}"
|
||||
Skip.tests.cpp:<line number>: skipped: 'This generator is empty'
|
||||
Stream.tests.cpp:<line number>: passed: Catch::makeStream( "" )->isConsole() for: true
|
||||
Matchers.tests.cpp:<line number>: failed: testStringForMatching(), EndsWith( "Substring" ) for: "this string contains 'abc' as a substring" ends with: "Substring"
|
||||
Matchers.tests.cpp:<line number>: failed: testStringForMatching(), EndsWith( "this", Catch::CaseSensitive::No ) for: "this string contains 'abc' as a substring" ends with: "this" (case insensitive)
|
||||
EnumToString.tests.cpp:<line number>: passed: stringify( LargeEnum::Flag1 ) == "Flag1" for: "Flag1" == "Flag1"
|
||||
EnumToString.tests.cpp:<line number>: passed: stringify( LargeEnum::Flag2 ) == "Flag2" for: "Flag2" == "Flag2"
|
||||
EnumToString.tests.cpp:<line number>: passed: stringify( LargeEnum::Flag5 ) == "Flag5" for: "Flag5" == "Flag5"
|
||||
EnumToString.tests.cpp:<line number>: passed: stringify( EnumClass3::Value1 ) == "Value1" for: "Value1" == "Value1"
|
||||
EnumToString.tests.cpp:<line number>: passed: stringify( EnumClass3::Value2 ) == "Value2" for: "Value2" == "Value2"
|
||||
EnumToString.tests.cpp:<line number>: passed: stringify( EnumClass3::Value3 ) == "Value3" for: "Value3" == "Value3"
|
||||
@@ -2744,13 +2747,13 @@ Tricky.tests.cpp:<line number>: passed: ptr.get() == 0 for: 0 == 0
|
||||
ToStringPair.tests.cpp:<line number>: passed: ::Catch::Detail::stringify( pair ) == "{ { 42, \"Arthur\" }, { \"Ford\", 24 } }" for: "{ { 42, "Arthur" }, { "Ford", 24 } }"
|
||||
==
|
||||
"{ { 42, "Arthur" }, { "Ford", 24 } }"
|
||||
ToString.tests.cpp:<line number>: passed: parseEnums( "" ), Equals( std::vector<Catch::StringRef>{} ) for: { } Equals: { }
|
||||
ToString.tests.cpp:<line number>: passed: parseEnums( "ClassName::EnumName::Value1" ), Equals(std::vector<Catch::StringRef>{"Value1"} ) for: { Value1 } Equals: { Value1 }
|
||||
ToString.tests.cpp:<line number>: passed: parseEnums( "Value1" ), Equals( std::vector<Catch::StringRef>{"Value1"} ) for: { Value1 } Equals: { Value1 }
|
||||
ToString.tests.cpp:<line number>: passed: parseEnums( "EnumName::Value1" ), Equals(std::vector<Catch::StringRef>{"Value1"} ) for: { Value1 } Equals: { Value1 }
|
||||
ToString.tests.cpp:<line number>: passed: parseEnums( "ClassName::EnumName::Value1, ClassName::EnumName::Value2" ), Equals( std::vector<Catch::StringRef>{"Value1", "Value2"} ) for: { Value1, Value2 } Equals: { Value1, Value2 }
|
||||
ToString.tests.cpp:<line number>: passed: parseEnums( "ClassName::EnumName::Value1, ClassName::EnumName::Value2, ClassName::EnumName::Value3" ), Equals( std::vector<Catch::StringRef>{"Value1", "Value2", "Value3"} ) for: { Value1, Value2, Value3 } Equals: { Value1, Value2, Value3 }
|
||||
ToString.tests.cpp:<line number>: passed: parseEnums( "ClassName::EnumName::Value1,ClassName::EnumName::Value2 , ClassName::EnumName::Value3" ), Equals( std::vector<Catch::StringRef>{"Value1", "Value2", "Value3"} ) for: { Value1, Value2, Value3 } Equals: { Value1, Value2, Value3 }
|
||||
EnumToString.tests.cpp:<line number>: passed: parseEnums( "" ), Equals( std::vector<Catch::StringRef>{} ) for: { } Equals: { }
|
||||
EnumToString.tests.cpp:<line number>: passed: parseEnums( "ClassName::EnumName::Value1" ), Equals(std::vector<Catch::StringRef>{"Value1"} ) for: { Value1 } Equals: { Value1 }
|
||||
EnumToString.tests.cpp:<line number>: passed: parseEnums( "Value1" ), Equals( std::vector<Catch::StringRef>{"Value1"} ) for: { Value1 } Equals: { Value1 }
|
||||
EnumToString.tests.cpp:<line number>: passed: parseEnums( "EnumName::Value1" ), Equals(std::vector<Catch::StringRef>{"Value1"} ) for: { Value1 } Equals: { Value1 }
|
||||
EnumToString.tests.cpp:<line number>: passed: parseEnums( "ClassName::EnumName::Value1, ClassName::EnumName::Value2" ), Equals( std::vector<Catch::StringRef>{"Value1", "Value2"} ) for: { Value1, Value2 } Equals: { Value1, Value2 }
|
||||
EnumToString.tests.cpp:<line number>: passed: parseEnums( "ClassName::EnumName::Value1, ClassName::EnumName::Value2, ClassName::EnumName::Value3" ), Equals( std::vector<Catch::StringRef>{"Value1", "Value2", "Value3"} ) for: { Value1, Value2, Value3 } Equals: { Value1, Value2, Value3 }
|
||||
EnumToString.tests.cpp:<line number>: passed: parseEnums( "ClassName::EnumName::Value1,ClassName::EnumName::Value2 , ClassName::EnumName::Value3" ), Equals( std::vector<Catch::StringRef>{"Value1", "Value2", "Value3"} ) for: { Value1, Value2, Value3 } Equals: { Value1, Value2, Value3 }
|
||||
Tricky.tests.cpp:<line number>: passed: p == 0 for: 0 == 0
|
||||
Message.tests.cpp:<line number>: passed: true with 1 message: 'this MAY be seen IF info is printed for passing assertions'
|
||||
Message.tests.cpp:<line number>: failed: false with 2 messages: 'this SHOULD be seen' and 'this SHOULD also be seen'
|
||||
@@ -2986,7 +2989,7 @@ InternalBenchmark.tests.cpp:<line number>: passed: med == 18. for: 18.0 == 18.0
|
||||
InternalBenchmark.tests.cpp:<line number>: passed: q3 == 23. for: 23.0 == 23.0
|
||||
Misc.tests.cpp:<line number>: passed:
|
||||
Misc.tests.cpp:<line number>: passed:
|
||||
test cases: 450 | 330 passed | 96 failed | 6 skipped | 18 failed as expected
|
||||
assertions: 2413 | 2212 passed | 158 failed | 43 failed as expected
|
||||
test cases: 451 | 331 passed | 96 failed | 6 skipped | 18 failed as expected
|
||||
assertions: 2416 | 2215 passed | 158 failed | 43 failed as expected
|
||||
|
||||
|
||||
|
||||
@@ -1743,6 +1743,6 @@ due to unexpected exception with message:
|
||||
Why would you throw a std::string?
|
||||
|
||||
===============================================================================
|
||||
test cases: 450 | 348 passed | 76 failed | 7 skipped | 19 failed as expected
|
||||
assertions: 2391 | 2212 passed | 136 failed | 43 failed as expected
|
||||
test cases: 451 | 349 passed | 76 failed | 7 skipped | 19 failed as expected
|
||||
assertions: 2394 | 2215 passed | 136 failed | 43 failed as expected
|
||||
|
||||
|
||||
@@ -4241,21 +4241,21 @@ with message:
|
||||
-------------------------------------------------------------------------------
|
||||
Directly creating an EnumInfo
|
||||
-------------------------------------------------------------------------------
|
||||
ToString.tests.cpp:<line number>
|
||||
EnumToString.tests.cpp:<line number>
|
||||
...............................................................................
|
||||
|
||||
ToString.tests.cpp:<line number>: PASSED:
|
||||
CHECK( enumInfo->lookup(0) == "Value1" )
|
||||
EnumToString.tests.cpp:<line number>: PASSED:
|
||||
CHECK( enumInfo.lookup(0) == "Value1" )
|
||||
with expansion:
|
||||
Value1 == "Value1"
|
||||
|
||||
ToString.tests.cpp:<line number>: PASSED:
|
||||
CHECK( enumInfo->lookup(1) == "Value2" )
|
||||
EnumToString.tests.cpp:<line number>: PASSED:
|
||||
CHECK( enumInfo.lookup(1) == "Value2" )
|
||||
with expansion:
|
||||
Value2 == "Value2"
|
||||
|
||||
ToString.tests.cpp:<line number>: PASSED:
|
||||
CHECK( enumInfo->lookup(3) == "{** unexpected enum value **}" )
|
||||
EnumToString.tests.cpp:<line number>: PASSED:
|
||||
CHECK( enumInfo.lookup(3) == "{** unexpected enum value **}" )
|
||||
with expansion:
|
||||
{** unexpected enum value **}
|
||||
==
|
||||
@@ -4299,6 +4299,27 @@ with expansion:
|
||||
"this string contains 'abc' as a substring" ends with: "this" (case
|
||||
insensitive)
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
Enum backed by larger underlying type
|
||||
-------------------------------------------------------------------------------
|
||||
EnumToString.tests.cpp:<line number>
|
||||
...............................................................................
|
||||
|
||||
EnumToString.tests.cpp:<line number>: PASSED:
|
||||
REQUIRE( stringify( LargeEnum::Flag1 ) == "Flag1" )
|
||||
with expansion:
|
||||
"Flag1" == "Flag1"
|
||||
|
||||
EnumToString.tests.cpp:<line number>: PASSED:
|
||||
REQUIRE( stringify( LargeEnum::Flag2 ) == "Flag2" )
|
||||
with expansion:
|
||||
"Flag2" == "Flag2"
|
||||
|
||||
EnumToString.tests.cpp:<line number>: PASSED:
|
||||
REQUIRE( stringify( LargeEnum::Flag5 ) == "Flag5" )
|
||||
with expansion:
|
||||
"Flag5" == "Flag5"
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
Enums can quickly have stringification enabled using CATCH_REGISTER_ENUM
|
||||
-------------------------------------------------------------------------------
|
||||
@@ -18383,10 +18404,10 @@ with expansion:
|
||||
parseEnums
|
||||
No enums
|
||||
-------------------------------------------------------------------------------
|
||||
ToString.tests.cpp:<line number>
|
||||
EnumToString.tests.cpp:<line number>
|
||||
...............................................................................
|
||||
|
||||
ToString.tests.cpp:<line number>: PASSED:
|
||||
EnumToString.tests.cpp:<line number>: PASSED:
|
||||
CHECK_THAT( parseEnums( "" ), Equals( std::vector<Catch::StringRef>{} ) )
|
||||
with expansion:
|
||||
{ } Equals: { }
|
||||
@@ -18395,20 +18416,20 @@ with expansion:
|
||||
parseEnums
|
||||
One enum value
|
||||
-------------------------------------------------------------------------------
|
||||
ToString.tests.cpp:<line number>
|
||||
EnumToString.tests.cpp:<line number>
|
||||
...............................................................................
|
||||
|
||||
ToString.tests.cpp:<line number>: PASSED:
|
||||
EnumToString.tests.cpp:<line number>: PASSED:
|
||||
CHECK_THAT( parseEnums( "ClassName::EnumName::Value1" ), Equals(std::vector<Catch::StringRef>{"Value1"} ) )
|
||||
with expansion:
|
||||
{ Value1 } Equals: { Value1 }
|
||||
|
||||
ToString.tests.cpp:<line number>: PASSED:
|
||||
EnumToString.tests.cpp:<line number>: PASSED:
|
||||
CHECK_THAT( parseEnums( "Value1" ), Equals( std::vector<Catch::StringRef>{"Value1"} ) )
|
||||
with expansion:
|
||||
{ Value1 } Equals: { Value1 }
|
||||
|
||||
ToString.tests.cpp:<line number>: PASSED:
|
||||
EnumToString.tests.cpp:<line number>: PASSED:
|
||||
CHECK_THAT( parseEnums( "EnumName::Value1" ), Equals(std::vector<Catch::StringRef>{"Value1"} ) )
|
||||
with expansion:
|
||||
{ Value1 } Equals: { Value1 }
|
||||
@@ -18417,20 +18438,20 @@ with expansion:
|
||||
parseEnums
|
||||
Multiple enum values
|
||||
-------------------------------------------------------------------------------
|
||||
ToString.tests.cpp:<line number>
|
||||
EnumToString.tests.cpp:<line number>
|
||||
...............................................................................
|
||||
|
||||
ToString.tests.cpp:<line number>: PASSED:
|
||||
EnumToString.tests.cpp:<line number>: PASSED:
|
||||
CHECK_THAT( parseEnums( "ClassName::EnumName::Value1, ClassName::EnumName::Value2" ), Equals( std::vector<Catch::StringRef>{"Value1", "Value2"} ) )
|
||||
with expansion:
|
||||
{ Value1, Value2 } Equals: { Value1, Value2 }
|
||||
|
||||
ToString.tests.cpp:<line number>: PASSED:
|
||||
EnumToString.tests.cpp:<line number>: PASSED:
|
||||
CHECK_THAT( parseEnums( "ClassName::EnumName::Value1, ClassName::EnumName::Value2, ClassName::EnumName::Value3" ), Equals( std::vector<Catch::StringRef>{"Value1", "Value2", "Value3"} ) )
|
||||
with expansion:
|
||||
{ Value1, Value2, Value3 } Equals: { Value1, Value2, Value3 }
|
||||
|
||||
ToString.tests.cpp:<line number>: PASSED:
|
||||
EnumToString.tests.cpp:<line number>: PASSED:
|
||||
CHECK_THAT( parseEnums( "ClassName::EnumName::Value1,ClassName::EnumName::Value2 , ClassName::EnumName::Value3" ), Equals( std::vector<Catch::StringRef>{"Value1", "Value2", "Value3"} ) )
|
||||
with expansion:
|
||||
{ Value1, Value2, Value3 } Equals: { Value1, Value2, Value3 }
|
||||
@@ -20113,6 +20134,6 @@ Misc.tests.cpp:<line number>
|
||||
Misc.tests.cpp:<line number>: PASSED:
|
||||
|
||||
===============================================================================
|
||||
test cases: 450 | 330 passed | 96 failed | 6 skipped | 18 failed as expected
|
||||
assertions: 2413 | 2212 passed | 158 failed | 43 failed as expected
|
||||
test cases: 451 | 331 passed | 96 failed | 6 skipped | 18 failed as expected
|
||||
assertions: 2416 | 2215 passed | 158 failed | 43 failed as expected
|
||||
|
||||
|
||||
@@ -4239,21 +4239,21 @@ with message:
|
||||
-------------------------------------------------------------------------------
|
||||
Directly creating an EnumInfo
|
||||
-------------------------------------------------------------------------------
|
||||
ToString.tests.cpp:<line number>
|
||||
EnumToString.tests.cpp:<line number>
|
||||
...............................................................................
|
||||
|
||||
ToString.tests.cpp:<line number>: PASSED:
|
||||
CHECK( enumInfo->lookup(0) == "Value1" )
|
||||
EnumToString.tests.cpp:<line number>: PASSED:
|
||||
CHECK( enumInfo.lookup(0) == "Value1" )
|
||||
with expansion:
|
||||
Value1 == "Value1"
|
||||
|
||||
ToString.tests.cpp:<line number>: PASSED:
|
||||
CHECK( enumInfo->lookup(1) == "Value2" )
|
||||
EnumToString.tests.cpp:<line number>: PASSED:
|
||||
CHECK( enumInfo.lookup(1) == "Value2" )
|
||||
with expansion:
|
||||
Value2 == "Value2"
|
||||
|
||||
ToString.tests.cpp:<line number>: PASSED:
|
||||
CHECK( enumInfo->lookup(3) == "{** unexpected enum value **}" )
|
||||
EnumToString.tests.cpp:<line number>: PASSED:
|
||||
CHECK( enumInfo.lookup(3) == "{** unexpected enum value **}" )
|
||||
with expansion:
|
||||
{** unexpected enum value **}
|
||||
==
|
||||
@@ -4297,6 +4297,27 @@ with expansion:
|
||||
"this string contains 'abc' as a substring" ends with: "this" (case
|
||||
insensitive)
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
Enum backed by larger underlying type
|
||||
-------------------------------------------------------------------------------
|
||||
EnumToString.tests.cpp:<line number>
|
||||
...............................................................................
|
||||
|
||||
EnumToString.tests.cpp:<line number>: PASSED:
|
||||
REQUIRE( stringify( LargeEnum::Flag1 ) == "Flag1" )
|
||||
with expansion:
|
||||
"Flag1" == "Flag1"
|
||||
|
||||
EnumToString.tests.cpp:<line number>: PASSED:
|
||||
REQUIRE( stringify( LargeEnum::Flag2 ) == "Flag2" )
|
||||
with expansion:
|
||||
"Flag2" == "Flag2"
|
||||
|
||||
EnumToString.tests.cpp:<line number>: PASSED:
|
||||
REQUIRE( stringify( LargeEnum::Flag5 ) == "Flag5" )
|
||||
with expansion:
|
||||
"Flag5" == "Flag5"
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
Enums can quickly have stringification enabled using CATCH_REGISTER_ENUM
|
||||
-------------------------------------------------------------------------------
|
||||
@@ -18372,10 +18393,10 @@ with expansion:
|
||||
parseEnums
|
||||
No enums
|
||||
-------------------------------------------------------------------------------
|
||||
ToString.tests.cpp:<line number>
|
||||
EnumToString.tests.cpp:<line number>
|
||||
...............................................................................
|
||||
|
||||
ToString.tests.cpp:<line number>: PASSED:
|
||||
EnumToString.tests.cpp:<line number>: PASSED:
|
||||
CHECK_THAT( parseEnums( "" ), Equals( std::vector<Catch::StringRef>{} ) )
|
||||
with expansion:
|
||||
{ } Equals: { }
|
||||
@@ -18384,20 +18405,20 @@ with expansion:
|
||||
parseEnums
|
||||
One enum value
|
||||
-------------------------------------------------------------------------------
|
||||
ToString.tests.cpp:<line number>
|
||||
EnumToString.tests.cpp:<line number>
|
||||
...............................................................................
|
||||
|
||||
ToString.tests.cpp:<line number>: PASSED:
|
||||
EnumToString.tests.cpp:<line number>: PASSED:
|
||||
CHECK_THAT( parseEnums( "ClassName::EnumName::Value1" ), Equals(std::vector<Catch::StringRef>{"Value1"} ) )
|
||||
with expansion:
|
||||
{ Value1 } Equals: { Value1 }
|
||||
|
||||
ToString.tests.cpp:<line number>: PASSED:
|
||||
EnumToString.tests.cpp:<line number>: PASSED:
|
||||
CHECK_THAT( parseEnums( "Value1" ), Equals( std::vector<Catch::StringRef>{"Value1"} ) )
|
||||
with expansion:
|
||||
{ Value1 } Equals: { Value1 }
|
||||
|
||||
ToString.tests.cpp:<line number>: PASSED:
|
||||
EnumToString.tests.cpp:<line number>: PASSED:
|
||||
CHECK_THAT( parseEnums( "EnumName::Value1" ), Equals(std::vector<Catch::StringRef>{"Value1"} ) )
|
||||
with expansion:
|
||||
{ Value1 } Equals: { Value1 }
|
||||
@@ -18406,20 +18427,20 @@ with expansion:
|
||||
parseEnums
|
||||
Multiple enum values
|
||||
-------------------------------------------------------------------------------
|
||||
ToString.tests.cpp:<line number>
|
||||
EnumToString.tests.cpp:<line number>
|
||||
...............................................................................
|
||||
|
||||
ToString.tests.cpp:<line number>: PASSED:
|
||||
EnumToString.tests.cpp:<line number>: PASSED:
|
||||
CHECK_THAT( parseEnums( "ClassName::EnumName::Value1, ClassName::EnumName::Value2" ), Equals( std::vector<Catch::StringRef>{"Value1", "Value2"} ) )
|
||||
with expansion:
|
||||
{ Value1, Value2 } Equals: { Value1, Value2 }
|
||||
|
||||
ToString.tests.cpp:<line number>: PASSED:
|
||||
EnumToString.tests.cpp:<line number>: PASSED:
|
||||
CHECK_THAT( parseEnums( "ClassName::EnumName::Value1, ClassName::EnumName::Value2, ClassName::EnumName::Value3" ), Equals( std::vector<Catch::StringRef>{"Value1", "Value2", "Value3"} ) )
|
||||
with expansion:
|
||||
{ Value1, Value2, Value3 } Equals: { Value1, Value2, Value3 }
|
||||
|
||||
ToString.tests.cpp:<line number>: PASSED:
|
||||
EnumToString.tests.cpp:<line number>: PASSED:
|
||||
CHECK_THAT( parseEnums( "ClassName::EnumName::Value1,ClassName::EnumName::Value2 , ClassName::EnumName::Value3" ), Equals( std::vector<Catch::StringRef>{"Value1", "Value2", "Value3"} ) )
|
||||
with expansion:
|
||||
{ Value1, Value2, Value3 } Equals: { Value1, Value2, Value3 }
|
||||
@@ -20102,6 +20123,6 @@ Misc.tests.cpp:<line number>
|
||||
Misc.tests.cpp:<line number>: PASSED:
|
||||
|
||||
===============================================================================
|
||||
test cases: 450 | 330 passed | 96 failed | 6 skipped | 18 failed as expected
|
||||
assertions: 2413 | 2212 passed | 158 failed | 43 failed as expected
|
||||
test cases: 451 | 331 passed | 96 failed | 6 skipped | 18 failed as expected
|
||||
assertions: 2416 | 2215 passed | 158 failed | 43 failed as expected
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<testsuitesloose text artifact
|
||||
>
|
||||
<testsuite name="<exe-name>" errors="17" failures="141" skipped="12" tests="2425" hostname="tbd" time="{duration}" timestamp="{iso8601-timestamp}">
|
||||
<testsuite name="<exe-name>" errors="17" failures="141" skipped="12" tests="2428" hostname="tbd" time="{duration}" timestamp="{iso8601-timestamp}">
|
||||
<properties>
|
||||
<property name="random-seed" value="1"/>
|
||||
<property name="filters" value=""*" ~[!nonportable] ~[!benchmark] ~[approvals]"/>
|
||||
@@ -506,6 +506,7 @@ with expansion:
|
||||
at Matchers.tests.cpp:<line number>
|
||||
</failure>
|
||||
</testcase>
|
||||
<testcase classname="<exe-name>.global" name="Enum backed by larger underlying type" time="{duration}" status="run"/>
|
||||
<testcase classname="<exe-name>.global" name="Enums can quickly have stringification enabled using CATCH_REGISTER_ENUM" time="{duration}" status="run"/>
|
||||
<testcase classname="<exe-name>.global" name="Enums in namespaces can quickly have stringification enabled using CATCH_REGISTER_ENUM" time="{duration}" status="run"/>
|
||||
<testcase classname="<exe-name>.global" name="Epsilon only applies to Approx's value" time="{duration}" status="run"/>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<testsuites>
|
||||
<testsuite name="<exe-name>" errors="17" failures="141" skipped="12" tests="2425" hostname="tbd" time="{duration}" timestamp="{iso8601-timestamp}">
|
||||
<testsuite name="<exe-name>" errors="17" failures="141" skipped="12" tests="2428" hostname="tbd" time="{duration}" timestamp="{iso8601-timestamp}">
|
||||
<properties>
|
||||
<property name="random-seed" value="1"/>
|
||||
<property name="filters" value=""*" ~[!nonportable] ~[!benchmark] ~[approvals]"/>
|
||||
@@ -505,6 +505,7 @@ with expansion:
|
||||
at Matchers.tests.cpp:<line number>
|
||||
</failure>
|
||||
</testcase>
|
||||
<testcase classname="<exe-name>.global" name="Enum backed by larger underlying type" time="{duration}" status="run"/>
|
||||
<testcase classname="<exe-name>.global" name="Enums can quickly have stringification enabled using CATCH_REGISTER_ENUM" time="{duration}" status="run"/>
|
||||
<testcase classname="<exe-name>.global" name="Enums in namespaces can quickly have stringification enabled using CATCH_REGISTER_ENUM" time="{duration}" status="run"/>
|
||||
<testcase classname="<exe-name>.global" name="Epsilon only applies to Approx's value" time="{duration}" status="run"/>
|
||||
|
||||
@@ -422,16 +422,11 @@ at AssertionHandler.tests.cpp:<line number>
|
||||
<testCase name="Parsing tags with non-alphabetical characters is pass-through" duration="{duration}"/>
|
||||
</file>
|
||||
<file path="tests/<exe-name>/IntrospectiveTests/ToString.tests.cpp">
|
||||
<testCase name="Directly creating an EnumInfo" duration="{duration}"/>
|
||||
<testCase name="Exception thrown inside stringify does not fail the test" duration="{duration}"/>
|
||||
<testCase name="Range type with sentinel" duration="{duration}"/>
|
||||
<testCase name="Stringifying char arrays with statically known sizes - char" duration="{duration}"/>
|
||||
<testCase name="Stringifying char arrays with statically known sizes - signed char" duration="{duration}"/>
|
||||
<testCase name="Stringifying char arrays with statically known sizes - unsigned char" duration="{duration}"/>
|
||||
<testCase name="parseEnums" duration="{duration}"/>
|
||||
<testCase name="parseEnums/No enums" duration="{duration}"/>
|
||||
<testCase name="parseEnums/One enum value" duration="{duration}"/>
|
||||
<testCase name="parseEnums/Multiple enum values" duration="{duration}"/>
|
||||
</file>
|
||||
<file path="tests/<exe-name>/IntrospectiveTests/UniquePtr.tests.cpp">
|
||||
<testCase name="Upcasting special member functions" duration="{duration}"/>
|
||||
@@ -1079,8 +1074,14 @@ at Decomposition.tests.cpp:<line number>
|
||||
</testCase>
|
||||
</file>
|
||||
<file path="tests/<exe-name>/UsageTests/EnumToString.tests.cpp">
|
||||
<testCase name="Directly creating an EnumInfo" duration="{duration}"/>
|
||||
<testCase name="Enum backed by larger underlying type" duration="{duration}"/>
|
||||
<testCase name="Enums can quickly have stringification enabled using CATCH_REGISTER_ENUM" duration="{duration}"/>
|
||||
<testCase name="Enums in namespaces can quickly have stringification enabled using CATCH_REGISTER_ENUM" duration="{duration}"/>
|
||||
<testCase name="parseEnums" duration="{duration}"/>
|
||||
<testCase name="parseEnums/No enums" duration="{duration}"/>
|
||||
<testCase name="parseEnums/One enum value" duration="{duration}"/>
|
||||
<testCase name="parseEnums/Multiple enum values" duration="{duration}"/>
|
||||
<testCase name="toString(enum class w/operator<<)" duration="{duration}"/>
|
||||
<testCase name="toString(enum class)" duration="{duration}"/>
|
||||
<testCase name="toString(enum w/operator<<)" duration="{duration}"/>
|
||||
|
||||
@@ -421,16 +421,11 @@ at AssertionHandler.tests.cpp:<line number>
|
||||
<testCase name="Parsing tags with non-alphabetical characters is pass-through" duration="{duration}"/>
|
||||
</file>
|
||||
<file path="tests/<exe-name>/IntrospectiveTests/ToString.tests.cpp">
|
||||
<testCase name="Directly creating an EnumInfo" duration="{duration}"/>
|
||||
<testCase name="Exception thrown inside stringify does not fail the test" duration="{duration}"/>
|
||||
<testCase name="Range type with sentinel" duration="{duration}"/>
|
||||
<testCase name="Stringifying char arrays with statically known sizes - char" duration="{duration}"/>
|
||||
<testCase name="Stringifying char arrays with statically known sizes - signed char" duration="{duration}"/>
|
||||
<testCase name="Stringifying char arrays with statically known sizes - unsigned char" duration="{duration}"/>
|
||||
<testCase name="parseEnums" duration="{duration}"/>
|
||||
<testCase name="parseEnums/No enums" duration="{duration}"/>
|
||||
<testCase name="parseEnums/One enum value" duration="{duration}"/>
|
||||
<testCase name="parseEnums/Multiple enum values" duration="{duration}"/>
|
||||
</file>
|
||||
<file path="tests/<exe-name>/IntrospectiveTests/UniquePtr.tests.cpp">
|
||||
<testCase name="Upcasting special member functions" duration="{duration}"/>
|
||||
@@ -1078,8 +1073,14 @@ at Decomposition.tests.cpp:<line number>
|
||||
</testCase>
|
||||
</file>
|
||||
<file path="tests/<exe-name>/UsageTests/EnumToString.tests.cpp">
|
||||
<testCase name="Directly creating an EnumInfo" duration="{duration}"/>
|
||||
<testCase name="Enum backed by larger underlying type" duration="{duration}"/>
|
||||
<testCase name="Enums can quickly have stringification enabled using CATCH_REGISTER_ENUM" duration="{duration}"/>
|
||||
<testCase name="Enums in namespaces can quickly have stringification enabled using CATCH_REGISTER_ENUM" duration="{duration}"/>
|
||||
<testCase name="parseEnums" duration="{duration}"/>
|
||||
<testCase name="parseEnums/No enums" duration="{duration}"/>
|
||||
<testCase name="parseEnums/One enum value" duration="{duration}"/>
|
||||
<testCase name="parseEnums/Multiple enum values" duration="{duration}"/>
|
||||
<testCase name="toString(enum class w/operator<<)" duration="{duration}"/>
|
||||
<testCase name="toString(enum class)" duration="{duration}"/>
|
||||
<testCase name="toString(enum w/operator<<)" duration="{duration}"/>
|
||||
|
||||
@@ -1053,11 +1053,11 @@ ok {test-number} - true with 1 message: 'a'
|
||||
# Delayed unscoped message clearing does not catch newly inserted messages
|
||||
not ok {test-number} - false with 1 message: 'b'
|
||||
# Directly creating an EnumInfo
|
||||
ok {test-number} - enumInfo->lookup(0) == "Value1" for: Value1 == "Value1"
|
||||
ok {test-number} - enumInfo.lookup(0) == "Value1" for: Value1 == "Value1"
|
||||
# Directly creating an EnumInfo
|
||||
ok {test-number} - enumInfo->lookup(1) == "Value2" for: Value2 == "Value2"
|
||||
ok {test-number} - enumInfo.lookup(1) == "Value2" for: Value2 == "Value2"
|
||||
# Directly creating an EnumInfo
|
||||
ok {test-number} - enumInfo->lookup(3) == "{** unexpected enum value **}" for: {** unexpected enum value **} == "{** unexpected enum value **}"
|
||||
ok {test-number} - enumInfo.lookup(3) == "{** unexpected enum value **}" for: {** unexpected enum value **} == "{** unexpected enum value **}"
|
||||
# Empty generators can SKIP in constructor
|
||||
ok {test-number} - # SKIP 'This generator is empty'
|
||||
# Empty stream name opens cout stream
|
||||
@@ -1066,6 +1066,12 @@ ok {test-number} - Catch::makeStream( "" )->isConsole() for: true
|
||||
not ok {test-number} - testStringForMatching(), EndsWith( "Substring" ) for: "this string contains 'abc' as a substring" ends with: "Substring"
|
||||
# EndsWith string matcher
|
||||
not ok {test-number} - testStringForMatching(), EndsWith( "this", Catch::CaseSensitive::No ) for: "this string contains 'abc' as a substring" ends with: "this" (case insensitive)
|
||||
# Enum backed by larger underlying type
|
||||
ok {test-number} - stringify( LargeEnum::Flag1 ) == "Flag1" for: "Flag1" == "Flag1"
|
||||
# Enum backed by larger underlying type
|
||||
ok {test-number} - stringify( LargeEnum::Flag2 ) == "Flag2" for: "Flag2" == "Flag2"
|
||||
# Enum backed by larger underlying type
|
||||
ok {test-number} - stringify( LargeEnum::Flag5 ) == "Flag5" for: "Flag5" == "Flag5"
|
||||
# Enums can quickly have stringification enabled using CATCH_REGISTER_ENUM
|
||||
ok {test-number} - stringify( EnumClass3::Value1 ) == "Value1" for: "Value1" == "Value1"
|
||||
# Enums can quickly have stringification enabled using CATCH_REGISTER_ENUM
|
||||
@@ -4845,5 +4851,5 @@ ok {test-number} - q3 == 23. for: 23.0 == 23.0
|
||||
ok {test-number} -
|
||||
# xmlentitycheck
|
||||
ok {test-number} -
|
||||
1..2425
|
||||
1..2428
|
||||
|
||||
|
||||
@@ -1051,11 +1051,11 @@ ok {test-number} - true with 1 message: 'a'
|
||||
# Delayed unscoped message clearing does not catch newly inserted messages
|
||||
not ok {test-number} - false with 1 message: 'b'
|
||||
# Directly creating an EnumInfo
|
||||
ok {test-number} - enumInfo->lookup(0) == "Value1" for: Value1 == "Value1"
|
||||
ok {test-number} - enumInfo.lookup(0) == "Value1" for: Value1 == "Value1"
|
||||
# Directly creating an EnumInfo
|
||||
ok {test-number} - enumInfo->lookup(1) == "Value2" for: Value2 == "Value2"
|
||||
ok {test-number} - enumInfo.lookup(1) == "Value2" for: Value2 == "Value2"
|
||||
# Directly creating an EnumInfo
|
||||
ok {test-number} - enumInfo->lookup(3) == "{** unexpected enum value **}" for: {** unexpected enum value **} == "{** unexpected enum value **}"
|
||||
ok {test-number} - enumInfo.lookup(3) == "{** unexpected enum value **}" for: {** unexpected enum value **} == "{** unexpected enum value **}"
|
||||
# Empty generators can SKIP in constructor
|
||||
ok {test-number} - # SKIP 'This generator is empty'
|
||||
# Empty stream name opens cout stream
|
||||
@@ -1064,6 +1064,12 @@ ok {test-number} - Catch::makeStream( "" )->isConsole() for: true
|
||||
not ok {test-number} - testStringForMatching(), EndsWith( "Substring" ) for: "this string contains 'abc' as a substring" ends with: "Substring"
|
||||
# EndsWith string matcher
|
||||
not ok {test-number} - testStringForMatching(), EndsWith( "this", Catch::CaseSensitive::No ) for: "this string contains 'abc' as a substring" ends with: "this" (case insensitive)
|
||||
# Enum backed by larger underlying type
|
||||
ok {test-number} - stringify( LargeEnum::Flag1 ) == "Flag1" for: "Flag1" == "Flag1"
|
||||
# Enum backed by larger underlying type
|
||||
ok {test-number} - stringify( LargeEnum::Flag2 ) == "Flag2" for: "Flag2" == "Flag2"
|
||||
# Enum backed by larger underlying type
|
||||
ok {test-number} - stringify( LargeEnum::Flag5 ) == "Flag5" for: "Flag5" == "Flag5"
|
||||
# Enums can quickly have stringification enabled using CATCH_REGISTER_ENUM
|
||||
ok {test-number} - stringify( EnumClass3::Value1 ) == "Value1" for: "Value1" == "Value1"
|
||||
# Enums can quickly have stringification enabled using CATCH_REGISTER_ENUM
|
||||
@@ -4834,5 +4840,5 @@ ok {test-number} - q3 == 23. for: 23.0 == 23.0
|
||||
ok {test-number} -
|
||||
# xmlentitycheck
|
||||
ok {test-number} -
|
||||
1..2425
|
||||
1..2428
|
||||
|
||||
|
||||
@@ -338,6 +338,8 @@
|
||||
##teamcity[testFailed name='EndsWith string matcher' message='Matchers.tests.cpp:<line number>|n...............................................................................|n|nMatchers.tests.cpp:<line number>|nexpression failed|n CHECK_THAT( testStringForMatching(), EndsWith( "Substring" ) )|nwith expansion:|n "this string contains |'abc|' as a substring" ends with: "Substring"|n']
|
||||
##teamcity[testFailed name='EndsWith string matcher' message='Matchers.tests.cpp:<line number>|nexpression failed|n CHECK_THAT( testStringForMatching(), EndsWith( "this", Catch::CaseSensitive::No ) )|nwith expansion:|n "this string contains |'abc|' as a substring" ends with: "this" (case insensitive)|n']
|
||||
##teamcity[testFinished name='EndsWith string matcher' duration="{duration}"]
|
||||
##teamcity[testStarted name='Enum backed by larger underlying type']
|
||||
##teamcity[testFinished name='Enum backed by larger underlying type' duration="{duration}"]
|
||||
##teamcity[testStarted name='Enums can quickly have stringification enabled using CATCH_REGISTER_ENUM']
|
||||
##teamcity[testFinished name='Enums can quickly have stringification enabled using CATCH_REGISTER_ENUM' duration="{duration}"]
|
||||
##teamcity[testStarted name='Enums in namespaces can quickly have stringification enabled using CATCH_REGISTER_ENUM']
|
||||
|
||||
@@ -338,6 +338,8 @@
|
||||
##teamcity[testFailed name='EndsWith string matcher' message='Matchers.tests.cpp:<line number>|n...............................................................................|n|nMatchers.tests.cpp:<line number>|nexpression failed|n CHECK_THAT( testStringForMatching(), EndsWith( "Substring" ) )|nwith expansion:|n "this string contains |'abc|' as a substring" ends with: "Substring"|n']
|
||||
##teamcity[testFailed name='EndsWith string matcher' message='Matchers.tests.cpp:<line number>|nexpression failed|n CHECK_THAT( testStringForMatching(), EndsWith( "this", Catch::CaseSensitive::No ) )|nwith expansion:|n "this string contains |'abc|' as a substring" ends with: "this" (case insensitive)|n']
|
||||
##teamcity[testFinished name='EndsWith string matcher' duration="{duration}"]
|
||||
##teamcity[testStarted name='Enum backed by larger underlying type']
|
||||
##teamcity[testFinished name='Enum backed by larger underlying type' duration="{duration}"]
|
||||
##teamcity[testStarted name='Enums can quickly have stringification enabled using CATCH_REGISTER_ENUM']
|
||||
##teamcity[testFinished name='Enums can quickly have stringification enabled using CATCH_REGISTER_ENUM' duration="{duration}"]
|
||||
##teamcity[testStarted name='Enums in namespaces can quickly have stringification enabled using CATCH_REGISTER_ENUM']
|
||||
|
||||
@@ -4743,26 +4743,26 @@ C
|
||||
</Expression>
|
||||
<OverallResult success="true" skips="0"/>
|
||||
</TestCase>
|
||||
<TestCase name="Directly creating an EnumInfo" filename="tests/<exe-name>/IntrospectiveTests/ToString.tests.cpp" >
|
||||
<Expression success="true" type="CHECK" filename="tests/<exe-name>/IntrospectiveTests/ToString.tests.cpp" >
|
||||
<TestCase name="Directly creating an EnumInfo" filename="tests/<exe-name>/UsageTests/EnumToString.tests.cpp" >
|
||||
<Expression success="true" type="CHECK" filename="tests/<exe-name>/UsageTests/EnumToString.tests.cpp" >
|
||||
<Original>
|
||||
enumInfo->lookup(0) == "Value1"
|
||||
enumInfo.lookup(0) == "Value1"
|
||||
</Original>
|
||||
<Expanded>
|
||||
Value1 == "Value1"
|
||||
</Expanded>
|
||||
</Expression>
|
||||
<Expression success="true" type="CHECK" filename="tests/<exe-name>/IntrospectiveTests/ToString.tests.cpp" >
|
||||
<Expression success="true" type="CHECK" filename="tests/<exe-name>/UsageTests/EnumToString.tests.cpp" >
|
||||
<Original>
|
||||
enumInfo->lookup(1) == "Value2"
|
||||
enumInfo.lookup(1) == "Value2"
|
||||
</Original>
|
||||
<Expanded>
|
||||
Value2 == "Value2"
|
||||
</Expanded>
|
||||
</Expression>
|
||||
<Expression success="true" type="CHECK" filename="tests/<exe-name>/IntrospectiveTests/ToString.tests.cpp" >
|
||||
<Expression success="true" type="CHECK" filename="tests/<exe-name>/UsageTests/EnumToString.tests.cpp" >
|
||||
<Original>
|
||||
enumInfo->lookup(3) == "{** unexpected enum value **}"
|
||||
enumInfo.lookup(3) == "{** unexpected enum value **}"
|
||||
</Original>
|
||||
<Expanded>
|
||||
{** unexpected enum value **}
|
||||
@@ -4808,6 +4808,33 @@ C
|
||||
</Expression>
|
||||
<OverallResult success="false" skips="0"/>
|
||||
</TestCase>
|
||||
<TestCase name="Enum backed by larger underlying type" tags="[enum][toString]" filename="tests/<exe-name>/UsageTests/EnumToString.tests.cpp" >
|
||||
<Expression success="true" type="REQUIRE" filename="tests/<exe-name>/UsageTests/EnumToString.tests.cpp" >
|
||||
<Original>
|
||||
stringify( LargeEnum::Flag1 ) == "Flag1"
|
||||
</Original>
|
||||
<Expanded>
|
||||
"Flag1" == "Flag1"
|
||||
</Expanded>
|
||||
</Expression>
|
||||
<Expression success="true" type="REQUIRE" filename="tests/<exe-name>/UsageTests/EnumToString.tests.cpp" >
|
||||
<Original>
|
||||
stringify( LargeEnum::Flag2 ) == "Flag2"
|
||||
</Original>
|
||||
<Expanded>
|
||||
"Flag2" == "Flag2"
|
||||
</Expanded>
|
||||
</Expression>
|
||||
<Expression success="true" type="REQUIRE" filename="tests/<exe-name>/UsageTests/EnumToString.tests.cpp" >
|
||||
<Original>
|
||||
stringify( LargeEnum::Flag5 ) == "Flag5"
|
||||
</Original>
|
||||
<Expanded>
|
||||
"Flag5" == "Flag5"
|
||||
</Expanded>
|
||||
</Expression>
|
||||
<OverallResult success="true" skips="0"/>
|
||||
</TestCase>
|
||||
<TestCase name="Enums can quickly have stringification enabled using CATCH_REGISTER_ENUM" filename="tests/<exe-name>/UsageTests/EnumToString.tests.cpp" >
|
||||
<Expression success="true" type="REQUIRE" filename="tests/<exe-name>/UsageTests/EnumToString.tests.cpp" >
|
||||
<Original>
|
||||
@@ -21361,9 +21388,9 @@ Approx( -1.95996398454005449 )
|
||||
</Expression>
|
||||
<OverallResult success="true" skips="0"/>
|
||||
</TestCase>
|
||||
<TestCase name="parseEnums" tags="[enums][Strings]" filename="tests/<exe-name>/IntrospectiveTests/ToString.tests.cpp" >
|
||||
<Section name="No enums" filename="tests/<exe-name>/IntrospectiveTests/ToString.tests.cpp" >
|
||||
<Expression success="true" type="CHECK_THAT" filename="tests/<exe-name>/IntrospectiveTests/ToString.tests.cpp" >
|
||||
<TestCase name="parseEnums" tags="[enums][Strings]" filename="tests/<exe-name>/UsageTests/EnumToString.tests.cpp" >
|
||||
<Section name="No enums" filename="tests/<exe-name>/UsageTests/EnumToString.tests.cpp" >
|
||||
<Expression success="true" type="CHECK_THAT" filename="tests/<exe-name>/UsageTests/EnumToString.tests.cpp" >
|
||||
<Original>
|
||||
parseEnums( "" ), Equals( std::vector<Catch::StringRef>{} )
|
||||
</Original>
|
||||
@@ -21373,8 +21400,8 @@ Approx( -1.95996398454005449 )
|
||||
</Expression>
|
||||
<OverallResults successes="1" failures="0" expectedFailures="0" skipped="false"/>
|
||||
</Section>
|
||||
<Section name="One enum value" filename="tests/<exe-name>/IntrospectiveTests/ToString.tests.cpp" >
|
||||
<Expression success="true" type="CHECK_THAT" filename="tests/<exe-name>/IntrospectiveTests/ToString.tests.cpp" >
|
||||
<Section name="One enum value" filename="tests/<exe-name>/UsageTests/EnumToString.tests.cpp" >
|
||||
<Expression success="true" type="CHECK_THAT" filename="tests/<exe-name>/UsageTests/EnumToString.tests.cpp" >
|
||||
<Original>
|
||||
parseEnums( "ClassName::EnumName::Value1" ), Equals(std::vector<Catch::StringRef>{"Value1"} )
|
||||
</Original>
|
||||
@@ -21382,7 +21409,7 @@ Approx( -1.95996398454005449 )
|
||||
{ Value1 } Equals: { Value1 }
|
||||
</Expanded>
|
||||
</Expression>
|
||||
<Expression success="true" type="CHECK_THAT" filename="tests/<exe-name>/IntrospectiveTests/ToString.tests.cpp" >
|
||||
<Expression success="true" type="CHECK_THAT" filename="tests/<exe-name>/UsageTests/EnumToString.tests.cpp" >
|
||||
<Original>
|
||||
parseEnums( "Value1" ), Equals( std::vector<Catch::StringRef>{"Value1"} )
|
||||
</Original>
|
||||
@@ -21390,7 +21417,7 @@ Approx( -1.95996398454005449 )
|
||||
{ Value1 } Equals: { Value1 }
|
||||
</Expanded>
|
||||
</Expression>
|
||||
<Expression success="true" type="CHECK_THAT" filename="tests/<exe-name>/IntrospectiveTests/ToString.tests.cpp" >
|
||||
<Expression success="true" type="CHECK_THAT" filename="tests/<exe-name>/UsageTests/EnumToString.tests.cpp" >
|
||||
<Original>
|
||||
parseEnums( "EnumName::Value1" ), Equals(std::vector<Catch::StringRef>{"Value1"} )
|
||||
</Original>
|
||||
@@ -21400,8 +21427,8 @@ Approx( -1.95996398454005449 )
|
||||
</Expression>
|
||||
<OverallResults successes="3" failures="0" expectedFailures="0" skipped="false"/>
|
||||
</Section>
|
||||
<Section name="Multiple enum values" filename="tests/<exe-name>/IntrospectiveTests/ToString.tests.cpp" >
|
||||
<Expression success="true" type="CHECK_THAT" filename="tests/<exe-name>/IntrospectiveTests/ToString.tests.cpp" >
|
||||
<Section name="Multiple enum values" filename="tests/<exe-name>/UsageTests/EnumToString.tests.cpp" >
|
||||
<Expression success="true" type="CHECK_THAT" filename="tests/<exe-name>/UsageTests/EnumToString.tests.cpp" >
|
||||
<Original>
|
||||
parseEnums( "ClassName::EnumName::Value1, ClassName::EnumName::Value2" ), Equals( std::vector<Catch::StringRef>{"Value1", "Value2"} )
|
||||
</Original>
|
||||
@@ -21409,7 +21436,7 @@ Approx( -1.95996398454005449 )
|
||||
{ Value1, Value2 } Equals: { Value1, Value2 }
|
||||
</Expanded>
|
||||
</Expression>
|
||||
<Expression success="true" type="CHECK_THAT" filename="tests/<exe-name>/IntrospectiveTests/ToString.tests.cpp" >
|
||||
<Expression success="true" type="CHECK_THAT" filename="tests/<exe-name>/UsageTests/EnumToString.tests.cpp" >
|
||||
<Original>
|
||||
parseEnums( "ClassName::EnumName::Value1, ClassName::EnumName::Value2, ClassName::EnumName::Value3" ), Equals( std::vector<Catch::StringRef>{"Value1", "Value2", "Value3"} )
|
||||
</Original>
|
||||
@@ -21417,7 +21444,7 @@ Approx( -1.95996398454005449 )
|
||||
{ Value1, Value2, Value3 } Equals: { Value1, Value2, Value3 }
|
||||
</Expanded>
|
||||
</Expression>
|
||||
<Expression success="true" type="CHECK_THAT" filename="tests/<exe-name>/IntrospectiveTests/ToString.tests.cpp" >
|
||||
<Expression success="true" type="CHECK_THAT" filename="tests/<exe-name>/UsageTests/EnumToString.tests.cpp" >
|
||||
<Original>
|
||||
parseEnums( "ClassName::EnumName::Value1,ClassName::EnumName::Value2 , ClassName::EnumName::Value3" ), Equals( std::vector<Catch::StringRef>{"Value1", "Value2", "Value3"} )
|
||||
</Original>
|
||||
@@ -23358,6 +23385,6 @@ Approx( -1.95996398454005449 )
|
||||
</Section>
|
||||
<OverallResult success="true" skips="0"/>
|
||||
</TestCase>
|
||||
<OverallResults successes="2212" failures="158" expectedFailures="43" skips="12"/>
|
||||
<OverallResultsCases successes="330" failures="96" expectedFailures="18" skips="6"/>
|
||||
<OverallResults successes="2215" failures="158" expectedFailures="43" skips="12"/>
|
||||
<OverallResultsCases successes="331" failures="96" expectedFailures="18" skips="6"/>
|
||||
</Catch2TestRun>
|
||||
|
||||
@@ -4743,26 +4743,26 @@ C
|
||||
</Expression>
|
||||
<OverallResult success="true" skips="0"/>
|
||||
</TestCase>
|
||||
<TestCase name="Directly creating an EnumInfo" filename="tests/<exe-name>/IntrospectiveTests/ToString.tests.cpp" >
|
||||
<Expression success="true" type="CHECK" filename="tests/<exe-name>/IntrospectiveTests/ToString.tests.cpp" >
|
||||
<TestCase name="Directly creating an EnumInfo" filename="tests/<exe-name>/UsageTests/EnumToString.tests.cpp" >
|
||||
<Expression success="true" type="CHECK" filename="tests/<exe-name>/UsageTests/EnumToString.tests.cpp" >
|
||||
<Original>
|
||||
enumInfo->lookup(0) == "Value1"
|
||||
enumInfo.lookup(0) == "Value1"
|
||||
</Original>
|
||||
<Expanded>
|
||||
Value1 == "Value1"
|
||||
</Expanded>
|
||||
</Expression>
|
||||
<Expression success="true" type="CHECK" filename="tests/<exe-name>/IntrospectiveTests/ToString.tests.cpp" >
|
||||
<Expression success="true" type="CHECK" filename="tests/<exe-name>/UsageTests/EnumToString.tests.cpp" >
|
||||
<Original>
|
||||
enumInfo->lookup(1) == "Value2"
|
||||
enumInfo.lookup(1) == "Value2"
|
||||
</Original>
|
||||
<Expanded>
|
||||
Value2 == "Value2"
|
||||
</Expanded>
|
||||
</Expression>
|
||||
<Expression success="true" type="CHECK" filename="tests/<exe-name>/IntrospectiveTests/ToString.tests.cpp" >
|
||||
<Expression success="true" type="CHECK" filename="tests/<exe-name>/UsageTests/EnumToString.tests.cpp" >
|
||||
<Original>
|
||||
enumInfo->lookup(3) == "{** unexpected enum value **}"
|
||||
enumInfo.lookup(3) == "{** unexpected enum value **}"
|
||||
</Original>
|
||||
<Expanded>
|
||||
{** unexpected enum value **}
|
||||
@@ -4808,6 +4808,33 @@ C
|
||||
</Expression>
|
||||
<OverallResult success="false" skips="0"/>
|
||||
</TestCase>
|
||||
<TestCase name="Enum backed by larger underlying type" tags="[enum][toString]" filename="tests/<exe-name>/UsageTests/EnumToString.tests.cpp" >
|
||||
<Expression success="true" type="REQUIRE" filename="tests/<exe-name>/UsageTests/EnumToString.tests.cpp" >
|
||||
<Original>
|
||||
stringify( LargeEnum::Flag1 ) == "Flag1"
|
||||
</Original>
|
||||
<Expanded>
|
||||
"Flag1" == "Flag1"
|
||||
</Expanded>
|
||||
</Expression>
|
||||
<Expression success="true" type="REQUIRE" filename="tests/<exe-name>/UsageTests/EnumToString.tests.cpp" >
|
||||
<Original>
|
||||
stringify( LargeEnum::Flag2 ) == "Flag2"
|
||||
</Original>
|
||||
<Expanded>
|
||||
"Flag2" == "Flag2"
|
||||
</Expanded>
|
||||
</Expression>
|
||||
<Expression success="true" type="REQUIRE" filename="tests/<exe-name>/UsageTests/EnumToString.tests.cpp" >
|
||||
<Original>
|
||||
stringify( LargeEnum::Flag5 ) == "Flag5"
|
||||
</Original>
|
||||
<Expanded>
|
||||
"Flag5" == "Flag5"
|
||||
</Expanded>
|
||||
</Expression>
|
||||
<OverallResult success="true" skips="0"/>
|
||||
</TestCase>
|
||||
<TestCase name="Enums can quickly have stringification enabled using CATCH_REGISTER_ENUM" filename="tests/<exe-name>/UsageTests/EnumToString.tests.cpp" >
|
||||
<Expression success="true" type="REQUIRE" filename="tests/<exe-name>/UsageTests/EnumToString.tests.cpp" >
|
||||
<Original>
|
||||
@@ -21360,9 +21387,9 @@ Approx( -1.95996398454005449 )
|
||||
</Expression>
|
||||
<OverallResult success="true" skips="0"/>
|
||||
</TestCase>
|
||||
<TestCase name="parseEnums" tags="[enums][Strings]" filename="tests/<exe-name>/IntrospectiveTests/ToString.tests.cpp" >
|
||||
<Section name="No enums" filename="tests/<exe-name>/IntrospectiveTests/ToString.tests.cpp" >
|
||||
<Expression success="true" type="CHECK_THAT" filename="tests/<exe-name>/IntrospectiveTests/ToString.tests.cpp" >
|
||||
<TestCase name="parseEnums" tags="[enums][Strings]" filename="tests/<exe-name>/UsageTests/EnumToString.tests.cpp" >
|
||||
<Section name="No enums" filename="tests/<exe-name>/UsageTests/EnumToString.tests.cpp" >
|
||||
<Expression success="true" type="CHECK_THAT" filename="tests/<exe-name>/UsageTests/EnumToString.tests.cpp" >
|
||||
<Original>
|
||||
parseEnums( "" ), Equals( std::vector<Catch::StringRef>{} )
|
||||
</Original>
|
||||
@@ -21372,8 +21399,8 @@ Approx( -1.95996398454005449 )
|
||||
</Expression>
|
||||
<OverallResults successes="1" failures="0" expectedFailures="0" skipped="false"/>
|
||||
</Section>
|
||||
<Section name="One enum value" filename="tests/<exe-name>/IntrospectiveTests/ToString.tests.cpp" >
|
||||
<Expression success="true" type="CHECK_THAT" filename="tests/<exe-name>/IntrospectiveTests/ToString.tests.cpp" >
|
||||
<Section name="One enum value" filename="tests/<exe-name>/UsageTests/EnumToString.tests.cpp" >
|
||||
<Expression success="true" type="CHECK_THAT" filename="tests/<exe-name>/UsageTests/EnumToString.tests.cpp" >
|
||||
<Original>
|
||||
parseEnums( "ClassName::EnumName::Value1" ), Equals(std::vector<Catch::StringRef>{"Value1"} )
|
||||
</Original>
|
||||
@@ -21381,7 +21408,7 @@ Approx( -1.95996398454005449 )
|
||||
{ Value1 } Equals: { Value1 }
|
||||
</Expanded>
|
||||
</Expression>
|
||||
<Expression success="true" type="CHECK_THAT" filename="tests/<exe-name>/IntrospectiveTests/ToString.tests.cpp" >
|
||||
<Expression success="true" type="CHECK_THAT" filename="tests/<exe-name>/UsageTests/EnumToString.tests.cpp" >
|
||||
<Original>
|
||||
parseEnums( "Value1" ), Equals( std::vector<Catch::StringRef>{"Value1"} )
|
||||
</Original>
|
||||
@@ -21389,7 +21416,7 @@ Approx( -1.95996398454005449 )
|
||||
{ Value1 } Equals: { Value1 }
|
||||
</Expanded>
|
||||
</Expression>
|
||||
<Expression success="true" type="CHECK_THAT" filename="tests/<exe-name>/IntrospectiveTests/ToString.tests.cpp" >
|
||||
<Expression success="true" type="CHECK_THAT" filename="tests/<exe-name>/UsageTests/EnumToString.tests.cpp" >
|
||||
<Original>
|
||||
parseEnums( "EnumName::Value1" ), Equals(std::vector<Catch::StringRef>{"Value1"} )
|
||||
</Original>
|
||||
@@ -21399,8 +21426,8 @@ Approx( -1.95996398454005449 )
|
||||
</Expression>
|
||||
<OverallResults successes="3" failures="0" expectedFailures="0" skipped="false"/>
|
||||
</Section>
|
||||
<Section name="Multiple enum values" filename="tests/<exe-name>/IntrospectiveTests/ToString.tests.cpp" >
|
||||
<Expression success="true" type="CHECK_THAT" filename="tests/<exe-name>/IntrospectiveTests/ToString.tests.cpp" >
|
||||
<Section name="Multiple enum values" filename="tests/<exe-name>/UsageTests/EnumToString.tests.cpp" >
|
||||
<Expression success="true" type="CHECK_THAT" filename="tests/<exe-name>/UsageTests/EnumToString.tests.cpp" >
|
||||
<Original>
|
||||
parseEnums( "ClassName::EnumName::Value1, ClassName::EnumName::Value2" ), Equals( std::vector<Catch::StringRef>{"Value1", "Value2"} )
|
||||
</Original>
|
||||
@@ -21408,7 +21435,7 @@ Approx( -1.95996398454005449 )
|
||||
{ Value1, Value2 } Equals: { Value1, Value2 }
|
||||
</Expanded>
|
||||
</Expression>
|
||||
<Expression success="true" type="CHECK_THAT" filename="tests/<exe-name>/IntrospectiveTests/ToString.tests.cpp" >
|
||||
<Expression success="true" type="CHECK_THAT" filename="tests/<exe-name>/UsageTests/EnumToString.tests.cpp" >
|
||||
<Original>
|
||||
parseEnums( "ClassName::EnumName::Value1, ClassName::EnumName::Value2, ClassName::EnumName::Value3" ), Equals( std::vector<Catch::StringRef>{"Value1", "Value2", "Value3"} )
|
||||
</Original>
|
||||
@@ -21416,7 +21443,7 @@ Approx( -1.95996398454005449 )
|
||||
{ Value1, Value2, Value3 } Equals: { Value1, Value2, Value3 }
|
||||
</Expanded>
|
||||
</Expression>
|
||||
<Expression success="true" type="CHECK_THAT" filename="tests/<exe-name>/IntrospectiveTests/ToString.tests.cpp" >
|
||||
<Expression success="true" type="CHECK_THAT" filename="tests/<exe-name>/UsageTests/EnumToString.tests.cpp" >
|
||||
<Original>
|
||||
parseEnums( "ClassName::EnumName::Value1,ClassName::EnumName::Value2 , ClassName::EnumName::Value3" ), Equals( std::vector<Catch::StringRef>{"Value1", "Value2", "Value3"} )
|
||||
</Original>
|
||||
@@ -23357,6 +23384,6 @@ Approx( -1.95996398454005449 )
|
||||
</Section>
|
||||
<OverallResult success="true" skips="0"/>
|
||||
</TestCase>
|
||||
<OverallResults successes="2212" failures="158" expectedFailures="43" skips="12"/>
|
||||
<OverallResultsCases successes="330" failures="96" expectedFailures="18" skips="6"/>
|
||||
<OverallResults successes="2215" failures="158" expectedFailures="43" skips="12"/>
|
||||
<OverallResultsCases successes="331" failures="96" expectedFailures="18" skips="6"/>
|
||||
</Catch2TestRun>
|
||||
|
||||
@@ -39,8 +39,8 @@ namespace {
|
||||
// -------------------------
|
||||
// | a | b | c | d |
|
||||
|
||||
#define CarryBits( x ) ( x >> 32 )
|
||||
#define Digits( x ) ( x & 0xFF'FF'FF'FF )
|
||||
#define CarryBits( x ) ( (x) >> 32 )
|
||||
#define Digits( x ) ( (x) & 0xFF'FF'FF'FF )
|
||||
|
||||
auto r2l2 = Digits( rhs ) * Digits( lhs );
|
||||
auto r2l1 = Digits( rhs ) * CarryBits( lhs );
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
#include <catch2/catch_config.hpp>
|
||||
#include <catch2/interfaces/catch_interfaces_reporter.hpp>
|
||||
#include <catch2/interfaces/catch_interfaces_reporter_factory.hpp>
|
||||
#include <catch2/interfaces/catch_interfaces_registry_hub.hpp>
|
||||
#include <catch2/internal/catch_console_colour.hpp>
|
||||
#include <catch2/internal/catch_enforce.hpp>
|
||||
#include <catch2/internal/catch_list.hpp>
|
||||
|
||||
@@ -437,6 +437,25 @@ TEST_CASE( "TextFlow::AnsiSkippingString iterates UTF-8 codepoints",
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE( "TextFlow::AnsiSkippingString handles invalid UTF-8",
|
||||
"[TextFlow][ansiskippingstring][approvals]" ) {
|
||||
SECTION( "Continuation byte at the start" ) {
|
||||
// 0x80 is a continuation byte
|
||||
AnsiSkippingString str( "\x80" );
|
||||
auto it = str.end();
|
||||
--it;
|
||||
CHECK( it == str.begin() );
|
||||
CHECK( *it == static_cast<char>( 0x80 ) );
|
||||
}
|
||||
SECTION( "Multiple continuation bytes at the start" ) {
|
||||
AnsiSkippingString str( "\x80\x80\x80" );
|
||||
auto it = str.end();
|
||||
--it;
|
||||
CHECK( it == str.begin() );
|
||||
CHECK( *it == static_cast<char>( 0x80 ) );
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE( "TextFlow::Column wraps UTF-8 text correctly",
|
||||
"[TextFlow][column][approvals]" ) {
|
||||
// "äöü äöü äöü" = 11 codepoints, 17 bytes
|
||||
|
||||
@@ -10,14 +10,10 @@
|
||||
#include <catch2/catch_template_test_macros.hpp>
|
||||
#include <catch2/catch_test_macros.hpp>
|
||||
#include <catch2/generators/catch_generators.hpp>
|
||||
#include <catch2/internal/catch_enum_values_registry.hpp>
|
||||
#include <catch2/matchers/catch_matchers_string.hpp>
|
||||
#include <catch2/matchers/catch_matchers_vector.hpp>
|
||||
|
||||
#include <chrono>
|
||||
|
||||
enum class EnumClass3 { Value1, Value2, Value3, Value4 };
|
||||
|
||||
struct UsesSentinel {
|
||||
using const_iterator = int const*;
|
||||
using const_sentinel = std::nullptr_t;
|
||||
@@ -26,42 +22,6 @@ struct UsesSentinel {
|
||||
const_iterator end() const { return nullptr; }
|
||||
};
|
||||
|
||||
TEST_CASE( "parseEnums", "[Strings][enums]" ) {
|
||||
using namespace Catch::Matchers;
|
||||
using Catch::Detail::parseEnums;
|
||||
|
||||
SECTION( "No enums" )
|
||||
CHECK_THAT( parseEnums( "" ), Equals( std::vector<Catch::StringRef>{} ) );
|
||||
|
||||
SECTION( "One enum value" ) {
|
||||
CHECK_THAT( parseEnums( "ClassName::EnumName::Value1" ),
|
||||
Equals(std::vector<Catch::StringRef>{"Value1"} ) );
|
||||
CHECK_THAT( parseEnums( "Value1" ),
|
||||
Equals( std::vector<Catch::StringRef>{"Value1"} ) );
|
||||
CHECK_THAT( parseEnums( "EnumName::Value1" ),
|
||||
Equals(std::vector<Catch::StringRef>{"Value1"} ) );
|
||||
}
|
||||
|
||||
SECTION( "Multiple enum values" ) {
|
||||
CHECK_THAT( parseEnums( "ClassName::EnumName::Value1, ClassName::EnumName::Value2" ),
|
||||
Equals( std::vector<Catch::StringRef>{"Value1", "Value2"} ) );
|
||||
CHECK_THAT( parseEnums( "ClassName::EnumName::Value1, ClassName::EnumName::Value2, ClassName::EnumName::Value3" ),
|
||||
Equals( std::vector<Catch::StringRef>{"Value1", "Value2", "Value3"} ) );
|
||||
CHECK_THAT( parseEnums( "ClassName::EnumName::Value1,ClassName::EnumName::Value2 , ClassName::EnumName::Value3" ),
|
||||
Equals( std::vector<Catch::StringRef>{"Value1", "Value2", "Value3"} ) );
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE( "Directly creating an EnumInfo" ) {
|
||||
|
||||
using namespace Catch::Detail;
|
||||
auto enumInfo = makeEnumInfo( "EnumName", "EnumName::Value1, EnumName::Value2", {0, 1} );
|
||||
|
||||
CHECK( enumInfo->lookup(0) == "Value1" );
|
||||
CHECK( enumInfo->lookup(1) == "Value2" );
|
||||
CHECK( enumInfo->lookup(3) == "{** unexpected enum value **}" );
|
||||
}
|
||||
|
||||
TEST_CASE("Range type with sentinel") {
|
||||
CHECK( Catch::Detail::stringify(UsesSentinel{}) == "{ }" );
|
||||
}
|
||||
|
||||
@@ -7,8 +7,60 @@
|
||||
// SPDX-License-Identifier: BSL-1.0
|
||||
|
||||
#include <catch2/catch_test_macros.hpp>
|
||||
#include <catch2/internal/catch_enum_values_registry.hpp>
|
||||
#include <catch2/internal/catch_enum_info.hpp>
|
||||
#include <catch2/matchers/catch_matchers_vector.hpp>
|
||||
|
||||
namespace Bikeshed {
|
||||
enum class Colours { Red, Green, Blue };
|
||||
}
|
||||
|
||||
// Important!: This macro must appear at top level scope - not inside a namespace
|
||||
// You can fully qualify the names, or use a using if you prefer
|
||||
CATCH_REGISTER_ENUM( Bikeshed::Colours,
|
||||
Bikeshed::Colours::Red,
|
||||
Bikeshed::Colours::Green,
|
||||
Bikeshed::Colours::Blue )
|
||||
|
||||
TEST_CASE( "Enums in namespaces can quickly have stringification enabled using CATCH_REGISTER_ENUM" ) {
|
||||
using Catch::Detail::stringify;
|
||||
REQUIRE( stringify( Bikeshed::Colours::Red ) == "Red" );
|
||||
REQUIRE( stringify( Bikeshed::Colours::Blue ) == "Blue" );
|
||||
}
|
||||
|
||||
TEST_CASE( "parseEnums", "[Strings][enums]" ) {
|
||||
using namespace Catch::Matchers;
|
||||
using Catch::Detail::parseEnums;
|
||||
|
||||
SECTION( "No enums" )
|
||||
CHECK_THAT( parseEnums( "" ), Equals( std::vector<Catch::StringRef>{} ) );
|
||||
|
||||
SECTION( "One enum value" ) {
|
||||
CHECK_THAT( parseEnums( "ClassName::EnumName::Value1" ),
|
||||
Equals(std::vector<Catch::StringRef>{"Value1"} ) );
|
||||
CHECK_THAT( parseEnums( "Value1" ),
|
||||
Equals( std::vector<Catch::StringRef>{"Value1"} ) );
|
||||
CHECK_THAT( parseEnums( "EnumName::Value1" ),
|
||||
Equals(std::vector<Catch::StringRef>{"Value1"} ) );
|
||||
}
|
||||
|
||||
SECTION( "Multiple enum values" ) {
|
||||
CHECK_THAT( parseEnums( "ClassName::EnumName::Value1, ClassName::EnumName::Value2" ),
|
||||
Equals( std::vector<Catch::StringRef>{"Value1", "Value2"} ) );
|
||||
CHECK_THAT( parseEnums( "ClassName::EnumName::Value1, ClassName::EnumName::Value2, ClassName::EnumName::Value3" ),
|
||||
Equals( std::vector<Catch::StringRef>{"Value1", "Value2", "Value3"} ) );
|
||||
CHECK_THAT( parseEnums( "ClassName::EnumName::Value1,ClassName::EnumName::Value2 , ClassName::EnumName::Value3" ),
|
||||
Equals( std::vector<Catch::StringRef>{"Value1", "Value2", "Value3"} ) );
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE( "Directly creating an EnumInfo" ) {
|
||||
using namespace Catch::Detail;
|
||||
auto enumInfo = makeEnumInfo( "EnumName", "EnumName::Value1, EnumName::Value2", {0, 1} );
|
||||
|
||||
CHECK( enumInfo.lookup(0) == "Value1" );
|
||||
CHECK( enumInfo.lookup(1) == "Value2" );
|
||||
CHECK( enumInfo.lookup(3) == "{** unexpected enum value **}" );
|
||||
}
|
||||
|
||||
namespace {
|
||||
// Enum without user-provided stream operator
|
||||
@@ -90,19 +142,24 @@ TEST_CASE( "Enums can quickly have stringification enabled using CATCH_REGISTER_
|
||||
REQUIRE( stringify( ec3 ) == "Value2" );
|
||||
}
|
||||
|
||||
namespace Bikeshed {
|
||||
enum class Colours { Red, Green, Blue };
|
||||
}
|
||||
enum class LargeEnum : std::int64_t {
|
||||
Flag1 = 0x01,
|
||||
Flag2 = 0x02,
|
||||
Flag3 = 0x04,
|
||||
Flag4 = 0x08,
|
||||
Flag5 = 0x10,
|
||||
};
|
||||
|
||||
// Important!: This macro must appear at top level scope - not inside a namespace
|
||||
// You can fully qualify the names, or use a using if you prefer
|
||||
CATCH_REGISTER_ENUM( Bikeshed::Colours,
|
||||
Bikeshed::Colours::Red,
|
||||
Bikeshed::Colours::Green,
|
||||
Bikeshed::Colours::Blue )
|
||||
CATCH_REGISTER_ENUM( LargeEnum,
|
||||
LargeEnum::Flag1,
|
||||
LargeEnum::Flag2,
|
||||
LargeEnum::Flag3,
|
||||
LargeEnum::Flag4,
|
||||
LargeEnum::Flag5 )
|
||||
|
||||
TEST_CASE( "Enums in namespaces can quickly have stringification enabled using CATCH_REGISTER_ENUM" ) {
|
||||
TEST_CASE( "Enum backed by larger underlying type", "[enum][toString]" ) {
|
||||
using Catch::Detail::stringify;
|
||||
REQUIRE( stringify( Bikeshed::Colours::Red ) == "Red" );
|
||||
REQUIRE( stringify( Bikeshed::Colours::Blue ) == "Blue" );
|
||||
REQUIRE( stringify( LargeEnum::Flag1 ) == "Flag1" );
|
||||
REQUIRE( stringify( LargeEnum::Flag2 ) == "Flag2" );
|
||||
REQUIRE( stringify( LargeEnum::Flag5 ) == "Flag5" );
|
||||
}
|
||||
|
||||
@@ -0,0 +1,131 @@
|
||||
|
||||
// Copyright Catch2 Authors
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// (See accompanying file LICENSE.txt or copy at
|
||||
// https://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
// SPDX-License-Identifier: BSL-1.0
|
||||
|
||||
#include <catch2/internal/catch_compiler_capabilities.hpp>
|
||||
|
||||
#if defined( CATCH_INTERNAL_CONSTEXPR_MATCHERS_ENABLED )
|
||||
|
||||
#include <catch2/catch_test_macros.hpp>
|
||||
#include <catch2/matchers/catch_matchers_templated.hpp>
|
||||
#include <catch2/matchers/catch_matchers_container_properties.hpp>
|
||||
#include <catch2/matchers/catch_matchers_quantifiers.hpp>
|
||||
#include <catch2/matchers/catch_matchers_contains.hpp>
|
||||
#include <catch2/matchers/catch_matchers_range_equals.hpp>
|
||||
|
||||
#include <array>
|
||||
|
||||
namespace {
|
||||
struct MatchAllMatcher final : public Catch::Matchers::MatcherGenericBase {
|
||||
public:
|
||||
template <typename Any>
|
||||
constexpr bool match( Any&& ) const {
|
||||
return true;
|
||||
}
|
||||
|
||||
std::string describe() const override {
|
||||
using namespace std::string_literals;
|
||||
return "Matches anything"s;
|
||||
}
|
||||
};
|
||||
|
||||
constexpr MatchAllMatcher MatchAll() { return MatchAllMatcher(); }
|
||||
|
||||
struct MatchTrueMatcher final : public Catch::Matchers::MatcherGenericBase {
|
||||
public:
|
||||
constexpr bool match( bool b ) const {
|
||||
return b;
|
||||
}
|
||||
|
||||
std::string describe() const override {
|
||||
using namespace std::string_literals;
|
||||
return "Matches true"s;
|
||||
}
|
||||
};
|
||||
|
||||
constexpr MatchTrueMatcher MatchTrue() { return MatchTrueMatcher(); }
|
||||
|
||||
constexpr std::array<bool, 3> compute_bools( int type ) {
|
||||
switch ( type ) {
|
||||
case 0:
|
||||
return { true, true, true };
|
||||
case 1:
|
||||
return { false, true, false };
|
||||
case 2:
|
||||
return { false, false, false };
|
||||
case 3:
|
||||
return { true, false, false };
|
||||
case 4:
|
||||
return { true, true, false };
|
||||
default:
|
||||
return { false, false, false };
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
TEST_CASE( "Constexpr support for matchers", "[constexpr][matchers][approvals]" ) {
|
||||
STATIC_REQUIRE( MatchAll().match( 1 ) );
|
||||
STATIC_REQUIRE_THAT( 1, MatchAll() );
|
||||
}
|
||||
|
||||
TEST_CASE( "IsEmpty and HasSize matchers can be used in constexpr contexts",
|
||||
"[constexpr][matchers][approvals]" ){
|
||||
using namespace Catch::Matchers;
|
||||
static constexpr std::array<int, 0> empty{};
|
||||
STATIC_REQUIRE_THAT( empty, IsEmpty() );
|
||||
static constexpr int arr[1] = { 2 };
|
||||
STATIC_REQUIRE_THAT( arr, SizeIs( 1 ) );
|
||||
STATIC_REQUIRE_THAT( arr, SizeIs( MatchAll() ) );
|
||||
}
|
||||
|
||||
TEST_CASE( "Quantifier matchers can be used in constexpr contexts",
|
||||
"[constexpr][matchers][approvals]" ) {
|
||||
using namespace Catch::Matchers;
|
||||
STATIC_REQUIRE_THAT( compute_bools( 0 ), AllTrue() );
|
||||
STATIC_REQUIRE_THAT( compute_bools( 1 ), AnyTrue() );
|
||||
STATIC_REQUIRE_THAT( compute_bools( 2 ), NoneTrue() );
|
||||
|
||||
STATIC_REQUIRE_THAT( compute_bools( 0 ), AllMatch( MatchTrue() ) );
|
||||
STATIC_REQUIRE_THAT( compute_bools( 1 ), AnyMatch( MatchTrue() ) );
|
||||
STATIC_REQUIRE_THAT( compute_bools( 2 ), NoneMatch( MatchTrue() ) );
|
||||
}
|
||||
|
||||
TEST_CASE( "Generic Equals matchers can be used in constexpr contexts",
|
||||
"[constexpr][matchers][approvals]" ) {
|
||||
using Catch::Matchers::Contains;
|
||||
STATIC_REQUIRE_THAT( compute_bools( 0 ), Contains( true ) );
|
||||
STATIC_REQUIRE_THAT( compute_bools( 1 ), Contains( MatchTrue() ) );
|
||||
STATIC_REQUIRE_THAT( compute_bools( 2 ), Contains( true, std::not_equal_to<>{} ) );
|
||||
}
|
||||
|
||||
TEST_CASE( "Range equals matchers can be used in constexpr contexts",
|
||||
"[constexpr][matchers][approvals]" ) {
|
||||
using Catch::Matchers::RangeEquals;
|
||||
using Catch::Matchers::UnorderedRangeEquals;
|
||||
STATIC_REQUIRE_THAT( compute_bools( 0 ), RangeEquals( compute_bools( 0 ) ) );
|
||||
STATIC_REQUIRE_THAT( compute_bools( 2 ), RangeEquals( compute_bools( 0 ), std::not_equal_to<>{} ) );
|
||||
STATIC_REQUIRE_THAT( compute_bools( 1 ), UnorderedRangeEquals( compute_bools( 3 ) ) );
|
||||
STATIC_REQUIRE_THAT( compute_bools( 1 ), UnorderedRangeEquals( compute_bools( 4 ), std::not_equal_to<>{} ) );
|
||||
}
|
||||
|
||||
// Combining matchers needs C++26 and P2738, so they are in separate preprocessor block
|
||||
# if __cpp_constexpr >= 202306L
|
||||
|
||||
TEST_CASE("Constexpr support for combining matchers",
|
||||
"[constexpr][matchers][approvals]") {
|
||||
STATIC_REQUIRE( ( MatchAll() && MatchAll() ).match( 1 ) );
|
||||
STATIC_REQUIRE( ( MatchAll() || MatchAll() ).match( 1 ) );
|
||||
STATIC_REQUIRE( ( !!MatchAll() ).match( 1 ) );
|
||||
STATIC_REQUIRE_THAT( 1, MatchAll() && MatchAll() );
|
||||
STATIC_REQUIRE_THAT( 1, MatchAll() || MatchAll() );
|
||||
STATIC_REQUIRE_THAT( 1, !!MatchAll() );
|
||||
}
|
||||
|
||||
#endif // __cpp_constexpr >= 202306L
|
||||
|
||||
#endif
|
||||
@@ -27,8 +27,8 @@ TEST_CASE( "std::vector<std::pair<std::string,int> > -> toString", "[toString][p
|
||||
|
||||
// This is pretty contrived - I figure if this works, anything will...
|
||||
TEST_CASE( "pair<pair<int,const char *,pair<std::string,int> > -> toString", "[toString][pair]" ) {
|
||||
typedef std::pair<int,const char *> left_t;
|
||||
typedef std::pair<std::string,int> right_t;
|
||||
using left_t = std::pair<int,const char *>;
|
||||
using right_t = std::pair<std::string,int>;
|
||||
|
||||
left_t left( 42, "Arthur" );
|
||||
right_t right( "Ford", 24 );
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
|
||||
TEST_CASE( "tuple<>", "[toString][tuple]" )
|
||||
{
|
||||
typedef std::tuple<> type;
|
||||
using type = std::tuple<>;
|
||||
CHECK( "{ }" == ::Catch::Detail::stringify(type{}) );
|
||||
type value {};
|
||||
CHECK( "{ }" == ::Catch::Detail::stringify(value) );
|
||||
@@ -21,33 +21,33 @@ TEST_CASE( "tuple<>", "[toString][tuple]" )
|
||||
|
||||
TEST_CASE( "tuple<int>", "[toString][tuple]" )
|
||||
{
|
||||
typedef std::tuple<int> type;
|
||||
using type = std::tuple<int>;
|
||||
CHECK( "{ 0 }" == ::Catch::Detail::stringify(type{0}) );
|
||||
}
|
||||
|
||||
|
||||
TEST_CASE( "tuple<float,int>", "[toString][tuple]" )
|
||||
{
|
||||
typedef std::tuple<float,int> type;
|
||||
using type = std::tuple<float,int>;
|
||||
CHECK( "1.5f" == ::Catch::Detail::stringify(float(1.5)) );
|
||||
CHECK( "{ 1.5f, 0 }" == ::Catch::Detail::stringify(type{1.5f,0}) );
|
||||
}
|
||||
|
||||
TEST_CASE( "tuple<string,string>", "[toString][tuple]" )
|
||||
{
|
||||
typedef std::tuple<std::string,std::string> type;
|
||||
using type = std::tuple<std::string,std::string>;
|
||||
CHECK( "{ \"hello\", \"world\" }" == ::Catch::Detail::stringify(type{"hello","world"}) );
|
||||
}
|
||||
|
||||
TEST_CASE( "tuple<tuple<int>,tuple<>,float>", "[toString][tuple]" )
|
||||
{
|
||||
typedef std::tuple<std::tuple<int>,std::tuple<>,float> type;
|
||||
using type = std::tuple<std::tuple<int>,std::tuple<>,float>;
|
||||
type value { std::tuple<int>{42}, {}, 1.5f };
|
||||
CHECK( "{ { 42 }, { }, 1.5f }" == ::Catch::Detail::stringify(value) );
|
||||
}
|
||||
|
||||
TEST_CASE( "tuple<nullptr,int,const char *>", "[approvals][toString][tuple]" ) {
|
||||
typedef std::tuple<std::nullptr_t,int,const char *> type;
|
||||
using type = std::tuple<std::nullptr_t,int,const char *>;
|
||||
type value { nullptr, 42, "Catch me" };
|
||||
CHECK( "{ nullptr, 42, \"Catch me\" }" == ::Catch::Detail::stringify(value) );
|
||||
}
|
||||
|
||||
@@ -49,6 +49,7 @@ self_test_sources = files(
|
||||
'SelfTest/UsageTests/Exception.tests.cpp',
|
||||
'SelfTest/UsageTests/Generators.tests.cpp',
|
||||
'SelfTest/UsageTests/Matchers.tests.cpp',
|
||||
'SelfTest/UsageTests/MatchersConstexpr.tests.cpp',
|
||||
'SelfTest/UsageTests/MatchersRanges.tests.cpp',
|
||||
'SelfTest/UsageTests/Message.tests.cpp',
|
||||
'SelfTest/UsageTests/Misc.tests.cpp',
|
||||
|
||||
Reference in New Issue
Block a user