mirror of
https://github.com/catchorg/Catch2.git
synced 2025-10-17 01:05:32 +02:00
Compare commits
39 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
3f0283de7a | ||
|
6fbb3f0723 | ||
|
9ff3cde87b | ||
|
4d802ca58f | ||
|
13711be7cf | ||
|
27ba26f743 | ||
|
a209bcfb54 | ||
|
584973a485 | ||
|
4f7c8cb28a | ||
|
e1dbad4c9e | ||
|
2befd98da2 | ||
|
00f259aeb2 | ||
|
fed1436246 | ||
|
0477326ad9 | ||
|
f04c93462b | ||
|
1af351cea1 | ||
|
dcc9fa3f38 | ||
|
bf6a15a69a | ||
|
6135a78c31 | ||
|
e8ba329b6c | ||
|
4aa88299af | ||
|
4ff9be3bc5 | ||
|
76cdaa3b51 | ||
|
644294df60 | ||
|
cefa8fcf32 | ||
|
772fa3f790 | ||
|
f3c0a3cd09 | ||
|
42d9d4533e | ||
|
618d44c448 | ||
|
388f7e1737 | ||
|
2ab20a0e00 | ||
|
60264b8807 | ||
|
65ffee5189 | ||
|
43f02027e4 | ||
|
906552f8c8 | ||
|
356dfc1439 | ||
|
e5d1eb757f | ||
|
2403f5620e | ||
|
d58491c85a |
@@ -31,7 +31,7 @@ if (CMAKE_BINARY_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR)
|
||||
endif()
|
||||
|
||||
project(Catch2
|
||||
VERSION 3.3.0 # CML version placeholder, don't delete
|
||||
VERSION 3.3.2 # CML version placeholder, don't delete
|
||||
LANGUAGES CXX
|
||||
# HOMEPAGE_URL is not supported until CMake version 3.12, which
|
||||
# we do not target yet.
|
||||
|
@@ -90,12 +90,12 @@ cmake_minimum_required(VERSION 3.5)
|
||||
project(baz LANGUAGES CXX VERSION 0.0.1)
|
||||
|
||||
find_package(Catch2 REQUIRED)
|
||||
add_executable(foo test.cpp)
|
||||
target_link_libraries(foo PRIVATE Catch2::Catch2)
|
||||
add_executable(tests test.cpp)
|
||||
target_link_libraries(tests PRIVATE Catch2::Catch2)
|
||||
|
||||
include(CTest)
|
||||
include(Catch)
|
||||
catch_discover_tests(foo)
|
||||
catch_discover_tests(tests)
|
||||
```
|
||||
|
||||
When using `FetchContent`, `include(Catch)` will fail unless
|
||||
@@ -108,7 +108,7 @@ directory.
|
||||
list(APPEND CMAKE_MODULE_PATH ${catch2_SOURCE_DIR}/extras)
|
||||
include(CTest)
|
||||
include(Catch)
|
||||
catch_discover_tests()
|
||||
catch_discover_tests(tests)
|
||||
```
|
||||
|
||||
#### Customization
|
||||
@@ -222,12 +222,12 @@ cmake_minimum_required(VERSION 3.5)
|
||||
project(baz LANGUAGES CXX VERSION 0.0.1)
|
||||
|
||||
find_package(Catch2 REQUIRED)
|
||||
add_executable(foo test.cpp)
|
||||
target_link_libraries(foo PRIVATE Catch2::Catch2)
|
||||
add_executable(tests test.cpp)
|
||||
target_link_libraries(tests PRIVATE Catch2::Catch2)
|
||||
|
||||
include(CTest)
|
||||
include(ParseAndAddCatchTests)
|
||||
ParseAndAddCatchTests(foo)
|
||||
ParseAndAddCatchTests(tests)
|
||||
```
|
||||
|
||||
|
||||
|
@@ -507,10 +507,13 @@ start of the first section.</br>
|
||||
## Filenames as tags
|
||||
<pre>-#, --filenames-as-tags</pre>
|
||||
|
||||
When this option is used then every test is given an additional tag which is formed of the unqualified
|
||||
filename it is found in, with any extension stripped, prefixed with the `#` character.
|
||||
This option adds an extra tag to all test cases. The tag is `#` followed
|
||||
by the unqualified filename the test case is defined in, with the _last_
|
||||
extension stripped out.
|
||||
|
||||
For example, tests within the file `tests\SelfTest\UsageTests\BDD.tests.cpp`
|
||||
will be given the `[#BDD.tests]` tag.
|
||||
|
||||
So, for example, tests within the file `~\Dev\MyProject\Ferrets.cpp` would be tagged `[#Ferrets]`.
|
||||
|
||||
<a id="colour-mode"></a>
|
||||
## Override output colouring
|
||||
|
@@ -55,6 +55,15 @@ tests from `SelfTest` through a specific reporter and then compare the
|
||||
generated output with a known good output ("Baseline"). By default, new
|
||||
tests should be placed here.
|
||||
|
||||
To configure a Catch2 build with just the basic tests, use the `basic-tests`
|
||||
preset, like so:
|
||||
|
||||
```
|
||||
# Assuming you are in Catch2's root folder
|
||||
|
||||
cmake -B basic-test-build -S . -DCMAKE_BUILD_TYPE=Debug --preset basic-tests
|
||||
```
|
||||
|
||||
However, not all tests can be written as plain unit tests. For example,
|
||||
checking that Catch2 orders tests randomly when asked to, and that this
|
||||
random ordering is subset-invariant, is better done as an integration
|
||||
@@ -76,21 +85,23 @@ configuration and require separate compilation.
|
||||
Finally, CMake config tests test that you set Catch2's compile-time
|
||||
configuration options through CMake, using CMake options of the same name.
|
||||
|
||||
None of these tests are enabled by default. To enable them, add
|
||||
These test categories can be enabled one by one, by passing
|
||||
`-DCATCH_BUILD_EXAMPLES=ON`, `-DCATCH_BUILD_EXTRA_TESTS=ON`, and
|
||||
`-DCATCH_ENABLE_CONFIGURE_TESTS=ON` when configuration the CMake build.
|
||||
`-DCATCH_ENABLE_CONFIGURE_TESTS=ON` when configuring the build.
|
||||
|
||||
Bringing this all together, the steps below should configure, build,
|
||||
and run all tests in the `Debug` compilation.
|
||||
Catch2 also provides a preset that promises to enable _all_ test types,
|
||||
`all-tests`.
|
||||
|
||||
The snippet below will build & run all tests, in `Debug` compilation mode.
|
||||
|
||||
<!-- snippet: catch2-build-and-test -->
|
||||
<a id='snippet-catch2-build-and-test'></a>
|
||||
```sh
|
||||
# 1. Regenerate the amalgamated distribution
|
||||
# 1. Regenerate the amalgamated distribution (some tests are built against it)
|
||||
./tools/scripts/generateAmalgamatedFiles.py
|
||||
|
||||
# 2. Configure the full test build
|
||||
cmake -Bdebug-build -H. -DCMAKE_BUILD_TYPE=Debug -DCATCH_DEVELOPMENT_BUILD=ON -DCATCH_BUILD_EXAMPLES=ON -DCATCH_BUILD_EXTRA_TESTS=ON
|
||||
cmake -B debug-build -S . -DCMAKE_BUILD_TYPE=Debug --preset all-tests
|
||||
|
||||
# 3. Run the actual build
|
||||
cmake --build debug-build
|
||||
|
@@ -88,8 +88,8 @@ because only one thread passes the `REQUIRE` macro and this is not
|
||||
REQUIRE(cnt == 16);
|
||||
```
|
||||
|
||||
Because C++11 provides the necessary tools to do this, we are planning
|
||||
to remove this limitation in the future.
|
||||
We currently do not plan to support thread-safe assertions.
|
||||
|
||||
|
||||
### Process isolation in a test
|
||||
Catch does not support running tests in isolated (forked) processes. While this might in the future, the fact that Windows does not support forking and only allows full-on process creation and the desire to keep code as similar as possible across platforms, mean that this is likely to take significant development time, that is not currently available.
|
||||
|
@@ -141,18 +141,27 @@ are a permutation of the ones in `some_vec`.
|
||||
|
||||
### Floating point matchers
|
||||
|
||||
Catch2 provides 3 matchers that target floating point numbers. These
|
||||
Catch2 provides 4 matchers that target floating point numbers. These
|
||||
are:
|
||||
|
||||
* `WithinAbs(double target, double margin)`,
|
||||
* `WithinULP(FloatingPoint target, uint64_t maxUlpDiff)`, and
|
||||
* `WithinRel(FloatingPoint target, FloatingPoint eps)`.
|
||||
* `IsNaN()`
|
||||
|
||||
> `WithinRel` matcher was introduced in Catch2 2.10.0
|
||||
|
||||
For more details, read [the docs on comparing floating point
|
||||
> `IsNaN` matcher was introduced in Catch2 3.3.2.
|
||||
|
||||
The first three serve to compare two floating pointe numbers. For more
|
||||
details about how they work, read [the docs on comparing floating point
|
||||
numbers](comparing-floating-point-numbers.md#floating-point-matchers).
|
||||
|
||||
`IsNaN` then does exactly what it says on the tin. It matches the input
|
||||
if it is a NaN (Not a Number). The advantage of using it over just plain
|
||||
`REQUIRE(std::isnan(x))`, is that if the check fails, with `REQUIRE` you
|
||||
won't see the value of `x`, but with `REQUIRE_THAT(x, IsNaN())`, you will.
|
||||
|
||||
|
||||
### Miscellaneous matchers
|
||||
|
||||
|
@@ -2,6 +2,8 @@
|
||||
|
||||
# Release notes
|
||||
**Contents**<br>
|
||||
[3.3.2](#332)<br>
|
||||
[3.3.1](#331)<br>
|
||||
[3.3.0](#330)<br>
|
||||
[3.2.1](#321)<br>
|
||||
[3.2.0](#320)<br>
|
||||
@@ -55,6 +57,38 @@
|
||||
|
||||
|
||||
|
||||
## 3.3.2
|
||||
|
||||
### Improvements
|
||||
* Further reduced allocations
|
||||
* The compact, console, TAP and XML reporters perform less allocations in various cases
|
||||
* Removed 1 allocation per entered `SECTION`/`TEST_CASE`.
|
||||
* Removed 2 allocations per test case exit, if stdout/stderr is captured
|
||||
* Improved performance
|
||||
* Section tracking is 10%-25% faster than in v3.3.0
|
||||
* Assertion handling is 5%-10% faster than in v3.3.0
|
||||
* Test case registration is 1%-2% faster than in v3.3.0
|
||||
* Tiny speedup for registering listeners
|
||||
* Tiny speedup for `CAPTURE`, `TEST_CASE_METHOD`, `METHOD_AS_TEST_CASE`, and `TEMPLATE_LIST_TEST_*` macros.
|
||||
* `Contains`, `RangeEquals` and `UnorderedRangeEquals` matchers now support ranges with iterator + sentinel pair
|
||||
* Added `IsNaN` matcher
|
||||
* Unlike `REQUIRE(isnan(x))`, `REQUIRE_THAT(x, IsNaN())` shows you the value of `x`.
|
||||
* Suppressed `declared_but_not_referenced` warning for NVHPC (#2637)
|
||||
|
||||
### Fixes
|
||||
* Fixed performance regression in section tracking introduced in v3.3.1
|
||||
* Extreme cases would cause the tracking to run about 4x slower than in 3.3.0
|
||||
|
||||
|
||||
## 3.3.1
|
||||
|
||||
### Improvements
|
||||
* Reduced allocations and improved performance
|
||||
* The exact improvements are dependent on your usage of Catch2.
|
||||
* For example running Catch2's SelfTest binary performs 8k less allocations.
|
||||
* The main improvement comes from smarter handling of `SECTION`s, especially sibling `SECTION`s
|
||||
|
||||
|
||||
## 3.3.0
|
||||
|
||||
### Improvements
|
||||
|
@@ -69,7 +69,8 @@ All tag names beginning with non-alphanumeric characters are reserved by Catch.
|
||||
|
||||
* `[!nonportable]` - Indicates that behaviour may vary between platforms or compilers.
|
||||
|
||||
* `[#<filename>]` - running with `-#` or `--filenames-as-tags` causes Catch to add the filename, prefixed with `#` (and with any extension stripped), as a tag to all contained tests, e.g. tests in testfile.cpp would all be tagged `[#testfile]`.
|
||||
* `[#<filename>]` - these tags are added to test cases when you run Catch2
|
||||
with [`-#` or `--filenames-as-tags`](command-line.md#filenames-as-tags).
|
||||
|
||||
* `[@<alias>]` - tag aliases all begin with `@` (see below).
|
||||
|
||||
|
@@ -5,8 +5,8 @@
|
||||
|
||||
// SPDX-License-Identifier: BSL-1.0
|
||||
|
||||
// Catch v3.3.0
|
||||
// Generated: 2023-01-22 19:46:24.251531
|
||||
// Catch v3.3.2
|
||||
// Generated: 2023-02-26 10:28:48.270752
|
||||
// ----------------------------------------------------------
|
||||
// This file is an amalgamation of multiple different files.
|
||||
// You probably shouldn't edit it directly.
|
||||
@@ -428,9 +428,9 @@ namespace Catch {
|
||||
return reconstructedExpression;
|
||||
}
|
||||
|
||||
AssertionResult::AssertionResult( AssertionInfo const& info, AssertionResultData const& data )
|
||||
AssertionResult::AssertionResult( AssertionInfo const& info, AssertionResultData&& data )
|
||||
: m_info( info ),
|
||||
m_resultData( data )
|
||||
m_resultData( CATCH_MOVE(data) )
|
||||
{}
|
||||
|
||||
// Result was a success
|
||||
@@ -469,16 +469,15 @@ namespace Catch {
|
||||
}
|
||||
|
||||
std::string AssertionResult::getExpressionInMacro() const {
|
||||
std::string expr;
|
||||
if( m_info.macroName.empty() )
|
||||
expr = static_cast<std::string>(m_info.capturedExpression);
|
||||
else {
|
||||
expr.reserve( m_info.macroName.size() + m_info.capturedExpression.size() + 4 );
|
||||
expr += m_info.macroName;
|
||||
expr += "( ";
|
||||
expr += m_info.capturedExpression;
|
||||
expr += " )";
|
||||
if ( m_info.macroName.empty() ) {
|
||||
return static_cast<std::string>( m_info.capturedExpression );
|
||||
}
|
||||
std::string expr;
|
||||
expr.reserve( m_info.macroName.size() + m_info.capturedExpression.size() + 4 );
|
||||
expr += m_info.macroName;
|
||||
expr += "( ";
|
||||
expr += m_info.capturedExpression;
|
||||
expr += " )";
|
||||
return expr;
|
||||
}
|
||||
|
||||
@@ -758,8 +757,8 @@ namespace Catch {
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
ScopedMessage::ScopedMessage( MessageBuilder const& builder ):
|
||||
m_info( builder.m_info ) {
|
||||
ScopedMessage::ScopedMessage( MessageBuilder&& builder ):
|
||||
m_info( CATCH_MOVE(builder.m_info) ) {
|
||||
m_info.message = builder.m_stream.str();
|
||||
getResultCapture().pushScopedMessage( m_info );
|
||||
}
|
||||
@@ -2022,7 +2021,7 @@ namespace Catch {
|
||||
}
|
||||
|
||||
Version const& libraryVersion() {
|
||||
static Version version( 3, 3, 0, "", 0 );
|
||||
static Version version( 3, 3, 2, "", 0 );
|
||||
return version;
|
||||
}
|
||||
|
||||
@@ -2179,18 +2178,17 @@ namespace Catch {
|
||||
// Copy message into messages list.
|
||||
// !TBD This should have been done earlier, somewhere
|
||||
MessageBuilder builder( assertionResult.getTestMacroName(), assertionResult.getSourceInfo(), assertionResult.getResultType() );
|
||||
builder << assertionResult.getMessage();
|
||||
builder.m_info.message = builder.m_stream.str();
|
||||
builder.m_info.message = static_cast<std::string>(assertionResult.getMessage());
|
||||
|
||||
infoMessages.push_back( builder.m_info );
|
||||
infoMessages.push_back( CATCH_MOVE(builder.m_info) );
|
||||
}
|
||||
}
|
||||
|
||||
SectionStats::SectionStats( SectionInfo const& _sectionInfo,
|
||||
SectionStats::SectionStats( SectionInfo&& _sectionInfo,
|
||||
Counts const& _assertions,
|
||||
double _durationInSeconds,
|
||||
bool _missingAssertions )
|
||||
: sectionInfo( _sectionInfo ),
|
||||
: sectionInfo( CATCH_MOVE(_sectionInfo) ),
|
||||
assertions( _assertions ),
|
||||
durationInSeconds( _durationInSeconds ),
|
||||
missingAssertions( _missingAssertions )
|
||||
@@ -2199,13 +2197,13 @@ namespace Catch {
|
||||
|
||||
TestCaseStats::TestCaseStats( TestCaseInfo const& _testInfo,
|
||||
Totals const& _totals,
|
||||
std::string const& _stdOut,
|
||||
std::string const& _stdErr,
|
||||
std::string&& _stdOut,
|
||||
std::string&& _stdErr,
|
||||
bool _aborting )
|
||||
: testInfo( &_testInfo ),
|
||||
totals( _totals ),
|
||||
stdOut( _stdOut ),
|
||||
stdErr( _stdErr ),
|
||||
stdOut( CATCH_MOVE(_stdOut) ),
|
||||
stdErr( CATCH_MOVE(_stdErr) ),
|
||||
aborting( _aborting )
|
||||
{}
|
||||
|
||||
@@ -4993,12 +4991,12 @@ namespace Catch {
|
||||
struct GeneratorTracker : TestCaseTracking::TrackerBase, IGeneratorTracker {
|
||||
GeneratorBasePtr m_generator;
|
||||
|
||||
GeneratorTracker( TestCaseTracking::NameAndLocation const& nameAndLocation, TrackerContext& ctx, ITracker* parent )
|
||||
: TrackerBase( nameAndLocation, ctx, parent )
|
||||
GeneratorTracker( TestCaseTracking::NameAndLocation&& nameAndLocation, TrackerContext& ctx, ITracker* parent )
|
||||
: TrackerBase( CATCH_MOVE(nameAndLocation), ctx, parent )
|
||||
{}
|
||||
~GeneratorTracker() override;
|
||||
|
||||
static GeneratorTracker* acquire( TrackerContext& ctx, TestCaseTracking::NameAndLocation const& nameAndLocation ) {
|
||||
static GeneratorTracker* acquire( TrackerContext& ctx, TestCaseTracking::NameAndLocationRef const& nameAndLocation ) {
|
||||
GeneratorTracker* tracker;
|
||||
|
||||
ITracker& currentTracker = ctx.currentTracker();
|
||||
@@ -5140,13 +5138,8 @@ namespace Catch {
|
||||
Totals RunContext::runTest(TestCaseHandle const& testCase) {
|
||||
const Totals prevTotals = m_totals;
|
||||
|
||||
std::string redirectedCout;
|
||||
std::string redirectedCerr;
|
||||
|
||||
auto const& testInfo = testCase.getTestCaseInfo();
|
||||
|
||||
m_reporter->testCaseStarting(testInfo);
|
||||
|
||||
m_activeTestCase = &testCase;
|
||||
|
||||
|
||||
@@ -5188,9 +5181,11 @@ namespace Catch {
|
||||
seedRng( *m_config );
|
||||
|
||||
uint64_t testRuns = 0;
|
||||
std::string redirectedCout;
|
||||
std::string redirectedCerr;
|
||||
do {
|
||||
m_trackerContext.startCycle();
|
||||
m_testCaseTracker = &SectionTracker::acquire(m_trackerContext, TestCaseTracking::NameAndLocation(testInfo.name, testInfo.lineInfo));
|
||||
m_testCaseTracker = &SectionTracker::acquire(m_trackerContext, TestCaseTracking::NameAndLocationRef(testInfo.name, testInfo.lineInfo));
|
||||
|
||||
m_reporter->testCasePartialStarting(testInfo, testRuns);
|
||||
|
||||
@@ -5201,7 +5196,7 @@ namespace Catch {
|
||||
redirectedCerr += oneRunCerr;
|
||||
|
||||
const auto singleRunTotals = m_totals.delta(beforeRunTotals);
|
||||
auto statsForOneRun = TestCaseStats(testInfo, singleRunTotals, oneRunCout, oneRunCerr, aborting());
|
||||
auto statsForOneRun = TestCaseStats(testInfo, singleRunTotals, CATCH_MOVE(oneRunCout), CATCH_MOVE(oneRunCerr), aborting());
|
||||
|
||||
m_reporter->testCasePartialEnded(statsForOneRun, testRuns);
|
||||
++testRuns;
|
||||
@@ -5216,8 +5211,8 @@ namespace Catch {
|
||||
m_totals.testCases += deltaTotals.testCases;
|
||||
m_reporter->testCaseEnded(TestCaseStats(testInfo,
|
||||
deltaTotals,
|
||||
redirectedCout,
|
||||
redirectedCerr,
|
||||
CATCH_MOVE(redirectedCout),
|
||||
CATCH_MOVE(redirectedCerr),
|
||||
aborting()));
|
||||
|
||||
m_activeTestCase = nullptr;
|
||||
@@ -5261,12 +5256,17 @@ namespace Catch {
|
||||
m_lastAssertionInfo.capturedExpression = "{Unknown expression after the reported line}"_sr;
|
||||
}
|
||||
|
||||
bool RunContext::sectionStarted(SectionInfo const & sectionInfo, Counts & assertions) {
|
||||
ITracker& sectionTracker = SectionTracker::acquire(m_trackerContext, TestCaseTracking::NameAndLocation(sectionInfo.name, sectionInfo.lineInfo));
|
||||
bool RunContext::sectionStarted(StringRef sectionName, SourceLineInfo const& sectionLineInfo, Counts & assertions) {
|
||||
ITracker& sectionTracker =
|
||||
SectionTracker::acquire( m_trackerContext,
|
||||
TestCaseTracking::NameAndLocationRef(
|
||||
sectionName, sectionLineInfo ) );
|
||||
|
||||
if (!sectionTracker.isOpen())
|
||||
return false;
|
||||
m_activeSections.push_back(§ionTracker);
|
||||
|
||||
SectionInfo sectionInfo( sectionLineInfo, static_cast<std::string>(sectionName) );
|
||||
m_lastAssertionInfo.lineInfo = sectionInfo.lineInfo;
|
||||
|
||||
m_reporter->sectionStarting(sectionInfo);
|
||||
@@ -5281,8 +5281,8 @@ namespace Catch {
|
||||
using namespace Generators;
|
||||
GeneratorTracker* tracker = GeneratorTracker::acquire(
|
||||
m_trackerContext,
|
||||
TestCaseTracking::NameAndLocation(
|
||||
static_cast<std::string>( generatorName ), lineInfo ) );
|
||||
TestCaseTracking::NameAndLocationRef(
|
||||
generatorName, lineInfo ) );
|
||||
m_lastAssertionInfo.lineInfo = lineInfo;
|
||||
return tracker;
|
||||
}
|
||||
@@ -5299,7 +5299,7 @@ namespace Catch {
|
||||
"Trying to create tracker for a genreator that already has one" );
|
||||
|
||||
auto newTracker = Catch::Detail::make_unique<Generators::GeneratorTracker>(
|
||||
nameAndLoc, m_trackerContext, ¤tTracker );
|
||||
CATCH_MOVE(nameAndLoc), m_trackerContext, ¤tTracker );
|
||||
auto ret = newTracker.get();
|
||||
currentTracker.addChild( CATCH_MOVE( newTracker ) );
|
||||
|
||||
@@ -5320,7 +5320,7 @@ namespace Catch {
|
||||
return true;
|
||||
}
|
||||
|
||||
void RunContext::sectionEnded(SectionEndInfo const & endInfo) {
|
||||
void RunContext::sectionEnded(SectionEndInfo&& endInfo) {
|
||||
Counts assertions = m_totals.assertions - endInfo.prevAssertions;
|
||||
bool missingAssertions = testForMissingAssertions(assertions);
|
||||
|
||||
@@ -5329,19 +5329,20 @@ namespace Catch {
|
||||
m_activeSections.pop_back();
|
||||
}
|
||||
|
||||
m_reporter->sectionEnded(SectionStats(endInfo.sectionInfo, assertions, endInfo.durationInSeconds, missingAssertions));
|
||||
m_reporter->sectionEnded(SectionStats(CATCH_MOVE(endInfo.sectionInfo), assertions, endInfo.durationInSeconds, missingAssertions));
|
||||
m_messages.clear();
|
||||
m_messageScopes.clear();
|
||||
}
|
||||
|
||||
void RunContext::sectionEndedEarly(SectionEndInfo const & endInfo) {
|
||||
if (m_unfinishedSections.empty())
|
||||
void RunContext::sectionEndedEarly(SectionEndInfo&& endInfo) {
|
||||
if ( m_unfinishedSections.empty() ) {
|
||||
m_activeSections.back()->fail();
|
||||
else
|
||||
} else {
|
||||
m_activeSections.back()->close();
|
||||
}
|
||||
m_activeSections.pop_back();
|
||||
|
||||
m_unfinishedSections.push_back(endInfo);
|
||||
m_unfinishedSections.push_back(CATCH_MOVE(endInfo));
|
||||
}
|
||||
|
||||
void RunContext::benchmarkPreparing( StringRef name ) {
|
||||
@@ -5365,8 +5366,8 @@ namespace Catch {
|
||||
m_messages.erase(std::remove(m_messages.begin(), m_messages.end(), message), m_messages.end());
|
||||
}
|
||||
|
||||
void RunContext::emplaceUnscopedMessage( MessageBuilder const& builder ) {
|
||||
m_messageScopes.emplace_back( builder );
|
||||
void RunContext::emplaceUnscopedMessage( MessageBuilder&& builder ) {
|
||||
m_messageScopes.emplace_back( CATCH_MOVE(builder) );
|
||||
}
|
||||
|
||||
std::string RunContext::getCurrentTestName() const {
|
||||
@@ -5391,7 +5392,7 @@ namespace Catch {
|
||||
// Instead, fake a result data.
|
||||
AssertionResultData tempResult( ResultWas::FatalErrorCondition, { false } );
|
||||
tempResult.message = static_cast<std::string>(message);
|
||||
AssertionResult result(m_lastAssertionInfo, tempResult);
|
||||
AssertionResult result(m_lastAssertionInfo, CATCH_MOVE(tempResult));
|
||||
|
||||
assertionEnded(result);
|
||||
|
||||
@@ -5403,7 +5404,7 @@ namespace Catch {
|
||||
|
||||
Counts assertions;
|
||||
assertions.failed = 1;
|
||||
SectionStats testCaseSectionStats(testCaseSection, assertions, 0, false);
|
||||
SectionStats testCaseSectionStats(CATCH_MOVE(testCaseSection), assertions, 0, false);
|
||||
m_reporter->sectionEnded(testCaseSectionStats);
|
||||
|
||||
auto const& testInfo = m_activeTestCase->getTestCaseInfo();
|
||||
@@ -5482,7 +5483,7 @@ namespace Catch {
|
||||
m_messages.clear();
|
||||
m_messageScopes.clear();
|
||||
|
||||
SectionStats testCaseSectionStats(testCaseSection, assertions, duration, missingAssertions);
|
||||
SectionStats testCaseSectionStats(CATCH_MOVE(testCaseSection), assertions, duration, missingAssertions);
|
||||
m_reporter->sectionEnded(testCaseSectionStats);
|
||||
}
|
||||
|
||||
@@ -5506,7 +5507,7 @@ namespace Catch {
|
||||
itEnd = m_unfinishedSections.rend();
|
||||
it != itEnd;
|
||||
++it)
|
||||
sectionEnded(*it);
|
||||
sectionEnded(CATCH_MOVE(*it));
|
||||
m_unfinishedSections.clear();
|
||||
}
|
||||
|
||||
@@ -5542,7 +5543,7 @@ namespace Catch {
|
||||
m_lastAssertionInfo = info;
|
||||
AssertionResultData data( resultType, LazyExpression( negated ) );
|
||||
|
||||
AssertionResult assertionResult{ info, data };
|
||||
AssertionResult assertionResult{ info, CATCH_MOVE( data ) };
|
||||
assertionResult.m_resultData.lazyExpression.m_transientExpression = expr;
|
||||
|
||||
assertionEnded( assertionResult );
|
||||
@@ -5560,7 +5561,8 @@ namespace Catch {
|
||||
|
||||
AssertionResultData data( resultType, LazyExpression( false ) );
|
||||
data.message = static_cast<std::string>(message);
|
||||
AssertionResult assertionResult{ m_lastAssertionInfo, data };
|
||||
AssertionResult assertionResult{ m_lastAssertionInfo,
|
||||
CATCH_MOVE( data ) };
|
||||
assertionEnded( assertionResult );
|
||||
if ( !assertionResult.isOk() ) {
|
||||
populateReaction( reaction );
|
||||
@@ -5586,7 +5588,7 @@ namespace Catch {
|
||||
|
||||
AssertionResultData data( ResultWas::ThrewException, LazyExpression( false ) );
|
||||
data.message = message;
|
||||
AssertionResult assertionResult{ info, data };
|
||||
AssertionResult assertionResult{ info, CATCH_MOVE(data) };
|
||||
assertionEnded( assertionResult );
|
||||
populateReaction( reaction );
|
||||
}
|
||||
@@ -5599,11 +5601,12 @@ namespace Catch {
|
||||
void RunContext::handleIncomplete(
|
||||
AssertionInfo const& info
|
||||
) {
|
||||
using namespace std::string_literals;
|
||||
m_lastAssertionInfo = info;
|
||||
|
||||
AssertionResultData data( ResultWas::ThrewException, LazyExpression( false ) );
|
||||
data.message = "Exception translation was disabled by CATCH_CONFIG_FAST_COMPILE";
|
||||
AssertionResult assertionResult{ info, data };
|
||||
data.message = "Exception translation was disabled by CATCH_CONFIG_FAST_COMPILE"s;
|
||||
AssertionResult assertionResult{ info, CATCH_MOVE( data ) };
|
||||
assertionEnded( assertionResult );
|
||||
}
|
||||
void RunContext::handleNonExpr(
|
||||
@@ -5614,7 +5617,7 @@ namespace Catch {
|
||||
m_lastAssertionInfo = info;
|
||||
|
||||
AssertionResultData data( resultType, LazyExpression( false ) );
|
||||
AssertionResult assertionResult{ info, data };
|
||||
AssertionResult assertionResult{ info, CATCH_MOVE( data ) };
|
||||
assertionEnded( assertionResult );
|
||||
|
||||
if( !assertionResult.isOk() )
|
||||
@@ -5646,7 +5649,7 @@ namespace Catch {
|
||||
Section::Section( SectionInfo&& info ):
|
||||
m_info( CATCH_MOVE( info ) ),
|
||||
m_sectionIncluded(
|
||||
getResultCapture().sectionStarted( m_info, m_assertions ) ) {
|
||||
getResultCapture().sectionStarted( m_info.name, m_info.lineInfo, m_assertions ) ) {
|
||||
// Non-"included" sections will not use the timing information
|
||||
// anyway, so don't bother with the potential syscall.
|
||||
if (m_sectionIncluded) {
|
||||
@@ -5654,13 +5657,31 @@ namespace Catch {
|
||||
}
|
||||
}
|
||||
|
||||
Section::Section( SourceLineInfo const& _lineInfo,
|
||||
StringRef _name,
|
||||
const char* const ):
|
||||
m_info( { "invalid", static_cast<std::size_t>( -1 ) }, std::string{} ),
|
||||
m_sectionIncluded(
|
||||
getResultCapture().sectionStarted( _name, _lineInfo, m_assertions ) ) {
|
||||
// We delay initialization the SectionInfo member until we know
|
||||
// this section needs it, so we avoid allocating std::string for name.
|
||||
// We also delay timer start to avoid the potential syscall unless we
|
||||
// will actually use the result.
|
||||
if ( m_sectionIncluded ) {
|
||||
m_info.name = static_cast<std::string>( _name );
|
||||
m_info.lineInfo = _lineInfo;
|
||||
m_timer.start();
|
||||
}
|
||||
}
|
||||
|
||||
Section::~Section() {
|
||||
if( m_sectionIncluded ) {
|
||||
SectionEndInfo endInfo{ m_info, m_assertions, m_timer.getElapsedSeconds() };
|
||||
if( uncaught_exceptions() )
|
||||
getResultCapture().sectionEndedEarly( endInfo );
|
||||
else
|
||||
getResultCapture().sectionEnded( endInfo );
|
||||
SectionEndInfo endInfo{ CATCH_MOVE(m_info), m_assertions, m_timer.getElapsedSeconds() };
|
||||
if ( uncaught_exceptions() ) {
|
||||
getResultCapture().sectionEndedEarly( CATCH_MOVE(endInfo) );
|
||||
} else {
|
||||
getResultCapture().sectionEnded( CATCH_MOVE( endInfo ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5876,10 +5897,6 @@ namespace Catch {
|
||||
: StringRef( rawChars, std::strlen(rawChars) )
|
||||
{}
|
||||
|
||||
auto StringRef::operator == ( StringRef other ) const noexcept -> bool {
|
||||
return m_size == other.m_size
|
||||
&& (std::memcmp( m_start, other.m_start, m_size ) == 0);
|
||||
}
|
||||
|
||||
bool StringRef::operator<(StringRef rhs) const noexcept {
|
||||
if (m_size < rhs.m_size) {
|
||||
@@ -6155,8 +6172,8 @@ namespace Catch {
|
||||
namespace Catch {
|
||||
namespace TestCaseTracking {
|
||||
|
||||
NameAndLocation::NameAndLocation( std::string const& _name, SourceLineInfo const& _location )
|
||||
: name( _name ),
|
||||
NameAndLocation::NameAndLocation( std::string&& _name, SourceLineInfo const& _location )
|
||||
: name( CATCH_MOVE(_name) ),
|
||||
location( _location )
|
||||
{}
|
||||
|
||||
@@ -6171,14 +6188,17 @@ namespace TestCaseTracking {
|
||||
m_children.push_back( CATCH_MOVE(child) );
|
||||
}
|
||||
|
||||
ITracker* ITracker::findChild( NameAndLocation const& nameAndLocation ) {
|
||||
ITracker* ITracker::findChild( NameAndLocationRef const& nameAndLocation ) {
|
||||
auto it = std::find_if(
|
||||
m_children.begin(),
|
||||
m_children.end(),
|
||||
[&nameAndLocation]( ITrackerPtr const& tracker ) {
|
||||
return tracker->nameAndLocation().location ==
|
||||
nameAndLocation.location &&
|
||||
tracker->nameAndLocation().name == nameAndLocation.name;
|
||||
auto const& tnameAndLoc = tracker->nameAndLocation();
|
||||
if ( tnameAndLoc.location.line !=
|
||||
nameAndLocation.location.line ) {
|
||||
return false;
|
||||
}
|
||||
return tnameAndLoc == nameAndLocation;
|
||||
} );
|
||||
return ( it != m_children.end() ) ? it->get() : nullptr;
|
||||
}
|
||||
@@ -6186,10 +6206,6 @@ namespace TestCaseTracking {
|
||||
bool ITracker::isSectionTracker() const { return false; }
|
||||
bool ITracker::isGeneratorTracker() const { return false; }
|
||||
|
||||
bool ITracker::isSuccessfullyCompleted() const {
|
||||
return m_runState == CompletedSuccessfully;
|
||||
}
|
||||
|
||||
bool ITracker::isOpen() const {
|
||||
return m_runState != NotStarted && !isComplete();
|
||||
}
|
||||
@@ -6216,16 +6232,6 @@ namespace TestCaseTracking {
|
||||
return *m_rootTracker;
|
||||
}
|
||||
|
||||
void TrackerContext::endRun() {
|
||||
m_rootTracker.reset();
|
||||
m_currentTracker = nullptr;
|
||||
m_runState = NotStarted;
|
||||
}
|
||||
|
||||
void TrackerContext::startCycle() {
|
||||
m_currentTracker = m_rootTracker.get();
|
||||
m_runState = Executing;
|
||||
}
|
||||
void TrackerContext::completeCycle() {
|
||||
m_runState = CompletedCycle;
|
||||
}
|
||||
@@ -6233,16 +6239,13 @@ namespace TestCaseTracking {
|
||||
bool TrackerContext::completedCycle() const {
|
||||
return m_runState == CompletedCycle;
|
||||
}
|
||||
ITracker& TrackerContext::currentTracker() {
|
||||
return *m_currentTracker;
|
||||
}
|
||||
void TrackerContext::setCurrentTracker( ITracker* tracker ) {
|
||||
m_currentTracker = tracker;
|
||||
}
|
||||
|
||||
|
||||
TrackerBase::TrackerBase( NameAndLocation const& nameAndLocation, TrackerContext& ctx, ITracker* parent ):
|
||||
ITracker(nameAndLocation, parent),
|
||||
TrackerBase::TrackerBase( NameAndLocation&& nameAndLocation, TrackerContext& ctx, ITracker* parent ):
|
||||
ITracker(CATCH_MOVE(nameAndLocation), parent),
|
||||
m_ctx( ctx )
|
||||
{}
|
||||
|
||||
@@ -6302,13 +6305,14 @@ namespace TestCaseTracking {
|
||||
m_ctx.setCurrentTracker( this );
|
||||
}
|
||||
|
||||
SectionTracker::SectionTracker( NameAndLocation const& nameAndLocation, TrackerContext& ctx, ITracker* parent )
|
||||
: TrackerBase( nameAndLocation, ctx, parent ),
|
||||
m_trimmed_name(trim(nameAndLocation.name))
|
||||
SectionTracker::SectionTracker( NameAndLocation&& nameAndLocation, TrackerContext& ctx, ITracker* parent )
|
||||
: TrackerBase( CATCH_MOVE(nameAndLocation), ctx, parent ),
|
||||
m_trimmed_name(trim(StringRef(ITracker::nameAndLocation().name)))
|
||||
{
|
||||
if( parent ) {
|
||||
while( !parent->isSectionTracker() )
|
||||
while ( !parent->isSectionTracker() ) {
|
||||
parent = parent->parent();
|
||||
}
|
||||
|
||||
SectionTracker& parentSection = static_cast<SectionTracker&>( *parent );
|
||||
addNextFilters( parentSection.m_filters );
|
||||
@@ -6328,24 +6332,30 @@ namespace TestCaseTracking {
|
||||
|
||||
bool SectionTracker::isSectionTracker() const { return true; }
|
||||
|
||||
SectionTracker& SectionTracker::acquire( TrackerContext& ctx, NameAndLocation const& nameAndLocation ) {
|
||||
SectionTracker* section;
|
||||
SectionTracker& SectionTracker::acquire( TrackerContext& ctx, NameAndLocationRef const& nameAndLocation ) {
|
||||
SectionTracker* tracker;
|
||||
|
||||
ITracker& currentTracker = ctx.currentTracker();
|
||||
if ( ITracker* childTracker =
|
||||
currentTracker.findChild( nameAndLocation ) ) {
|
||||
assert( childTracker );
|
||||
assert( childTracker->isSectionTracker() );
|
||||
section = static_cast<SectionTracker*>( childTracker );
|
||||
tracker = static_cast<SectionTracker*>( childTracker );
|
||||
} else {
|
||||
auto newSection = Catch::Detail::make_unique<SectionTracker>(
|
||||
nameAndLocation, ctx, ¤tTracker );
|
||||
section = newSection.get();
|
||||
currentTracker.addChild( CATCH_MOVE( newSection ) );
|
||||
auto newTracker = Catch::Detail::make_unique<SectionTracker>(
|
||||
NameAndLocation{ static_cast<std::string>(nameAndLocation.name),
|
||||
nameAndLocation.location },
|
||||
ctx,
|
||||
¤tTracker );
|
||||
tracker = newTracker.get();
|
||||
currentTracker.addChild( CATCH_MOVE( newTracker ) );
|
||||
}
|
||||
if( !ctx.completedCycle() )
|
||||
section->tryOpen();
|
||||
return *section;
|
||||
|
||||
if ( !ctx.completedCycle() ) {
|
||||
tracker->tryOpen();
|
||||
}
|
||||
|
||||
return *tracker;
|
||||
}
|
||||
|
||||
void SectionTracker::tryOpen() {
|
||||
@@ -6366,10 +6376,6 @@ namespace TestCaseTracking {
|
||||
m_filters.insert( m_filters.end(), filters.begin()+1, filters.end() );
|
||||
}
|
||||
|
||||
std::vector<StringRef> const& SectionTracker::getFilters() const {
|
||||
return m_filters;
|
||||
}
|
||||
|
||||
StringRef SectionTracker::trimmedName() const {
|
||||
return m_trimmed_name;
|
||||
}
|
||||
@@ -6668,10 +6674,8 @@ namespace Catch {
|
||||
token.erase(token.begin());
|
||||
if (m_exclusion) {
|
||||
m_currentFilter.m_forbidden.emplace_back(Detail::make_unique<TestSpec::TagPattern>(".", m_substring));
|
||||
m_currentFilter.m_forbidden.emplace_back(Detail::make_unique<TestSpec::TagPattern>(token, m_substring));
|
||||
} else {
|
||||
m_currentFilter.m_required.emplace_back(Detail::make_unique<TestSpec::TagPattern>(".", m_substring));
|
||||
m_currentFilter.m_required.emplace_back(Detail::make_unique<TestSpec::TagPattern>(token, m_substring));
|
||||
}
|
||||
}
|
||||
if (m_exclusion) {
|
||||
@@ -7614,7 +7618,19 @@ WithinRelMatcher WithinRel(float target) {
|
||||
}
|
||||
|
||||
|
||||
} // namespace Matchers
|
||||
|
||||
bool IsNaNMatcher::match( double const& matchee ) const {
|
||||
return std::isnan( matchee );
|
||||
}
|
||||
|
||||
std::string IsNaNMatcher::describe() const {
|
||||
using namespace std::string_literals;
|
||||
return "is NaN"s;
|
||||
}
|
||||
|
||||
IsNaNMatcher IsNaN() { return IsNaNMatcher(); }
|
||||
|
||||
} // namespace Matchers
|
||||
} // namespace Catch
|
||||
|
||||
|
||||
@@ -8051,7 +8067,7 @@ private:
|
||||
private:
|
||||
std::ostream& stream;
|
||||
AssertionResult const& result;
|
||||
std::vector<MessageInfo> messages;
|
||||
std::vector<MessageInfo> const& messages;
|
||||
std::vector<MessageInfo>::const_iterator itMessage;
|
||||
bool printInfoMessages;
|
||||
ColourImpl* colourImpl;
|
||||
@@ -8145,7 +8161,6 @@ public:
|
||||
stats(_stats),
|
||||
result(_stats.assertionResult),
|
||||
colour(Colour::None),
|
||||
message(result.getMessage()),
|
||||
messages(_stats.infoMessages),
|
||||
colourImpl(colourImpl_),
|
||||
printInfoMessages(_printInfoMessages) {
|
||||
@@ -8154,10 +8169,10 @@ public:
|
||||
colour = Colour::Success;
|
||||
passOrFail = "PASSED"_sr;
|
||||
//if( result.hasMessage() )
|
||||
if (_stats.infoMessages.size() == 1)
|
||||
messageLabel = "with message";
|
||||
if (_stats.infoMessages.size() > 1)
|
||||
messageLabel = "with messages";
|
||||
if (messages.size() == 1)
|
||||
messageLabel = "with message"_sr;
|
||||
if (messages.size() > 1)
|
||||
messageLabel = "with messages"_sr;
|
||||
break;
|
||||
case ResultWas::ExpressionFailed:
|
||||
if (result.isOk()) {
|
||||
@@ -8167,51 +8182,57 @@ public:
|
||||
colour = Colour::Error;
|
||||
passOrFail = "FAILED"_sr;
|
||||
}
|
||||
if (_stats.infoMessages.size() == 1)
|
||||
messageLabel = "with message";
|
||||
if (_stats.infoMessages.size() > 1)
|
||||
messageLabel = "with messages";
|
||||
if (messages.size() == 1)
|
||||
messageLabel = "with message"_sr;
|
||||
if (messages.size() > 1)
|
||||
messageLabel = "with messages"_sr;
|
||||
break;
|
||||
case ResultWas::ThrewException:
|
||||
colour = Colour::Error;
|
||||
passOrFail = "FAILED"_sr;
|
||||
messageLabel = "due to unexpected exception with ";
|
||||
if (_stats.infoMessages.size() == 1)
|
||||
messageLabel += "message";
|
||||
if (_stats.infoMessages.size() > 1)
|
||||
messageLabel += "messages";
|
||||
// todo switch
|
||||
switch (messages.size()) { case 0:
|
||||
messageLabel = "due to unexpected exception with "_sr;
|
||||
break;
|
||||
case 1:
|
||||
messageLabel = "due to unexpected exception with message"_sr;
|
||||
break;
|
||||
default:
|
||||
messageLabel = "due to unexpected exception with messages"_sr;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case ResultWas::FatalErrorCondition:
|
||||
colour = Colour::Error;
|
||||
passOrFail = "FAILED"_sr;
|
||||
messageLabel = "due to a fatal error condition";
|
||||
messageLabel = "due to a fatal error condition"_sr;
|
||||
break;
|
||||
case ResultWas::DidntThrowException:
|
||||
colour = Colour::Error;
|
||||
passOrFail = "FAILED"_sr;
|
||||
messageLabel = "because no exception was thrown where one was expected";
|
||||
messageLabel = "because no exception was thrown where one was expected"_sr;
|
||||
break;
|
||||
case ResultWas::Info:
|
||||
messageLabel = "info";
|
||||
messageLabel = "info"_sr;
|
||||
break;
|
||||
case ResultWas::Warning:
|
||||
messageLabel = "warning";
|
||||
messageLabel = "warning"_sr;
|
||||
break;
|
||||
case ResultWas::ExplicitFailure:
|
||||
passOrFail = "FAILED"_sr;
|
||||
colour = Colour::Error;
|
||||
if (_stats.infoMessages.size() == 1)
|
||||
messageLabel = "explicitly with message";
|
||||
if (_stats.infoMessages.size() > 1)
|
||||
messageLabel = "explicitly with messages";
|
||||
if (messages.size() == 1)
|
||||
messageLabel = "explicitly with message"_sr;
|
||||
if (messages.size() > 1)
|
||||
messageLabel = "explicitly with messages"_sr;
|
||||
break;
|
||||
case ResultWas::ExplicitSkip:
|
||||
colour = Colour::Skip;
|
||||
passOrFail = "SKIPPED"_sr;
|
||||
if (_stats.infoMessages.size() == 1)
|
||||
messageLabel = "explicitly with message";
|
||||
if (_stats.infoMessages.size() > 1)
|
||||
messageLabel = "explicitly with messages";
|
||||
if (messages.size() == 1)
|
||||
messageLabel = "explicitly with message"_sr;
|
||||
if (messages.size() > 1)
|
||||
messageLabel = "explicitly with messages"_sr;
|
||||
break;
|
||||
// These cases are here to prevent compiler warnings
|
||||
case ResultWas::Unknown:
|
||||
@@ -8275,9 +8296,8 @@ private:
|
||||
AssertionResult const& result;
|
||||
Colour::Code colour;
|
||||
StringRef passOrFail;
|
||||
std::string messageLabel;
|
||||
std::string message;
|
||||
std::vector<MessageInfo> messages;
|
||||
StringRef messageLabel;
|
||||
std::vector<MessageInfo> const& messages;
|
||||
ColourImpl* colourImpl;
|
||||
bool printInfoMessages;
|
||||
};
|
||||
@@ -8809,7 +8829,8 @@ namespace Catch {
|
||||
|
||||
void
|
||||
CumulativeReporterBase::sectionStarting( SectionInfo const& sectionInfo ) {
|
||||
SectionStats incompleteStats( sectionInfo, Counts(), 0, false );
|
||||
// We need a copy, because SectionStats expect to take ownership
|
||||
SectionStats incompleteStats( SectionInfo(sectionInfo), Counts(), 0, false );
|
||||
SectionNode* node;
|
||||
if ( m_sectionStack.empty() ) {
|
||||
if ( !m_rootSection ) {
|
||||
@@ -9792,7 +9813,7 @@ namespace Catch {
|
||||
}
|
||||
|
||||
void SonarQubeReporter::writeRun( TestRunNode const& runNode ) {
|
||||
std::map<std::string, std::vector<TestCaseNode const*>> testsPerFile;
|
||||
std::map<StringRef, std::vector<TestCaseNode const*>> testsPerFile;
|
||||
|
||||
for ( auto const& child : runNode.children ) {
|
||||
testsPerFile[child->value.testInfo->lineInfo.file].push_back(
|
||||
@@ -9804,7 +9825,7 @@ namespace Catch {
|
||||
}
|
||||
}
|
||||
|
||||
void SonarQubeReporter::writeTestFile(std::string const& filename, std::vector<TestCaseNode const*> const& testCaseNodes) {
|
||||
void SonarQubeReporter::writeTestFile(StringRef filename, std::vector<TestCaseNode const*> const& testCaseNodes) {
|
||||
XmlWriter::ScopedElement e = xml.scopedElement("file");
|
||||
xml.writeAttribute("path"_sr, filename);
|
||||
|
||||
@@ -10103,7 +10124,7 @@ namespace Catch {
|
||||
private:
|
||||
std::ostream& stream;
|
||||
AssertionResult const& result;
|
||||
std::vector<MessageInfo> messages;
|
||||
std::vector<MessageInfo> const& messages;
|
||||
std::vector<MessageInfo>::const_iterator itMessage;
|
||||
bool printInfoMessages;
|
||||
std::size_t counter;
|
||||
@@ -10366,7 +10387,7 @@ namespace Catch {
|
||||
void XmlReporter::testCaseStarting( TestCaseInfo const& testInfo ) {
|
||||
StreamingReporterBase::testCaseStarting(testInfo);
|
||||
m_xml.startElement( "TestCase" )
|
||||
.writeAttribute( "name"_sr, trim( testInfo.name ) )
|
||||
.writeAttribute( "name"_sr, trim( StringRef(testInfo.name) ) )
|
||||
.writeAttribute( "tags"_sr, testInfo.tagsAsString() );
|
||||
|
||||
writeSourceInfo( testInfo.lineInfo );
|
||||
@@ -10380,7 +10401,7 @@ namespace Catch {
|
||||
StreamingReporterBase::sectionStarting( sectionInfo );
|
||||
if( m_sectionDepth++ > 0 ) {
|
||||
m_xml.startElement( "Section" )
|
||||
.writeAttribute( "name"_sr, trim( sectionInfo.name ) );
|
||||
.writeAttribute( "name"_sr, trim( StringRef(sectionInfo.name) ) );
|
||||
writeSourceInfo( sectionInfo.lineInfo );
|
||||
m_xml.ensureTagClosed();
|
||||
}
|
||||
@@ -10494,11 +10515,10 @@ namespace Catch {
|
||||
|
||||
if ( m_config->showDurations() == ShowDurations::Always )
|
||||
e.writeAttribute( "durationInSeconds"_sr, m_testCaseTimer.getElapsedSeconds() );
|
||||
|
||||
if( !testCaseStats.stdOut.empty() )
|
||||
m_xml.scopedElement( "StdOut" ).writeText( trim( testCaseStats.stdOut ), XmlFormatting::Newline );
|
||||
m_xml.scopedElement( "StdOut" ).writeText( trim( StringRef(testCaseStats.stdOut) ), XmlFormatting::Newline );
|
||||
if( !testCaseStats.stdErr.empty() )
|
||||
m_xml.scopedElement( "StdErr" ).writeText( trim( testCaseStats.stdErr ), XmlFormatting::Newline );
|
||||
m_xml.scopedElement( "StdErr" ).writeText( trim( StringRef(testCaseStats.stdErr) ), XmlFormatting::Newline );
|
||||
|
||||
m_xml.endElement();
|
||||
}
|
||||
|
@@ -5,8 +5,8 @@
|
||||
|
||||
// SPDX-License-Identifier: BSL-1.0
|
||||
|
||||
// Catch v3.3.0
|
||||
// Generated: 2023-01-22 19:46:23.163056
|
||||
// Catch v3.3.2
|
||||
// Generated: 2023-02-26 10:28:46.785908
|
||||
// ----------------------------------------------------------
|
||||
// This file is an amalgamation of multiple different files.
|
||||
// You probably shouldn't edit it directly.
|
||||
@@ -95,6 +95,8 @@ namespace Catch {
|
||||
#include <iosfwd>
|
||||
#include <cassert>
|
||||
|
||||
#include <cstring>
|
||||
|
||||
namespace Catch {
|
||||
|
||||
/// A non-owning string class (similar to the forthcoming std::string_view)
|
||||
@@ -131,7 +133,10 @@ namespace Catch {
|
||||
}
|
||||
|
||||
public: // operators
|
||||
auto operator == ( StringRef other ) const noexcept -> bool;
|
||||
auto operator == ( StringRef other ) const noexcept -> bool {
|
||||
return m_size == other.m_size
|
||||
&& (std::memcmp( m_start, other.m_start, m_size ) == 0);
|
||||
}
|
||||
auto operator != (StringRef other) const noexcept -> bool {
|
||||
return !(*this == other);
|
||||
}
|
||||
@@ -352,7 +357,7 @@ namespace Catch {
|
||||
|
||||
// Only GCC compiler should be used in this block, so other compilers trying to
|
||||
// mask themselves as GCC should be ignored.
|
||||
#if defined(__GNUC__) && !defined(__clang__) && !defined(__ICC) && !defined(__CUDACC__) && !defined(__LCC__)
|
||||
#if defined(__GNUC__) && !defined(__clang__) && !defined(__ICC) && !defined(__CUDACC__) && !defined(__LCC__) && !defined(__NVCOMPILER)
|
||||
# define CATCH_INTERNAL_START_WARNINGS_SUPPRESSION _Pragma( "GCC diagnostic push" )
|
||||
# define CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION _Pragma( "GCC diagnostic pop" )
|
||||
|
||||
@@ -371,6 +376,12 @@ namespace Catch {
|
||||
|
||||
#endif
|
||||
|
||||
#if defined(__NVCOMPILER)
|
||||
# define CATCH_INTERNAL_START_WARNINGS_SUPPRESSION _Pragma( "diag push" )
|
||||
# define CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION _Pragma( "diag pop" )
|
||||
# define CATCH_INTERNAL_SUPPRESS_UNUSED_VARIABLE_WARNINGS _Pragma( "diag_suppress declared_but_not_referenced" )
|
||||
#endif
|
||||
|
||||
#if defined(__CUDACC__) && !defined(__clang__)
|
||||
# ifdef __NVCC_DIAG_PRAGMA_SUPPORT__
|
||||
// New pragmas introduced in CUDA 11.5+
|
||||
@@ -1039,7 +1050,7 @@ namespace Catch {
|
||||
class AssertionResult {
|
||||
public:
|
||||
AssertionResult() = delete;
|
||||
AssertionResult( AssertionInfo const& info, AssertionResultData const& data );
|
||||
AssertionResult( AssertionInfo const& info, AssertionResultData&& data );
|
||||
|
||||
bool isOk() const;
|
||||
bool succeeded() const;
|
||||
@@ -1217,10 +1228,11 @@ namespace Catch {
|
||||
public:
|
||||
virtual ~IResultCapture();
|
||||
|
||||
virtual bool sectionStarted( SectionInfo const& sectionInfo,
|
||||
Counts& assertions ) = 0;
|
||||
virtual void sectionEnded( SectionEndInfo const& endInfo ) = 0;
|
||||
virtual void sectionEndedEarly( SectionEndInfo const& endInfo ) = 0;
|
||||
virtual bool sectionStarted( StringRef sectionName,
|
||||
SourceLineInfo const& sectionLineInfo,
|
||||
Counts& assertions ) = 0;
|
||||
virtual void sectionEnded( SectionEndInfo&& endInfo ) = 0;
|
||||
virtual void sectionEndedEarly( SectionEndInfo&& endInfo ) = 0;
|
||||
|
||||
virtual IGeneratorTracker*
|
||||
acquireGeneratorTracker( StringRef generatorName,
|
||||
@@ -1238,7 +1250,7 @@ namespace Catch {
|
||||
virtual void pushScopedMessage( MessageInfo const& message ) = 0;
|
||||
virtual void popScopedMessage( MessageInfo const& message ) = 0;
|
||||
|
||||
virtual void emplaceUnscopedMessage( MessageBuilder const& builder ) = 0;
|
||||
virtual void emplaceUnscopedMessage( MessageBuilder&& builder ) = 0;
|
||||
|
||||
virtual void handleFatalErrorCondition( StringRef message ) = 0;
|
||||
|
||||
@@ -1419,7 +1431,7 @@ namespace Catch {
|
||||
};
|
||||
|
||||
struct SectionStats {
|
||||
SectionStats( SectionInfo const& _sectionInfo,
|
||||
SectionStats( SectionInfo&& _sectionInfo,
|
||||
Counts const& _assertions,
|
||||
double _durationInSeconds,
|
||||
bool _missingAssertions );
|
||||
@@ -1433,8 +1445,8 @@ namespace Catch {
|
||||
struct TestCaseStats {
|
||||
TestCaseStats( TestCaseInfo const& _testInfo,
|
||||
Totals const& _totals,
|
||||
std::string const& _stdOut,
|
||||
std::string const& _stdErr,
|
||||
std::string&& _stdOut,
|
||||
std::string&& _stdErr,
|
||||
bool _aborting );
|
||||
|
||||
TestCaseInfo const * testInfo;
|
||||
@@ -2691,7 +2703,7 @@ namespace Catch {
|
||||
});
|
||||
|
||||
BenchmarkInfo info {
|
||||
name,
|
||||
CATCH_MOVE(name),
|
||||
plan.estimated_duration.count(),
|
||||
plan.iterations_per_sample,
|
||||
cfg->benchmarkSamples(),
|
||||
@@ -2707,7 +2719,7 @@ namespace Catch {
|
||||
});
|
||||
|
||||
auto analysis = Detail::analyse(*cfg, env, samples.begin(), samples.end());
|
||||
BenchmarkStats<FloatDuration<Clock>> stats{ info, analysis.samples, analysis.mean, analysis.standard_deviation, analysis.outliers, analysis.outlier_variance };
|
||||
BenchmarkStats<FloatDuration<Clock>> stats{ CATCH_MOVE(info), CATCH_MOVE(analysis.samples), analysis.mean, analysis.standard_deviation, analysis.outliers, analysis.outlier_variance };
|
||||
getResultCapture().benchmarkEnded(stats);
|
||||
} CATCH_CATCH_ANON (TestFailureException) {
|
||||
getResultCapture().benchmarkFailed("Benchmark failed due to failed assertion"_sr);
|
||||
@@ -4459,11 +4471,10 @@ namespace Catch {
|
||||
ResultWas::OfType type ):
|
||||
m_info(macroName, lineInfo, type) {}
|
||||
|
||||
|
||||
template<typename T>
|
||||
MessageBuilder& operator << ( T const& value ) {
|
||||
MessageBuilder&& operator << ( T const& value ) && {
|
||||
m_stream << value;
|
||||
return *this;
|
||||
return CATCH_MOVE(*this);
|
||||
}
|
||||
|
||||
MessageInfo m_info;
|
||||
@@ -4471,7 +4482,7 @@ namespace Catch {
|
||||
|
||||
class ScopedMessage {
|
||||
public:
|
||||
explicit ScopedMessage( MessageBuilder const& builder );
|
||||
explicit ScopedMessage( MessageBuilder&& builder );
|
||||
ScopedMessage( ScopedMessage& duplicate ) = delete;
|
||||
ScopedMessage( ScopedMessage&& old ) noexcept;
|
||||
~ScopedMessage();
|
||||
@@ -4518,7 +4529,10 @@ namespace Catch {
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
#define INTERNAL_CATCH_CAPTURE( varName, macroName, ... ) \
|
||||
Catch::Capturer varName( macroName, CATCH_INTERNAL_LINEINFO, Catch::ResultWas::Info, #__VA_ARGS__ ); \
|
||||
Catch::Capturer varName( macroName##_catch_sr, \
|
||||
CATCH_INTERNAL_LINEINFO, \
|
||||
Catch::ResultWas::Info, \
|
||||
#__VA_ARGS__##_catch_sr ); \
|
||||
varName.captureValues( 0, __VA_ARGS__ )
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
@@ -5904,9 +5918,9 @@ namespace Catch {
|
||||
#if !defined(CATCH_CONFIG_DISABLE)
|
||||
|
||||
#if !defined(CATCH_CONFIG_DISABLE_STRINGIFICATION)
|
||||
#define CATCH_INTERNAL_STRINGIFY(...) #__VA_ARGS__
|
||||
#define CATCH_INTERNAL_STRINGIFY(...) #__VA_ARGS__##_catch_sr
|
||||
#else
|
||||
#define CATCH_INTERNAL_STRINGIFY(...) "Disabled by CATCH_CONFIG_DISABLE_STRINGIFICATION"
|
||||
#define CATCH_INTERNAL_STRINGIFY(...) "Disabled by CATCH_CONFIG_DISABLE_STRINGIFICATION"_catch_sr
|
||||
#endif
|
||||
|
||||
#if defined(CATCH_CONFIG_FAST_COMPILE) || defined(CATCH_CONFIG_DISABLE_EXCEPTIONS)
|
||||
@@ -6071,6 +6085,9 @@ namespace Catch {
|
||||
class Section : Detail::NonCopyable {
|
||||
public:
|
||||
Section( SectionInfo&& info );
|
||||
Section( SourceLineInfo const& _lineInfo,
|
||||
StringRef _name,
|
||||
const char* const = nullptr );
|
||||
~Section();
|
||||
|
||||
// This indicates whether the section should be executed or not
|
||||
@@ -6089,7 +6106,7 @@ namespace Catch {
|
||||
#define INTERNAL_CATCH_SECTION( ... ) \
|
||||
CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \
|
||||
CATCH_INTERNAL_SUPPRESS_UNUSED_VARIABLE_WARNINGS \
|
||||
if( Catch::Section const& INTERNAL_CATCH_UNIQUE_NAME( catch_internal_Section ) = Catch::SectionInfo( CATCH_INTERNAL_LINEINFO, __VA_ARGS__ ) ) \
|
||||
if( Catch::Section const& INTERNAL_CATCH_UNIQUE_NAME( catch_internal_Section ) = Catch::Section( CATCH_INTERNAL_LINEINFO, __VA_ARGS__ ) ) \
|
||||
CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION
|
||||
|
||||
#define INTERNAL_CATCH_DYNAMIC_SECTION( ... ) \
|
||||
@@ -6230,7 +6247,13 @@ struct AutoReg : Detail::NonCopyable {
|
||||
CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \
|
||||
CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
|
||||
CATCH_INTERNAL_SUPPRESS_UNUSED_VARIABLE_WARNINGS \
|
||||
namespace{ const Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( Catch::makeTestInvoker( &QualifiedMethod ), CATCH_INTERNAL_LINEINFO, "&" #QualifiedMethod, Catch::NameAndTags{ __VA_ARGS__ } ); } /* NOLINT */ \
|
||||
namespace { \
|
||||
const Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( \
|
||||
Catch::makeTestInvoker( &QualifiedMethod ), \
|
||||
CATCH_INTERNAL_LINEINFO, \
|
||||
"&" #QualifiedMethod##_catch_sr, \
|
||||
Catch::NameAndTags{ __VA_ARGS__ } ); \
|
||||
} /* NOLINT */ \
|
||||
CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
@@ -6242,7 +6265,11 @@ struct AutoReg : Detail::NonCopyable {
|
||||
struct TestName : INTERNAL_CATCH_REMOVE_PARENS(ClassName) { \
|
||||
void test(); \
|
||||
}; \
|
||||
const Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar ) ( Catch::makeTestInvoker( &TestName::test ), CATCH_INTERNAL_LINEINFO, #ClassName, Catch::NameAndTags{ __VA_ARGS__ } ); /* NOLINT */ \
|
||||
const Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( \
|
||||
Catch::makeTestInvoker( &TestName::test ), \
|
||||
CATCH_INTERNAL_LINEINFO, \
|
||||
#ClassName##_catch_sr, \
|
||||
Catch::NameAndTags{ __VA_ARGS__ } ); /* NOLINT */ \
|
||||
} \
|
||||
CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION \
|
||||
void TestName::test()
|
||||
@@ -6875,7 +6902,7 @@ struct AutoReg : Detail::NonCopyable {
|
||||
void reg_tests() { \
|
||||
size_t index = 0; \
|
||||
using expander = size_t[]; \
|
||||
(void)expander{(Catch::AutoReg( Catch::makeTestInvoker( &TestFunc<Types> ), CATCH_INTERNAL_LINEINFO, Catch::StringRef(), Catch::NameAndTags{ Name " - " + std::string(INTERNAL_CATCH_STRINGIZE(TmplList)) + " - " + std::to_string(index), Tags } ), index++)... };/* NOLINT */\
|
||||
(void)expander{(Catch::AutoReg( Catch::makeTestInvoker( &TestFunc<Types> ), CATCH_INTERNAL_LINEINFO, Catch::StringRef(), Catch::NameAndTags{ Name " - " INTERNAL_CATCH_STRINGIZE(TmplList) " - " + std::to_string(index), Tags } ), index++)... };/* NOLINT */\
|
||||
} \
|
||||
};\
|
||||
static int INTERNAL_CATCH_UNIQUE_NAME( globalRegistrar ) = [](){ \
|
||||
@@ -7010,7 +7037,7 @@ struct AutoReg : Detail::NonCopyable {
|
||||
void reg_tests(){\
|
||||
size_t index = 0;\
|
||||
using expander = size_t[];\
|
||||
(void)expander{(Catch::AutoReg( Catch::makeTestInvoker( &TestName<Types>::test ), CATCH_INTERNAL_LINEINFO, #ClassName, Catch::NameAndTags{ Name " - " + std::string(INTERNAL_CATCH_STRINGIZE(TmplList)) + " - " + std::to_string(index), Tags } ), index++)... };/* NOLINT */ \
|
||||
(void)expander{(Catch::AutoReg( Catch::makeTestInvoker( &TestName<Types>::test ), CATCH_INTERNAL_LINEINFO, #ClassName##_catch_sr, Catch::NameAndTags{ Name " - " INTERNAL_CATCH_STRINGIZE(TmplList) " - " + std::to_string(index), Tags } ), index++)... };/* NOLINT */ \
|
||||
}\
|
||||
};\
|
||||
static int INTERNAL_CATCH_UNIQUE_NAME( globalRegistrar ) = [](){\
|
||||
@@ -7399,7 +7426,7 @@ namespace Catch {
|
||||
|
||||
#define CATCH_VERSION_MAJOR 3
|
||||
#define CATCH_VERSION_MINOR 3
|
||||
#define CATCH_VERSION_PATCH 0
|
||||
#define CATCH_VERSION_PATCH 2
|
||||
|
||||
#endif // CATCH_VERSION_MACROS_HPP_INCLUDED
|
||||
|
||||
@@ -7751,16 +7778,19 @@ namespace Detail {
|
||||
} // namespace Generators
|
||||
} // namespace Catch
|
||||
|
||||
#define CATCH_INTERNAL_GENERATOR_STRINGIZE_IMPL( ... ) #__VA_ARGS__##_catch_sr
|
||||
#define CATCH_INTERNAL_GENERATOR_STRINGIZE(...) CATCH_INTERNAL_GENERATOR_STRINGIZE_IMPL(__VA_ARGS__)
|
||||
|
||||
#define GENERATE( ... ) \
|
||||
Catch::Generators::generate( INTERNAL_CATCH_STRINGIZE(INTERNAL_CATCH_UNIQUE_NAME(generator)), \
|
||||
Catch::Generators::generate( CATCH_INTERNAL_GENERATOR_STRINGIZE(INTERNAL_CATCH_UNIQUE_NAME(generator)), \
|
||||
CATCH_INTERNAL_LINEINFO, \
|
||||
[ ]{ using namespace Catch::Generators; return makeGenerators( __VA_ARGS__ ); } ) //NOLINT(google-build-using-namespace)
|
||||
#define GENERATE_COPY( ... ) \
|
||||
Catch::Generators::generate( INTERNAL_CATCH_STRINGIZE(INTERNAL_CATCH_UNIQUE_NAME(generator)), \
|
||||
Catch::Generators::generate( CATCH_INTERNAL_GENERATOR_STRINGIZE(INTERNAL_CATCH_UNIQUE_NAME(generator)), \
|
||||
CATCH_INTERNAL_LINEINFO, \
|
||||
[=]{ using namespace Catch::Generators; return makeGenerators( __VA_ARGS__ ); } ) //NOLINT(google-build-using-namespace)
|
||||
#define GENERATE_REF( ... ) \
|
||||
Catch::Generators::generate( INTERNAL_CATCH_STRINGIZE(INTERNAL_CATCH_UNIQUE_NAME(generator)), \
|
||||
Catch::Generators::generate( CATCH_INTERNAL_GENERATOR_STRINGIZE(INTERNAL_CATCH_UNIQUE_NAME(generator)), \
|
||||
CATCH_INTERNAL_LINEINFO, \
|
||||
[&]{ using namespace Catch::Generators; return makeGenerators( __VA_ARGS__ ); } ) //NOLINT(google-build-using-namespace)
|
||||
|
||||
@@ -8916,6 +8946,139 @@ namespace Detail {
|
||||
#endif // CATCH_GETENV_HPP_INCLUDED
|
||||
|
||||
|
||||
#ifndef CATCH_IS_PERMUTATION_HPP_INCLUDED
|
||||
#define CATCH_IS_PERMUTATION_HPP_INCLUDED
|
||||
|
||||
#include <algorithm>
|
||||
#include <iterator>
|
||||
|
||||
namespace Catch {
|
||||
namespace Detail {
|
||||
|
||||
template <typename ForwardIter,
|
||||
typename Sentinel,
|
||||
typename T,
|
||||
typename Comparator>
|
||||
ForwardIter find_sentinel( ForwardIter start,
|
||||
Sentinel sentinel,
|
||||
T const& value,
|
||||
Comparator cmp ) {
|
||||
while ( start != sentinel ) {
|
||||
if ( cmp( *start, value ) ) { break; }
|
||||
++start;
|
||||
}
|
||||
return start;
|
||||
}
|
||||
|
||||
template <typename ForwardIter,
|
||||
typename Sentinel,
|
||||
typename T,
|
||||
typename Comparator>
|
||||
std::ptrdiff_t count_sentinel( ForwardIter start,
|
||||
Sentinel sentinel,
|
||||
T const& value,
|
||||
Comparator cmp ) {
|
||||
std::ptrdiff_t count = 0;
|
||||
while ( start != sentinel ) {
|
||||
if ( cmp( *start, value ) ) { ++count; }
|
||||
++start;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
template <typename ForwardIter, typename Sentinel>
|
||||
std::enable_if_t<!std::is_same<ForwardIter, Sentinel>::value,
|
||||
std::ptrdiff_t>
|
||||
sentinel_distance( ForwardIter iter, const Sentinel sentinel ) {
|
||||
std::ptrdiff_t dist = 0;
|
||||
while ( iter != sentinel ) {
|
||||
++iter;
|
||||
++dist;
|
||||
}
|
||||
return dist;
|
||||
}
|
||||
|
||||
template <typename ForwardIter>
|
||||
std::ptrdiff_t sentinel_distance( ForwardIter first,
|
||||
ForwardIter last ) {
|
||||
return std::distance( first, last );
|
||||
}
|
||||
|
||||
template <typename ForwardIter1,
|
||||
typename Sentinel1,
|
||||
typename ForwardIter2,
|
||||
typename Sentinel2,
|
||||
typename Comparator>
|
||||
bool check_element_counts( ForwardIter1 first_1,
|
||||
const Sentinel1 end_1,
|
||||
ForwardIter2 first_2,
|
||||
const Sentinel2 end_2,
|
||||
Comparator cmp ) {
|
||||
auto cursor = first_1;
|
||||
while ( cursor != end_1 ) {
|
||||
if ( find_sentinel( first_1, cursor, *cursor, cmp ) ==
|
||||
cursor ) {
|
||||
// we haven't checked this element yet
|
||||
const auto count_in_range_2 =
|
||||
count_sentinel( first_2, end_2, *cursor, cmp );
|
||||
// Not a single instance in 2nd range, so it cannot be a
|
||||
// permutation of 1st range
|
||||
if ( count_in_range_2 == 0 ) { return false; }
|
||||
|
||||
const auto count_in_range_1 =
|
||||
count_sentinel( cursor, end_1, *cursor, cmp );
|
||||
if ( count_in_range_1 != count_in_range_2 ) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
++cursor;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
template <typename ForwardIter1,
|
||||
typename Sentinel1,
|
||||
typename ForwardIter2,
|
||||
typename Sentinel2,
|
||||
typename Comparator>
|
||||
bool is_permutation( ForwardIter1 first_1,
|
||||
const Sentinel1 end_1,
|
||||
ForwardIter2 first_2,
|
||||
const Sentinel2 end_2,
|
||||
Comparator cmp ) {
|
||||
// TODO: no optimization for stronger iterators, because we would also have to constrain on sentinel vs not sentinel types
|
||||
// TODO: Comparator has to be "both sides", e.g. a == b => b == a
|
||||
// This skips shared prefix of the two ranges
|
||||
while (first_1 != end_1 && first_2 != end_2 && cmp(*first_1, *first_2)) {
|
||||
++first_1;
|
||||
++first_2;
|
||||
}
|
||||
|
||||
// We need to handle case where at least one of the ranges has no more elements
|
||||
if (first_1 == end_1 || first_2 == end_2) {
|
||||
return first_1 == end_1 && first_2 == end_2;
|
||||
}
|
||||
|
||||
// pair counting is n**2, so we pay linear walk to compare the sizes first
|
||||
auto dist_1 = sentinel_distance( first_1, end_1 );
|
||||
auto dist_2 = sentinel_distance( first_2, end_2 );
|
||||
|
||||
if (dist_1 != dist_2) { return false; }
|
||||
|
||||
// Since we do not try to handle stronger iterators pair (e.g.
|
||||
// bidir) optimally, the only thing left to do is to check counts in
|
||||
// the remaining ranges.
|
||||
return check_element_counts( first_1, end_1, first_2, end_2, cmp );
|
||||
}
|
||||
|
||||
} // namespace Detail
|
||||
} // namespace Catch
|
||||
|
||||
#endif // CATCH_IS_PERMUTATION_HPP_INCLUDED
|
||||
|
||||
|
||||
#ifndef CATCH_ISTREAM_HPP_INCLUDED
|
||||
#define CATCH_ISTREAM_HPP_INCLUDED
|
||||
|
||||
@@ -9194,10 +9357,14 @@ namespace TestCaseTracking {
|
||||
std::string name;
|
||||
SourceLineInfo location;
|
||||
|
||||
NameAndLocation( std::string const& _name, SourceLineInfo const& _location );
|
||||
NameAndLocation( std::string&& _name, SourceLineInfo const& _location );
|
||||
friend bool operator==(NameAndLocation const& lhs, NameAndLocation const& rhs) {
|
||||
return lhs.name == rhs.name
|
||||
&& lhs.location == rhs.location;
|
||||
// This is a very cheap check that should have a very high hit rate.
|
||||
// If we get to SourceLineInfo::operator==, we will redo it, but the
|
||||
// cost of repeating is trivial at that point (we will be paying
|
||||
// multiple strcmp/memcmps at that point).
|
||||
if ( lhs.location.line != rhs.location.line ) { return false; }
|
||||
return lhs.name == rhs.name && lhs.location == rhs.location;
|
||||
}
|
||||
friend bool operator!=(NameAndLocation const& lhs,
|
||||
NameAndLocation const& rhs) {
|
||||
@@ -9205,6 +9372,37 @@ namespace TestCaseTracking {
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* This is a variant of `NameAndLocation` that does not own the name string
|
||||
*
|
||||
* This avoids extra allocations when trying to locate a tracker by its
|
||||
* name and location, as long as we make sure that trackers only keep
|
||||
* around the owning variant.
|
||||
*/
|
||||
struct NameAndLocationRef {
|
||||
StringRef name;
|
||||
SourceLineInfo location;
|
||||
|
||||
constexpr NameAndLocationRef( StringRef name_,
|
||||
SourceLineInfo location_ ):
|
||||
name( name_ ), location( location_ ) {}
|
||||
|
||||
friend bool operator==( NameAndLocation const& lhs,
|
||||
NameAndLocationRef const& rhs ) {
|
||||
// This is a very cheap check that should have a very high hit rate.
|
||||
// If we get to SourceLineInfo::operator==, we will redo it, but the
|
||||
// cost of repeating is trivial at that point (we will be paying
|
||||
// multiple strcmp/memcmps at that point).
|
||||
if ( lhs.location.line != rhs.location.line ) { return false; }
|
||||
return StringRef( lhs.name ) == rhs.name &&
|
||||
lhs.location == rhs.location;
|
||||
}
|
||||
friend bool operator==( NameAndLocationRef const& lhs,
|
||||
NameAndLocation const& rhs ) {
|
||||
return rhs == lhs;
|
||||
}
|
||||
};
|
||||
|
||||
class ITracker;
|
||||
|
||||
using ITrackerPtr = Catch::Detail::unique_ptr<ITracker>;
|
||||
@@ -9229,8 +9427,8 @@ namespace TestCaseTracking {
|
||||
CycleState m_runState = NotStarted;
|
||||
|
||||
public:
|
||||
ITracker( NameAndLocation const& nameAndLoc, ITracker* parent ):
|
||||
m_nameAndLocation( nameAndLoc ),
|
||||
ITracker( NameAndLocation&& nameAndLoc, ITracker* parent ):
|
||||
m_nameAndLocation( CATCH_MOVE(nameAndLoc) ),
|
||||
m_parent( parent )
|
||||
{}
|
||||
|
||||
@@ -9251,7 +9449,9 @@ namespace TestCaseTracking {
|
||||
//! Returns true if tracker run to completion (successfully or not)
|
||||
virtual bool isComplete() const = 0;
|
||||
//! Returns true if tracker run to completion succesfully
|
||||
bool isSuccessfullyCompleted() const;
|
||||
bool isSuccessfullyCompleted() const {
|
||||
return m_runState == CompletedSuccessfully;
|
||||
}
|
||||
//! Returns true if tracker has started but hasn't been completed
|
||||
bool isOpen() const;
|
||||
//! Returns true iff tracker has started
|
||||
@@ -9269,7 +9469,7 @@ namespace TestCaseTracking {
|
||||
*
|
||||
* Returns nullptr if not found.
|
||||
*/
|
||||
ITracker* findChild( NameAndLocation const& nameAndLocation );
|
||||
ITracker* findChild( NameAndLocationRef const& nameAndLocation );
|
||||
//! Have any children been added?
|
||||
bool hasChildren() const {
|
||||
return !m_children.empty();
|
||||
@@ -9310,13 +9510,15 @@ namespace TestCaseTracking {
|
||||
public:
|
||||
|
||||
ITracker& startRun();
|
||||
void endRun();
|
||||
|
||||
void startCycle();
|
||||
void startCycle() {
|
||||
m_currentTracker = m_rootTracker.get();
|
||||
m_runState = Executing;
|
||||
}
|
||||
void completeCycle();
|
||||
|
||||
bool completedCycle() const;
|
||||
ITracker& currentTracker();
|
||||
ITracker& currentTracker() { return *m_currentTracker; }
|
||||
void setCurrentTracker( ITracker* tracker );
|
||||
};
|
||||
|
||||
@@ -9326,7 +9528,7 @@ namespace TestCaseTracking {
|
||||
TrackerContext& m_ctx;
|
||||
|
||||
public:
|
||||
TrackerBase( NameAndLocation const& nameAndLocation, TrackerContext& ctx, ITracker* parent );
|
||||
TrackerBase( NameAndLocation&& nameAndLocation, TrackerContext& ctx, ITracker* parent );
|
||||
|
||||
bool isComplete() const override;
|
||||
|
||||
@@ -9342,22 +9544,26 @@ namespace TestCaseTracking {
|
||||
|
||||
class SectionTracker : public TrackerBase {
|
||||
std::vector<StringRef> m_filters;
|
||||
std::string m_trimmed_name;
|
||||
// Note that lifetime-wise we piggy back off the name stored in the `ITracker` parent`.
|
||||
// Currently it allocates owns the name, so this is safe. If it is later refactored
|
||||
// to not own the name, the name still has to outlive the `ITracker` parent, so
|
||||
// this should still be safe.
|
||||
StringRef m_trimmed_name;
|
||||
public:
|
||||
SectionTracker( NameAndLocation const& nameAndLocation, TrackerContext& ctx, ITracker* parent );
|
||||
SectionTracker( NameAndLocation&& nameAndLocation, TrackerContext& ctx, ITracker* parent );
|
||||
|
||||
bool isSectionTracker() const override;
|
||||
|
||||
bool isComplete() const override;
|
||||
|
||||
static SectionTracker& acquire( TrackerContext& ctx, NameAndLocation const& nameAndLocation );
|
||||
static SectionTracker& acquire( TrackerContext& ctx, NameAndLocationRef const& nameAndLocation );
|
||||
|
||||
void tryOpen();
|
||||
|
||||
void addInitialFilters( std::vector<std::string> const& filters );
|
||||
void addNextFilters( std::vector<StringRef> const& filters );
|
||||
//! Returns filters active in this tracker
|
||||
std::vector<StringRef> const& getFilters() const;
|
||||
std::vector<StringRef> const& getFilters() const { return m_filters; }
|
||||
//! Returns whitespace-trimmed name of the tracked section
|
||||
StringRef trimmedName() const;
|
||||
};
|
||||
@@ -9420,10 +9626,12 @@ namespace Catch {
|
||||
ResultWas::OfType resultType,
|
||||
AssertionReaction &reaction ) override;
|
||||
|
||||
bool sectionStarted( SectionInfo const& sectionInfo, Counts& assertions ) override;
|
||||
bool sectionStarted( StringRef sectionName,
|
||||
SourceLineInfo const& sectionLineInfo,
|
||||
Counts& assertions ) override;
|
||||
|
||||
void sectionEnded( SectionEndInfo const& endInfo ) override;
|
||||
void sectionEndedEarly( SectionEndInfo const& endInfo ) override;
|
||||
void sectionEnded( SectionEndInfo&& endInfo ) override;
|
||||
void sectionEndedEarly( SectionEndInfo&& endInfo ) override;
|
||||
|
||||
IGeneratorTracker*
|
||||
acquireGeneratorTracker( StringRef generatorName,
|
||||
@@ -9442,7 +9650,7 @@ namespace Catch {
|
||||
void pushScopedMessage( MessageInfo const& message ) override;
|
||||
void popScopedMessage( MessageInfo const& message ) override;
|
||||
|
||||
void emplaceUnscopedMessage( MessageBuilder const& builder ) override;
|
||||
void emplaceUnscopedMessage( MessageBuilder&& builder ) override;
|
||||
|
||||
std::string getCurrentTestName() const override;
|
||||
|
||||
@@ -10929,13 +11137,11 @@ namespace Catch {
|
||||
}
|
||||
|
||||
template <typename RangeLike>
|
||||
bool match(RangeLike&& rng) const {
|
||||
using std::begin; using std::end;
|
||||
|
||||
return end(rng) != std::find_if(begin(rng), end(rng),
|
||||
[&](auto const& elem) {
|
||||
return m_eq(elem, m_desired);
|
||||
});
|
||||
bool match( RangeLike&& rng ) const {
|
||||
for ( auto&& elem : rng ) {
|
||||
if ( m_eq( elem, m_desired ) ) { return true; }
|
||||
}
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -10987,7 +11193,7 @@ namespace Catch {
|
||||
/**
|
||||
* Creates a matcher that checks whether a range contains a specific element.
|
||||
*
|
||||
* Uses `eq` to do the comparisons
|
||||
* 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) {
|
||||
@@ -11076,6 +11282,11 @@ namespace Matchers {
|
||||
double m_margin;
|
||||
};
|
||||
|
||||
//! Creates a matcher that accepts numbers within certain range of target
|
||||
WithinAbsMatcher WithinAbs( double target, double margin );
|
||||
|
||||
|
||||
|
||||
class WithinUlpsMatcher final : public MatcherBase<double> {
|
||||
public:
|
||||
WithinUlpsMatcher( double target,
|
||||
@@ -11089,6 +11300,13 @@ namespace Matchers {
|
||||
Detail::FloatingPointKind m_type;
|
||||
};
|
||||
|
||||
//! Creates a matcher that accepts doubles within certain ULP range of target
|
||||
WithinUlpsMatcher WithinULP(double target, uint64_t maxUlpDiff);
|
||||
//! Creates a matcher that accepts floats within certain ULP range of target
|
||||
WithinUlpsMatcher WithinULP(float target, uint64_t maxUlpDiff);
|
||||
|
||||
|
||||
|
||||
// Given IEEE-754 format for floats and doubles, we can assume
|
||||
// that float -> double promotion is lossless. Given this, we can
|
||||
// assume that if we do the standard relative comparison of
|
||||
@@ -11105,13 +11323,6 @@ namespace Matchers {
|
||||
double m_epsilon;
|
||||
};
|
||||
|
||||
//! Creates a matcher that accepts doubles within certain ULP range of target
|
||||
WithinUlpsMatcher WithinULP(double target, uint64_t maxUlpDiff);
|
||||
//! Creates a matcher that accepts floats within certain ULP range of target
|
||||
WithinUlpsMatcher WithinULP(float target, uint64_t maxUlpDiff);
|
||||
//! Creates a matcher that accepts numbers within certain range of target
|
||||
WithinAbsMatcher WithinAbs(double target, double margin);
|
||||
|
||||
//! Creates a matcher that accepts doubles within certain relative range of target
|
||||
WithinRelMatcher WithinRel(double target, double eps);
|
||||
//! Creates a matcher that accepts doubles within 100*DBL_EPS relative range of target
|
||||
@@ -11121,6 +11332,17 @@ namespace Matchers {
|
||||
//! Creates a matcher that accepts floats within 100*FLT_EPS relative range of target
|
||||
WithinRelMatcher WithinRel(float target);
|
||||
|
||||
|
||||
|
||||
class IsNaNMatcher final : public MatcherBase<double> {
|
||||
public:
|
||||
IsNaNMatcher() = default;
|
||||
bool match( double const& matchee ) const override;
|
||||
std::string describe() const override;
|
||||
};
|
||||
|
||||
IsNaNMatcher IsNaN();
|
||||
|
||||
} // namespace Matchers
|
||||
} // namespace Catch
|
||||
|
||||
@@ -11339,6 +11561,7 @@ namespace Catch {
|
||||
#ifndef CATCH_MATCHERS_RANGE_EQUALS_HPP_INCLUDED
|
||||
#define CATCH_MATCHERS_RANGE_EQUALS_HPP_INCLUDED
|
||||
|
||||
|
||||
#include <algorithm>
|
||||
#include <utility>
|
||||
|
||||
@@ -11363,13 +11586,19 @@ namespace Catch {
|
||||
|
||||
template <typename RangeLike>
|
||||
bool match( RangeLike&& rng ) const {
|
||||
using std::begin;
|
||||
using std::end;
|
||||
return std::equal( begin(m_desired),
|
||||
end(m_desired),
|
||||
begin(rng),
|
||||
end(rng),
|
||||
m_predicate );
|
||||
auto rng_start = begin( rng );
|
||||
const auto rng_end = end( rng );
|
||||
auto target_start = begin( m_desired );
|
||||
const auto target_end = end( m_desired );
|
||||
|
||||
while (rng_start != rng_end && target_start != target_end) {
|
||||
if (!m_predicate(*rng_start, *target_start)) {
|
||||
return false;
|
||||
}
|
||||
++rng_start;
|
||||
++target_start;
|
||||
}
|
||||
return rng_start == rng_end && target_start == target_end;
|
||||
}
|
||||
|
||||
std::string describe() const override {
|
||||
@@ -11397,11 +11626,11 @@ namespace Catch {
|
||||
bool match( RangeLike&& rng ) const {
|
||||
using std::begin;
|
||||
using std::end;
|
||||
return std::is_permutation( begin( m_desired ),
|
||||
end( m_desired ),
|
||||
begin( rng ),
|
||||
end( rng ),
|
||||
m_predicate );
|
||||
return Catch::Detail::is_permutation( begin( m_desired ),
|
||||
end( m_desired ),
|
||||
begin( rng ),
|
||||
end( rng ),
|
||||
m_predicate );
|
||||
}
|
||||
|
||||
std::string describe() const override {
|
||||
@@ -12518,7 +12747,7 @@ namespace Catch {
|
||||
CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
|
||||
namespace { \
|
||||
Catch::ListenerRegistrar<listenerType> INTERNAL_CATCH_UNIQUE_NAME( \
|
||||
catch_internal_RegistrarFor )( #listenerType ); \
|
||||
catch_internal_RegistrarFor )( #listenerType##_catch_sr ); \
|
||||
} \
|
||||
CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION
|
||||
|
||||
@@ -12565,7 +12794,7 @@ namespace Catch {
|
||||
|
||||
void writeRun( TestRunNode const& groupNode );
|
||||
|
||||
void writeTestFile(std::string const& filename, std::vector<TestCaseNode const*> const& testCaseNodes);
|
||||
void writeTestFile(StringRef filename, std::vector<TestCaseNode const*> const& testCaseNodes);
|
||||
|
||||
void writeTestCase(TestCaseNode const& testCaseNode);
|
||||
|
||||
|
@@ -8,7 +8,7 @@
|
||||
project(
|
||||
'catch2',
|
||||
'cpp',
|
||||
version: '3.3.0', # CML version placeholder, don't delete
|
||||
version: '3.3.2', # CML version placeholder, don't delete
|
||||
license: 'BSL-1.0',
|
||||
meson_version: '>=0.50.0',
|
||||
)
|
||||
|
@@ -88,6 +88,7 @@ set(IMPL_HEADERS
|
||||
${SOURCES_DIR}/internal/catch_floating_point_helpers.hpp
|
||||
${SOURCES_DIR}/internal/catch_getenv.hpp
|
||||
${SOURCES_DIR}/internal/catch_istream.hpp
|
||||
${SOURCES_DIR}/internal/catch_is_permutation.hpp
|
||||
${SOURCES_DIR}/internal/catch_lazy_expr.hpp
|
||||
${SOURCES_DIR}/internal/catch_leak_detector.hpp
|
||||
${SOURCES_DIR}/internal/catch_list.hpp
|
||||
|
@@ -64,7 +64,7 @@ namespace Catch {
|
||||
});
|
||||
|
||||
BenchmarkInfo info {
|
||||
name,
|
||||
CATCH_MOVE(name),
|
||||
plan.estimated_duration.count(),
|
||||
plan.iterations_per_sample,
|
||||
cfg->benchmarkSamples(),
|
||||
@@ -80,7 +80,7 @@ namespace Catch {
|
||||
});
|
||||
|
||||
auto analysis = Detail::analyse(*cfg, env, samples.begin(), samples.end());
|
||||
BenchmarkStats<FloatDuration<Clock>> stats{ info, analysis.samples, analysis.mean, analysis.standard_deviation, analysis.outliers, analysis.outlier_variance };
|
||||
BenchmarkStats<FloatDuration<Clock>> stats{ CATCH_MOVE(info), CATCH_MOVE(analysis.samples), analysis.mean, analysis.standard_deviation, analysis.outliers, analysis.outlier_variance };
|
||||
getResultCapture().benchmarkEnded(stats);
|
||||
} CATCH_CATCH_ANON (TestFailureException) {
|
||||
getResultCapture().benchmarkFailed("Benchmark failed due to failed assertion"_sr);
|
||||
|
@@ -70,6 +70,7 @@
|
||||
#include <catch2/internal/catch_fatal_condition_handler.hpp>
|
||||
#include <catch2/internal/catch_floating_point_helpers.hpp>
|
||||
#include <catch2/internal/catch_getenv.hpp>
|
||||
#include <catch2/internal/catch_is_permutation.hpp>
|
||||
#include <catch2/internal/catch_istream.hpp>
|
||||
#include <catch2/internal/catch_lazy_expr.hpp>
|
||||
#include <catch2/internal/catch_leak_detector.hpp>
|
||||
|
@@ -7,6 +7,7 @@
|
||||
// SPDX-License-Identifier: BSL-1.0
|
||||
#include <catch2/catch_assertion_result.hpp>
|
||||
#include <catch2/internal/catch_reusable_string_stream.hpp>
|
||||
#include <catch2/internal/catch_move_and_forward.hpp>
|
||||
|
||||
namespace Catch {
|
||||
|
||||
@@ -26,9 +27,9 @@ namespace Catch {
|
||||
return reconstructedExpression;
|
||||
}
|
||||
|
||||
AssertionResult::AssertionResult( AssertionInfo const& info, AssertionResultData const& data )
|
||||
AssertionResult::AssertionResult( AssertionInfo const& info, AssertionResultData&& data )
|
||||
: m_info( info ),
|
||||
m_resultData( data )
|
||||
m_resultData( CATCH_MOVE(data) )
|
||||
{}
|
||||
|
||||
// Result was a success
|
||||
@@ -67,16 +68,15 @@ namespace Catch {
|
||||
}
|
||||
|
||||
std::string AssertionResult::getExpressionInMacro() const {
|
||||
std::string expr;
|
||||
if( m_info.macroName.empty() )
|
||||
expr = static_cast<std::string>(m_info.capturedExpression);
|
||||
else {
|
||||
expr.reserve( m_info.macroName.size() + m_info.capturedExpression.size() + 4 );
|
||||
expr += m_info.macroName;
|
||||
expr += "( ";
|
||||
expr += m_info.capturedExpression;
|
||||
expr += " )";
|
||||
if ( m_info.macroName.empty() ) {
|
||||
return static_cast<std::string>( m_info.capturedExpression );
|
||||
}
|
||||
std::string expr;
|
||||
expr.reserve( m_info.macroName.size() + m_info.capturedExpression.size() + 4 );
|
||||
expr += m_info.macroName;
|
||||
expr += "( ";
|
||||
expr += m_info.capturedExpression;
|
||||
expr += " )";
|
||||
return expr;
|
||||
}
|
||||
|
||||
|
@@ -35,7 +35,7 @@ namespace Catch {
|
||||
class AssertionResult {
|
||||
public:
|
||||
AssertionResult() = delete;
|
||||
AssertionResult( AssertionInfo const& info, AssertionResultData const& data );
|
||||
AssertionResult( AssertionInfo const& info, AssertionResultData&& data );
|
||||
|
||||
bool isOk() const;
|
||||
bool succeeded() const;
|
||||
|
@@ -19,8 +19,8 @@ namespace Catch {
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
ScopedMessage::ScopedMessage( MessageBuilder const& builder ):
|
||||
m_info( builder.m_info ) {
|
||||
ScopedMessage::ScopedMessage( MessageBuilder&& builder ):
|
||||
m_info( CATCH_MOVE(builder.m_info) ) {
|
||||
m_info.message = builder.m_stream.str();
|
||||
getResultCapture().pushScopedMessage( m_info );
|
||||
}
|
||||
|
@@ -39,11 +39,10 @@ namespace Catch {
|
||||
ResultWas::OfType type ):
|
||||
m_info(macroName, lineInfo, type) {}
|
||||
|
||||
|
||||
template<typename T>
|
||||
MessageBuilder& operator << ( T const& value ) {
|
||||
MessageBuilder&& operator << ( T const& value ) && {
|
||||
m_stream << value;
|
||||
return *this;
|
||||
return CATCH_MOVE(*this);
|
||||
}
|
||||
|
||||
MessageInfo m_info;
|
||||
@@ -51,7 +50,7 @@ namespace Catch {
|
||||
|
||||
class ScopedMessage {
|
||||
public:
|
||||
explicit ScopedMessage( MessageBuilder const& builder );
|
||||
explicit ScopedMessage( MessageBuilder&& builder );
|
||||
ScopedMessage( ScopedMessage& duplicate ) = delete;
|
||||
ScopedMessage( ScopedMessage&& old ) noexcept;
|
||||
~ScopedMessage();
|
||||
@@ -98,7 +97,10 @@ namespace Catch {
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
#define INTERNAL_CATCH_CAPTURE( varName, macroName, ... ) \
|
||||
Catch::Capturer varName( macroName, CATCH_INTERNAL_LINEINFO, Catch::ResultWas::Info, #__VA_ARGS__ ); \
|
||||
Catch::Capturer varName( macroName##_catch_sr, \
|
||||
CATCH_INTERNAL_LINEINFO, \
|
||||
Catch::ResultWas::Info, \
|
||||
#__VA_ARGS__##_catch_sr ); \
|
||||
varName.captureValues( 0, __VA_ARGS__ )
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
@@ -36,7 +36,7 @@ namespace Catch {
|
||||
}
|
||||
|
||||
Version const& libraryVersion() {
|
||||
static Version version( 3, 3, 0, "", 0 );
|
||||
static Version version( 3, 3, 2, "", 0 );
|
||||
return version;
|
||||
}
|
||||
|
||||
|
@@ -10,6 +10,6 @@
|
||||
|
||||
#define CATCH_VERSION_MAJOR 3
|
||||
#define CATCH_VERSION_MINOR 3
|
||||
#define CATCH_VERSION_PATCH 0
|
||||
#define CATCH_VERSION_PATCH 2
|
||||
|
||||
#endif // CATCH_VERSION_MACROS_HPP_INCLUDED
|
||||
|
@@ -14,7 +14,6 @@
|
||||
#include <catch2/internal/catch_stringref.hpp>
|
||||
#include <catch2/internal/catch_move_and_forward.hpp>
|
||||
#include <catch2/internal/catch_unique_name.hpp>
|
||||
#include <catch2/internal/catch_preprocessor.hpp>
|
||||
|
||||
#include <vector>
|
||||
#include <tuple>
|
||||
@@ -232,16 +231,19 @@ namespace Detail {
|
||||
} // namespace Generators
|
||||
} // namespace Catch
|
||||
|
||||
#define CATCH_INTERNAL_GENERATOR_STRINGIZE_IMPL( ... ) #__VA_ARGS__##_catch_sr
|
||||
#define CATCH_INTERNAL_GENERATOR_STRINGIZE(...) CATCH_INTERNAL_GENERATOR_STRINGIZE_IMPL(__VA_ARGS__)
|
||||
|
||||
#define GENERATE( ... ) \
|
||||
Catch::Generators::generate( INTERNAL_CATCH_STRINGIZE(INTERNAL_CATCH_UNIQUE_NAME(generator)), \
|
||||
Catch::Generators::generate( CATCH_INTERNAL_GENERATOR_STRINGIZE(INTERNAL_CATCH_UNIQUE_NAME(generator)), \
|
||||
CATCH_INTERNAL_LINEINFO, \
|
||||
[ ]{ using namespace Catch::Generators; return makeGenerators( __VA_ARGS__ ); } ) //NOLINT(google-build-using-namespace)
|
||||
#define GENERATE_COPY( ... ) \
|
||||
Catch::Generators::generate( INTERNAL_CATCH_STRINGIZE(INTERNAL_CATCH_UNIQUE_NAME(generator)), \
|
||||
Catch::Generators::generate( CATCH_INTERNAL_GENERATOR_STRINGIZE(INTERNAL_CATCH_UNIQUE_NAME(generator)), \
|
||||
CATCH_INTERNAL_LINEINFO, \
|
||||
[=]{ using namespace Catch::Generators; return makeGenerators( __VA_ARGS__ ); } ) //NOLINT(google-build-using-namespace)
|
||||
#define GENERATE_REF( ... ) \
|
||||
Catch::Generators::generate( INTERNAL_CATCH_STRINGIZE(INTERNAL_CATCH_UNIQUE_NAME(generator)), \
|
||||
Catch::Generators::generate( CATCH_INTERNAL_GENERATOR_STRINGIZE(INTERNAL_CATCH_UNIQUE_NAME(generator)), \
|
||||
CATCH_INTERNAL_LINEINFO, \
|
||||
[&]{ using namespace Catch::Generators; return makeGenerators( __VA_ARGS__ ); } ) //NOLINT(google-build-using-namespace)
|
||||
|
||||
|
@@ -44,10 +44,11 @@ namespace Catch {
|
||||
public:
|
||||
virtual ~IResultCapture();
|
||||
|
||||
virtual bool sectionStarted( SectionInfo const& sectionInfo,
|
||||
Counts& assertions ) = 0;
|
||||
virtual void sectionEnded( SectionEndInfo const& endInfo ) = 0;
|
||||
virtual void sectionEndedEarly( SectionEndInfo const& endInfo ) = 0;
|
||||
virtual bool sectionStarted( StringRef sectionName,
|
||||
SourceLineInfo const& sectionLineInfo,
|
||||
Counts& assertions ) = 0;
|
||||
virtual void sectionEnded( SectionEndInfo&& endInfo ) = 0;
|
||||
virtual void sectionEndedEarly( SectionEndInfo&& endInfo ) = 0;
|
||||
|
||||
virtual IGeneratorTracker*
|
||||
acquireGeneratorTracker( StringRef generatorName,
|
||||
@@ -65,7 +66,7 @@ namespace Catch {
|
||||
virtual void pushScopedMessage( MessageInfo const& message ) = 0;
|
||||
virtual void popScopedMessage( MessageInfo const& message ) = 0;
|
||||
|
||||
virtual void emplaceUnscopedMessage( MessageBuilder const& builder ) = 0;
|
||||
virtual void emplaceUnscopedMessage( MessageBuilder&& builder ) = 0;
|
||||
|
||||
virtual void handleFatalErrorCondition( StringRef message ) = 0;
|
||||
|
||||
|
@@ -60,18 +60,17 @@ namespace Catch {
|
||||
// Copy message into messages list.
|
||||
// !TBD This should have been done earlier, somewhere
|
||||
MessageBuilder builder( assertionResult.getTestMacroName(), assertionResult.getSourceInfo(), assertionResult.getResultType() );
|
||||
builder << assertionResult.getMessage();
|
||||
builder.m_info.message = builder.m_stream.str();
|
||||
builder.m_info.message = static_cast<std::string>(assertionResult.getMessage());
|
||||
|
||||
infoMessages.push_back( builder.m_info );
|
||||
infoMessages.push_back( CATCH_MOVE(builder.m_info) );
|
||||
}
|
||||
}
|
||||
|
||||
SectionStats::SectionStats( SectionInfo const& _sectionInfo,
|
||||
SectionStats::SectionStats( SectionInfo&& _sectionInfo,
|
||||
Counts const& _assertions,
|
||||
double _durationInSeconds,
|
||||
bool _missingAssertions )
|
||||
: sectionInfo( _sectionInfo ),
|
||||
: sectionInfo( CATCH_MOVE(_sectionInfo) ),
|
||||
assertions( _assertions ),
|
||||
durationInSeconds( _durationInSeconds ),
|
||||
missingAssertions( _missingAssertions )
|
||||
@@ -80,13 +79,13 @@ namespace Catch {
|
||||
|
||||
TestCaseStats::TestCaseStats( TestCaseInfo const& _testInfo,
|
||||
Totals const& _totals,
|
||||
std::string const& _stdOut,
|
||||
std::string const& _stdErr,
|
||||
std::string&& _stdOut,
|
||||
std::string&& _stdErr,
|
||||
bool _aborting )
|
||||
: testInfo( &_testInfo ),
|
||||
totals( _totals ),
|
||||
stdOut( _stdOut ),
|
||||
stdErr( _stdErr ),
|
||||
stdOut( CATCH_MOVE(_stdOut) ),
|
||||
stdErr( CATCH_MOVE(_stdErr) ),
|
||||
aborting( _aborting )
|
||||
{}
|
||||
|
||||
|
@@ -78,7 +78,7 @@ namespace Catch {
|
||||
};
|
||||
|
||||
struct SectionStats {
|
||||
SectionStats( SectionInfo const& _sectionInfo,
|
||||
SectionStats( SectionInfo&& _sectionInfo,
|
||||
Counts const& _assertions,
|
||||
double _durationInSeconds,
|
||||
bool _missingAssertions );
|
||||
@@ -92,8 +92,8 @@ namespace Catch {
|
||||
struct TestCaseStats {
|
||||
TestCaseStats( TestCaseInfo const& _testInfo,
|
||||
Totals const& _totals,
|
||||
std::string const& _stdOut,
|
||||
std::string const& _stdErr,
|
||||
std::string&& _stdOut,
|
||||
std::string&& _stdErr,
|
||||
bool _aborting );
|
||||
|
||||
TestCaseInfo const * testInfo;
|
||||
|
@@ -41,7 +41,7 @@
|
||||
|
||||
// Only GCC compiler should be used in this block, so other compilers trying to
|
||||
// mask themselves as GCC should be ignored.
|
||||
#if defined(__GNUC__) && !defined(__clang__) && !defined(__ICC) && !defined(__CUDACC__) && !defined(__LCC__)
|
||||
#if defined(__GNUC__) && !defined(__clang__) && !defined(__ICC) && !defined(__CUDACC__) && !defined(__LCC__) && !defined(__NVCOMPILER)
|
||||
# define CATCH_INTERNAL_START_WARNINGS_SUPPRESSION _Pragma( "GCC diagnostic push" )
|
||||
# define CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION _Pragma( "GCC diagnostic pop" )
|
||||
|
||||
@@ -60,6 +60,12 @@
|
||||
|
||||
#endif
|
||||
|
||||
#if defined(__NVCOMPILER)
|
||||
# define CATCH_INTERNAL_START_WARNINGS_SUPPRESSION _Pragma( "diag push" )
|
||||
# define CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION _Pragma( "diag pop" )
|
||||
# define CATCH_INTERNAL_SUPPRESS_UNUSED_VARIABLE_WARNINGS _Pragma( "diag_suppress declared_but_not_referenced" )
|
||||
#endif
|
||||
|
||||
#if defined(__CUDACC__) && !defined(__clang__)
|
||||
# ifdef __NVCC_DIAG_PRAGMA_SUPPORT__
|
||||
// New pragmas introduced in CUDA 11.5+
|
||||
|
138
src/catch2/internal/catch_is_permutation.hpp
Normal file
138
src/catch2/internal/catch_is_permutation.hpp
Normal file
@@ -0,0 +1,138 @@
|
||||
|
||||
// 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_IS_PERMUTATION_HPP_INCLUDED
|
||||
#define CATCH_IS_PERMUTATION_HPP_INCLUDED
|
||||
|
||||
#include <algorithm>
|
||||
#include <iterator>
|
||||
|
||||
namespace Catch {
|
||||
namespace Detail {
|
||||
|
||||
template <typename ForwardIter,
|
||||
typename Sentinel,
|
||||
typename T,
|
||||
typename Comparator>
|
||||
ForwardIter find_sentinel( ForwardIter start,
|
||||
Sentinel sentinel,
|
||||
T const& value,
|
||||
Comparator cmp ) {
|
||||
while ( start != sentinel ) {
|
||||
if ( cmp( *start, value ) ) { break; }
|
||||
++start;
|
||||
}
|
||||
return start;
|
||||
}
|
||||
|
||||
template <typename ForwardIter,
|
||||
typename Sentinel,
|
||||
typename T,
|
||||
typename Comparator>
|
||||
std::ptrdiff_t count_sentinel( ForwardIter start,
|
||||
Sentinel sentinel,
|
||||
T const& value,
|
||||
Comparator cmp ) {
|
||||
std::ptrdiff_t count = 0;
|
||||
while ( start != sentinel ) {
|
||||
if ( cmp( *start, value ) ) { ++count; }
|
||||
++start;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
template <typename ForwardIter, typename Sentinel>
|
||||
std::enable_if_t<!std::is_same<ForwardIter, Sentinel>::value,
|
||||
std::ptrdiff_t>
|
||||
sentinel_distance( ForwardIter iter, const Sentinel sentinel ) {
|
||||
std::ptrdiff_t dist = 0;
|
||||
while ( iter != sentinel ) {
|
||||
++iter;
|
||||
++dist;
|
||||
}
|
||||
return dist;
|
||||
}
|
||||
|
||||
template <typename ForwardIter>
|
||||
std::ptrdiff_t sentinel_distance( ForwardIter first,
|
||||
ForwardIter last ) {
|
||||
return std::distance( first, last );
|
||||
}
|
||||
|
||||
template <typename ForwardIter1,
|
||||
typename Sentinel1,
|
||||
typename ForwardIter2,
|
||||
typename Sentinel2,
|
||||
typename Comparator>
|
||||
bool check_element_counts( ForwardIter1 first_1,
|
||||
const Sentinel1 end_1,
|
||||
ForwardIter2 first_2,
|
||||
const Sentinel2 end_2,
|
||||
Comparator cmp ) {
|
||||
auto cursor = first_1;
|
||||
while ( cursor != end_1 ) {
|
||||
if ( find_sentinel( first_1, cursor, *cursor, cmp ) ==
|
||||
cursor ) {
|
||||
// we haven't checked this element yet
|
||||
const auto count_in_range_2 =
|
||||
count_sentinel( first_2, end_2, *cursor, cmp );
|
||||
// Not a single instance in 2nd range, so it cannot be a
|
||||
// permutation of 1st range
|
||||
if ( count_in_range_2 == 0 ) { return false; }
|
||||
|
||||
const auto count_in_range_1 =
|
||||
count_sentinel( cursor, end_1, *cursor, cmp );
|
||||
if ( count_in_range_1 != count_in_range_2 ) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
++cursor;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
template <typename ForwardIter1,
|
||||
typename Sentinel1,
|
||||
typename ForwardIter2,
|
||||
typename Sentinel2,
|
||||
typename Comparator>
|
||||
bool is_permutation( ForwardIter1 first_1,
|
||||
const Sentinel1 end_1,
|
||||
ForwardIter2 first_2,
|
||||
const Sentinel2 end_2,
|
||||
Comparator cmp ) {
|
||||
// TODO: no optimization for stronger iterators, because we would also have to constrain on sentinel vs not sentinel types
|
||||
// TODO: Comparator has to be "both sides", e.g. a == b => b == a
|
||||
// This skips shared prefix of the two ranges
|
||||
while (first_1 != end_1 && first_2 != end_2 && cmp(*first_1, *first_2)) {
|
||||
++first_1;
|
||||
++first_2;
|
||||
}
|
||||
|
||||
// We need to handle case where at least one of the ranges has no more elements
|
||||
if (first_1 == end_1 || first_2 == end_2) {
|
||||
return first_1 == end_1 && first_2 == end_2;
|
||||
}
|
||||
|
||||
// pair counting is n**2, so we pay linear walk to compare the sizes first
|
||||
auto dist_1 = sentinel_distance( first_1, end_1 );
|
||||
auto dist_2 = sentinel_distance( first_2, end_2 );
|
||||
|
||||
if (dist_1 != dist_2) { return false; }
|
||||
|
||||
// Since we do not try to handle stronger iterators pair (e.g.
|
||||
// bidir) optimally, the only thing left to do is to check counts in
|
||||
// the remaining ranges.
|
||||
return check_element_counts( first_1, end_1, first_2, end_2, cmp );
|
||||
}
|
||||
|
||||
} // namespace Detail
|
||||
} // namespace Catch
|
||||
|
||||
#endif // CATCH_IS_PERMUTATION_HPP_INCLUDED
|
@@ -29,12 +29,12 @@ namespace Catch {
|
||||
struct GeneratorTracker : TestCaseTracking::TrackerBase, IGeneratorTracker {
|
||||
GeneratorBasePtr m_generator;
|
||||
|
||||
GeneratorTracker( TestCaseTracking::NameAndLocation const& nameAndLocation, TrackerContext& ctx, ITracker* parent )
|
||||
: TrackerBase( nameAndLocation, ctx, parent )
|
||||
GeneratorTracker( TestCaseTracking::NameAndLocation&& nameAndLocation, TrackerContext& ctx, ITracker* parent )
|
||||
: TrackerBase( CATCH_MOVE(nameAndLocation), ctx, parent )
|
||||
{}
|
||||
~GeneratorTracker() override;
|
||||
|
||||
static GeneratorTracker* acquire( TrackerContext& ctx, TestCaseTracking::NameAndLocation const& nameAndLocation ) {
|
||||
static GeneratorTracker* acquire( TrackerContext& ctx, TestCaseTracking::NameAndLocationRef const& nameAndLocation ) {
|
||||
GeneratorTracker* tracker;
|
||||
|
||||
ITracker& currentTracker = ctx.currentTracker();
|
||||
@@ -176,13 +176,8 @@ namespace Catch {
|
||||
Totals RunContext::runTest(TestCaseHandle const& testCase) {
|
||||
const Totals prevTotals = m_totals;
|
||||
|
||||
std::string redirectedCout;
|
||||
std::string redirectedCerr;
|
||||
|
||||
auto const& testInfo = testCase.getTestCaseInfo();
|
||||
|
||||
m_reporter->testCaseStarting(testInfo);
|
||||
|
||||
m_activeTestCase = &testCase;
|
||||
|
||||
|
||||
@@ -224,9 +219,11 @@ namespace Catch {
|
||||
seedRng( *m_config );
|
||||
|
||||
uint64_t testRuns = 0;
|
||||
std::string redirectedCout;
|
||||
std::string redirectedCerr;
|
||||
do {
|
||||
m_trackerContext.startCycle();
|
||||
m_testCaseTracker = &SectionTracker::acquire(m_trackerContext, TestCaseTracking::NameAndLocation(testInfo.name, testInfo.lineInfo));
|
||||
m_testCaseTracker = &SectionTracker::acquire(m_trackerContext, TestCaseTracking::NameAndLocationRef(testInfo.name, testInfo.lineInfo));
|
||||
|
||||
m_reporter->testCasePartialStarting(testInfo, testRuns);
|
||||
|
||||
@@ -237,7 +234,7 @@ namespace Catch {
|
||||
redirectedCerr += oneRunCerr;
|
||||
|
||||
const auto singleRunTotals = m_totals.delta(beforeRunTotals);
|
||||
auto statsForOneRun = TestCaseStats(testInfo, singleRunTotals, oneRunCout, oneRunCerr, aborting());
|
||||
auto statsForOneRun = TestCaseStats(testInfo, singleRunTotals, CATCH_MOVE(oneRunCout), CATCH_MOVE(oneRunCerr), aborting());
|
||||
|
||||
m_reporter->testCasePartialEnded(statsForOneRun, testRuns);
|
||||
++testRuns;
|
||||
@@ -252,8 +249,8 @@ namespace Catch {
|
||||
m_totals.testCases += deltaTotals.testCases;
|
||||
m_reporter->testCaseEnded(TestCaseStats(testInfo,
|
||||
deltaTotals,
|
||||
redirectedCout,
|
||||
redirectedCerr,
|
||||
CATCH_MOVE(redirectedCout),
|
||||
CATCH_MOVE(redirectedCerr),
|
||||
aborting()));
|
||||
|
||||
m_activeTestCase = nullptr;
|
||||
@@ -297,12 +294,17 @@ namespace Catch {
|
||||
m_lastAssertionInfo.capturedExpression = "{Unknown expression after the reported line}"_sr;
|
||||
}
|
||||
|
||||
bool RunContext::sectionStarted(SectionInfo const & sectionInfo, Counts & assertions) {
|
||||
ITracker& sectionTracker = SectionTracker::acquire(m_trackerContext, TestCaseTracking::NameAndLocation(sectionInfo.name, sectionInfo.lineInfo));
|
||||
bool RunContext::sectionStarted(StringRef sectionName, SourceLineInfo const& sectionLineInfo, Counts & assertions) {
|
||||
ITracker& sectionTracker =
|
||||
SectionTracker::acquire( m_trackerContext,
|
||||
TestCaseTracking::NameAndLocationRef(
|
||||
sectionName, sectionLineInfo ) );
|
||||
|
||||
if (!sectionTracker.isOpen())
|
||||
return false;
|
||||
m_activeSections.push_back(§ionTracker);
|
||||
|
||||
SectionInfo sectionInfo( sectionLineInfo, static_cast<std::string>(sectionName) );
|
||||
m_lastAssertionInfo.lineInfo = sectionInfo.lineInfo;
|
||||
|
||||
m_reporter->sectionStarting(sectionInfo);
|
||||
@@ -317,8 +319,8 @@ namespace Catch {
|
||||
using namespace Generators;
|
||||
GeneratorTracker* tracker = GeneratorTracker::acquire(
|
||||
m_trackerContext,
|
||||
TestCaseTracking::NameAndLocation(
|
||||
static_cast<std::string>( generatorName ), lineInfo ) );
|
||||
TestCaseTracking::NameAndLocationRef(
|
||||
generatorName, lineInfo ) );
|
||||
m_lastAssertionInfo.lineInfo = lineInfo;
|
||||
return tracker;
|
||||
}
|
||||
@@ -335,7 +337,7 @@ namespace Catch {
|
||||
"Trying to create tracker for a genreator that already has one" );
|
||||
|
||||
auto newTracker = Catch::Detail::make_unique<Generators::GeneratorTracker>(
|
||||
nameAndLoc, m_trackerContext, ¤tTracker );
|
||||
CATCH_MOVE(nameAndLoc), m_trackerContext, ¤tTracker );
|
||||
auto ret = newTracker.get();
|
||||
currentTracker.addChild( CATCH_MOVE( newTracker ) );
|
||||
|
||||
@@ -356,7 +358,7 @@ namespace Catch {
|
||||
return true;
|
||||
}
|
||||
|
||||
void RunContext::sectionEnded(SectionEndInfo const & endInfo) {
|
||||
void RunContext::sectionEnded(SectionEndInfo&& endInfo) {
|
||||
Counts assertions = m_totals.assertions - endInfo.prevAssertions;
|
||||
bool missingAssertions = testForMissingAssertions(assertions);
|
||||
|
||||
@@ -365,19 +367,20 @@ namespace Catch {
|
||||
m_activeSections.pop_back();
|
||||
}
|
||||
|
||||
m_reporter->sectionEnded(SectionStats(endInfo.sectionInfo, assertions, endInfo.durationInSeconds, missingAssertions));
|
||||
m_reporter->sectionEnded(SectionStats(CATCH_MOVE(endInfo.sectionInfo), assertions, endInfo.durationInSeconds, missingAssertions));
|
||||
m_messages.clear();
|
||||
m_messageScopes.clear();
|
||||
}
|
||||
|
||||
void RunContext::sectionEndedEarly(SectionEndInfo const & endInfo) {
|
||||
if (m_unfinishedSections.empty())
|
||||
void RunContext::sectionEndedEarly(SectionEndInfo&& endInfo) {
|
||||
if ( m_unfinishedSections.empty() ) {
|
||||
m_activeSections.back()->fail();
|
||||
else
|
||||
} else {
|
||||
m_activeSections.back()->close();
|
||||
}
|
||||
m_activeSections.pop_back();
|
||||
|
||||
m_unfinishedSections.push_back(endInfo);
|
||||
m_unfinishedSections.push_back(CATCH_MOVE(endInfo));
|
||||
}
|
||||
|
||||
void RunContext::benchmarkPreparing( StringRef name ) {
|
||||
@@ -401,8 +404,8 @@ namespace Catch {
|
||||
m_messages.erase(std::remove(m_messages.begin(), m_messages.end(), message), m_messages.end());
|
||||
}
|
||||
|
||||
void RunContext::emplaceUnscopedMessage( MessageBuilder const& builder ) {
|
||||
m_messageScopes.emplace_back( builder );
|
||||
void RunContext::emplaceUnscopedMessage( MessageBuilder&& builder ) {
|
||||
m_messageScopes.emplace_back( CATCH_MOVE(builder) );
|
||||
}
|
||||
|
||||
std::string RunContext::getCurrentTestName() const {
|
||||
@@ -427,7 +430,7 @@ namespace Catch {
|
||||
// Instead, fake a result data.
|
||||
AssertionResultData tempResult( ResultWas::FatalErrorCondition, { false } );
|
||||
tempResult.message = static_cast<std::string>(message);
|
||||
AssertionResult result(m_lastAssertionInfo, tempResult);
|
||||
AssertionResult result(m_lastAssertionInfo, CATCH_MOVE(tempResult));
|
||||
|
||||
assertionEnded(result);
|
||||
|
||||
@@ -439,7 +442,7 @@ namespace Catch {
|
||||
|
||||
Counts assertions;
|
||||
assertions.failed = 1;
|
||||
SectionStats testCaseSectionStats(testCaseSection, assertions, 0, false);
|
||||
SectionStats testCaseSectionStats(CATCH_MOVE(testCaseSection), assertions, 0, false);
|
||||
m_reporter->sectionEnded(testCaseSectionStats);
|
||||
|
||||
auto const& testInfo = m_activeTestCase->getTestCaseInfo();
|
||||
@@ -518,7 +521,7 @@ namespace Catch {
|
||||
m_messages.clear();
|
||||
m_messageScopes.clear();
|
||||
|
||||
SectionStats testCaseSectionStats(testCaseSection, assertions, duration, missingAssertions);
|
||||
SectionStats testCaseSectionStats(CATCH_MOVE(testCaseSection), assertions, duration, missingAssertions);
|
||||
m_reporter->sectionEnded(testCaseSectionStats);
|
||||
}
|
||||
|
||||
@@ -542,7 +545,7 @@ namespace Catch {
|
||||
itEnd = m_unfinishedSections.rend();
|
||||
it != itEnd;
|
||||
++it)
|
||||
sectionEnded(*it);
|
||||
sectionEnded(CATCH_MOVE(*it));
|
||||
m_unfinishedSections.clear();
|
||||
}
|
||||
|
||||
@@ -578,7 +581,7 @@ namespace Catch {
|
||||
m_lastAssertionInfo = info;
|
||||
AssertionResultData data( resultType, LazyExpression( negated ) );
|
||||
|
||||
AssertionResult assertionResult{ info, data };
|
||||
AssertionResult assertionResult{ info, CATCH_MOVE( data ) };
|
||||
assertionResult.m_resultData.lazyExpression.m_transientExpression = expr;
|
||||
|
||||
assertionEnded( assertionResult );
|
||||
@@ -596,7 +599,8 @@ namespace Catch {
|
||||
|
||||
AssertionResultData data( resultType, LazyExpression( false ) );
|
||||
data.message = static_cast<std::string>(message);
|
||||
AssertionResult assertionResult{ m_lastAssertionInfo, data };
|
||||
AssertionResult assertionResult{ m_lastAssertionInfo,
|
||||
CATCH_MOVE( data ) };
|
||||
assertionEnded( assertionResult );
|
||||
if ( !assertionResult.isOk() ) {
|
||||
populateReaction( reaction );
|
||||
@@ -622,7 +626,7 @@ namespace Catch {
|
||||
|
||||
AssertionResultData data( ResultWas::ThrewException, LazyExpression( false ) );
|
||||
data.message = message;
|
||||
AssertionResult assertionResult{ info, data };
|
||||
AssertionResult assertionResult{ info, CATCH_MOVE(data) };
|
||||
assertionEnded( assertionResult );
|
||||
populateReaction( reaction );
|
||||
}
|
||||
@@ -635,11 +639,12 @@ namespace Catch {
|
||||
void RunContext::handleIncomplete(
|
||||
AssertionInfo const& info
|
||||
) {
|
||||
using namespace std::string_literals;
|
||||
m_lastAssertionInfo = info;
|
||||
|
||||
AssertionResultData data( ResultWas::ThrewException, LazyExpression( false ) );
|
||||
data.message = "Exception translation was disabled by CATCH_CONFIG_FAST_COMPILE";
|
||||
AssertionResult assertionResult{ info, data };
|
||||
data.message = "Exception translation was disabled by CATCH_CONFIG_FAST_COMPILE"s;
|
||||
AssertionResult assertionResult{ info, CATCH_MOVE( data ) };
|
||||
assertionEnded( assertionResult );
|
||||
}
|
||||
void RunContext::handleNonExpr(
|
||||
@@ -650,7 +655,7 @@ namespace Catch {
|
||||
m_lastAssertionInfo = info;
|
||||
|
||||
AssertionResultData data( resultType, LazyExpression( false ) );
|
||||
AssertionResult assertionResult{ info, data };
|
||||
AssertionResult assertionResult{ info, CATCH_MOVE( data ) };
|
||||
assertionEnded( assertionResult );
|
||||
|
||||
if( !assertionResult.isOk() )
|
||||
|
@@ -68,10 +68,12 @@ namespace Catch {
|
||||
ResultWas::OfType resultType,
|
||||
AssertionReaction &reaction ) override;
|
||||
|
||||
bool sectionStarted( SectionInfo const& sectionInfo, Counts& assertions ) override;
|
||||
bool sectionStarted( StringRef sectionName,
|
||||
SourceLineInfo const& sectionLineInfo,
|
||||
Counts& assertions ) override;
|
||||
|
||||
void sectionEnded( SectionEndInfo const& endInfo ) override;
|
||||
void sectionEndedEarly( SectionEndInfo const& endInfo ) override;
|
||||
void sectionEnded( SectionEndInfo&& endInfo ) override;
|
||||
void sectionEndedEarly( SectionEndInfo&& endInfo ) override;
|
||||
|
||||
IGeneratorTracker*
|
||||
acquireGeneratorTracker( StringRef generatorName,
|
||||
@@ -90,7 +92,7 @@ namespace Catch {
|
||||
void pushScopedMessage( MessageInfo const& message ) override;
|
||||
void popScopedMessage( MessageInfo const& message ) override;
|
||||
|
||||
void emplaceUnscopedMessage( MessageBuilder const& builder ) override;
|
||||
void emplaceUnscopedMessage( MessageBuilder&& builder ) override;
|
||||
|
||||
std::string getCurrentTestName() const override;
|
||||
|
||||
|
@@ -15,7 +15,7 @@ namespace Catch {
|
||||
Section::Section( SectionInfo&& info ):
|
||||
m_info( CATCH_MOVE( info ) ),
|
||||
m_sectionIncluded(
|
||||
getResultCapture().sectionStarted( m_info, m_assertions ) ) {
|
||||
getResultCapture().sectionStarted( m_info.name, m_info.lineInfo, m_assertions ) ) {
|
||||
// Non-"included" sections will not use the timing information
|
||||
// anyway, so don't bother with the potential syscall.
|
||||
if (m_sectionIncluded) {
|
||||
@@ -23,13 +23,31 @@ namespace Catch {
|
||||
}
|
||||
}
|
||||
|
||||
Section::Section( SourceLineInfo const& _lineInfo,
|
||||
StringRef _name,
|
||||
const char* const ):
|
||||
m_info( { "invalid", static_cast<std::size_t>( -1 ) }, std::string{} ),
|
||||
m_sectionIncluded(
|
||||
getResultCapture().sectionStarted( _name, _lineInfo, m_assertions ) ) {
|
||||
// We delay initialization the SectionInfo member until we know
|
||||
// this section needs it, so we avoid allocating std::string for name.
|
||||
// We also delay timer start to avoid the potential syscall unless we
|
||||
// will actually use the result.
|
||||
if ( m_sectionIncluded ) {
|
||||
m_info.name = static_cast<std::string>( _name );
|
||||
m_info.lineInfo = _lineInfo;
|
||||
m_timer.start();
|
||||
}
|
||||
}
|
||||
|
||||
Section::~Section() {
|
||||
if( m_sectionIncluded ) {
|
||||
SectionEndInfo endInfo{ m_info, m_assertions, m_timer.getElapsedSeconds() };
|
||||
if( uncaught_exceptions() )
|
||||
getResultCapture().sectionEndedEarly( endInfo );
|
||||
else
|
||||
getResultCapture().sectionEnded( endInfo );
|
||||
SectionEndInfo endInfo{ CATCH_MOVE(m_info), m_assertions, m_timer.getElapsedSeconds() };
|
||||
if ( uncaught_exceptions() ) {
|
||||
getResultCapture().sectionEndedEarly( CATCH_MOVE(endInfo) );
|
||||
} else {
|
||||
getResultCapture().sectionEnded( CATCH_MOVE( endInfo ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -20,6 +20,9 @@ namespace Catch {
|
||||
class Section : Detail::NonCopyable {
|
||||
public:
|
||||
Section( SectionInfo&& info );
|
||||
Section( SourceLineInfo const& _lineInfo,
|
||||
StringRef _name,
|
||||
const char* const = nullptr );
|
||||
~Section();
|
||||
|
||||
// This indicates whether the section should be executed or not
|
||||
@@ -38,7 +41,7 @@ namespace Catch {
|
||||
#define INTERNAL_CATCH_SECTION( ... ) \
|
||||
CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \
|
||||
CATCH_INTERNAL_SUPPRESS_UNUSED_VARIABLE_WARNINGS \
|
||||
if( Catch::Section const& INTERNAL_CATCH_UNIQUE_NAME( catch_internal_Section ) = Catch::SectionInfo( CATCH_INTERNAL_LINEINFO, __VA_ARGS__ ) ) \
|
||||
if( Catch::Section const& INTERNAL_CATCH_UNIQUE_NAME( catch_internal_Section ) = Catch::Section( CATCH_INTERNAL_LINEINFO, __VA_ARGS__ ) ) \
|
||||
CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION
|
||||
|
||||
#define INTERNAL_CATCH_DYNAMIC_SECTION( ... ) \
|
||||
|
@@ -17,10 +17,6 @@ namespace Catch {
|
||||
: StringRef( rawChars, std::strlen(rawChars) )
|
||||
{}
|
||||
|
||||
auto StringRef::operator == ( StringRef other ) const noexcept -> bool {
|
||||
return m_size == other.m_size
|
||||
&& (std::memcmp( m_start, other.m_start, m_size ) == 0);
|
||||
}
|
||||
|
||||
bool StringRef::operator<(StringRef rhs) const noexcept {
|
||||
if (m_size < rhs.m_size) {
|
||||
|
@@ -13,6 +13,8 @@
|
||||
#include <iosfwd>
|
||||
#include <cassert>
|
||||
|
||||
#include <cstring>
|
||||
|
||||
namespace Catch {
|
||||
|
||||
/// A non-owning string class (similar to the forthcoming std::string_view)
|
||||
@@ -49,7 +51,10 @@ namespace Catch {
|
||||
}
|
||||
|
||||
public: // operators
|
||||
auto operator == ( StringRef other ) const noexcept -> bool;
|
||||
auto operator == ( StringRef other ) const noexcept -> bool {
|
||||
return m_size == other.m_size
|
||||
&& (std::memcmp( m_start, other.m_start, m_size ) == 0);
|
||||
}
|
||||
auto operator != (StringRef other) const noexcept -> bool {
|
||||
return !(*this == other);
|
||||
}
|
||||
|
@@ -181,7 +181,7 @@
|
||||
void reg_tests() { \
|
||||
size_t index = 0; \
|
||||
using expander = size_t[]; \
|
||||
(void)expander{(Catch::AutoReg( Catch::makeTestInvoker( &TestFunc<Types> ), CATCH_INTERNAL_LINEINFO, Catch::StringRef(), Catch::NameAndTags{ Name " - " + std::string(INTERNAL_CATCH_STRINGIZE(TmplList)) + " - " + std::to_string(index), Tags } ), index++)... };/* NOLINT */\
|
||||
(void)expander{(Catch::AutoReg( Catch::makeTestInvoker( &TestFunc<Types> ), CATCH_INTERNAL_LINEINFO, Catch::StringRef(), Catch::NameAndTags{ Name " - " INTERNAL_CATCH_STRINGIZE(TmplList) " - " + std::to_string(index), Tags } ), index++)... };/* NOLINT */\
|
||||
} \
|
||||
};\
|
||||
static int INTERNAL_CATCH_UNIQUE_NAME( globalRegistrar ) = [](){ \
|
||||
@@ -316,7 +316,7 @@
|
||||
void reg_tests(){\
|
||||
size_t index = 0;\
|
||||
using expander = size_t[];\
|
||||
(void)expander{(Catch::AutoReg( Catch::makeTestInvoker( &TestName<Types>::test ), CATCH_INTERNAL_LINEINFO, #ClassName, Catch::NameAndTags{ Name " - " + std::string(INTERNAL_CATCH_STRINGIZE(TmplList)) + " - " + std::to_string(index), Tags } ), index++)... };/* NOLINT */ \
|
||||
(void)expander{(Catch::AutoReg( Catch::makeTestInvoker( &TestName<Types>::test ), CATCH_INTERNAL_LINEINFO, #ClassName##_catch_sr, Catch::NameAndTags{ Name " - " INTERNAL_CATCH_STRINGIZE(TmplList) " - " + std::to_string(index), Tags } ), index++)... };/* NOLINT */ \
|
||||
}\
|
||||
};\
|
||||
static int INTERNAL_CATCH_UNIQUE_NAME( globalRegistrar ) = [](){\
|
||||
|
@@ -22,8 +22,8 @@
|
||||
namespace Catch {
|
||||
namespace TestCaseTracking {
|
||||
|
||||
NameAndLocation::NameAndLocation( std::string const& _name, SourceLineInfo const& _location )
|
||||
: name( _name ),
|
||||
NameAndLocation::NameAndLocation( std::string&& _name, SourceLineInfo const& _location )
|
||||
: name( CATCH_MOVE(_name) ),
|
||||
location( _location )
|
||||
{}
|
||||
|
||||
@@ -38,14 +38,17 @@ namespace TestCaseTracking {
|
||||
m_children.push_back( CATCH_MOVE(child) );
|
||||
}
|
||||
|
||||
ITracker* ITracker::findChild( NameAndLocation const& nameAndLocation ) {
|
||||
ITracker* ITracker::findChild( NameAndLocationRef const& nameAndLocation ) {
|
||||
auto it = std::find_if(
|
||||
m_children.begin(),
|
||||
m_children.end(),
|
||||
[&nameAndLocation]( ITrackerPtr const& tracker ) {
|
||||
return tracker->nameAndLocation().location ==
|
||||
nameAndLocation.location &&
|
||||
tracker->nameAndLocation().name == nameAndLocation.name;
|
||||
auto const& tnameAndLoc = tracker->nameAndLocation();
|
||||
if ( tnameAndLoc.location.line !=
|
||||
nameAndLocation.location.line ) {
|
||||
return false;
|
||||
}
|
||||
return tnameAndLoc == nameAndLocation;
|
||||
} );
|
||||
return ( it != m_children.end() ) ? it->get() : nullptr;
|
||||
}
|
||||
@@ -53,10 +56,6 @@ namespace TestCaseTracking {
|
||||
bool ITracker::isSectionTracker() const { return false; }
|
||||
bool ITracker::isGeneratorTracker() const { return false; }
|
||||
|
||||
bool ITracker::isSuccessfullyCompleted() const {
|
||||
return m_runState == CompletedSuccessfully;
|
||||
}
|
||||
|
||||
bool ITracker::isOpen() const {
|
||||
return m_runState != NotStarted && !isComplete();
|
||||
}
|
||||
@@ -83,16 +82,6 @@ namespace TestCaseTracking {
|
||||
return *m_rootTracker;
|
||||
}
|
||||
|
||||
void TrackerContext::endRun() {
|
||||
m_rootTracker.reset();
|
||||
m_currentTracker = nullptr;
|
||||
m_runState = NotStarted;
|
||||
}
|
||||
|
||||
void TrackerContext::startCycle() {
|
||||
m_currentTracker = m_rootTracker.get();
|
||||
m_runState = Executing;
|
||||
}
|
||||
void TrackerContext::completeCycle() {
|
||||
m_runState = CompletedCycle;
|
||||
}
|
||||
@@ -100,16 +89,13 @@ namespace TestCaseTracking {
|
||||
bool TrackerContext::completedCycle() const {
|
||||
return m_runState == CompletedCycle;
|
||||
}
|
||||
ITracker& TrackerContext::currentTracker() {
|
||||
return *m_currentTracker;
|
||||
}
|
||||
void TrackerContext::setCurrentTracker( ITracker* tracker ) {
|
||||
m_currentTracker = tracker;
|
||||
}
|
||||
|
||||
|
||||
TrackerBase::TrackerBase( NameAndLocation const& nameAndLocation, TrackerContext& ctx, ITracker* parent ):
|
||||
ITracker(nameAndLocation, parent),
|
||||
TrackerBase::TrackerBase( NameAndLocation&& nameAndLocation, TrackerContext& ctx, ITracker* parent ):
|
||||
ITracker(CATCH_MOVE(nameAndLocation), parent),
|
||||
m_ctx( ctx )
|
||||
{}
|
||||
|
||||
@@ -169,13 +155,14 @@ namespace TestCaseTracking {
|
||||
m_ctx.setCurrentTracker( this );
|
||||
}
|
||||
|
||||
SectionTracker::SectionTracker( NameAndLocation const& nameAndLocation, TrackerContext& ctx, ITracker* parent )
|
||||
: TrackerBase( nameAndLocation, ctx, parent ),
|
||||
m_trimmed_name(trim(nameAndLocation.name))
|
||||
SectionTracker::SectionTracker( NameAndLocation&& nameAndLocation, TrackerContext& ctx, ITracker* parent )
|
||||
: TrackerBase( CATCH_MOVE(nameAndLocation), ctx, parent ),
|
||||
m_trimmed_name(trim(StringRef(ITracker::nameAndLocation().name)))
|
||||
{
|
||||
if( parent ) {
|
||||
while( !parent->isSectionTracker() )
|
||||
while ( !parent->isSectionTracker() ) {
|
||||
parent = parent->parent();
|
||||
}
|
||||
|
||||
SectionTracker& parentSection = static_cast<SectionTracker&>( *parent );
|
||||
addNextFilters( parentSection.m_filters );
|
||||
@@ -195,24 +182,30 @@ namespace TestCaseTracking {
|
||||
|
||||
bool SectionTracker::isSectionTracker() const { return true; }
|
||||
|
||||
SectionTracker& SectionTracker::acquire( TrackerContext& ctx, NameAndLocation const& nameAndLocation ) {
|
||||
SectionTracker* section;
|
||||
SectionTracker& SectionTracker::acquire( TrackerContext& ctx, NameAndLocationRef const& nameAndLocation ) {
|
||||
SectionTracker* tracker;
|
||||
|
||||
ITracker& currentTracker = ctx.currentTracker();
|
||||
if ( ITracker* childTracker =
|
||||
currentTracker.findChild( nameAndLocation ) ) {
|
||||
assert( childTracker );
|
||||
assert( childTracker->isSectionTracker() );
|
||||
section = static_cast<SectionTracker*>( childTracker );
|
||||
tracker = static_cast<SectionTracker*>( childTracker );
|
||||
} else {
|
||||
auto newSection = Catch::Detail::make_unique<SectionTracker>(
|
||||
nameAndLocation, ctx, ¤tTracker );
|
||||
section = newSection.get();
|
||||
currentTracker.addChild( CATCH_MOVE( newSection ) );
|
||||
auto newTracker = Catch::Detail::make_unique<SectionTracker>(
|
||||
NameAndLocation{ static_cast<std::string>(nameAndLocation.name),
|
||||
nameAndLocation.location },
|
||||
ctx,
|
||||
¤tTracker );
|
||||
tracker = newTracker.get();
|
||||
currentTracker.addChild( CATCH_MOVE( newTracker ) );
|
||||
}
|
||||
if( !ctx.completedCycle() )
|
||||
section->tryOpen();
|
||||
return *section;
|
||||
|
||||
if ( !ctx.completedCycle() ) {
|
||||
tracker->tryOpen();
|
||||
}
|
||||
|
||||
return *tracker;
|
||||
}
|
||||
|
||||
void SectionTracker::tryOpen() {
|
||||
@@ -233,10 +226,6 @@ namespace TestCaseTracking {
|
||||
m_filters.insert( m_filters.end(), filters.begin()+1, filters.end() );
|
||||
}
|
||||
|
||||
std::vector<StringRef> const& SectionTracker::getFilters() const {
|
||||
return m_filters;
|
||||
}
|
||||
|
||||
StringRef SectionTracker::trimmedName() const {
|
||||
return m_trimmed_name;
|
||||
}
|
||||
|
@@ -22,10 +22,14 @@ namespace TestCaseTracking {
|
||||
std::string name;
|
||||
SourceLineInfo location;
|
||||
|
||||
NameAndLocation( std::string const& _name, SourceLineInfo const& _location );
|
||||
NameAndLocation( std::string&& _name, SourceLineInfo const& _location );
|
||||
friend bool operator==(NameAndLocation const& lhs, NameAndLocation const& rhs) {
|
||||
return lhs.name == rhs.name
|
||||
&& lhs.location == rhs.location;
|
||||
// This is a very cheap check that should have a very high hit rate.
|
||||
// If we get to SourceLineInfo::operator==, we will redo it, but the
|
||||
// cost of repeating is trivial at that point (we will be paying
|
||||
// multiple strcmp/memcmps at that point).
|
||||
if ( lhs.location.line != rhs.location.line ) { return false; }
|
||||
return lhs.name == rhs.name && lhs.location == rhs.location;
|
||||
}
|
||||
friend bool operator!=(NameAndLocation const& lhs,
|
||||
NameAndLocation const& rhs) {
|
||||
@@ -33,6 +37,37 @@ namespace TestCaseTracking {
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* This is a variant of `NameAndLocation` that does not own the name string
|
||||
*
|
||||
* This avoids extra allocations when trying to locate a tracker by its
|
||||
* name and location, as long as we make sure that trackers only keep
|
||||
* around the owning variant.
|
||||
*/
|
||||
struct NameAndLocationRef {
|
||||
StringRef name;
|
||||
SourceLineInfo location;
|
||||
|
||||
constexpr NameAndLocationRef( StringRef name_,
|
||||
SourceLineInfo location_ ):
|
||||
name( name_ ), location( location_ ) {}
|
||||
|
||||
friend bool operator==( NameAndLocation const& lhs,
|
||||
NameAndLocationRef const& rhs ) {
|
||||
// This is a very cheap check that should have a very high hit rate.
|
||||
// If we get to SourceLineInfo::operator==, we will redo it, but the
|
||||
// cost of repeating is trivial at that point (we will be paying
|
||||
// multiple strcmp/memcmps at that point).
|
||||
if ( lhs.location.line != rhs.location.line ) { return false; }
|
||||
return StringRef( lhs.name ) == rhs.name &&
|
||||
lhs.location == rhs.location;
|
||||
}
|
||||
friend bool operator==( NameAndLocationRef const& lhs,
|
||||
NameAndLocation const& rhs ) {
|
||||
return rhs == lhs;
|
||||
}
|
||||
};
|
||||
|
||||
class ITracker;
|
||||
|
||||
using ITrackerPtr = Catch::Detail::unique_ptr<ITracker>;
|
||||
@@ -57,8 +92,8 @@ namespace TestCaseTracking {
|
||||
CycleState m_runState = NotStarted;
|
||||
|
||||
public:
|
||||
ITracker( NameAndLocation const& nameAndLoc, ITracker* parent ):
|
||||
m_nameAndLocation( nameAndLoc ),
|
||||
ITracker( NameAndLocation&& nameAndLoc, ITracker* parent ):
|
||||
m_nameAndLocation( CATCH_MOVE(nameAndLoc) ),
|
||||
m_parent( parent )
|
||||
{}
|
||||
|
||||
@@ -79,7 +114,9 @@ namespace TestCaseTracking {
|
||||
//! Returns true if tracker run to completion (successfully or not)
|
||||
virtual bool isComplete() const = 0;
|
||||
//! Returns true if tracker run to completion succesfully
|
||||
bool isSuccessfullyCompleted() const;
|
||||
bool isSuccessfullyCompleted() const {
|
||||
return m_runState == CompletedSuccessfully;
|
||||
}
|
||||
//! Returns true if tracker has started but hasn't been completed
|
||||
bool isOpen() const;
|
||||
//! Returns true iff tracker has started
|
||||
@@ -97,7 +134,7 @@ namespace TestCaseTracking {
|
||||
*
|
||||
* Returns nullptr if not found.
|
||||
*/
|
||||
ITracker* findChild( NameAndLocation const& nameAndLocation );
|
||||
ITracker* findChild( NameAndLocationRef const& nameAndLocation );
|
||||
//! Have any children been added?
|
||||
bool hasChildren() const {
|
||||
return !m_children.empty();
|
||||
@@ -138,13 +175,15 @@ namespace TestCaseTracking {
|
||||
public:
|
||||
|
||||
ITracker& startRun();
|
||||
void endRun();
|
||||
|
||||
void startCycle();
|
||||
void startCycle() {
|
||||
m_currentTracker = m_rootTracker.get();
|
||||
m_runState = Executing;
|
||||
}
|
||||
void completeCycle();
|
||||
|
||||
bool completedCycle() const;
|
||||
ITracker& currentTracker();
|
||||
ITracker& currentTracker() { return *m_currentTracker; }
|
||||
void setCurrentTracker( ITracker* tracker );
|
||||
};
|
||||
|
||||
@@ -154,7 +193,7 @@ namespace TestCaseTracking {
|
||||
TrackerContext& m_ctx;
|
||||
|
||||
public:
|
||||
TrackerBase( NameAndLocation const& nameAndLocation, TrackerContext& ctx, ITracker* parent );
|
||||
TrackerBase( NameAndLocation&& nameAndLocation, TrackerContext& ctx, ITracker* parent );
|
||||
|
||||
bool isComplete() const override;
|
||||
|
||||
@@ -170,22 +209,26 @@ namespace TestCaseTracking {
|
||||
|
||||
class SectionTracker : public TrackerBase {
|
||||
std::vector<StringRef> m_filters;
|
||||
std::string m_trimmed_name;
|
||||
// Note that lifetime-wise we piggy back off the name stored in the `ITracker` parent`.
|
||||
// Currently it allocates owns the name, so this is safe. If it is later refactored
|
||||
// to not own the name, the name still has to outlive the `ITracker` parent, so
|
||||
// this should still be safe.
|
||||
StringRef m_trimmed_name;
|
||||
public:
|
||||
SectionTracker( NameAndLocation const& nameAndLocation, TrackerContext& ctx, ITracker* parent );
|
||||
SectionTracker( NameAndLocation&& nameAndLocation, TrackerContext& ctx, ITracker* parent );
|
||||
|
||||
bool isSectionTracker() const override;
|
||||
|
||||
bool isComplete() const override;
|
||||
|
||||
static SectionTracker& acquire( TrackerContext& ctx, NameAndLocation const& nameAndLocation );
|
||||
static SectionTracker& acquire( TrackerContext& ctx, NameAndLocationRef const& nameAndLocation );
|
||||
|
||||
void tryOpen();
|
||||
|
||||
void addInitialFilters( std::vector<std::string> const& filters );
|
||||
void addNextFilters( std::vector<StringRef> const& filters );
|
||||
//! Returns filters active in this tracker
|
||||
std::vector<StringRef> const& getFilters() const;
|
||||
std::vector<StringRef> const& getFilters() const { return m_filters; }
|
||||
//! Returns whitespace-trimmed name of the tracked section
|
||||
StringRef trimmedName() const;
|
||||
};
|
||||
|
@@ -23,9 +23,9 @@
|
||||
#if !defined(CATCH_CONFIG_DISABLE)
|
||||
|
||||
#if !defined(CATCH_CONFIG_DISABLE_STRINGIFICATION)
|
||||
#define CATCH_INTERNAL_STRINGIFY(...) #__VA_ARGS__
|
||||
#define CATCH_INTERNAL_STRINGIFY(...) #__VA_ARGS__##_catch_sr
|
||||
#else
|
||||
#define CATCH_INTERNAL_STRINGIFY(...) "Disabled by CATCH_CONFIG_DISABLE_STRINGIFICATION"
|
||||
#define CATCH_INTERNAL_STRINGIFY(...) "Disabled by CATCH_CONFIG_DISABLE_STRINGIFICATION"_catch_sr
|
||||
#endif
|
||||
|
||||
#if defined(CATCH_CONFIG_FAST_COMPILE) || defined(CATCH_CONFIG_DISABLE_EXCEPTIONS)
|
||||
|
@@ -89,7 +89,13 @@ struct AutoReg : Detail::NonCopyable {
|
||||
CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \
|
||||
CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
|
||||
CATCH_INTERNAL_SUPPRESS_UNUSED_VARIABLE_WARNINGS \
|
||||
namespace{ const Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( Catch::makeTestInvoker( &QualifiedMethod ), CATCH_INTERNAL_LINEINFO, "&" #QualifiedMethod, Catch::NameAndTags{ __VA_ARGS__ } ); } /* NOLINT */ \
|
||||
namespace { \
|
||||
const Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( \
|
||||
Catch::makeTestInvoker( &QualifiedMethod ), \
|
||||
CATCH_INTERNAL_LINEINFO, \
|
||||
"&" #QualifiedMethod##_catch_sr, \
|
||||
Catch::NameAndTags{ __VA_ARGS__ } ); \
|
||||
} /* NOLINT */ \
|
||||
CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
@@ -101,7 +107,11 @@ struct AutoReg : Detail::NonCopyable {
|
||||
struct TestName : INTERNAL_CATCH_REMOVE_PARENS(ClassName) { \
|
||||
void test(); \
|
||||
}; \
|
||||
const Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar ) ( Catch::makeTestInvoker( &TestName::test ), CATCH_INTERNAL_LINEINFO, #ClassName, Catch::NameAndTags{ __VA_ARGS__ } ); /* NOLINT */ \
|
||||
const Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( \
|
||||
Catch::makeTestInvoker( &TestName::test ), \
|
||||
CATCH_INTERNAL_LINEINFO, \
|
||||
#ClassName##_catch_sr, \
|
||||
Catch::NameAndTags{ __VA_ARGS__ } ); /* NOLINT */ \
|
||||
} \
|
||||
CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION \
|
||||
void TestName::test()
|
||||
|
@@ -221,10 +221,8 @@ namespace Catch {
|
||||
token.erase(token.begin());
|
||||
if (m_exclusion) {
|
||||
m_currentFilter.m_forbidden.emplace_back(Detail::make_unique<TestSpec::TagPattern>(".", m_substring));
|
||||
m_currentFilter.m_forbidden.emplace_back(Detail::make_unique<TestSpec::TagPattern>(token, m_substring));
|
||||
} else {
|
||||
m_currentFilter.m_required.emplace_back(Detail::make_unique<TestSpec::TagPattern>(".", m_substring));
|
||||
m_currentFilter.m_required.emplace_back(Detail::make_unique<TestSpec::TagPattern>(token, m_substring));
|
||||
}
|
||||
}
|
||||
if (m_exclusion) {
|
||||
|
@@ -33,13 +33,11 @@ namespace Catch {
|
||||
}
|
||||
|
||||
template <typename RangeLike>
|
||||
bool match(RangeLike&& rng) const {
|
||||
using std::begin; using std::end;
|
||||
|
||||
return end(rng) != std::find_if(begin(rng), end(rng),
|
||||
[&](auto const& elem) {
|
||||
return m_eq(elem, m_desired);
|
||||
});
|
||||
bool match( RangeLike&& rng ) const {
|
||||
for ( auto&& elem : rng ) {
|
||||
if ( m_eq( elem, m_desired ) ) { return true; }
|
||||
}
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -91,7 +89,7 @@ namespace Catch {
|
||||
/**
|
||||
* Creates a matcher that checks whether a range contains a specific element.
|
||||
*
|
||||
* Uses `eq` to do the comparisons
|
||||
* 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) {
|
||||
|
@@ -225,5 +225,17 @@ WithinRelMatcher WithinRel(float target) {
|
||||
}
|
||||
|
||||
|
||||
} // namespace Matchers
|
||||
|
||||
bool IsNaNMatcher::match( double const& matchee ) const {
|
||||
return std::isnan( matchee );
|
||||
}
|
||||
|
||||
std::string IsNaNMatcher::describe() const {
|
||||
using namespace std::string_literals;
|
||||
return "is NaN"s;
|
||||
}
|
||||
|
||||
IsNaNMatcher IsNaN() { return IsNaNMatcher(); }
|
||||
|
||||
} // namespace Matchers
|
||||
} // namespace Catch
|
||||
|
@@ -27,6 +27,11 @@ namespace Matchers {
|
||||
double m_margin;
|
||||
};
|
||||
|
||||
//! Creates a matcher that accepts numbers within certain range of target
|
||||
WithinAbsMatcher WithinAbs( double target, double margin );
|
||||
|
||||
|
||||
|
||||
class WithinUlpsMatcher final : public MatcherBase<double> {
|
||||
public:
|
||||
WithinUlpsMatcher( double target,
|
||||
@@ -40,6 +45,13 @@ namespace Matchers {
|
||||
Detail::FloatingPointKind m_type;
|
||||
};
|
||||
|
||||
//! Creates a matcher that accepts doubles within certain ULP range of target
|
||||
WithinUlpsMatcher WithinULP(double target, uint64_t maxUlpDiff);
|
||||
//! Creates a matcher that accepts floats within certain ULP range of target
|
||||
WithinUlpsMatcher WithinULP(float target, uint64_t maxUlpDiff);
|
||||
|
||||
|
||||
|
||||
// Given IEEE-754 format for floats and doubles, we can assume
|
||||
// that float -> double promotion is lossless. Given this, we can
|
||||
// assume that if we do the standard relative comparison of
|
||||
@@ -56,13 +68,6 @@ namespace Matchers {
|
||||
double m_epsilon;
|
||||
};
|
||||
|
||||
//! Creates a matcher that accepts doubles within certain ULP range of target
|
||||
WithinUlpsMatcher WithinULP(double target, uint64_t maxUlpDiff);
|
||||
//! Creates a matcher that accepts floats within certain ULP range of target
|
||||
WithinUlpsMatcher WithinULP(float target, uint64_t maxUlpDiff);
|
||||
//! Creates a matcher that accepts numbers within certain range of target
|
||||
WithinAbsMatcher WithinAbs(double target, double margin);
|
||||
|
||||
//! Creates a matcher that accepts doubles within certain relative range of target
|
||||
WithinRelMatcher WithinRel(double target, double eps);
|
||||
//! Creates a matcher that accepts doubles within 100*DBL_EPS relative range of target
|
||||
@@ -72,6 +77,17 @@ namespace Matchers {
|
||||
//! Creates a matcher that accepts floats within 100*FLT_EPS relative range of target
|
||||
WithinRelMatcher WithinRel(float target);
|
||||
|
||||
|
||||
|
||||
class IsNaNMatcher final : public MatcherBase<double> {
|
||||
public:
|
||||
IsNaNMatcher() = default;
|
||||
bool match( double const& matchee ) const override;
|
||||
std::string describe() const override;
|
||||
};
|
||||
|
||||
IsNaNMatcher IsNaN();
|
||||
|
||||
} // namespace Matchers
|
||||
} // namespace Catch
|
||||
|
||||
|
@@ -8,8 +8,10 @@
|
||||
#ifndef CATCH_MATCHERS_RANGE_EQUALS_HPP_INCLUDED
|
||||
#define CATCH_MATCHERS_RANGE_EQUALS_HPP_INCLUDED
|
||||
|
||||
#include <algorithm>
|
||||
#include <catch2/internal/catch_is_permutation.hpp>
|
||||
#include <catch2/matchers/catch_matchers_templated.hpp>
|
||||
|
||||
#include <algorithm>
|
||||
#include <utility>
|
||||
|
||||
namespace Catch {
|
||||
@@ -33,13 +35,19 @@ namespace Catch {
|
||||
|
||||
template <typename RangeLike>
|
||||
bool match( RangeLike&& rng ) const {
|
||||
using std::begin;
|
||||
using std::end;
|
||||
return std::equal( begin(m_desired),
|
||||
end(m_desired),
|
||||
begin(rng),
|
||||
end(rng),
|
||||
m_predicate );
|
||||
auto rng_start = begin( rng );
|
||||
const auto rng_end = end( rng );
|
||||
auto target_start = begin( m_desired );
|
||||
const auto target_end = end( m_desired );
|
||||
|
||||
while (rng_start != rng_end && target_start != target_end) {
|
||||
if (!m_predicate(*rng_start, *target_start)) {
|
||||
return false;
|
||||
}
|
||||
++rng_start;
|
||||
++target_start;
|
||||
}
|
||||
return rng_start == rng_end && target_start == target_end;
|
||||
}
|
||||
|
||||
std::string describe() const override {
|
||||
@@ -67,11 +75,11 @@ namespace Catch {
|
||||
bool match( RangeLike&& rng ) const {
|
||||
using std::begin;
|
||||
using std::end;
|
||||
return std::is_permutation( begin( m_desired ),
|
||||
end( m_desired ),
|
||||
begin( rng ),
|
||||
end( rng ),
|
||||
m_predicate );
|
||||
return Catch::Detail::is_permutation( begin( m_desired ),
|
||||
end( m_desired ),
|
||||
begin( rng ),
|
||||
end( rng ),
|
||||
m_predicate );
|
||||
}
|
||||
|
||||
std::string describe() const override {
|
||||
|
@@ -93,6 +93,7 @@ internal_headers = [
|
||||
'internal/catch_floating_point_helpers.hpp',
|
||||
'internal/catch_getenv.hpp',
|
||||
'internal/catch_istream.hpp',
|
||||
'internal/catch_is_permutation.hpp',
|
||||
'internal/catch_lazy_expr.hpp',
|
||||
'internal/catch_leak_detector.hpp',
|
||||
'internal/catch_list.hpp',
|
||||
|
@@ -192,7 +192,7 @@ private:
|
||||
private:
|
||||
std::ostream& stream;
|
||||
AssertionResult const& result;
|
||||
std::vector<MessageInfo> messages;
|
||||
std::vector<MessageInfo> const& messages;
|
||||
std::vector<MessageInfo>::const_iterator itMessage;
|
||||
bool printInfoMessages;
|
||||
ColourImpl* colourImpl;
|
||||
|
@@ -51,7 +51,6 @@ public:
|
||||
stats(_stats),
|
||||
result(_stats.assertionResult),
|
||||
colour(Colour::None),
|
||||
message(result.getMessage()),
|
||||
messages(_stats.infoMessages),
|
||||
colourImpl(colourImpl_),
|
||||
printInfoMessages(_printInfoMessages) {
|
||||
@@ -60,10 +59,10 @@ public:
|
||||
colour = Colour::Success;
|
||||
passOrFail = "PASSED"_sr;
|
||||
//if( result.hasMessage() )
|
||||
if (_stats.infoMessages.size() == 1)
|
||||
messageLabel = "with message";
|
||||
if (_stats.infoMessages.size() > 1)
|
||||
messageLabel = "with messages";
|
||||
if (messages.size() == 1)
|
||||
messageLabel = "with message"_sr;
|
||||
if (messages.size() > 1)
|
||||
messageLabel = "with messages"_sr;
|
||||
break;
|
||||
case ResultWas::ExpressionFailed:
|
||||
if (result.isOk()) {
|
||||
@@ -73,51 +72,57 @@ public:
|
||||
colour = Colour::Error;
|
||||
passOrFail = "FAILED"_sr;
|
||||
}
|
||||
if (_stats.infoMessages.size() == 1)
|
||||
messageLabel = "with message";
|
||||
if (_stats.infoMessages.size() > 1)
|
||||
messageLabel = "with messages";
|
||||
if (messages.size() == 1)
|
||||
messageLabel = "with message"_sr;
|
||||
if (messages.size() > 1)
|
||||
messageLabel = "with messages"_sr;
|
||||
break;
|
||||
case ResultWas::ThrewException:
|
||||
colour = Colour::Error;
|
||||
passOrFail = "FAILED"_sr;
|
||||
messageLabel = "due to unexpected exception with ";
|
||||
if (_stats.infoMessages.size() == 1)
|
||||
messageLabel += "message";
|
||||
if (_stats.infoMessages.size() > 1)
|
||||
messageLabel += "messages";
|
||||
// todo switch
|
||||
switch (messages.size()) { case 0:
|
||||
messageLabel = "due to unexpected exception with "_sr;
|
||||
break;
|
||||
case 1:
|
||||
messageLabel = "due to unexpected exception with message"_sr;
|
||||
break;
|
||||
default:
|
||||
messageLabel = "due to unexpected exception with messages"_sr;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case ResultWas::FatalErrorCondition:
|
||||
colour = Colour::Error;
|
||||
passOrFail = "FAILED"_sr;
|
||||
messageLabel = "due to a fatal error condition";
|
||||
messageLabel = "due to a fatal error condition"_sr;
|
||||
break;
|
||||
case ResultWas::DidntThrowException:
|
||||
colour = Colour::Error;
|
||||
passOrFail = "FAILED"_sr;
|
||||
messageLabel = "because no exception was thrown where one was expected";
|
||||
messageLabel = "because no exception was thrown where one was expected"_sr;
|
||||
break;
|
||||
case ResultWas::Info:
|
||||
messageLabel = "info";
|
||||
messageLabel = "info"_sr;
|
||||
break;
|
||||
case ResultWas::Warning:
|
||||
messageLabel = "warning";
|
||||
messageLabel = "warning"_sr;
|
||||
break;
|
||||
case ResultWas::ExplicitFailure:
|
||||
passOrFail = "FAILED"_sr;
|
||||
colour = Colour::Error;
|
||||
if (_stats.infoMessages.size() == 1)
|
||||
messageLabel = "explicitly with message";
|
||||
if (_stats.infoMessages.size() > 1)
|
||||
messageLabel = "explicitly with messages";
|
||||
if (messages.size() == 1)
|
||||
messageLabel = "explicitly with message"_sr;
|
||||
if (messages.size() > 1)
|
||||
messageLabel = "explicitly with messages"_sr;
|
||||
break;
|
||||
case ResultWas::ExplicitSkip:
|
||||
colour = Colour::Skip;
|
||||
passOrFail = "SKIPPED"_sr;
|
||||
if (_stats.infoMessages.size() == 1)
|
||||
messageLabel = "explicitly with message";
|
||||
if (_stats.infoMessages.size() > 1)
|
||||
messageLabel = "explicitly with messages";
|
||||
if (messages.size() == 1)
|
||||
messageLabel = "explicitly with message"_sr;
|
||||
if (messages.size() > 1)
|
||||
messageLabel = "explicitly with messages"_sr;
|
||||
break;
|
||||
// These cases are here to prevent compiler warnings
|
||||
case ResultWas::Unknown:
|
||||
@@ -181,9 +186,8 @@ private:
|
||||
AssertionResult const& result;
|
||||
Colour::Code colour;
|
||||
StringRef passOrFail;
|
||||
std::string messageLabel;
|
||||
std::string message;
|
||||
std::vector<MessageInfo> messages;
|
||||
StringRef messageLabel;
|
||||
std::vector<MessageInfo> const& messages;
|
||||
ColourImpl* colourImpl;
|
||||
bool printInfoMessages;
|
||||
};
|
||||
|
@@ -70,7 +70,8 @@ namespace Catch {
|
||||
|
||||
void
|
||||
CumulativeReporterBase::sectionStarting( SectionInfo const& sectionInfo ) {
|
||||
SectionStats incompleteStats( sectionInfo, Counts(), 0, false );
|
||||
// We need a copy, because SectionStats expect to take ownership
|
||||
SectionStats incompleteStats( SectionInfo(sectionInfo), Counts(), 0, false );
|
||||
SectionNode* node;
|
||||
if ( m_sectionStack.empty() ) {
|
||||
if ( !m_rootSection ) {
|
||||
|
@@ -118,7 +118,7 @@ namespace Catch {
|
||||
CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
|
||||
namespace { \
|
||||
Catch::ListenerRegistrar<listenerType> INTERNAL_CATCH_UNIQUE_NAME( \
|
||||
catch_internal_RegistrarFor )( #listenerType ); \
|
||||
catch_internal_RegistrarFor )( #listenerType##_catch_sr ); \
|
||||
} \
|
||||
CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION
|
||||
|
||||
|
@@ -40,7 +40,7 @@ namespace Catch {
|
||||
}
|
||||
|
||||
void SonarQubeReporter::writeRun( TestRunNode const& runNode ) {
|
||||
std::map<std::string, std::vector<TestCaseNode const*>> testsPerFile;
|
||||
std::map<StringRef, std::vector<TestCaseNode const*>> testsPerFile;
|
||||
|
||||
for ( auto const& child : runNode.children ) {
|
||||
testsPerFile[child->value.testInfo->lineInfo.file].push_back(
|
||||
@@ -52,7 +52,7 @@ namespace Catch {
|
||||
}
|
||||
}
|
||||
|
||||
void SonarQubeReporter::writeTestFile(std::string const& filename, std::vector<TestCaseNode const*> const& testCaseNodes) {
|
||||
void SonarQubeReporter::writeTestFile(StringRef filename, std::vector<TestCaseNode const*> const& testCaseNodes) {
|
||||
XmlWriter::ScopedElement e = xml.scopedElement("file");
|
||||
xml.writeAttribute("path"_sr, filename);
|
||||
|
||||
|
@@ -41,7 +41,7 @@ namespace Catch {
|
||||
|
||||
void writeRun( TestRunNode const& groupNode );
|
||||
|
||||
void writeTestFile(std::string const& filename, std::vector<TestCaseNode const*> const& testCaseNodes);
|
||||
void writeTestFile(StringRef filename, std::vector<TestCaseNode const*> const& testCaseNodes);
|
||||
|
||||
void writeTestCase(TestCaseNode const& testCaseNode);
|
||||
|
||||
|
@@ -184,7 +184,7 @@ namespace Catch {
|
||||
private:
|
||||
std::ostream& stream;
|
||||
AssertionResult const& result;
|
||||
std::vector<MessageInfo> messages;
|
||||
std::vector<MessageInfo> const& messages;
|
||||
std::vector<MessageInfo>::const_iterator itMessage;
|
||||
bool printInfoMessages;
|
||||
std::size_t counter;
|
||||
|
@@ -66,7 +66,7 @@ namespace Catch {
|
||||
void XmlReporter::testCaseStarting( TestCaseInfo const& testInfo ) {
|
||||
StreamingReporterBase::testCaseStarting(testInfo);
|
||||
m_xml.startElement( "TestCase" )
|
||||
.writeAttribute( "name"_sr, trim( testInfo.name ) )
|
||||
.writeAttribute( "name"_sr, trim( StringRef(testInfo.name) ) )
|
||||
.writeAttribute( "tags"_sr, testInfo.tagsAsString() );
|
||||
|
||||
writeSourceInfo( testInfo.lineInfo );
|
||||
@@ -80,7 +80,7 @@ namespace Catch {
|
||||
StreamingReporterBase::sectionStarting( sectionInfo );
|
||||
if( m_sectionDepth++ > 0 ) {
|
||||
m_xml.startElement( "Section" )
|
||||
.writeAttribute( "name"_sr, trim( sectionInfo.name ) );
|
||||
.writeAttribute( "name"_sr, trim( StringRef(sectionInfo.name) ) );
|
||||
writeSourceInfo( sectionInfo.lineInfo );
|
||||
m_xml.ensureTagClosed();
|
||||
}
|
||||
@@ -194,11 +194,10 @@ namespace Catch {
|
||||
|
||||
if ( m_config->showDurations() == ShowDurations::Always )
|
||||
e.writeAttribute( "durationInSeconds"_sr, m_testCaseTimer.getElapsedSeconds() );
|
||||
|
||||
if( !testCaseStats.stdOut.empty() )
|
||||
m_xml.scopedElement( "StdOut" ).writeText( trim( testCaseStats.stdOut ), XmlFormatting::Newline );
|
||||
m_xml.scopedElement( "StdOut" ).writeText( trim( StringRef(testCaseStats.stdOut) ), XmlFormatting::Newline );
|
||||
if( !testCaseStats.stdErr.empty() )
|
||||
m_xml.scopedElement( "StdErr" ).writeText( trim( testCaseStats.stdErr ), XmlFormatting::Newline );
|
||||
m_xml.scopedElement( "StdErr" ).writeText( trim( StringRef(testCaseStats.stdErr) ), XmlFormatting::Newline );
|
||||
|
||||
m_xml.endElement();
|
||||
}
|
||||
|
@@ -77,6 +77,7 @@ endif(MSVC) #Temporary workaround
|
||||
# Please keep these ordered alphabetically
|
||||
set(TEST_SOURCES
|
||||
${SELF_TEST_DIR}/TestRegistrations.cpp
|
||||
${SELF_TEST_DIR}/IntrospectiveTests/Algorithms.tests.cpp
|
||||
${SELF_TEST_DIR}/IntrospectiveTests/Clara.tests.cpp
|
||||
${SELF_TEST_DIR}/IntrospectiveTests/CmdLine.tests.cpp
|
||||
${SELF_TEST_DIR}/IntrospectiveTests/CmdLineHelpers.tests.cpp
|
||||
@@ -134,6 +135,7 @@ set(TEST_SOURCES
|
||||
|
||||
set(TEST_HEADERS
|
||||
${SELF_TEST_DIR}/helpers/parse_test_spec.hpp
|
||||
${SELF_TEST_DIR}/helpers/range_test_helpers.hpp
|
||||
${SELF_TEST_DIR}/helpers/type_with_lit_0_comparisons.hpp
|
||||
)
|
||||
|
||||
|
@@ -151,6 +151,7 @@ Nor would this
|
||||
:test-result: FAIL FAIL does not require an argument
|
||||
:test-result: FAIL FAIL_CHECK does not abort the test
|
||||
:test-result: PASS Factorials are computed
|
||||
:test-result: PASS Filter generator throws exception for empty generator
|
||||
:test-result: PASS Floating point matchers: double
|
||||
:test-result: PASS Floating point matchers: float
|
||||
:test-result: PASS Generators -- adapters
|
||||
|
@@ -149,6 +149,7 @@
|
||||
:test-result: FAIL FAIL does not require an argument
|
||||
:test-result: FAIL FAIL_CHECK does not abort the test
|
||||
:test-result: PASS Factorials are computed
|
||||
:test-result: PASS Filter generator throws exception for empty generator
|
||||
:test-result: PASS Floating point matchers: double
|
||||
:test-result: PASS Floating point matchers: float
|
||||
:test-result: PASS Generators -- adapters
|
||||
|
@@ -599,6 +599,7 @@ Misc.tests.cpp:<line number>: passed: Factorial(1) == 1 for: 1 == 1
|
||||
Misc.tests.cpp:<line number>: passed: Factorial(2) == 2 for: 2 == 2
|
||||
Misc.tests.cpp:<line number>: passed: Factorial(3) == 6 for: 6 == 6
|
||||
Misc.tests.cpp:<line number>: passed: Factorial(10) == 3628800 for: 3628800 (0x<hex digits>) == 3628800 (0x<hex digits>)
|
||||
GeneratorsImpl.tests.cpp:<line number>: passed: filter( []( int ) { return false; }, value( 3 ) ), Catch::GeneratorException
|
||||
Matchers.tests.cpp:<line number>: passed: 10., WithinRel( 11.1, 0.1 ) for: 10.0 and 11.1 are within 10% of each other
|
||||
Matchers.tests.cpp:<line number>: passed: 10., !WithinRel( 11.2, 0.1 ) for: 10.0 not and 11.2 are within 10% of each other
|
||||
Matchers.tests.cpp:<line number>: passed: 1., !WithinRel( 0., 0.99 ) for: 1.0 not and 0 are within 99% of each other
|
||||
@@ -628,6 +629,7 @@ Matchers.tests.cpp:<line number>: passed: WithinULP( 1., 0 )
|
||||
Matchers.tests.cpp:<line number>: passed: WithinRel( 1., 0. )
|
||||
Matchers.tests.cpp:<line number>: passed: WithinRel( 1., -0.2 ), std::domain_error
|
||||
Matchers.tests.cpp:<line number>: passed: WithinRel( 1., 1. ), std::domain_error
|
||||
Matchers.tests.cpp:<line number>: passed: 1., !IsNaN() for: 1.0 not is NaN
|
||||
Matchers.tests.cpp:<line number>: passed: 10.f, WithinRel( 11.1f, 0.1f ) for: 10.0f and 11.1 are within 10% of each other
|
||||
Matchers.tests.cpp:<line number>: passed: 10.f, !WithinRel( 11.2f, 0.1f ) for: 10.0f not and 11.2 are within 10% of each other
|
||||
Matchers.tests.cpp:<line number>: passed: 1.f, !WithinRel( 0.f, 0.99f ) for: 1.0f not and 0 are within 99% of each other
|
||||
@@ -660,6 +662,7 @@ Matchers.tests.cpp:<line number>: passed: WithinULP( 1.f, static_cast<uint64_t>(
|
||||
Matchers.tests.cpp:<line number>: passed: WithinRel( 1.f, 0.f )
|
||||
Matchers.tests.cpp:<line number>: passed: WithinRel( 1.f, -0.2f ), std::domain_error
|
||||
Matchers.tests.cpp:<line number>: passed: WithinRel( 1.f, 1.f ), std::domain_error
|
||||
Matchers.tests.cpp:<line number>: passed: 1., !IsNaN() for: 1.0 not is NaN
|
||||
Generators.tests.cpp:<line number>: passed: i % 2 == 0 for: 0 == 0
|
||||
Generators.tests.cpp:<line number>: passed: i % 2 == 0 for: 0 == 0
|
||||
Generators.tests.cpp:<line number>: passed: i % 2 == 0 for: 0 == 0
|
||||
@@ -1992,6 +1995,18 @@ MatchersRanges.tests.cpp:<line number>: passed: array_a, !RangeEquals( array_c )
|
||||
MatchersRanges.tests.cpp:<line number>: passed: vector_a, !RangeEquals( vector_b ) for: { 1, 2, 3 } not elements are { 1, 2, 3, 4 }
|
||||
MatchersRanges.tests.cpp:<line number>: passed: vector_a, RangeEquals( vector_a_plus_1, close_enough ) for: { 1, 2, 3 } elements are { 2, 3, 4 }
|
||||
MatchersRanges.tests.cpp:<line number>: passed: vector_a, !RangeEquals( vector_b, close_enough ) for: { 1, 2, 3 } not elements are { 3, 3, 4 }
|
||||
MatchersRanges.tests.cpp:<line number>: passed: needs_adl1, RangeEquals( needs_adl2 ) for: { 1, 2, 3, 4, 5 } elements are { 1, 2, 3, 4, 5 }
|
||||
MatchersRanges.tests.cpp:<line number>: passed: needs_adl1, RangeEquals( needs_adl3, []( int l, int r ) { return l + 1 == r; } ) for: { 1, 2, 3, 4, 5 } elements are { 2, 3, 4, 5, 6 }
|
||||
MatchersRanges.tests.cpp:<line number>: passed: mocked1, !RangeEquals( arr ) for: { 1, 2, 3, 4 } not elements are { 1, 2, 4, 4 }
|
||||
MatchersRanges.tests.cpp:<line number>: passed: mocked1.m_derefed[0] for: true
|
||||
MatchersRanges.tests.cpp:<line number>: passed: mocked1.m_derefed[1] for: true
|
||||
MatchersRanges.tests.cpp:<line number>: passed: mocked1.m_derefed[2] for: true
|
||||
MatchersRanges.tests.cpp:<line number>: passed: !(mocked1.m_derefed[3]) for: !false
|
||||
MatchersRanges.tests.cpp:<line number>: passed: mocked1, RangeEquals( arr ) for: { 1, 2, 3, 4 } elements are { 1, 2, 3, 4 }
|
||||
MatchersRanges.tests.cpp:<line number>: passed: mocked1.m_derefed[0] for: true
|
||||
MatchersRanges.tests.cpp:<line number>: passed: mocked1.m_derefed[1] for: true
|
||||
MatchersRanges.tests.cpp:<line number>: passed: mocked1.m_derefed[2] for: true
|
||||
MatchersRanges.tests.cpp:<line number>: passed: mocked1.m_derefed[3] for: true
|
||||
MatchersRanges.tests.cpp:<line number>: passed: empty_vector, UnorderedRangeEquals( empty_vector ) for: { } unordered elements are { }
|
||||
MatchersRanges.tests.cpp:<line number>: passed: empty_vector, !UnorderedRangeEquals( non_empty_vector ) for: { } not unordered elements are { 1 }
|
||||
MatchersRanges.tests.cpp:<line number>: passed: non_empty_vector, !UnorderedRangeEquals( empty_vector ) for: { 1 } not unordered elements are { }
|
||||
@@ -2001,6 +2016,7 @@ MatchersRanges.tests.cpp:<line number>: passed: array_a, !UnorderedRangeEquals(
|
||||
MatchersRanges.tests.cpp:<line number>: passed: vector_a, !UnorderedRangeEquals( vector_b ) for: { 1, 2, 3 } not unordered elements are { 1, 2, 3, 4 }
|
||||
MatchersRanges.tests.cpp:<line number>: passed: vector_a, UnorderedRangeEquals( vector_a_plus_1, close_enough ) for: { 1, 10, 20 } unordered elements are { 11, 21, 2 }
|
||||
MatchersRanges.tests.cpp:<line number>: passed: vector_a, !UnorderedRangeEquals( vector_b, close_enough ) for: { 1, 10, 21 } not unordered elements are { 11, 21, 3 }
|
||||
MatchersRanges.tests.cpp:<line number>: passed: needs_adl1, UnorderedRangeEquals( needs_adl2 ) for: { 1, 2, 3, 4, 5 } unordered elements are { 1, 2, 3, 4, 5 }
|
||||
MatchersRanges.tests.cpp:<line number>: passed: empty_vec, SizeIs(0) for: { } has size == 0
|
||||
MatchersRanges.tests.cpp:<line number>: passed: empty_vec, !SizeIs(2) for: { } not has size == 2
|
||||
MatchersRanges.tests.cpp:<line number>: passed: empty_vec, SizeIs(Lt(2)) for: { } size matches is less than 2
|
||||
@@ -2522,7 +2538,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: 408 | 308 passed | 84 failed | 5 skipped | 11 failed as expected
|
||||
assertions: 2210 | 2033 passed | 145 failed | 32 failed as expected
|
||||
test cases: 409 | 309 passed | 84 failed | 5 skipped | 11 failed as expected
|
||||
assertions: 2226 | 2049 passed | 145 failed | 32 failed as expected
|
||||
|
||||
|
||||
|
@@ -597,6 +597,7 @@ Misc.tests.cpp:<line number>: passed: Factorial(1) == 1 for: 1 == 1
|
||||
Misc.tests.cpp:<line number>: passed: Factorial(2) == 2 for: 2 == 2
|
||||
Misc.tests.cpp:<line number>: passed: Factorial(3) == 6 for: 6 == 6
|
||||
Misc.tests.cpp:<line number>: passed: Factorial(10) == 3628800 for: 3628800 (0x<hex digits>) == 3628800 (0x<hex digits>)
|
||||
GeneratorsImpl.tests.cpp:<line number>: passed: filter( []( int ) { return false; }, value( 3 ) ), Catch::GeneratorException
|
||||
Matchers.tests.cpp:<line number>: passed: 10., WithinRel( 11.1, 0.1 ) for: 10.0 and 11.1 are within 10% of each other
|
||||
Matchers.tests.cpp:<line number>: passed: 10., !WithinRel( 11.2, 0.1 ) for: 10.0 not and 11.2 are within 10% of each other
|
||||
Matchers.tests.cpp:<line number>: passed: 1., !WithinRel( 0., 0.99 ) for: 1.0 not and 0 are within 99% of each other
|
||||
@@ -626,6 +627,7 @@ Matchers.tests.cpp:<line number>: passed: WithinULP( 1., 0 )
|
||||
Matchers.tests.cpp:<line number>: passed: WithinRel( 1., 0. )
|
||||
Matchers.tests.cpp:<line number>: passed: WithinRel( 1., -0.2 ), std::domain_error
|
||||
Matchers.tests.cpp:<line number>: passed: WithinRel( 1., 1. ), std::domain_error
|
||||
Matchers.tests.cpp:<line number>: passed: 1., !IsNaN() for: 1.0 not is NaN
|
||||
Matchers.tests.cpp:<line number>: passed: 10.f, WithinRel( 11.1f, 0.1f ) for: 10.0f and 11.1 are within 10% of each other
|
||||
Matchers.tests.cpp:<line number>: passed: 10.f, !WithinRel( 11.2f, 0.1f ) for: 10.0f not and 11.2 are within 10% of each other
|
||||
Matchers.tests.cpp:<line number>: passed: 1.f, !WithinRel( 0.f, 0.99f ) for: 1.0f not and 0 are within 99% of each other
|
||||
@@ -658,6 +660,7 @@ Matchers.tests.cpp:<line number>: passed: WithinULP( 1.f, static_cast<uint64_t>(
|
||||
Matchers.tests.cpp:<line number>: passed: WithinRel( 1.f, 0.f )
|
||||
Matchers.tests.cpp:<line number>: passed: WithinRel( 1.f, -0.2f ), std::domain_error
|
||||
Matchers.tests.cpp:<line number>: passed: WithinRel( 1.f, 1.f ), std::domain_error
|
||||
Matchers.tests.cpp:<line number>: passed: 1., !IsNaN() for: 1.0 not is NaN
|
||||
Generators.tests.cpp:<line number>: passed: i % 2 == 0 for: 0 == 0
|
||||
Generators.tests.cpp:<line number>: passed: i % 2 == 0 for: 0 == 0
|
||||
Generators.tests.cpp:<line number>: passed: i % 2 == 0 for: 0 == 0
|
||||
@@ -1985,6 +1988,18 @@ MatchersRanges.tests.cpp:<line number>: passed: array_a, !RangeEquals( array_c )
|
||||
MatchersRanges.tests.cpp:<line number>: passed: vector_a, !RangeEquals( vector_b ) for: { 1, 2, 3 } not elements are { 1, 2, 3, 4 }
|
||||
MatchersRanges.tests.cpp:<line number>: passed: vector_a, RangeEquals( vector_a_plus_1, close_enough ) for: { 1, 2, 3 } elements are { 2, 3, 4 }
|
||||
MatchersRanges.tests.cpp:<line number>: passed: vector_a, !RangeEquals( vector_b, close_enough ) for: { 1, 2, 3 } not elements are { 3, 3, 4 }
|
||||
MatchersRanges.tests.cpp:<line number>: passed: needs_adl1, RangeEquals( needs_adl2 ) for: { 1, 2, 3, 4, 5 } elements are { 1, 2, 3, 4, 5 }
|
||||
MatchersRanges.tests.cpp:<line number>: passed: needs_adl1, RangeEquals( needs_adl3, []( int l, int r ) { return l + 1 == r; } ) for: { 1, 2, 3, 4, 5 } elements are { 2, 3, 4, 5, 6 }
|
||||
MatchersRanges.tests.cpp:<line number>: passed: mocked1, !RangeEquals( arr ) for: { 1, 2, 3, 4 } not elements are { 1, 2, 4, 4 }
|
||||
MatchersRanges.tests.cpp:<line number>: passed: mocked1.m_derefed[0] for: true
|
||||
MatchersRanges.tests.cpp:<line number>: passed: mocked1.m_derefed[1] for: true
|
||||
MatchersRanges.tests.cpp:<line number>: passed: mocked1.m_derefed[2] for: true
|
||||
MatchersRanges.tests.cpp:<line number>: passed: !(mocked1.m_derefed[3]) for: !false
|
||||
MatchersRanges.tests.cpp:<line number>: passed: mocked1, RangeEquals( arr ) for: { 1, 2, 3, 4 } elements are { 1, 2, 3, 4 }
|
||||
MatchersRanges.tests.cpp:<line number>: passed: mocked1.m_derefed[0] for: true
|
||||
MatchersRanges.tests.cpp:<line number>: passed: mocked1.m_derefed[1] for: true
|
||||
MatchersRanges.tests.cpp:<line number>: passed: mocked1.m_derefed[2] for: true
|
||||
MatchersRanges.tests.cpp:<line number>: passed: mocked1.m_derefed[3] for: true
|
||||
MatchersRanges.tests.cpp:<line number>: passed: empty_vector, UnorderedRangeEquals( empty_vector ) for: { } unordered elements are { }
|
||||
MatchersRanges.tests.cpp:<line number>: passed: empty_vector, !UnorderedRangeEquals( non_empty_vector ) for: { } not unordered elements are { 1 }
|
||||
MatchersRanges.tests.cpp:<line number>: passed: non_empty_vector, !UnorderedRangeEquals( empty_vector ) for: { 1 } not unordered elements are { }
|
||||
@@ -1994,6 +2009,7 @@ MatchersRanges.tests.cpp:<line number>: passed: array_a, !UnorderedRangeEquals(
|
||||
MatchersRanges.tests.cpp:<line number>: passed: vector_a, !UnorderedRangeEquals( vector_b ) for: { 1, 2, 3 } not unordered elements are { 1, 2, 3, 4 }
|
||||
MatchersRanges.tests.cpp:<line number>: passed: vector_a, UnorderedRangeEquals( vector_a_plus_1, close_enough ) for: { 1, 10, 20 } unordered elements are { 11, 21, 2 }
|
||||
MatchersRanges.tests.cpp:<line number>: passed: vector_a, !UnorderedRangeEquals( vector_b, close_enough ) for: { 1, 10, 21 } not unordered elements are { 11, 21, 3 }
|
||||
MatchersRanges.tests.cpp:<line number>: passed: needs_adl1, UnorderedRangeEquals( needs_adl2 ) for: { 1, 2, 3, 4, 5 } unordered elements are { 1, 2, 3, 4, 5 }
|
||||
MatchersRanges.tests.cpp:<line number>: passed: empty_vec, SizeIs(0) for: { } has size == 0
|
||||
MatchersRanges.tests.cpp:<line number>: passed: empty_vec, !SizeIs(2) for: { } not has size == 2
|
||||
MatchersRanges.tests.cpp:<line number>: passed: empty_vec, SizeIs(Lt(2)) for: { } size matches is less than 2
|
||||
@@ -2511,7 +2527,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: 408 | 308 passed | 84 failed | 5 skipped | 11 failed as expected
|
||||
assertions: 2210 | 2033 passed | 145 failed | 32 failed as expected
|
||||
test cases: 409 | 309 passed | 84 failed | 5 skipped | 11 failed as expected
|
||||
assertions: 2226 | 2049 passed | 145 failed | 32 failed as expected
|
||||
|
||||
|
||||
|
@@ -1533,6 +1533,6 @@ due to unexpected exception with message:
|
||||
Why would you throw a std::string?
|
||||
|
||||
===============================================================================
|
||||
test cases: 408 | 322 passed | 69 failed | 6 skipped | 11 failed as expected
|
||||
assertions: 2193 | 2033 passed | 128 failed | 32 failed as expected
|
||||
test cases: 409 | 323 passed | 69 failed | 6 skipped | 11 failed as expected
|
||||
assertions: 2209 | 2049 passed | 128 failed | 32 failed as expected
|
||||
|
||||
|
@@ -4477,6 +4477,15 @@ Misc.tests.cpp:<line number>: PASSED:
|
||||
with expansion:
|
||||
3628800 (0x<hex digits>) == 3628800 (0x<hex digits>)
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
Filter generator throws exception for empty generator
|
||||
-------------------------------------------------------------------------------
|
||||
GeneratorsImpl.tests.cpp:<line number>
|
||||
...............................................................................
|
||||
|
||||
GeneratorsImpl.tests.cpp:<line number>: PASSED:
|
||||
REQUIRE_THROWS_AS( filter( []( int ) { return false; }, value( 3 ) ), Catch::GeneratorException )
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
Floating point matchers: double
|
||||
Relative
|
||||
@@ -4662,6 +4671,18 @@ Matchers.tests.cpp:<line number>: PASSED:
|
||||
Matchers.tests.cpp:<line number>: PASSED:
|
||||
REQUIRE_THROWS_AS( WithinRel( 1., 1. ), std::domain_error )
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
Floating point matchers: double
|
||||
IsNaN
|
||||
-------------------------------------------------------------------------------
|
||||
Matchers.tests.cpp:<line number>
|
||||
...............................................................................
|
||||
|
||||
Matchers.tests.cpp:<line number>: PASSED:
|
||||
REQUIRE_THAT( 1., !IsNaN() )
|
||||
with expansion:
|
||||
1.0 not is NaN
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
Floating point matchers: float
|
||||
Relative
|
||||
@@ -4855,6 +4876,18 @@ Matchers.tests.cpp:<line number>: PASSED:
|
||||
Matchers.tests.cpp:<line number>: PASSED:
|
||||
REQUIRE_THROWS_AS( WithinRel( 1.f, 1.f ), std::domain_error )
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
Floating point matchers: float
|
||||
IsNaN
|
||||
-------------------------------------------------------------------------------
|
||||
Matchers.tests.cpp:<line number>
|
||||
...............................................................................
|
||||
|
||||
Matchers.tests.cpp:<line number>: PASSED:
|
||||
REQUIRE_THAT( 1., !IsNaN() )
|
||||
with expansion:
|
||||
1.0 not is NaN
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
Generators -- adapters
|
||||
Filtering by predicate
|
||||
@@ -14229,6 +14262,89 @@ MatchersRanges.tests.cpp:<line number>: PASSED:
|
||||
with expansion:
|
||||
{ 1, 2, 3 } not elements are { 3, 3, 4 }
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
Usage of RangeEquals range matcher
|
||||
Ranges that need ADL begin/end
|
||||
-------------------------------------------------------------------------------
|
||||
MatchersRanges.tests.cpp:<line number>
|
||||
...............................................................................
|
||||
|
||||
MatchersRanges.tests.cpp:<line number>: PASSED:
|
||||
REQUIRE_THAT( needs_adl1, RangeEquals( needs_adl2 ) )
|
||||
with expansion:
|
||||
{ 1, 2, 3, 4, 5 } elements are { 1, 2, 3, 4, 5 }
|
||||
|
||||
MatchersRanges.tests.cpp:<line number>: PASSED:
|
||||
REQUIRE_THAT( needs_adl1, RangeEquals( needs_adl3, []( int l, int r ) { return l + 1 == r; } ) )
|
||||
with expansion:
|
||||
{ 1, 2, 3, 4, 5 } elements are { 2, 3, 4, 5, 6 }
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
Usage of RangeEquals range matcher
|
||||
Check short-circuiting behaviour
|
||||
Check short-circuits on failure
|
||||
-------------------------------------------------------------------------------
|
||||
MatchersRanges.tests.cpp:<line number>
|
||||
...............................................................................
|
||||
|
||||
MatchersRanges.tests.cpp:<line number>: PASSED:
|
||||
REQUIRE_THAT( mocked1, !RangeEquals( arr ) )
|
||||
with expansion:
|
||||
{ 1, 2, 3, 4 } not elements are { 1, 2, 4, 4 }
|
||||
|
||||
MatchersRanges.tests.cpp:<line number>: PASSED:
|
||||
REQUIRE( mocked1.m_derefed[0] )
|
||||
with expansion:
|
||||
true
|
||||
|
||||
MatchersRanges.tests.cpp:<line number>: PASSED:
|
||||
REQUIRE( mocked1.m_derefed[1] )
|
||||
with expansion:
|
||||
true
|
||||
|
||||
MatchersRanges.tests.cpp:<line number>: PASSED:
|
||||
REQUIRE( mocked1.m_derefed[2] )
|
||||
with expansion:
|
||||
true
|
||||
|
||||
MatchersRanges.tests.cpp:<line number>: PASSED:
|
||||
REQUIRE_FALSE( mocked1.m_derefed[3] )
|
||||
with expansion:
|
||||
!false
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
Usage of RangeEquals range matcher
|
||||
Check short-circuiting behaviour
|
||||
All elements are checked on success
|
||||
-------------------------------------------------------------------------------
|
||||
MatchersRanges.tests.cpp:<line number>
|
||||
...............................................................................
|
||||
|
||||
MatchersRanges.tests.cpp:<line number>: PASSED:
|
||||
REQUIRE_THAT( mocked1, RangeEquals( arr ) )
|
||||
with expansion:
|
||||
{ 1, 2, 3, 4 } elements are { 1, 2, 3, 4 }
|
||||
|
||||
MatchersRanges.tests.cpp:<line number>: PASSED:
|
||||
REQUIRE( mocked1.m_derefed[0] )
|
||||
with expansion:
|
||||
true
|
||||
|
||||
MatchersRanges.tests.cpp:<line number>: PASSED:
|
||||
REQUIRE( mocked1.m_derefed[1] )
|
||||
with expansion:
|
||||
true
|
||||
|
||||
MatchersRanges.tests.cpp:<line number>: PASSED:
|
||||
REQUIRE( mocked1.m_derefed[2] )
|
||||
with expansion:
|
||||
true
|
||||
|
||||
MatchersRanges.tests.cpp:<line number>: PASSED:
|
||||
REQUIRE( mocked1.m_derefed[3] )
|
||||
with expansion:
|
||||
true
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
Usage of UnorderedRangeEquals range matcher
|
||||
Basic usage
|
||||
@@ -14338,6 +14454,18 @@ MatchersRanges.tests.cpp:<line number>: PASSED:
|
||||
with expansion:
|
||||
{ 1, 10, 21 } not unordered elements are { 11, 21, 3 }
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
Usage of UnorderedRangeEquals range matcher
|
||||
Ranges that need ADL begin/end
|
||||
-------------------------------------------------------------------------------
|
||||
MatchersRanges.tests.cpp:<line number>
|
||||
...............................................................................
|
||||
|
||||
MatchersRanges.tests.cpp:<line number>: PASSED:
|
||||
REQUIRE_THAT( needs_adl1, UnorderedRangeEquals( needs_adl2 ) )
|
||||
with expansion:
|
||||
{ 1, 2, 3, 4, 5 } unordered elements are { 1, 2, 3, 4, 5 }
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
Usage of the SizeIs range matcher
|
||||
Some with stdlib containers
|
||||
@@ -18103,6 +18231,6 @@ Misc.tests.cpp:<line number>
|
||||
Misc.tests.cpp:<line number>: PASSED:
|
||||
|
||||
===============================================================================
|
||||
test cases: 408 | 308 passed | 84 failed | 5 skipped | 11 failed as expected
|
||||
assertions: 2210 | 2033 passed | 145 failed | 32 failed as expected
|
||||
test cases: 409 | 309 passed | 84 failed | 5 skipped | 11 failed as expected
|
||||
assertions: 2226 | 2049 passed | 145 failed | 32 failed as expected
|
||||
|
||||
|
@@ -4475,6 +4475,15 @@ Misc.tests.cpp:<line number>: PASSED:
|
||||
with expansion:
|
||||
3628800 (0x<hex digits>) == 3628800 (0x<hex digits>)
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
Filter generator throws exception for empty generator
|
||||
-------------------------------------------------------------------------------
|
||||
GeneratorsImpl.tests.cpp:<line number>
|
||||
...............................................................................
|
||||
|
||||
GeneratorsImpl.tests.cpp:<line number>: PASSED:
|
||||
REQUIRE_THROWS_AS( filter( []( int ) { return false; }, value( 3 ) ), Catch::GeneratorException )
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
Floating point matchers: double
|
||||
Relative
|
||||
@@ -4660,6 +4669,18 @@ Matchers.tests.cpp:<line number>: PASSED:
|
||||
Matchers.tests.cpp:<line number>: PASSED:
|
||||
REQUIRE_THROWS_AS( WithinRel( 1., 1. ), std::domain_error )
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
Floating point matchers: double
|
||||
IsNaN
|
||||
-------------------------------------------------------------------------------
|
||||
Matchers.tests.cpp:<line number>
|
||||
...............................................................................
|
||||
|
||||
Matchers.tests.cpp:<line number>: PASSED:
|
||||
REQUIRE_THAT( 1., !IsNaN() )
|
||||
with expansion:
|
||||
1.0 not is NaN
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
Floating point matchers: float
|
||||
Relative
|
||||
@@ -4853,6 +4874,18 @@ Matchers.tests.cpp:<line number>: PASSED:
|
||||
Matchers.tests.cpp:<line number>: PASSED:
|
||||
REQUIRE_THROWS_AS( WithinRel( 1.f, 1.f ), std::domain_error )
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
Floating point matchers: float
|
||||
IsNaN
|
||||
-------------------------------------------------------------------------------
|
||||
Matchers.tests.cpp:<line number>
|
||||
...............................................................................
|
||||
|
||||
Matchers.tests.cpp:<line number>: PASSED:
|
||||
REQUIRE_THAT( 1., !IsNaN() )
|
||||
with expansion:
|
||||
1.0 not is NaN
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
Generators -- adapters
|
||||
Filtering by predicate
|
||||
@@ -14222,6 +14255,89 @@ MatchersRanges.tests.cpp:<line number>: PASSED:
|
||||
with expansion:
|
||||
{ 1, 2, 3 } not elements are { 3, 3, 4 }
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
Usage of RangeEquals range matcher
|
||||
Ranges that need ADL begin/end
|
||||
-------------------------------------------------------------------------------
|
||||
MatchersRanges.tests.cpp:<line number>
|
||||
...............................................................................
|
||||
|
||||
MatchersRanges.tests.cpp:<line number>: PASSED:
|
||||
REQUIRE_THAT( needs_adl1, RangeEquals( needs_adl2 ) )
|
||||
with expansion:
|
||||
{ 1, 2, 3, 4, 5 } elements are { 1, 2, 3, 4, 5 }
|
||||
|
||||
MatchersRanges.tests.cpp:<line number>: PASSED:
|
||||
REQUIRE_THAT( needs_adl1, RangeEquals( needs_adl3, []( int l, int r ) { return l + 1 == r; } ) )
|
||||
with expansion:
|
||||
{ 1, 2, 3, 4, 5 } elements are { 2, 3, 4, 5, 6 }
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
Usage of RangeEquals range matcher
|
||||
Check short-circuiting behaviour
|
||||
Check short-circuits on failure
|
||||
-------------------------------------------------------------------------------
|
||||
MatchersRanges.tests.cpp:<line number>
|
||||
...............................................................................
|
||||
|
||||
MatchersRanges.tests.cpp:<line number>: PASSED:
|
||||
REQUIRE_THAT( mocked1, !RangeEquals( arr ) )
|
||||
with expansion:
|
||||
{ 1, 2, 3, 4 } not elements are { 1, 2, 4, 4 }
|
||||
|
||||
MatchersRanges.tests.cpp:<line number>: PASSED:
|
||||
REQUIRE( mocked1.m_derefed[0] )
|
||||
with expansion:
|
||||
true
|
||||
|
||||
MatchersRanges.tests.cpp:<line number>: PASSED:
|
||||
REQUIRE( mocked1.m_derefed[1] )
|
||||
with expansion:
|
||||
true
|
||||
|
||||
MatchersRanges.tests.cpp:<line number>: PASSED:
|
||||
REQUIRE( mocked1.m_derefed[2] )
|
||||
with expansion:
|
||||
true
|
||||
|
||||
MatchersRanges.tests.cpp:<line number>: PASSED:
|
||||
REQUIRE_FALSE( mocked1.m_derefed[3] )
|
||||
with expansion:
|
||||
!false
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
Usage of RangeEquals range matcher
|
||||
Check short-circuiting behaviour
|
||||
All elements are checked on success
|
||||
-------------------------------------------------------------------------------
|
||||
MatchersRanges.tests.cpp:<line number>
|
||||
...............................................................................
|
||||
|
||||
MatchersRanges.tests.cpp:<line number>: PASSED:
|
||||
REQUIRE_THAT( mocked1, RangeEquals( arr ) )
|
||||
with expansion:
|
||||
{ 1, 2, 3, 4 } elements are { 1, 2, 3, 4 }
|
||||
|
||||
MatchersRanges.tests.cpp:<line number>: PASSED:
|
||||
REQUIRE( mocked1.m_derefed[0] )
|
||||
with expansion:
|
||||
true
|
||||
|
||||
MatchersRanges.tests.cpp:<line number>: PASSED:
|
||||
REQUIRE( mocked1.m_derefed[1] )
|
||||
with expansion:
|
||||
true
|
||||
|
||||
MatchersRanges.tests.cpp:<line number>: PASSED:
|
||||
REQUIRE( mocked1.m_derefed[2] )
|
||||
with expansion:
|
||||
true
|
||||
|
||||
MatchersRanges.tests.cpp:<line number>: PASSED:
|
||||
REQUIRE( mocked1.m_derefed[3] )
|
||||
with expansion:
|
||||
true
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
Usage of UnorderedRangeEquals range matcher
|
||||
Basic usage
|
||||
@@ -14331,6 +14447,18 @@ MatchersRanges.tests.cpp:<line number>: PASSED:
|
||||
with expansion:
|
||||
{ 1, 10, 21 } not unordered elements are { 11, 21, 3 }
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
Usage of UnorderedRangeEquals range matcher
|
||||
Ranges that need ADL begin/end
|
||||
-------------------------------------------------------------------------------
|
||||
MatchersRanges.tests.cpp:<line number>
|
||||
...............................................................................
|
||||
|
||||
MatchersRanges.tests.cpp:<line number>: PASSED:
|
||||
REQUIRE_THAT( needs_adl1, UnorderedRangeEquals( needs_adl2 ) )
|
||||
with expansion:
|
||||
{ 1, 2, 3, 4, 5 } unordered elements are { 1, 2, 3, 4, 5 }
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
Usage of the SizeIs range matcher
|
||||
Some with stdlib containers
|
||||
@@ -18092,6 +18220,6 @@ Misc.tests.cpp:<line number>
|
||||
Misc.tests.cpp:<line number>: PASSED:
|
||||
|
||||
===============================================================================
|
||||
test cases: 408 | 308 passed | 84 failed | 5 skipped | 11 failed as expected
|
||||
assertions: 2210 | 2033 passed | 145 failed | 32 failed as expected
|
||||
test cases: 409 | 309 passed | 84 failed | 5 skipped | 11 failed as expected
|
||||
assertions: 2226 | 2049 passed | 145 failed | 32 failed as expected
|
||||
|
||||
|
@@ -1,7 +1,7 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<testsuitesloose text artifact
|
||||
>
|
||||
<testsuite name="<exe-name>" errors="17" failures="128" skipped="11" tests="2221" hostname="tbd" time="{duration}" timestamp="{iso8601-timestamp}">
|
||||
<testsuite name="<exe-name>" errors="17" failures="128" skipped="11" tests="2237" hostname="tbd" time="{duration}" timestamp="{iso8601-timestamp}">
|
||||
<properties>
|
||||
<property name="random-seed" value="1"/>
|
||||
<property name="filters" value=""*" ~[!nonportable] ~[!benchmark] ~[approvals]"/>
|
||||
@@ -687,18 +687,21 @@ at Message.tests.cpp:<line number>
|
||||
</failure>
|
||||
</testcase>
|
||||
<testcase classname="<exe-name>.global" name="Factorials are computed" time="{duration}" status="run"/>
|
||||
<testcase classname="<exe-name>.global" name="Filter generator throws exception for empty generator" time="{duration}" status="run"/>
|
||||
<testcase classname="<exe-name>.global" name="Floating point matchers: double/Relative" time="{duration}" status="run"/>
|
||||
<testcase classname="<exe-name>.global" name="Floating point matchers: double/Relative/Some subnormal values" time="{duration}" status="run"/>
|
||||
<testcase classname="<exe-name>.global" name="Floating point matchers: double/Margin" time="{duration}" status="run"/>
|
||||
<testcase classname="<exe-name>.global" name="Floating point matchers: double/ULPs" time="{duration}" status="run"/>
|
||||
<testcase classname="<exe-name>.global" name="Floating point matchers: double/Composed" time="{duration}" status="run"/>
|
||||
<testcase classname="<exe-name>.global" name="Floating point matchers: double/Constructor validation" time="{duration}" status="run"/>
|
||||
<testcase classname="<exe-name>.global" name="Floating point matchers: double/IsNaN" time="{duration}" status="run"/>
|
||||
<testcase classname="<exe-name>.global" name="Floating point matchers: float/Relative" time="{duration}" status="run"/>
|
||||
<testcase classname="<exe-name>.global" name="Floating point matchers: float/Relative/Some subnormal values" time="{duration}" status="run"/>
|
||||
<testcase classname="<exe-name>.global" name="Floating point matchers: float/Margin" time="{duration}" status="run"/>
|
||||
<testcase classname="<exe-name>.global" name="Floating point matchers: float/ULPs" time="{duration}" status="run"/>
|
||||
<testcase classname="<exe-name>.global" name="Floating point matchers: float/Composed" time="{duration}" status="run"/>
|
||||
<testcase classname="<exe-name>.global" name="Floating point matchers: float/Constructor validation" time="{duration}" status="run"/>
|
||||
<testcase classname="<exe-name>.global" name="Floating point matchers: float/IsNaN" time="{duration}" status="run"/>
|
||||
<testcase classname="<exe-name>.global" name="Generators -- adapters/Filtering by predicate/Basic usage" time="{duration}" status="run"/>
|
||||
<testcase classname="<exe-name>.global" name="Generators -- adapters/Filtering by predicate/Throws if there are no matching values" time="{duration}" status="run"/>
|
||||
<testcase classname="<exe-name>.global" name="Generators -- adapters/Shortening a range" time="{duration}" status="run"/>
|
||||
@@ -1439,6 +1442,9 @@ at Exception.tests.cpp:<line number>
|
||||
<testcase classname="<exe-name>.global" name="Usage of RangeEquals range matcher/Basic usage/Two non-equal-sized, non-empty containers (with same first elements)" time="{duration}" status="run"/>
|
||||
<testcase classname="<exe-name>.global" name="Usage of RangeEquals range matcher/Custom predicate/Two equal non-empty containers (close enough)" time="{duration}" status="run"/>
|
||||
<testcase classname="<exe-name>.global" name="Usage of RangeEquals range matcher/Custom predicate/Two non-equal non-empty containers (close enough)" time="{duration}" status="run"/>
|
||||
<testcase classname="<exe-name>.global" name="Usage of RangeEquals range matcher/Ranges that need ADL begin/end" time="{duration}" status="run"/>
|
||||
<testcase classname="<exe-name>.global" name="Usage of RangeEquals range matcher/Check short-circuiting behaviour/Check short-circuits on failure" time="{duration}" status="run"/>
|
||||
<testcase classname="<exe-name>.global" name="Usage of RangeEquals range matcher/Check short-circuiting behaviour/All elements are checked on success" time="{duration}" status="run"/>
|
||||
<testcase classname="<exe-name>.global" name="Usage of UnorderedRangeEquals range matcher/Basic usage/Empty container matches empty container" time="{duration}" status="run"/>
|
||||
<testcase classname="<exe-name>.global" name="Usage of UnorderedRangeEquals range matcher/Basic usage/Empty container does not match non-empty container" time="{duration}" status="run"/>
|
||||
<testcase classname="<exe-name>.global" name="Usage of UnorderedRangeEquals range matcher/Basic usage/Two equal 1-length non-empty containers" time="{duration}" status="run"/>
|
||||
@@ -1447,6 +1453,7 @@ at Exception.tests.cpp:<line number>
|
||||
<testcase classname="<exe-name>.global" name="Usage of UnorderedRangeEquals range matcher/Basic usage/Two non-equal-sized, non-empty containers" time="{duration}" status="run"/>
|
||||
<testcase classname="<exe-name>.global" name="Usage of UnorderedRangeEquals range matcher/Custom predicate/Two equal non-empty containers (close enough)" time="{duration}" status="run"/>
|
||||
<testcase classname="<exe-name>.global" name="Usage of UnorderedRangeEquals range matcher/Custom predicate/Two non-equal non-empty containers (close enough)" time="{duration}" status="run"/>
|
||||
<testcase classname="<exe-name>.global" name="Usage of UnorderedRangeEquals range matcher/Ranges that need ADL begin/end" time="{duration}" status="run"/>
|
||||
<testcase classname="<exe-name>.global" name="Usage of the SizeIs range matcher/Some with stdlib containers" time="{duration}" status="run"/>
|
||||
<testcase classname="<exe-name>.global" name="Usage of the SizeIs range matcher/Type requires ADL found size free function" time="{duration}" status="run"/>
|
||||
<testcase classname="<exe-name>.global" name="Usage of the SizeIs range matcher/Type has size member" time="{duration}" status="run"/>
|
||||
|
@@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<testsuites>
|
||||
<testsuite name="<exe-name>" errors="17" failures="128" skipped="11" tests="2221" hostname="tbd" time="{duration}" timestamp="{iso8601-timestamp}">
|
||||
<testsuite name="<exe-name>" errors="17" failures="128" skipped="11" tests="2237" hostname="tbd" time="{duration}" timestamp="{iso8601-timestamp}">
|
||||
<properties>
|
||||
<property name="random-seed" value="1"/>
|
||||
<property name="filters" value=""*" ~[!nonportable] ~[!benchmark] ~[approvals]"/>
|
||||
@@ -686,18 +686,21 @@ at Message.tests.cpp:<line number>
|
||||
</failure>
|
||||
</testcase>
|
||||
<testcase classname="<exe-name>.global" name="Factorials are computed" time="{duration}" status="run"/>
|
||||
<testcase classname="<exe-name>.global" name="Filter generator throws exception for empty generator" time="{duration}" status="run"/>
|
||||
<testcase classname="<exe-name>.global" name="Floating point matchers: double/Relative" time="{duration}" status="run"/>
|
||||
<testcase classname="<exe-name>.global" name="Floating point matchers: double/Relative/Some subnormal values" time="{duration}" status="run"/>
|
||||
<testcase classname="<exe-name>.global" name="Floating point matchers: double/Margin" time="{duration}" status="run"/>
|
||||
<testcase classname="<exe-name>.global" name="Floating point matchers: double/ULPs" time="{duration}" status="run"/>
|
||||
<testcase classname="<exe-name>.global" name="Floating point matchers: double/Composed" time="{duration}" status="run"/>
|
||||
<testcase classname="<exe-name>.global" name="Floating point matchers: double/Constructor validation" time="{duration}" status="run"/>
|
||||
<testcase classname="<exe-name>.global" name="Floating point matchers: double/IsNaN" time="{duration}" status="run"/>
|
||||
<testcase classname="<exe-name>.global" name="Floating point matchers: float/Relative" time="{duration}" status="run"/>
|
||||
<testcase classname="<exe-name>.global" name="Floating point matchers: float/Relative/Some subnormal values" time="{duration}" status="run"/>
|
||||
<testcase classname="<exe-name>.global" name="Floating point matchers: float/Margin" time="{duration}" status="run"/>
|
||||
<testcase classname="<exe-name>.global" name="Floating point matchers: float/ULPs" time="{duration}" status="run"/>
|
||||
<testcase classname="<exe-name>.global" name="Floating point matchers: float/Composed" time="{duration}" status="run"/>
|
||||
<testcase classname="<exe-name>.global" name="Floating point matchers: float/Constructor validation" time="{duration}" status="run"/>
|
||||
<testcase classname="<exe-name>.global" name="Floating point matchers: float/IsNaN" time="{duration}" status="run"/>
|
||||
<testcase classname="<exe-name>.global" name="Generators -- adapters/Filtering by predicate/Basic usage" time="{duration}" status="run"/>
|
||||
<testcase classname="<exe-name>.global" name="Generators -- adapters/Filtering by predicate/Throws if there are no matching values" time="{duration}" status="run"/>
|
||||
<testcase classname="<exe-name>.global" name="Generators -- adapters/Shortening a range" time="{duration}" status="run"/>
|
||||
@@ -1438,6 +1441,9 @@ at Exception.tests.cpp:<line number>
|
||||
<testcase classname="<exe-name>.global" name="Usage of RangeEquals range matcher/Basic usage/Two non-equal-sized, non-empty containers (with same first elements)" time="{duration}" status="run"/>
|
||||
<testcase classname="<exe-name>.global" name="Usage of RangeEquals range matcher/Custom predicate/Two equal non-empty containers (close enough)" time="{duration}" status="run"/>
|
||||
<testcase classname="<exe-name>.global" name="Usage of RangeEquals range matcher/Custom predicate/Two non-equal non-empty containers (close enough)" time="{duration}" status="run"/>
|
||||
<testcase classname="<exe-name>.global" name="Usage of RangeEquals range matcher/Ranges that need ADL begin/end" time="{duration}" status="run"/>
|
||||
<testcase classname="<exe-name>.global" name="Usage of RangeEquals range matcher/Check short-circuiting behaviour/Check short-circuits on failure" time="{duration}" status="run"/>
|
||||
<testcase classname="<exe-name>.global" name="Usage of RangeEquals range matcher/Check short-circuiting behaviour/All elements are checked on success" time="{duration}" status="run"/>
|
||||
<testcase classname="<exe-name>.global" name="Usage of UnorderedRangeEquals range matcher/Basic usage/Empty container matches empty container" time="{duration}" status="run"/>
|
||||
<testcase classname="<exe-name>.global" name="Usage of UnorderedRangeEquals range matcher/Basic usage/Empty container does not match non-empty container" time="{duration}" status="run"/>
|
||||
<testcase classname="<exe-name>.global" name="Usage of UnorderedRangeEquals range matcher/Basic usage/Two equal 1-length non-empty containers" time="{duration}" status="run"/>
|
||||
@@ -1446,6 +1452,7 @@ at Exception.tests.cpp:<line number>
|
||||
<testcase classname="<exe-name>.global" name="Usage of UnorderedRangeEquals range matcher/Basic usage/Two non-equal-sized, non-empty containers" time="{duration}" status="run"/>
|
||||
<testcase classname="<exe-name>.global" name="Usage of UnorderedRangeEquals range matcher/Custom predicate/Two equal non-empty containers (close enough)" time="{duration}" status="run"/>
|
||||
<testcase classname="<exe-name>.global" name="Usage of UnorderedRangeEquals range matcher/Custom predicate/Two non-equal non-empty containers (close enough)" time="{duration}" status="run"/>
|
||||
<testcase classname="<exe-name>.global" name="Usage of UnorderedRangeEquals range matcher/Ranges that need ADL begin/end" time="{duration}" status="run"/>
|
||||
<testcase classname="<exe-name>.global" name="Usage of the SizeIs range matcher/Some with stdlib containers" time="{duration}" status="run"/>
|
||||
<testcase classname="<exe-name>.global" name="Usage of the SizeIs range matcher/Type requires ADL found size free function" time="{duration}" status="run"/>
|
||||
<testcase classname="<exe-name>.global" name="Usage of the SizeIs range matcher/Type has size member" time="{duration}" status="run"/>
|
||||
|
@@ -71,6 +71,7 @@
|
||||
<testCase name="convertToBits" duration="{duration}"/>
|
||||
</file>
|
||||
<file path="tests/<exe-name>/IntrospectiveTests/GeneratorsImpl.tests.cpp">
|
||||
<testCase name="Filter generator throws exception for empty generator" duration="{duration}"/>
|
||||
<testCase name="Generators internals/Single value" duration="{duration}"/>
|
||||
<testCase name="Generators internals/Preset values" duration="{duration}"/>
|
||||
<testCase name="Generators internals/Generator combinator" duration="{duration}"/>
|
||||
@@ -1171,12 +1172,14 @@ at Matchers.tests.cpp:<line number>
|
||||
<testCase name="Floating point matchers: double/ULPs" duration="{duration}"/>
|
||||
<testCase name="Floating point matchers: double/Composed" duration="{duration}"/>
|
||||
<testCase name="Floating point matchers: double/Constructor validation" duration="{duration}"/>
|
||||
<testCase name="Floating point matchers: double/IsNaN" duration="{duration}"/>
|
||||
<testCase name="Floating point matchers: float/Relative" duration="{duration}"/>
|
||||
<testCase name="Floating point matchers: float/Relative/Some subnormal values" duration="{duration}"/>
|
||||
<testCase name="Floating point matchers: float/Margin" duration="{duration}"/>
|
||||
<testCase name="Floating point matchers: float/ULPs" duration="{duration}"/>
|
||||
<testCase name="Floating point matchers: float/Composed" duration="{duration}"/>
|
||||
<testCase name="Floating point matchers: float/Constructor validation" duration="{duration}"/>
|
||||
<testCase name="Floating point matchers: float/IsNaN" duration="{duration}"/>
|
||||
<testCase name="Matchers can be (AllOf) composed with the && operator" duration="{duration}"/>
|
||||
<testCase name="Matchers can be (AnyOf) composed with the || operator" duration="{duration}"/>
|
||||
<testCase name="Matchers can be composed with both && and ||" duration="{duration}"/>
|
||||
@@ -1427,6 +1430,9 @@ at Matchers.tests.cpp:<line number>
|
||||
<testCase name="Usage of RangeEquals range matcher/Basic usage/Two non-equal-sized, non-empty containers (with same first elements)" duration="{duration}"/>
|
||||
<testCase name="Usage of RangeEquals range matcher/Custom predicate/Two equal non-empty containers (close enough)" duration="{duration}"/>
|
||||
<testCase name="Usage of RangeEquals range matcher/Custom predicate/Two non-equal non-empty containers (close enough)" duration="{duration}"/>
|
||||
<testCase name="Usage of RangeEquals range matcher/Ranges that need ADL begin/end" duration="{duration}"/>
|
||||
<testCase name="Usage of RangeEquals range matcher/Check short-circuiting behaviour/Check short-circuits on failure" duration="{duration}"/>
|
||||
<testCase name="Usage of RangeEquals range matcher/Check short-circuiting behaviour/All elements are checked on success" duration="{duration}"/>
|
||||
<testCase name="Usage of UnorderedRangeEquals range matcher/Basic usage/Empty container matches empty container" duration="{duration}"/>
|
||||
<testCase name="Usage of UnorderedRangeEquals range matcher/Basic usage/Empty container does not match non-empty container" duration="{duration}"/>
|
||||
<testCase name="Usage of UnorderedRangeEquals range matcher/Basic usage/Two equal 1-length non-empty containers" duration="{duration}"/>
|
||||
@@ -1435,6 +1441,7 @@ at Matchers.tests.cpp:<line number>
|
||||
<testCase name="Usage of UnorderedRangeEquals range matcher/Basic usage/Two non-equal-sized, non-empty containers" duration="{duration}"/>
|
||||
<testCase name="Usage of UnorderedRangeEquals range matcher/Custom predicate/Two equal non-empty containers (close enough)" duration="{duration}"/>
|
||||
<testCase name="Usage of UnorderedRangeEquals range matcher/Custom predicate/Two non-equal non-empty containers (close enough)" duration="{duration}"/>
|
||||
<testCase name="Usage of UnorderedRangeEquals range matcher/Ranges that need ADL begin/end" duration="{duration}"/>
|
||||
<testCase name="Usage of the SizeIs range matcher/Some with stdlib containers" duration="{duration}"/>
|
||||
<testCase name="Usage of the SizeIs range matcher/Type requires ADL found size free function" duration="{duration}"/>
|
||||
<testCase name="Usage of the SizeIs range matcher/Type has size member" duration="{duration}"/>
|
||||
|
@@ -70,6 +70,7 @@
|
||||
<testCase name="convertToBits" duration="{duration}"/>
|
||||
</file>
|
||||
<file path="tests/<exe-name>/IntrospectiveTests/GeneratorsImpl.tests.cpp">
|
||||
<testCase name="Filter generator throws exception for empty generator" duration="{duration}"/>
|
||||
<testCase name="Generators internals/Single value" duration="{duration}"/>
|
||||
<testCase name="Generators internals/Preset values" duration="{duration}"/>
|
||||
<testCase name="Generators internals/Generator combinator" duration="{duration}"/>
|
||||
@@ -1170,12 +1171,14 @@ at Matchers.tests.cpp:<line number>
|
||||
<testCase name="Floating point matchers: double/ULPs" duration="{duration}"/>
|
||||
<testCase name="Floating point matchers: double/Composed" duration="{duration}"/>
|
||||
<testCase name="Floating point matchers: double/Constructor validation" duration="{duration}"/>
|
||||
<testCase name="Floating point matchers: double/IsNaN" duration="{duration}"/>
|
||||
<testCase name="Floating point matchers: float/Relative" duration="{duration}"/>
|
||||
<testCase name="Floating point matchers: float/Relative/Some subnormal values" duration="{duration}"/>
|
||||
<testCase name="Floating point matchers: float/Margin" duration="{duration}"/>
|
||||
<testCase name="Floating point matchers: float/ULPs" duration="{duration}"/>
|
||||
<testCase name="Floating point matchers: float/Composed" duration="{duration}"/>
|
||||
<testCase name="Floating point matchers: float/Constructor validation" duration="{duration}"/>
|
||||
<testCase name="Floating point matchers: float/IsNaN" duration="{duration}"/>
|
||||
<testCase name="Matchers can be (AllOf) composed with the && operator" duration="{duration}"/>
|
||||
<testCase name="Matchers can be (AnyOf) composed with the || operator" duration="{duration}"/>
|
||||
<testCase name="Matchers can be composed with both && and ||" duration="{duration}"/>
|
||||
@@ -1426,6 +1429,9 @@ at Matchers.tests.cpp:<line number>
|
||||
<testCase name="Usage of RangeEquals range matcher/Basic usage/Two non-equal-sized, non-empty containers (with same first elements)" duration="{duration}"/>
|
||||
<testCase name="Usage of RangeEquals range matcher/Custom predicate/Two equal non-empty containers (close enough)" duration="{duration}"/>
|
||||
<testCase name="Usage of RangeEquals range matcher/Custom predicate/Two non-equal non-empty containers (close enough)" duration="{duration}"/>
|
||||
<testCase name="Usage of RangeEquals range matcher/Ranges that need ADL begin/end" duration="{duration}"/>
|
||||
<testCase name="Usage of RangeEquals range matcher/Check short-circuiting behaviour/Check short-circuits on failure" duration="{duration}"/>
|
||||
<testCase name="Usage of RangeEquals range matcher/Check short-circuiting behaviour/All elements are checked on success" duration="{duration}"/>
|
||||
<testCase name="Usage of UnorderedRangeEquals range matcher/Basic usage/Empty container matches empty container" duration="{duration}"/>
|
||||
<testCase name="Usage of UnorderedRangeEquals range matcher/Basic usage/Empty container does not match non-empty container" duration="{duration}"/>
|
||||
<testCase name="Usage of UnorderedRangeEquals range matcher/Basic usage/Two equal 1-length non-empty containers" duration="{duration}"/>
|
||||
@@ -1434,6 +1440,7 @@ at Matchers.tests.cpp:<line number>
|
||||
<testCase name="Usage of UnorderedRangeEquals range matcher/Basic usage/Two non-equal-sized, non-empty containers" duration="{duration}"/>
|
||||
<testCase name="Usage of UnorderedRangeEquals range matcher/Custom predicate/Two equal non-empty containers (close enough)" duration="{duration}"/>
|
||||
<testCase name="Usage of UnorderedRangeEquals range matcher/Custom predicate/Two non-equal non-empty containers (close enough)" duration="{duration}"/>
|
||||
<testCase name="Usage of UnorderedRangeEquals range matcher/Ranges that need ADL begin/end" duration="{duration}"/>
|
||||
<testCase name="Usage of the SizeIs range matcher/Some with stdlib containers" duration="{duration}"/>
|
||||
<testCase name="Usage of the SizeIs range matcher/Type requires ADL found size free function" duration="{duration}"/>
|
||||
<testCase name="Usage of the SizeIs range matcher/Type has size member" duration="{duration}"/>
|
||||
|
@@ -1130,6 +1130,8 @@ ok {test-number} - Factorial(2) == 2 for: 2 == 2
|
||||
ok {test-number} - Factorial(3) == 6 for: 6 == 6
|
||||
# Factorials are computed
|
||||
ok {test-number} - Factorial(10) == 3628800 for: 3628800 (0x<hex digits>) == 3628800 (0x<hex digits>)
|
||||
# Filter generator throws exception for empty generator
|
||||
ok {test-number} - filter( []( int ) { return false; }, value( 3 ) ), Catch::GeneratorException
|
||||
# Floating point matchers: double
|
||||
ok {test-number} - 10., WithinRel( 11.1, 0.1 ) for: 10.0 and 11.1 are within 10% of each other
|
||||
# Floating point matchers: double
|
||||
@@ -1188,6 +1190,8 @@ ok {test-number} - WithinRel( 1., 0. )
|
||||
ok {test-number} - WithinRel( 1., -0.2 ), std::domain_error
|
||||
# Floating point matchers: double
|
||||
ok {test-number} - WithinRel( 1., 1. ), std::domain_error
|
||||
# Floating point matchers: double
|
||||
ok {test-number} - 1., !IsNaN() for: 1.0 not is NaN
|
||||
# Floating point matchers: float
|
||||
ok {test-number} - 10.f, WithinRel( 11.1f, 0.1f ) for: 10.0f and 11.1 are within 10% of each other
|
||||
# Floating point matchers: float
|
||||
@@ -1252,6 +1256,8 @@ ok {test-number} - WithinRel( 1.f, 0.f )
|
||||
ok {test-number} - WithinRel( 1.f, -0.2f ), std::domain_error
|
||||
# Floating point matchers: float
|
||||
ok {test-number} - WithinRel( 1.f, 1.f ), std::domain_error
|
||||
# Floating point matchers: float
|
||||
ok {test-number} - 1., !IsNaN() for: 1.0 not is NaN
|
||||
# Generators -- adapters
|
||||
ok {test-number} - i % 2 == 0 for: 0 == 0
|
||||
# Generators -- adapters
|
||||
@@ -3489,6 +3495,30 @@ ok {test-number} - vector_a, !RangeEquals( vector_b ) for: { 1, 2, 3 } not eleme
|
||||
ok {test-number} - vector_a, RangeEquals( vector_a_plus_1, close_enough ) for: { 1, 2, 3 } elements are { 2, 3, 4 }
|
||||
# Usage of RangeEquals range matcher
|
||||
ok {test-number} - vector_a, !RangeEquals( vector_b, close_enough ) for: { 1, 2, 3 } not elements are { 3, 3, 4 }
|
||||
# Usage of RangeEquals range matcher
|
||||
ok {test-number} - needs_adl1, RangeEquals( needs_adl2 ) for: { 1, 2, 3, 4, 5 } elements are { 1, 2, 3, 4, 5 }
|
||||
# Usage of RangeEquals range matcher
|
||||
ok {test-number} - needs_adl1, RangeEquals( needs_adl3, []( int l, int r ) { return l + 1 == r; } ) for: { 1, 2, 3, 4, 5 } elements are { 2, 3, 4, 5, 6 }
|
||||
# Usage of RangeEquals range matcher
|
||||
ok {test-number} - mocked1, !RangeEquals( arr ) for: { 1, 2, 3, 4 } not elements are { 1, 2, 4, 4 }
|
||||
# Usage of RangeEquals range matcher
|
||||
ok {test-number} - mocked1.m_derefed[0] for: true
|
||||
# Usage of RangeEquals range matcher
|
||||
ok {test-number} - mocked1.m_derefed[1] for: true
|
||||
# Usage of RangeEquals range matcher
|
||||
ok {test-number} - mocked1.m_derefed[2] for: true
|
||||
# Usage of RangeEquals range matcher
|
||||
ok {test-number} - !(mocked1.m_derefed[3]) for: !false
|
||||
# Usage of RangeEquals range matcher
|
||||
ok {test-number} - mocked1, RangeEquals( arr ) for: { 1, 2, 3, 4 } elements are { 1, 2, 3, 4 }
|
||||
# Usage of RangeEquals range matcher
|
||||
ok {test-number} - mocked1.m_derefed[0] for: true
|
||||
# Usage of RangeEquals range matcher
|
||||
ok {test-number} - mocked1.m_derefed[1] for: true
|
||||
# Usage of RangeEquals range matcher
|
||||
ok {test-number} - mocked1.m_derefed[2] for: true
|
||||
# Usage of RangeEquals range matcher
|
||||
ok {test-number} - mocked1.m_derefed[3] for: true
|
||||
# Usage of UnorderedRangeEquals range matcher
|
||||
ok {test-number} - empty_vector, UnorderedRangeEquals( empty_vector ) for: { } unordered elements are { }
|
||||
# Usage of UnorderedRangeEquals range matcher
|
||||
@@ -3507,6 +3537,8 @@ ok {test-number} - vector_a, !UnorderedRangeEquals( vector_b ) for: { 1, 2, 3 }
|
||||
ok {test-number} - vector_a, UnorderedRangeEquals( vector_a_plus_1, close_enough ) for: { 1, 10, 20 } unordered elements are { 11, 21, 2 }
|
||||
# Usage of UnorderedRangeEquals range matcher
|
||||
ok {test-number} - vector_a, !UnorderedRangeEquals( vector_b, close_enough ) for: { 1, 10, 21 } not unordered elements are { 11, 21, 3 }
|
||||
# Usage of UnorderedRangeEquals range matcher
|
||||
ok {test-number} - needs_adl1, UnorderedRangeEquals( needs_adl2 ) for: { 1, 2, 3, 4, 5 } unordered elements are { 1, 2, 3, 4, 5 }
|
||||
# Usage of the SizeIs range matcher
|
||||
ok {test-number} - empty_vec, SizeIs(0) for: { } has size == 0
|
||||
# Usage of the SizeIs range matcher
|
||||
@@ -4445,5 +4477,5 @@ ok {test-number} - q3 == 23. for: 23.0 == 23.0
|
||||
ok {test-number} -
|
||||
# xmlentitycheck
|
||||
ok {test-number} -
|
||||
1..2221
|
||||
1..2237
|
||||
|
||||
|
@@ -1128,6 +1128,8 @@ ok {test-number} - Factorial(2) == 2 for: 2 == 2
|
||||
ok {test-number} - Factorial(3) == 6 for: 6 == 6
|
||||
# Factorials are computed
|
||||
ok {test-number} - Factorial(10) == 3628800 for: 3628800 (0x<hex digits>) == 3628800 (0x<hex digits>)
|
||||
# Filter generator throws exception for empty generator
|
||||
ok {test-number} - filter( []( int ) { return false; }, value( 3 ) ), Catch::GeneratorException
|
||||
# Floating point matchers: double
|
||||
ok {test-number} - 10., WithinRel( 11.1, 0.1 ) for: 10.0 and 11.1 are within 10% of each other
|
||||
# Floating point matchers: double
|
||||
@@ -1186,6 +1188,8 @@ ok {test-number} - WithinRel( 1., 0. )
|
||||
ok {test-number} - WithinRel( 1., -0.2 ), std::domain_error
|
||||
# Floating point matchers: double
|
||||
ok {test-number} - WithinRel( 1., 1. ), std::domain_error
|
||||
# Floating point matchers: double
|
||||
ok {test-number} - 1., !IsNaN() for: 1.0 not is NaN
|
||||
# Floating point matchers: float
|
||||
ok {test-number} - 10.f, WithinRel( 11.1f, 0.1f ) for: 10.0f and 11.1 are within 10% of each other
|
||||
# Floating point matchers: float
|
||||
@@ -1250,6 +1254,8 @@ ok {test-number} - WithinRel( 1.f, 0.f )
|
||||
ok {test-number} - WithinRel( 1.f, -0.2f ), std::domain_error
|
||||
# Floating point matchers: float
|
||||
ok {test-number} - WithinRel( 1.f, 1.f ), std::domain_error
|
||||
# Floating point matchers: float
|
||||
ok {test-number} - 1., !IsNaN() for: 1.0 not is NaN
|
||||
# Generators -- adapters
|
||||
ok {test-number} - i % 2 == 0 for: 0 == 0
|
||||
# Generators -- adapters
|
||||
@@ -3482,6 +3488,30 @@ ok {test-number} - vector_a, !RangeEquals( vector_b ) for: { 1, 2, 3 } not eleme
|
||||
ok {test-number} - vector_a, RangeEquals( vector_a_plus_1, close_enough ) for: { 1, 2, 3 } elements are { 2, 3, 4 }
|
||||
# Usage of RangeEquals range matcher
|
||||
ok {test-number} - vector_a, !RangeEquals( vector_b, close_enough ) for: { 1, 2, 3 } not elements are { 3, 3, 4 }
|
||||
# Usage of RangeEquals range matcher
|
||||
ok {test-number} - needs_adl1, RangeEquals( needs_adl2 ) for: { 1, 2, 3, 4, 5 } elements are { 1, 2, 3, 4, 5 }
|
||||
# Usage of RangeEquals range matcher
|
||||
ok {test-number} - needs_adl1, RangeEquals( needs_adl3, []( int l, int r ) { return l + 1 == r; } ) for: { 1, 2, 3, 4, 5 } elements are { 2, 3, 4, 5, 6 }
|
||||
# Usage of RangeEquals range matcher
|
||||
ok {test-number} - mocked1, !RangeEquals( arr ) for: { 1, 2, 3, 4 } not elements are { 1, 2, 4, 4 }
|
||||
# Usage of RangeEquals range matcher
|
||||
ok {test-number} - mocked1.m_derefed[0] for: true
|
||||
# Usage of RangeEquals range matcher
|
||||
ok {test-number} - mocked1.m_derefed[1] for: true
|
||||
# Usage of RangeEquals range matcher
|
||||
ok {test-number} - mocked1.m_derefed[2] for: true
|
||||
# Usage of RangeEquals range matcher
|
||||
ok {test-number} - !(mocked1.m_derefed[3]) for: !false
|
||||
# Usage of RangeEquals range matcher
|
||||
ok {test-number} - mocked1, RangeEquals( arr ) for: { 1, 2, 3, 4 } elements are { 1, 2, 3, 4 }
|
||||
# Usage of RangeEquals range matcher
|
||||
ok {test-number} - mocked1.m_derefed[0] for: true
|
||||
# Usage of RangeEquals range matcher
|
||||
ok {test-number} - mocked1.m_derefed[1] for: true
|
||||
# Usage of RangeEquals range matcher
|
||||
ok {test-number} - mocked1.m_derefed[2] for: true
|
||||
# Usage of RangeEquals range matcher
|
||||
ok {test-number} - mocked1.m_derefed[3] for: true
|
||||
# Usage of UnorderedRangeEquals range matcher
|
||||
ok {test-number} - empty_vector, UnorderedRangeEquals( empty_vector ) for: { } unordered elements are { }
|
||||
# Usage of UnorderedRangeEquals range matcher
|
||||
@@ -3500,6 +3530,8 @@ ok {test-number} - vector_a, !UnorderedRangeEquals( vector_b ) for: { 1, 2, 3 }
|
||||
ok {test-number} - vector_a, UnorderedRangeEquals( vector_a_plus_1, close_enough ) for: { 1, 10, 20 } unordered elements are { 11, 21, 2 }
|
||||
# Usage of UnorderedRangeEquals range matcher
|
||||
ok {test-number} - vector_a, !UnorderedRangeEquals( vector_b, close_enough ) for: { 1, 10, 21 } not unordered elements are { 11, 21, 3 }
|
||||
# Usage of UnorderedRangeEquals range matcher
|
||||
ok {test-number} - needs_adl1, UnorderedRangeEquals( needs_adl2 ) for: { 1, 2, 3, 4, 5 } unordered elements are { 1, 2, 3, 4, 5 }
|
||||
# Usage of the SizeIs range matcher
|
||||
ok {test-number} - empty_vec, SizeIs(0) for: { } has size == 0
|
||||
# Usage of the SizeIs range matcher
|
||||
@@ -4434,5 +4466,5 @@ ok {test-number} - q3 == 23. for: 23.0 == 23.0
|
||||
ok {test-number} -
|
||||
# xmlentitycheck
|
||||
ok {test-number} -
|
||||
1..2221
|
||||
1..2237
|
||||
|
||||
|
@@ -370,6 +370,8 @@
|
||||
##teamcity[testFinished name='FAIL_CHECK does not abort the test' duration="{duration}"]
|
||||
##teamcity[testStarted name='Factorials are computed']
|
||||
##teamcity[testFinished name='Factorials are computed' duration="{duration}"]
|
||||
##teamcity[testStarted name='Filter generator throws exception for empty generator']
|
||||
##teamcity[testFinished name='Filter generator throws exception for empty generator' duration="{duration}"]
|
||||
##teamcity[testStarted name='Floating point matchers: double']
|
||||
##teamcity[testFinished name='Floating point matchers: double' duration="{duration}"]
|
||||
##teamcity[testStarted name='Floating point matchers: float']
|
||||
|
@@ -370,6 +370,8 @@
|
||||
##teamcity[testFinished name='FAIL_CHECK does not abort the test' duration="{duration}"]
|
||||
##teamcity[testStarted name='Factorials are computed']
|
||||
##teamcity[testFinished name='Factorials are computed' duration="{duration}"]
|
||||
##teamcity[testStarted name='Filter generator throws exception for empty generator']
|
||||
##teamcity[testFinished name='Filter generator throws exception for empty generator' duration="{duration}"]
|
||||
##teamcity[testStarted name='Floating point matchers: double']
|
||||
##teamcity[testFinished name='Floating point matchers: double' duration="{duration}"]
|
||||
##teamcity[testStarted name='Floating point matchers: float']
|
||||
|
@@ -5025,6 +5025,17 @@ C
|
||||
</Expression>
|
||||
<OverallResult success="true" skips="0"/>
|
||||
</TestCase>
|
||||
<TestCase name="Filter generator throws exception for empty generator" tags="[generators]" filename="tests/<exe-name>/IntrospectiveTests/GeneratorsImpl.tests.cpp" >
|
||||
<Expression success="true" type="REQUIRE_THROWS_AS" filename="tests/<exe-name>/IntrospectiveTests/GeneratorsImpl.tests.cpp" >
|
||||
<Original>
|
||||
filter( []( int ) { return false; }, value( 3 ) ), Catch::GeneratorException
|
||||
</Original>
|
||||
<Expanded>
|
||||
filter( []( int ) { return false; }, value( 3 ) ), Catch::GeneratorException
|
||||
</Expanded>
|
||||
</Expression>
|
||||
<OverallResult success="true" skips="0"/>
|
||||
</TestCase>
|
||||
<TestCase name="Floating point matchers: double" tags="[floating-point][matchers]" filename="tests/<exe-name>/UsageTests/Matchers.tests.cpp" >
|
||||
<Section name="Relative" filename="tests/<exe-name>/UsageTests/Matchers.tests.cpp" >
|
||||
<Expression success="true" type="REQUIRE_THAT" filename="tests/<exe-name>/UsageTests/Matchers.tests.cpp" >
|
||||
@@ -5276,6 +5287,17 @@ C
|
||||
</Expression>
|
||||
<OverallResults successes="6" failures="0" expectedFailures="0" skipped="false"/>
|
||||
</Section>
|
||||
<Section name="IsNaN" filename="tests/<exe-name>/UsageTests/Matchers.tests.cpp" >
|
||||
<Expression success="true" type="REQUIRE_THAT" filename="tests/<exe-name>/UsageTests/Matchers.tests.cpp" >
|
||||
<Original>
|
||||
1., !IsNaN()
|
||||
</Original>
|
||||
<Expanded>
|
||||
1.0 not is NaN
|
||||
</Expanded>
|
||||
</Expression>
|
||||
<OverallResults successes="1" failures="0" expectedFailures="0" skipped="false"/>
|
||||
</Section>
|
||||
<OverallResult success="true" skips="0"/>
|
||||
</TestCase>
|
||||
<TestCase name="Floating point matchers: float" tags="[floating-point][matchers]" filename="tests/<exe-name>/UsageTests/Matchers.tests.cpp" >
|
||||
@@ -5553,6 +5575,17 @@ C
|
||||
</Expression>
|
||||
<OverallResults successes="7" failures="0" expectedFailures="0" skipped="false"/>
|
||||
</Section>
|
||||
<Section name="IsNaN" filename="tests/<exe-name>/UsageTests/Matchers.tests.cpp" >
|
||||
<Expression success="true" type="REQUIRE_THAT" filename="tests/<exe-name>/UsageTests/Matchers.tests.cpp" >
|
||||
<Original>
|
||||
1., !IsNaN()
|
||||
</Original>
|
||||
<Expanded>
|
||||
1.0 not is NaN
|
||||
</Expanded>
|
||||
</Expression>
|
||||
<OverallResults successes="1" failures="0" expectedFailures="0" skipped="false"/>
|
||||
</Section>
|
||||
<OverallResult success="true" skips="0"/>
|
||||
</TestCase>
|
||||
<TestCase name="Generators -- adapters" tags="[generators][generic]" filename="tests/<exe-name>/UsageTests/Generators.tests.cpp" >
|
||||
@@ -16645,6 +16678,117 @@ There is no extra whitespace here
|
||||
</Section>
|
||||
<OverallResults successes="1" failures="0" expectedFailures="0" skipped="false"/>
|
||||
</Section>
|
||||
<Section name="Ranges that need ADL begin/end" filename="tests/<exe-name>/UsageTests/MatchersRanges.tests.cpp" >
|
||||
<Expression success="true" type="REQUIRE_THAT" filename="tests/<exe-name>/UsageTests/MatchersRanges.tests.cpp" >
|
||||
<Original>
|
||||
needs_adl1, RangeEquals( needs_adl2 )
|
||||
</Original>
|
||||
<Expanded>
|
||||
{ 1, 2, 3, 4, 5 } elements are { 1, 2, 3, 4, 5 }
|
||||
</Expanded>
|
||||
</Expression>
|
||||
<Expression success="true" type="REQUIRE_THAT" filename="tests/<exe-name>/UsageTests/MatchersRanges.tests.cpp" >
|
||||
<Original>
|
||||
needs_adl1, RangeEquals( needs_adl3, []( int l, int r ) { return l + 1 == r; } )
|
||||
</Original>
|
||||
<Expanded>
|
||||
{ 1, 2, 3, 4, 5 } elements are { 2, 3, 4, 5, 6 }
|
||||
</Expanded>
|
||||
</Expression>
|
||||
<OverallResults successes="2" failures="0" expectedFailures="0" skipped="false"/>
|
||||
</Section>
|
||||
<Section name="Check short-circuiting behaviour" filename="tests/<exe-name>/UsageTests/MatchersRanges.tests.cpp" >
|
||||
<Section name="Check short-circuits on failure" filename="tests/<exe-name>/UsageTests/MatchersRanges.tests.cpp" >
|
||||
<Expression success="true" type="REQUIRE_THAT" filename="tests/<exe-name>/UsageTests/MatchersRanges.tests.cpp" >
|
||||
<Original>
|
||||
mocked1, !RangeEquals( arr )
|
||||
</Original>
|
||||
<Expanded>
|
||||
{ 1, 2, 3, 4 } not elements are { 1, 2, 4, 4 }
|
||||
</Expanded>
|
||||
</Expression>
|
||||
<Expression success="true" type="REQUIRE" filename="tests/<exe-name>/UsageTests/MatchersRanges.tests.cpp" >
|
||||
<Original>
|
||||
mocked1.m_derefed[0]
|
||||
</Original>
|
||||
<Expanded>
|
||||
true
|
||||
</Expanded>
|
||||
</Expression>
|
||||
<Expression success="true" type="REQUIRE" filename="tests/<exe-name>/UsageTests/MatchersRanges.tests.cpp" >
|
||||
<Original>
|
||||
mocked1.m_derefed[1]
|
||||
</Original>
|
||||
<Expanded>
|
||||
true
|
||||
</Expanded>
|
||||
</Expression>
|
||||
<Expression success="true" type="REQUIRE" filename="tests/<exe-name>/UsageTests/MatchersRanges.tests.cpp" >
|
||||
<Original>
|
||||
mocked1.m_derefed[2]
|
||||
</Original>
|
||||
<Expanded>
|
||||
true
|
||||
</Expanded>
|
||||
</Expression>
|
||||
<Expression success="true" type="REQUIRE_FALSE" filename="tests/<exe-name>/UsageTests/MatchersRanges.tests.cpp" >
|
||||
<Original>
|
||||
!(mocked1.m_derefed[3])
|
||||
</Original>
|
||||
<Expanded>
|
||||
!false
|
||||
</Expanded>
|
||||
</Expression>
|
||||
<OverallResults successes="5" failures="0" expectedFailures="0" skipped="false"/>
|
||||
</Section>
|
||||
<OverallResults successes="5" failures="0" expectedFailures="0" skipped="false"/>
|
||||
</Section>
|
||||
<Section name="Check short-circuiting behaviour" filename="tests/<exe-name>/UsageTests/MatchersRanges.tests.cpp" >
|
||||
<Section name="All elements are checked on success" filename="tests/<exe-name>/UsageTests/MatchersRanges.tests.cpp" >
|
||||
<Expression success="true" type="REQUIRE_THAT" filename="tests/<exe-name>/UsageTests/MatchersRanges.tests.cpp" >
|
||||
<Original>
|
||||
mocked1, RangeEquals( arr )
|
||||
</Original>
|
||||
<Expanded>
|
||||
{ 1, 2, 3, 4 } elements are { 1, 2, 3, 4 }
|
||||
</Expanded>
|
||||
</Expression>
|
||||
<Expression success="true" type="REQUIRE" filename="tests/<exe-name>/UsageTests/MatchersRanges.tests.cpp" >
|
||||
<Original>
|
||||
mocked1.m_derefed[0]
|
||||
</Original>
|
||||
<Expanded>
|
||||
true
|
||||
</Expanded>
|
||||
</Expression>
|
||||
<Expression success="true" type="REQUIRE" filename="tests/<exe-name>/UsageTests/MatchersRanges.tests.cpp" >
|
||||
<Original>
|
||||
mocked1.m_derefed[1]
|
||||
</Original>
|
||||
<Expanded>
|
||||
true
|
||||
</Expanded>
|
||||
</Expression>
|
||||
<Expression success="true" type="REQUIRE" filename="tests/<exe-name>/UsageTests/MatchersRanges.tests.cpp" >
|
||||
<Original>
|
||||
mocked1.m_derefed[2]
|
||||
</Original>
|
||||
<Expanded>
|
||||
true
|
||||
</Expanded>
|
||||
</Expression>
|
||||
<Expression success="true" type="REQUIRE" filename="tests/<exe-name>/UsageTests/MatchersRanges.tests.cpp" >
|
||||
<Original>
|
||||
mocked1.m_derefed[3]
|
||||
</Original>
|
||||
<Expanded>
|
||||
true
|
||||
</Expanded>
|
||||
</Expression>
|
||||
<OverallResults successes="5" failures="0" expectedFailures="0" skipped="false"/>
|
||||
</Section>
|
||||
<OverallResults successes="5" failures="0" expectedFailures="0" skipped="false"/>
|
||||
</Section>
|
||||
<OverallResult success="true" skips="0"/>
|
||||
</TestCase>
|
||||
<TestCase name="Usage of UnorderedRangeEquals range matcher" tags="[matchers][quantifiers][templated]" filename="tests/<exe-name>/UsageTests/MatchersRanges.tests.cpp" >
|
||||
@@ -16768,6 +16912,17 @@ There is no extra whitespace here
|
||||
</Section>
|
||||
<OverallResults successes="1" failures="0" expectedFailures="0" skipped="false"/>
|
||||
</Section>
|
||||
<Section name="Ranges that need ADL begin/end" filename="tests/<exe-name>/UsageTests/MatchersRanges.tests.cpp" >
|
||||
<Expression success="true" type="REQUIRE_THAT" filename="tests/<exe-name>/UsageTests/MatchersRanges.tests.cpp" >
|
||||
<Original>
|
||||
needs_adl1, UnorderedRangeEquals( needs_adl2 )
|
||||
</Original>
|
||||
<Expanded>
|
||||
{ 1, 2, 3, 4, 5 } unordered elements are { 1, 2, 3, 4, 5 }
|
||||
</Expanded>
|
||||
</Expression>
|
||||
<OverallResults successes="1" failures="0" expectedFailures="0" skipped="false"/>
|
||||
</Section>
|
||||
<OverallResult success="true" skips="0"/>
|
||||
</TestCase>
|
||||
<TestCase name="Usage of the SizeIs range matcher" tags="[matchers][size][templated]" filename="tests/<exe-name>/UsageTests/MatchersRanges.tests.cpp" >
|
||||
@@ -21048,6 +21203,6 @@ b1!
|
||||
</Section>
|
||||
<OverallResult success="true" skips="0"/>
|
||||
</TestCase>
|
||||
<OverallResults successes="2033" failures="145" expectedFailures="32" skips="11"/>
|
||||
<OverallResultsCases successes="308" failures="84" expectedFailures="11" skips="5"/>
|
||||
<OverallResults successes="2049" failures="145" expectedFailures="32" skips="11"/>
|
||||
<OverallResultsCases successes="309" failures="84" expectedFailures="11" skips="5"/>
|
||||
</Catch2TestRun>
|
||||
|
@@ -5025,6 +5025,17 @@ C
|
||||
</Expression>
|
||||
<OverallResult success="true" skips="0"/>
|
||||
</TestCase>
|
||||
<TestCase name="Filter generator throws exception for empty generator" tags="[generators]" filename="tests/<exe-name>/IntrospectiveTests/GeneratorsImpl.tests.cpp" >
|
||||
<Expression success="true" type="REQUIRE_THROWS_AS" filename="tests/<exe-name>/IntrospectiveTests/GeneratorsImpl.tests.cpp" >
|
||||
<Original>
|
||||
filter( []( int ) { return false; }, value( 3 ) ), Catch::GeneratorException
|
||||
</Original>
|
||||
<Expanded>
|
||||
filter( []( int ) { return false; }, value( 3 ) ), Catch::GeneratorException
|
||||
</Expanded>
|
||||
</Expression>
|
||||
<OverallResult success="true" skips="0"/>
|
||||
</TestCase>
|
||||
<TestCase name="Floating point matchers: double" tags="[floating-point][matchers]" filename="tests/<exe-name>/UsageTests/Matchers.tests.cpp" >
|
||||
<Section name="Relative" filename="tests/<exe-name>/UsageTests/Matchers.tests.cpp" >
|
||||
<Expression success="true" type="REQUIRE_THAT" filename="tests/<exe-name>/UsageTests/Matchers.tests.cpp" >
|
||||
@@ -5276,6 +5287,17 @@ C
|
||||
</Expression>
|
||||
<OverallResults successes="6" failures="0" expectedFailures="0" skipped="false"/>
|
||||
</Section>
|
||||
<Section name="IsNaN" filename="tests/<exe-name>/UsageTests/Matchers.tests.cpp" >
|
||||
<Expression success="true" type="REQUIRE_THAT" filename="tests/<exe-name>/UsageTests/Matchers.tests.cpp" >
|
||||
<Original>
|
||||
1., !IsNaN()
|
||||
</Original>
|
||||
<Expanded>
|
||||
1.0 not is NaN
|
||||
</Expanded>
|
||||
</Expression>
|
||||
<OverallResults successes="1" failures="0" expectedFailures="0" skipped="false"/>
|
||||
</Section>
|
||||
<OverallResult success="true" skips="0"/>
|
||||
</TestCase>
|
||||
<TestCase name="Floating point matchers: float" tags="[floating-point][matchers]" filename="tests/<exe-name>/UsageTests/Matchers.tests.cpp" >
|
||||
@@ -5553,6 +5575,17 @@ C
|
||||
</Expression>
|
||||
<OverallResults successes="7" failures="0" expectedFailures="0" skipped="false"/>
|
||||
</Section>
|
||||
<Section name="IsNaN" filename="tests/<exe-name>/UsageTests/Matchers.tests.cpp" >
|
||||
<Expression success="true" type="REQUIRE_THAT" filename="tests/<exe-name>/UsageTests/Matchers.tests.cpp" >
|
||||
<Original>
|
||||
1., !IsNaN()
|
||||
</Original>
|
||||
<Expanded>
|
||||
1.0 not is NaN
|
||||
</Expanded>
|
||||
</Expression>
|
||||
<OverallResults successes="1" failures="0" expectedFailures="0" skipped="false"/>
|
||||
</Section>
|
||||
<OverallResult success="true" skips="0"/>
|
||||
</TestCase>
|
||||
<TestCase name="Generators -- adapters" tags="[generators][generic]" filename="tests/<exe-name>/UsageTests/Generators.tests.cpp" >
|
||||
@@ -16645,6 +16678,117 @@ There is no extra whitespace here
|
||||
</Section>
|
||||
<OverallResults successes="1" failures="0" expectedFailures="0" skipped="false"/>
|
||||
</Section>
|
||||
<Section name="Ranges that need ADL begin/end" filename="tests/<exe-name>/UsageTests/MatchersRanges.tests.cpp" >
|
||||
<Expression success="true" type="REQUIRE_THAT" filename="tests/<exe-name>/UsageTests/MatchersRanges.tests.cpp" >
|
||||
<Original>
|
||||
needs_adl1, RangeEquals( needs_adl2 )
|
||||
</Original>
|
||||
<Expanded>
|
||||
{ 1, 2, 3, 4, 5 } elements are { 1, 2, 3, 4, 5 }
|
||||
</Expanded>
|
||||
</Expression>
|
||||
<Expression success="true" type="REQUIRE_THAT" filename="tests/<exe-name>/UsageTests/MatchersRanges.tests.cpp" >
|
||||
<Original>
|
||||
needs_adl1, RangeEquals( needs_adl3, []( int l, int r ) { return l + 1 == r; } )
|
||||
</Original>
|
||||
<Expanded>
|
||||
{ 1, 2, 3, 4, 5 } elements are { 2, 3, 4, 5, 6 }
|
||||
</Expanded>
|
||||
</Expression>
|
||||
<OverallResults successes="2" failures="0" expectedFailures="0" skipped="false"/>
|
||||
</Section>
|
||||
<Section name="Check short-circuiting behaviour" filename="tests/<exe-name>/UsageTests/MatchersRanges.tests.cpp" >
|
||||
<Section name="Check short-circuits on failure" filename="tests/<exe-name>/UsageTests/MatchersRanges.tests.cpp" >
|
||||
<Expression success="true" type="REQUIRE_THAT" filename="tests/<exe-name>/UsageTests/MatchersRanges.tests.cpp" >
|
||||
<Original>
|
||||
mocked1, !RangeEquals( arr )
|
||||
</Original>
|
||||
<Expanded>
|
||||
{ 1, 2, 3, 4 } not elements are { 1, 2, 4, 4 }
|
||||
</Expanded>
|
||||
</Expression>
|
||||
<Expression success="true" type="REQUIRE" filename="tests/<exe-name>/UsageTests/MatchersRanges.tests.cpp" >
|
||||
<Original>
|
||||
mocked1.m_derefed[0]
|
||||
</Original>
|
||||
<Expanded>
|
||||
true
|
||||
</Expanded>
|
||||
</Expression>
|
||||
<Expression success="true" type="REQUIRE" filename="tests/<exe-name>/UsageTests/MatchersRanges.tests.cpp" >
|
||||
<Original>
|
||||
mocked1.m_derefed[1]
|
||||
</Original>
|
||||
<Expanded>
|
||||
true
|
||||
</Expanded>
|
||||
</Expression>
|
||||
<Expression success="true" type="REQUIRE" filename="tests/<exe-name>/UsageTests/MatchersRanges.tests.cpp" >
|
||||
<Original>
|
||||
mocked1.m_derefed[2]
|
||||
</Original>
|
||||
<Expanded>
|
||||
true
|
||||
</Expanded>
|
||||
</Expression>
|
||||
<Expression success="true" type="REQUIRE_FALSE" filename="tests/<exe-name>/UsageTests/MatchersRanges.tests.cpp" >
|
||||
<Original>
|
||||
!(mocked1.m_derefed[3])
|
||||
</Original>
|
||||
<Expanded>
|
||||
!false
|
||||
</Expanded>
|
||||
</Expression>
|
||||
<OverallResults successes="5" failures="0" expectedFailures="0" skipped="false"/>
|
||||
</Section>
|
||||
<OverallResults successes="5" failures="0" expectedFailures="0" skipped="false"/>
|
||||
</Section>
|
||||
<Section name="Check short-circuiting behaviour" filename="tests/<exe-name>/UsageTests/MatchersRanges.tests.cpp" >
|
||||
<Section name="All elements are checked on success" filename="tests/<exe-name>/UsageTests/MatchersRanges.tests.cpp" >
|
||||
<Expression success="true" type="REQUIRE_THAT" filename="tests/<exe-name>/UsageTests/MatchersRanges.tests.cpp" >
|
||||
<Original>
|
||||
mocked1, RangeEquals( arr )
|
||||
</Original>
|
||||
<Expanded>
|
||||
{ 1, 2, 3, 4 } elements are { 1, 2, 3, 4 }
|
||||
</Expanded>
|
||||
</Expression>
|
||||
<Expression success="true" type="REQUIRE" filename="tests/<exe-name>/UsageTests/MatchersRanges.tests.cpp" >
|
||||
<Original>
|
||||
mocked1.m_derefed[0]
|
||||
</Original>
|
||||
<Expanded>
|
||||
true
|
||||
</Expanded>
|
||||
</Expression>
|
||||
<Expression success="true" type="REQUIRE" filename="tests/<exe-name>/UsageTests/MatchersRanges.tests.cpp" >
|
||||
<Original>
|
||||
mocked1.m_derefed[1]
|
||||
</Original>
|
||||
<Expanded>
|
||||
true
|
||||
</Expanded>
|
||||
</Expression>
|
||||
<Expression success="true" type="REQUIRE" filename="tests/<exe-name>/UsageTests/MatchersRanges.tests.cpp" >
|
||||
<Original>
|
||||
mocked1.m_derefed[2]
|
||||
</Original>
|
||||
<Expanded>
|
||||
true
|
||||
</Expanded>
|
||||
</Expression>
|
||||
<Expression success="true" type="REQUIRE" filename="tests/<exe-name>/UsageTests/MatchersRanges.tests.cpp" >
|
||||
<Original>
|
||||
mocked1.m_derefed[3]
|
||||
</Original>
|
||||
<Expanded>
|
||||
true
|
||||
</Expanded>
|
||||
</Expression>
|
||||
<OverallResults successes="5" failures="0" expectedFailures="0" skipped="false"/>
|
||||
</Section>
|
||||
<OverallResults successes="5" failures="0" expectedFailures="0" skipped="false"/>
|
||||
</Section>
|
||||
<OverallResult success="true" skips="0"/>
|
||||
</TestCase>
|
||||
<TestCase name="Usage of UnorderedRangeEquals range matcher" tags="[matchers][quantifiers][templated]" filename="tests/<exe-name>/UsageTests/MatchersRanges.tests.cpp" >
|
||||
@@ -16768,6 +16912,17 @@ There is no extra whitespace here
|
||||
</Section>
|
||||
<OverallResults successes="1" failures="0" expectedFailures="0" skipped="false"/>
|
||||
</Section>
|
||||
<Section name="Ranges that need ADL begin/end" filename="tests/<exe-name>/UsageTests/MatchersRanges.tests.cpp" >
|
||||
<Expression success="true" type="REQUIRE_THAT" filename="tests/<exe-name>/UsageTests/MatchersRanges.tests.cpp" >
|
||||
<Original>
|
||||
needs_adl1, UnorderedRangeEquals( needs_adl2 )
|
||||
</Original>
|
||||
<Expanded>
|
||||
{ 1, 2, 3, 4, 5 } unordered elements are { 1, 2, 3, 4, 5 }
|
||||
</Expanded>
|
||||
</Expression>
|
||||
<OverallResults successes="1" failures="0" expectedFailures="0" skipped="false"/>
|
||||
</Section>
|
||||
<OverallResult success="true" skips="0"/>
|
||||
</TestCase>
|
||||
<TestCase name="Usage of the SizeIs range matcher" tags="[matchers][size][templated]" filename="tests/<exe-name>/UsageTests/MatchersRanges.tests.cpp" >
|
||||
@@ -21047,6 +21202,6 @@ b1!
|
||||
</Section>
|
||||
<OverallResult success="true" skips="0"/>
|
||||
</TestCase>
|
||||
<OverallResults successes="2033" failures="145" expectedFailures="32" skips="11"/>
|
||||
<OverallResultsCases successes="308" failures="84" expectedFailures="11" skips="5"/>
|
||||
<OverallResults successes="2049" failures="145" expectedFailures="32" skips="11"/>
|
||||
<OverallResultsCases successes="309" failures="84" expectedFailures="11" skips="5"/>
|
||||
</Catch2TestRun>
|
||||
|
94
tests/SelfTest/IntrospectiveTests/Algorithms.tests.cpp
Normal file
94
tests/SelfTest/IntrospectiveTests/Algorithms.tests.cpp
Normal file
@@ -0,0 +1,94 @@
|
||||
|
||||
// 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/catch_test_macros.hpp>
|
||||
#include <catch2/internal/catch_is_permutation.hpp>
|
||||
|
||||
#include <helpers/range_test_helpers.hpp>
|
||||
|
||||
#include <array>
|
||||
|
||||
namespace {
|
||||
template <typename Range1, typename Range2>
|
||||
static bool is_permutation(Range1 const& r1, Range2 const& r2) {
|
||||
using std::begin; using std::end;
|
||||
return Catch::Detail::is_permutation(
|
||||
begin( r1 ), end( r1 ), begin( r2 ), end( r2 ), std::equal_to<>{} );
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("is_permutation", "[algorithms][approvals]") {
|
||||
SECTION( "Handle empty ranges" ) {
|
||||
std::array<int, 0> empty;
|
||||
std::array<int, 2> non_empty{ { 2, 3 } };
|
||||
REQUIRE( is_permutation( empty, empty ) );
|
||||
REQUIRE_FALSE( is_permutation( empty, non_empty ) );
|
||||
REQUIRE_FALSE( is_permutation( non_empty, empty ) );
|
||||
}
|
||||
SECTION( "Different length ranges" ) {
|
||||
std::array<int, 6> arr1{ { 1, 3, 5, 7, 8, 9 } };
|
||||
// arr2 is prefix of arr1
|
||||
std::array<int, 4> arr2{ { 1, 3, 5, 7 } };
|
||||
// arr3 shares prefix with arr1 and arr2, but is not a permutation
|
||||
std::array<int, 5> arr3{ { 1, 3, 5, 9, 8 } };
|
||||
REQUIRE_FALSE( is_permutation( arr1, arr2 ) );
|
||||
REQUIRE_FALSE( is_permutation( arr1, arr3 ) );
|
||||
REQUIRE_FALSE( is_permutation( arr2, arr3 ) );
|
||||
}
|
||||
SECTION( "Same length ranges" ) {
|
||||
SECTION( "Shared elements, but different counts" ) {
|
||||
const std::array<int, 6>
|
||||
arr1{ { 1, 1, 1, 1, 2, 2 } },
|
||||
arr2{ { 1, 1, 2, 2, 2, 2 } };
|
||||
REQUIRE_FALSE( is_permutation( arr1, arr2 ) );
|
||||
}
|
||||
SECTION( "Identical ranges" ) {
|
||||
const std::array<int, 6>
|
||||
arr1{ { 1, 1, 1, 1, 2, 2 } },
|
||||
arr2{ { 1, 1, 2, 2, 2, 2 } };
|
||||
REQUIRE( is_permutation( arr1, arr1 ) );
|
||||
REQUIRE( is_permutation( arr2, arr2 ) );
|
||||
}
|
||||
SECTION( "Completely distinct elements" ) {
|
||||
// Completely distinct elements
|
||||
const std::array<int, 4>
|
||||
arr1{ { 1, 2, 3, 4 } },
|
||||
arr2{ { 10, 20, 30, 40 } };
|
||||
REQUIRE_FALSE( is_permutation( arr1, arr2 ) );
|
||||
}
|
||||
SECTION( "Reverse ranges" ) {
|
||||
const std::array<int, 5>
|
||||
arr1{ { 1, 2, 3, 4, 5 } },
|
||||
arr2{ { 5, 4, 3, 2, 1 } };
|
||||
REQUIRE( is_permutation( arr1, arr2 ) );
|
||||
}
|
||||
SECTION( "Shared prefix & permuted elements" ) {
|
||||
const std::array<int, 5>
|
||||
arr1{ { 1, 1, 2, 3, 4 } },
|
||||
arr2{ { 1, 1, 4, 2, 3 } };
|
||||
REQUIRE( is_permutation( arr1, arr2 ) );
|
||||
}
|
||||
SECTION( "Permutations with element count > 1" ) {
|
||||
const std::array<int, 7>
|
||||
arr1{ { 2, 2, 3, 3, 3, 1, 1 } },
|
||||
arr2{ { 3, 2, 1, 3, 2, 1, 3 } };
|
||||
REQUIRE( is_permutation( arr1, arr2 ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("is_permutation supports iterator + sentinel pairs",
|
||||
"[algorithms][is-permutation][approvals]") {
|
||||
const has_different_begin_end_types<int>
|
||||
range_1{ 1, 2, 3, 4 },
|
||||
range_2{ 4, 3, 2, 1 };
|
||||
REQUIRE( is_permutation( range_1, range_2 ) );
|
||||
|
||||
const has_different_begin_end_types<int> range_3{ 3, 3, 2, 1 };
|
||||
REQUIRE_FALSE( is_permutation( range_1, range_3 ) );
|
||||
}
|
@@ -16,6 +16,7 @@
|
||||
#include <catch2/generators/catch_generators_adapters.hpp>
|
||||
#include <catch2/generators/catch_generators_random.hpp>
|
||||
#include <catch2/generators/catch_generators_range.hpp>
|
||||
#include <catch2/generators/catch_generator_exception.hpp>
|
||||
|
||||
// Tests of generator implementation details
|
||||
TEST_CASE("Generators internals", "[generators][internals]") {
|
||||
@@ -534,3 +535,12 @@ TEST_CASE( "Random generators can be seeded", "[generators][approvals]" ) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("Filter generator throws exception for empty generator",
|
||||
"[generators]") {
|
||||
using namespace Catch::Generators;
|
||||
|
||||
REQUIRE_THROWS_AS(
|
||||
filter( []( int ) { return false; }, value( 3 ) ),
|
||||
Catch::GeneratorException );
|
||||
}
|
||||
|
@@ -14,8 +14,8 @@
|
||||
using namespace Catch;
|
||||
|
||||
namespace {
|
||||
Catch::TestCaseTracking::NameAndLocation makeNAL( std::string const& name ) {
|
||||
return Catch::TestCaseTracking::NameAndLocation( name, Catch::SourceLineInfo("",0) );
|
||||
Catch::TestCaseTracking::NameAndLocationRef makeNAL( StringRef name ) {
|
||||
return Catch::TestCaseTracking::NameAndLocationRef( name, Catch::SourceLineInfo("",0) );
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -497,6 +497,9 @@ TEST_CASE( "Floating point matchers: float", "[matchers][floating-point]" ) {
|
||||
REQUIRE_THROWS_AS( WithinRel( 1.f, -0.2f ), std::domain_error );
|
||||
REQUIRE_THROWS_AS( WithinRel( 1.f, 1.f ), std::domain_error );
|
||||
}
|
||||
SECTION( "IsNaN" ) {
|
||||
REQUIRE_THAT( 1., !IsNaN() );
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE( "Floating point matchers: double", "[matchers][floating-point]" ) {
|
||||
@@ -552,6 +555,9 @@ TEST_CASE( "Floating point matchers: double", "[matchers][floating-point]" ) {
|
||||
REQUIRE_THROWS_AS( WithinRel( 1., -0.2 ), std::domain_error );
|
||||
REQUIRE_THROWS_AS( WithinRel( 1., 1. ), std::domain_error );
|
||||
}
|
||||
SECTION("IsNaN") {
|
||||
REQUIRE_THAT( 1., !IsNaN() );
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE( "Floating point matchers that are problematic in approvals",
|
||||
@@ -566,6 +572,8 @@ TEST_CASE( "Floating point matchers that are problematic in approvals",
|
||||
REQUIRE_THAT( NAN, !WithinRel( NAN ) );
|
||||
REQUIRE_THAT( 1., !WithinRel( NAN ) );
|
||||
REQUIRE_THAT( NAN, !WithinRel( 1. ) );
|
||||
REQUIRE_THAT( NAN, IsNaN() );
|
||||
REQUIRE_THAT( static_cast<double>(NAN), IsNaN() );
|
||||
}
|
||||
|
||||
TEST_CASE( "Arbitrary predicate matcher", "[matchers][generic]" ) {
|
||||
|
@@ -15,195 +15,15 @@
|
||||
#include <catch2/matchers/catch_matchers_predicate.hpp>
|
||||
#include <catch2/matchers/catch_matchers_string.hpp>
|
||||
|
||||
#include <helpers/range_test_helpers.hpp>
|
||||
|
||||
#include <cmath>
|
||||
#include <initializer_list>
|
||||
#include <list>
|
||||
#include <map>
|
||||
#include <type_traits>
|
||||
#include <vector>
|
||||
#include <memory>
|
||||
|
||||
namespace {
|
||||
|
||||
namespace unrelated {
|
||||
template <typename T>
|
||||
class needs_ADL_begin {
|
||||
std::vector<T> m_elements;
|
||||
public:
|
||||
using iterator = typename std::vector<T>::iterator;
|
||||
using const_iterator = typename std::vector<T>::const_iterator;
|
||||
|
||||
needs_ADL_begin(std::initializer_list<T> init) : m_elements(init) {}
|
||||
|
||||
const_iterator Begin() const { return m_elements.begin(); }
|
||||
const_iterator End() const { return m_elements.end(); }
|
||||
|
||||
friend const_iterator begin(needs_ADL_begin const& lhs) {
|
||||
return lhs.Begin();
|
||||
}
|
||||
friend const_iterator end(needs_ADL_begin const& rhs) {
|
||||
return rhs.End();
|
||||
}
|
||||
};
|
||||
} // end unrelated namespace
|
||||
|
||||
#if defined(__clang__)
|
||||
# pragma clang diagnostic push
|
||||
# pragma clang diagnostic ignored "-Wunused-function"
|
||||
#endif
|
||||
|
||||
template <typename T>
|
||||
class has_different_begin_end_types {
|
||||
// Using std::vector<T> leads to annoying issues when T is bool
|
||||
// so we just use list because the perf is not critical and ugh.
|
||||
std::list<T> m_elements;
|
||||
|
||||
// Different type for the "end" iterator
|
||||
struct iterator_end {};
|
||||
// Fake-ish forward iterator that only compares to a different type
|
||||
class iterator {
|
||||
using underlying_iter = typename std::list<T>::const_iterator;
|
||||
underlying_iter m_start;
|
||||
underlying_iter m_end;
|
||||
|
||||
public:
|
||||
iterator( underlying_iter start, underlying_iter end ):
|
||||
m_start( start ), m_end( end ) {}
|
||||
|
||||
using iterator_category = std::forward_iterator_tag;
|
||||
using difference_type = std::ptrdiff_t;
|
||||
using value_type = T;
|
||||
using const_reference = T const&;
|
||||
using pointer = T const*;
|
||||
|
||||
|
||||
friend bool operator==( iterator iter, iterator_end ) {
|
||||
return iter.m_start == iter.m_end;
|
||||
}
|
||||
friend bool operator!=( iterator iter, iterator_end ) {
|
||||
return iter.m_start != iter.m_end;
|
||||
}
|
||||
iterator& operator++() {
|
||||
++m_start;
|
||||
return *this;
|
||||
}
|
||||
iterator operator++(int) {
|
||||
auto tmp(*this);
|
||||
++m_start;
|
||||
return tmp;
|
||||
}
|
||||
const_reference operator*() const {
|
||||
return *m_start;
|
||||
}
|
||||
pointer operator->() const {
|
||||
return m_start;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
public:
|
||||
explicit has_different_begin_end_types( std::initializer_list<T> init ):
|
||||
m_elements( init ) {}
|
||||
|
||||
iterator begin() const {
|
||||
return { m_elements.begin(), m_elements.end() };
|
||||
}
|
||||
|
||||
iterator_end end() const {
|
||||
return {};
|
||||
}
|
||||
};
|
||||
|
||||
#if defined(__clang__)
|
||||
# pragma clang diagnostic pop
|
||||
#endif
|
||||
|
||||
template <typename T> struct with_mocked_iterator_access {
|
||||
std::vector<T> m_elements;
|
||||
|
||||
// use plain arrays to have nicer printouts with CHECK(...)
|
||||
mutable std::unique_ptr<bool[]> m_derefed;
|
||||
|
||||
// We want to check which elements were dereferenced when iterating, so
|
||||
// we can check whether iterator-using code traverses range correctly
|
||||
template <bool is_const> class basic_iterator {
|
||||
template <typename U>
|
||||
using constify_t = std::conditional_t<is_const, std::add_const_t<U>, U>;
|
||||
|
||||
constify_t<with_mocked_iterator_access>* m_origin;
|
||||
size_t m_origin_idx;
|
||||
|
||||
public:
|
||||
using iterator_category = std::forward_iterator_tag;
|
||||
using difference_type = std::ptrdiff_t;
|
||||
using value_type = constify_t<T>;
|
||||
using const_reference = typename std::vector<T>::const_reference;
|
||||
using reference = typename std::vector<T>::reference;
|
||||
using pointer = typename std::vector<T>::pointer;
|
||||
|
||||
basic_iterator( constify_t<with_mocked_iterator_access>* origin,
|
||||
std::size_t origin_idx ):
|
||||
m_origin{ origin }, m_origin_idx{ origin_idx } {}
|
||||
|
||||
friend bool operator==( basic_iterator lhs, basic_iterator rhs ) {
|
||||
return lhs.m_origin == rhs.m_origin &&
|
||||
lhs.m_origin_idx == rhs.m_origin_idx;
|
||||
}
|
||||
friend bool operator!=( basic_iterator lhs, basic_iterator rhs ) {
|
||||
return !( lhs == rhs );
|
||||
}
|
||||
basic_iterator& operator++() {
|
||||
++m_origin_idx;
|
||||
return *this;
|
||||
}
|
||||
basic_iterator operator++( int ) {
|
||||
auto tmp( *this );
|
||||
++( *this );
|
||||
return tmp;
|
||||
}
|
||||
const_reference operator*() const {
|
||||
assert( m_origin_idx < m_origin->m_elements.size() && "Attempted to deref invalid position" );
|
||||
m_origin->m_derefed[m_origin_idx] = true;
|
||||
return m_origin->m_elements[m_origin_idx];
|
||||
}
|
||||
pointer operator->() const {
|
||||
assert( m_origin_idx < m_origin->m_elements.size() && "Attempted to deref invalid position" );
|
||||
return &m_origin->m_elements[m_origin_idx];
|
||||
}
|
||||
};
|
||||
|
||||
using iterator = basic_iterator<false>;
|
||||
using const_iterator = basic_iterator<true>;
|
||||
|
||||
with_mocked_iterator_access( std::initializer_list<T> init ):
|
||||
m_elements( init ),
|
||||
m_derefed( std::make_unique<bool[]>( m_elements.size() ) ) {}
|
||||
|
||||
const_iterator begin() const { return { this, 0 }; }
|
||||
const_iterator end() const { return { this, m_elements.size() }; }
|
||||
iterator begin() { return { this, 0 }; }
|
||||
iterator end() { return { this, m_elements.size() }; }
|
||||
};
|
||||
|
||||
} // end anon namespace
|
||||
|
||||
namespace Catch {
|
||||
// make sure with_mocked_iterator_access is not considered a range by Catch,
|
||||
// so that below StringMaker is used instead of the default one for ranges
|
||||
template <typename T>
|
||||
struct is_range<with_mocked_iterator_access<T>> : std::false_type {};
|
||||
|
||||
template <typename T>
|
||||
struct StringMaker<with_mocked_iterator_access<T>> {
|
||||
static std::string
|
||||
convert( with_mocked_iterator_access<T> const& access ) {
|
||||
// We have to avoid the type's iterators, because we check
|
||||
// their use in tests
|
||||
return ::Catch::Detail::stringify( access.m_elements );
|
||||
}
|
||||
};
|
||||
} // namespace Catch
|
||||
|
||||
struct MoveOnlyTestElement {
|
||||
int num = 0;
|
||||
MoveOnlyTestElement(int n) :num(n) {}
|
||||
@@ -287,16 +107,6 @@ namespace {
|
||||
bool empty() const { return false; }
|
||||
};
|
||||
|
||||
namespace unrelated {
|
||||
struct ADL_empty {
|
||||
bool Empty() const { return true; }
|
||||
|
||||
friend bool empty(ADL_empty e) {
|
||||
return e.Empty();
|
||||
}
|
||||
};
|
||||
|
||||
} // end namespace unrelated
|
||||
} // end unnamed namespace
|
||||
|
||||
TEST_CASE("Basic use of the Empty range matcher", "[matchers][templated][empty]") {
|
||||
@@ -346,17 +156,6 @@ namespace {
|
||||
return LessThanMatcher{ sz };
|
||||
}
|
||||
|
||||
namespace unrelated {
|
||||
struct ADL_size {
|
||||
size_t sz() const {
|
||||
return 12;
|
||||
}
|
||||
friend size_t size(ADL_size s) {
|
||||
return s.sz();
|
||||
}
|
||||
};
|
||||
} // end namespace unrelated
|
||||
|
||||
struct has_size {
|
||||
size_t size() const {
|
||||
return 13;
|
||||
@@ -832,6 +631,31 @@ TEST_CASE( "The quantifier range matchers support types with different types ret
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE( "RangeEquals supports ranges with different types returned from begin and end",
|
||||
"[matchers][templated][range][approvals] ") {
|
||||
using Catch::Matchers::RangeEquals;
|
||||
using Catch::Matchers::UnorderedRangeEquals;
|
||||
|
||||
has_different_begin_end_types<int> diff_types{ 1, 2, 3, 4, 5 };
|
||||
std::array<int, 5> arr1{ { 1, 2, 3, 4, 5 } }, arr2{ { 2, 3, 4, 5, 6 } };
|
||||
|
||||
REQUIRE_THAT( diff_types, RangeEquals( arr1 ) );
|
||||
REQUIRE_THAT( diff_types, RangeEquals( arr2, []( int l, int r ) {
|
||||
return l + 1 == r;
|
||||
} ) );
|
||||
REQUIRE_THAT( diff_types, UnorderedRangeEquals( diff_types ) );
|
||||
}
|
||||
|
||||
TEST_CASE( "RangeContains supports ranges with different types returned from "
|
||||
"begin and end",
|
||||
"[matchers][templated][range][approvals]" ) {
|
||||
using Catch::Matchers::Contains;
|
||||
|
||||
has_different_begin_end_types<size_t> diff_types{ 1, 2, 3, 4, 5 };
|
||||
REQUIRE_THAT( diff_types, Contains( size_t( 3 ) ) );
|
||||
REQUIRE_THAT( diff_types, Contains( LessThanMatcher( size_t( 4 ) ) ) );
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
TEST_CASE( "Usage of RangeEquals range matcher", "[matchers][templated][quantifiers]" ) {
|
||||
@@ -891,10 +715,40 @@ TEST_CASE( "Usage of RangeEquals range matcher", "[matchers][templated][quantifi
|
||||
}
|
||||
}
|
||||
|
||||
// Cannot usefully test short-circuits, as the complexiy of std::equal is
|
||||
// only guaranteed to be O(n) or better (even if many implementations
|
||||
// short-circuit if the range lengths differ for
|
||||
// LegacyRandomAccessIterators)
|
||||
SECTION( "Ranges that need ADL begin/end" ) {
|
||||
unrelated::needs_ADL_begin<int> const
|
||||
needs_adl1{ 1, 2, 3, 4, 5 },
|
||||
needs_adl2{ 1, 2, 3, 4, 5 },
|
||||
needs_adl3{ 2, 3, 4, 5, 6 };
|
||||
|
||||
REQUIRE_THAT( needs_adl1, RangeEquals( needs_adl2 ) );
|
||||
REQUIRE_THAT( needs_adl1, RangeEquals( needs_adl3, []( int l, int r ) {
|
||||
return l + 1 == r;
|
||||
} ) );
|
||||
}
|
||||
|
||||
SECTION("Check short-circuiting behaviour") {
|
||||
with_mocked_iterator_access<int> const mocked1{ 1, 2, 3, 4 };
|
||||
|
||||
SECTION( "Check short-circuits on failure" ) {
|
||||
std::array<int, 4> arr{ { 1, 2, 4, 4 } };
|
||||
|
||||
REQUIRE_THAT( mocked1, !RangeEquals( arr ) );
|
||||
REQUIRE( mocked1.m_derefed[0] );
|
||||
REQUIRE( mocked1.m_derefed[1] );
|
||||
REQUIRE( mocked1.m_derefed[2] );
|
||||
REQUIRE_FALSE( mocked1.m_derefed[3] );
|
||||
}
|
||||
SECTION("All elements are checked on success") {
|
||||
std::array<int, 4> arr{ { 1, 2, 3, 4 } };
|
||||
|
||||
REQUIRE_THAT( mocked1, RangeEquals( arr ) );
|
||||
REQUIRE( mocked1.m_derefed[0] );
|
||||
REQUIRE( mocked1.m_derefed[1] );
|
||||
REQUIRE( mocked1.m_derefed[2] );
|
||||
REQUIRE( mocked1.m_derefed[3] );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE( "Usage of UnorderedRangeEquals range matcher",
|
||||
@@ -958,8 +812,14 @@ TEST_CASE( "Usage of UnorderedRangeEquals range matcher",
|
||||
}
|
||||
}
|
||||
|
||||
// As above with RangeEquals, short cicuiting and other optimisations
|
||||
// are left to the STL implementation
|
||||
|
||||
SECTION( "Ranges that need ADL begin/end" ) {
|
||||
unrelated::needs_ADL_begin<int> const
|
||||
needs_adl1{ 1, 2, 3, 4, 5 },
|
||||
needs_adl2{ 1, 2, 3, 4, 5 };
|
||||
|
||||
REQUIRE_THAT( needs_adl1, UnorderedRangeEquals( needs_adl2 ) );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
210
tests/SelfTest/helpers/range_test_helpers.hpp
Normal file
210
tests/SelfTest/helpers/range_test_helpers.hpp
Normal file
@@ -0,0 +1,210 @@
|
||||
|
||||
// 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_TEST_HELPERS_RANGE_TEST_HELPERS_HPP_INCLUDED
|
||||
#define CATCH_TEST_HELPERS_RANGE_TEST_HELPERS_HPP_INCLUDED
|
||||
|
||||
#include <catch2/catch_tostring.hpp>
|
||||
|
||||
#include <initializer_list>
|
||||
#include <list>
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
namespace unrelated {
|
||||
template <typename T>
|
||||
class needs_ADL_begin {
|
||||
std::vector<T> m_elements;
|
||||
|
||||
public:
|
||||
using iterator = typename std::vector<T>::iterator;
|
||||
using const_iterator = typename std::vector<T>::const_iterator;
|
||||
|
||||
needs_ADL_begin( std::initializer_list<T> init ): m_elements( init ) {}
|
||||
|
||||
const_iterator Begin() const { return m_elements.begin(); }
|
||||
const_iterator End() const { return m_elements.end(); }
|
||||
|
||||
friend const_iterator begin( needs_ADL_begin const& lhs ) {
|
||||
return lhs.Begin();
|
||||
}
|
||||
friend const_iterator end( needs_ADL_begin const& rhs ) {
|
||||
return rhs.End();
|
||||
}
|
||||
};
|
||||
|
||||
struct ADL_empty {
|
||||
bool Empty() const { return true; }
|
||||
|
||||
friend bool empty( ADL_empty e ) { return e.Empty(); }
|
||||
};
|
||||
|
||||
struct ADL_size {
|
||||
size_t sz() const { return 12; }
|
||||
friend size_t size( ADL_size s ) { return s.sz(); }
|
||||
};
|
||||
|
||||
} // namespace unrelated
|
||||
|
||||
#if defined( __clang__ )
|
||||
# pragma clang diagnostic push
|
||||
# pragma clang diagnostic ignored "-Wunused-function"
|
||||
#endif
|
||||
|
||||
template <typename T>
|
||||
class has_different_begin_end_types {
|
||||
// Using std::vector<T> leads to annoying issues when T is bool
|
||||
// so we just use list because the perf is not critical and ugh.
|
||||
std::list<T> m_elements;
|
||||
|
||||
// Different type for the "end" iterator
|
||||
struct iterator_end {};
|
||||
// Fake-ish forward iterator that only compares to a different type
|
||||
class iterator {
|
||||
using underlying_iter = typename std::list<T>::const_iterator;
|
||||
underlying_iter m_start;
|
||||
underlying_iter m_end;
|
||||
|
||||
public:
|
||||
iterator( underlying_iter start, underlying_iter end ):
|
||||
m_start( start ), m_end( end ) {}
|
||||
|
||||
using iterator_category = std::forward_iterator_tag;
|
||||
using difference_type = std::ptrdiff_t;
|
||||
using value_type = T;
|
||||
using const_reference = T const&;
|
||||
using pointer = T const*;
|
||||
|
||||
friend bool operator==( iterator iter, iterator_end ) {
|
||||
return iter.m_start == iter.m_end;
|
||||
}
|
||||
friend bool operator==(iterator lhs, iterator rhs) {
|
||||
return lhs.m_start == rhs.m_start && lhs.m_end == rhs.m_end;
|
||||
}
|
||||
friend bool operator!=( iterator iter, iterator_end ) {
|
||||
return iter.m_start != iter.m_end;
|
||||
}
|
||||
friend bool operator!=( iterator lhs, iterator rhs ) {
|
||||
return !( lhs == rhs );
|
||||
}
|
||||
iterator& operator++() {
|
||||
++m_start;
|
||||
return *this;
|
||||
}
|
||||
iterator operator++( int ) {
|
||||
auto tmp( *this );
|
||||
++m_start;
|
||||
return tmp;
|
||||
}
|
||||
const_reference operator*() const { return *m_start; }
|
||||
pointer operator->() const { return m_start; }
|
||||
};
|
||||
|
||||
public:
|
||||
explicit has_different_begin_end_types( std::initializer_list<T> init ):
|
||||
m_elements( init ) {}
|
||||
|
||||
iterator begin() const { return { m_elements.begin(), m_elements.end() }; }
|
||||
|
||||
iterator_end end() const { return {}; }
|
||||
};
|
||||
|
||||
#if defined( __clang__ )
|
||||
# pragma clang diagnostic pop
|
||||
#endif
|
||||
|
||||
template <typename T>
|
||||
struct with_mocked_iterator_access {
|
||||
std::vector<T> m_elements;
|
||||
|
||||
// use plain arrays to have nicer printouts with CHECK(...)
|
||||
mutable std::unique_ptr<bool[]> m_derefed;
|
||||
|
||||
// We want to check which elements were dereferenced when iterating, so
|
||||
// we can check whether iterator-using code traverses range correctly
|
||||
template <bool is_const>
|
||||
class basic_iterator {
|
||||
template <typename U>
|
||||
using constify_t = std::conditional_t<is_const, std::add_const_t<U>, U>;
|
||||
|
||||
constify_t<with_mocked_iterator_access>* m_origin;
|
||||
size_t m_origin_idx;
|
||||
|
||||
public:
|
||||
using iterator_category = std::forward_iterator_tag;
|
||||
using difference_type = std::ptrdiff_t;
|
||||
using value_type = constify_t<T>;
|
||||
using const_reference = typename std::vector<T>::const_reference;
|
||||
using reference = typename std::vector<T>::reference;
|
||||
using pointer = typename std::vector<T>::pointer;
|
||||
|
||||
basic_iterator( constify_t<with_mocked_iterator_access>* origin,
|
||||
std::size_t origin_idx ):
|
||||
m_origin{ origin }, m_origin_idx{ origin_idx } {}
|
||||
|
||||
friend bool operator==( basic_iterator lhs, basic_iterator rhs ) {
|
||||
return lhs.m_origin == rhs.m_origin &&
|
||||
lhs.m_origin_idx == rhs.m_origin_idx;
|
||||
}
|
||||
friend bool operator!=( basic_iterator lhs, basic_iterator rhs ) {
|
||||
return !( lhs == rhs );
|
||||
}
|
||||
basic_iterator& operator++() {
|
||||
++m_origin_idx;
|
||||
return *this;
|
||||
}
|
||||
basic_iterator operator++( int ) {
|
||||
auto tmp( *this );
|
||||
++( *this );
|
||||
return tmp;
|
||||
}
|
||||
const_reference operator*() const {
|
||||
assert( m_origin_idx < m_origin->m_elements.size() &&
|
||||
"Attempted to deref invalid position" );
|
||||
m_origin->m_derefed[m_origin_idx] = true;
|
||||
return m_origin->m_elements[m_origin_idx];
|
||||
}
|
||||
pointer operator->() const {
|
||||
assert( m_origin_idx < m_origin->m_elements.size() &&
|
||||
"Attempted to deref invalid position" );
|
||||
return &m_origin->m_elements[m_origin_idx];
|
||||
}
|
||||
};
|
||||
|
||||
using iterator = basic_iterator<false>;
|
||||
using const_iterator = basic_iterator<true>;
|
||||
|
||||
with_mocked_iterator_access( std::initializer_list<T> init ):
|
||||
m_elements( init ),
|
||||
m_derefed( std::make_unique<bool[]>( m_elements.size() ) ) {}
|
||||
|
||||
const_iterator begin() const { return { this, 0 }; }
|
||||
const_iterator end() const { return { this, m_elements.size() }; }
|
||||
iterator begin() { return { this, 0 }; }
|
||||
iterator end() { return { this, m_elements.size() }; }
|
||||
};
|
||||
|
||||
|
||||
namespace Catch {
|
||||
// make sure with_mocked_iterator_access is not considered a range by Catch,
|
||||
// so that below StringMaker is used instead of the default one for ranges
|
||||
template <typename T>
|
||||
struct is_range<with_mocked_iterator_access<T>> : std::false_type {};
|
||||
|
||||
template <typename T>
|
||||
struct StringMaker<with_mocked_iterator_access<T>> {
|
||||
static std::string
|
||||
convert( with_mocked_iterator_access<T> const& access ) {
|
||||
// We have to avoid the type's iterators, because we check
|
||||
// their use in tests
|
||||
return ::Catch::Detail::stringify( access.m_elements );
|
||||
}
|
||||
};
|
||||
} // namespace Catch
|
||||
|
||||
#endif // CATCH_TEST_HELPERS_RANGE_TEST_HELPERS_HPP_INCLUDED
|
@@ -9,6 +9,7 @@
|
||||
# Please keep these ordered alphabetically
|
||||
self_test_sources = files(
|
||||
'SelfTest/helpers/parse_test_spec.cpp',
|
||||
'SelfTest/IntrospectiveTests/Algorithms.tests.cpp',
|
||||
'SelfTest/IntrospectiveTests/Clara.tests.cpp',
|
||||
'SelfTest/IntrospectiveTests/CmdLine.tests.cpp',
|
||||
'SelfTest/IntrospectiveTests/CmdLineHelpers.tests.cpp',
|
||||
|
@@ -6,7 +6,7 @@ rem 1. Regenerate the amalgamated distribution
|
||||
python tools\scripts\generateAmalgamatedFiles.py
|
||||
|
||||
rem 2. Configure the full test build
|
||||
cmake -Bdebug-build -H. -DCMAKE_BUILD_TYPE=Debug -DCATCH_DEVELOPMENT_BUILD=ON -DCATCH_BUILD_EXAMPLES=ON -DCATCH_BUILD_EXTRA_TESTS=ON -DCATCH_ENABLE_CONFIGURE_TESTS=ON
|
||||
cmake -B debug-build -S . -DCMAKE_BUILD_TYPE=Debug --preset all-tests
|
||||
|
||||
rem 3. Run the actual build
|
||||
cmake --build debug-build
|
||||
|
@@ -8,7 +8,7 @@
|
||||
./tools/scripts/generateAmalgamatedFiles.py
|
||||
|
||||
# 2. Configure the full test build
|
||||
cmake -Bdebug-build -H. -DCMAKE_BUILD_TYPE=Debug -DCATCH_DEVELOPMENT_BUILD=ON -DCATCH_BUILD_EXAMPLES=ON -DCATCH_BUILD_EXTRA_TESTS=ON -DCATCH_ENABLE_CONFIGURE_TESTS=ON
|
||||
cmake -B debug-build -S . -DCMAKE_BUILD_TYPE=Debug --preset all-tests
|
||||
|
||||
# 3. Run the actual build
|
||||
cmake --build debug-build
|
||||
|
Reference in New Issue
Block a user