This commit is contained in:
Martin Hořeňovský 2022-05-17 22:13:36 +02:00
parent abb669d4fd
commit 605a34765a
No known key found for this signature in database
GPG Key ID: DE48307B8B0D381A
12 changed files with 455 additions and 119 deletions

View File

@ -37,7 +37,7 @@ endif()
project(Catch2 project(Catch2
VERSION 3.0.0 # CML version placeholder, don't delete VERSION 3.0.1 # CML version placeholder, don't delete
LANGUAGES CXX LANGUAGES CXX
HOMEPAGE_URL "https://github.com/catchorg/Catch2" HOMEPAGE_URL "https://github.com/catchorg/Catch2"
DESCRIPTION "A modern, C++-native, unit test framework." DESCRIPTION "A modern, C++-native, unit test framework."

View File

@ -145,7 +145,7 @@ hardcoded into Catch2. Currently there are only 2,
_Note that the reporter might still check the X-prefixed options for _Note that the reporter might still check the X-prefixed options for
validity, and throw an error if they are wrong._ validity, and throw an error if they are wrong._
> Support for passing arguments to reporters through the `-r`, `--reporter` flag was introduced in Catch2 X.Y.Z > Support for passing arguments to reporters through the `-r`, `--reporter` flag was introduced in Catch2 3.0.1
There are multiple built-in reporters, you can see what they do by using the There are multiple built-in reporters, you can see what they do by using the
[`--list-reporter`](command-line.md#listing-available-tests-tags-or-reporters) [`--list-reporter`](command-line.md#listing-available-tests-tags-or-reporters)
@ -160,7 +160,7 @@ reporter can be provided without the output-file part of reporter spec.
This reporter will use the "default" output destination, based on This reporter will use the "default" output destination, based on
the [`-o`, `--out`](#sending-output-to-a-file) option. the [`-o`, `--out`](#sending-output-to-a-file) option.
> Support for using multiple different reporters at the same time was [introduced](https://github.com/catchorg/Catch2/pull/2183) in Catch2 X.Y.Z > Support for using multiple different reporters at the same time was [introduced](https://github.com/catchorg/Catch2/pull/2183) in Catch2 3.0.1
_Note: There is currently no way to escape `::` in the reporter spec, _Note: There is currently no way to escape `::` in the reporter spec,
@ -204,9 +204,9 @@ Sometimes this results in a flood of failure messages and you'd rather just see
--list-listeners --list-listeners
``` ```
> The `--list*` options became customizable through reporters in Catch2 X.Y.Z > The `--list*` options became customizable through reporters in Catch2 3.0.1
> The `--list-listeners` option was added in Catch2 X.Y.Z > The `--list-listeners` option was added in Catch2 3.0.1
`--list-tests` lists all registered tests matching specified test spec. `--list-tests` lists all registered tests matching specified test spec.
Usually this listing also includes tags, and potentially also other Usually this listing also includes tags, and potentially also other
@ -230,7 +230,7 @@ Use this option to send all output to a file, instead of stdout. You can
use `-` as the filename to explicitly send the output to stdout (this is use `-` as the filename to explicitly send the output to stdout (this is
useful e.g. when using multiple reporters). useful e.g. when using multiple reporters).
> Support for `-` as the filename was introduced in Catch2 X.Y.Z > Support for `-` as the filename was introduced in Catch2 3.0.1
Filenames starting with "%" (percent symbol) are reserved by Catch2 for Filenames starting with "%" (percent symbol) are reserved by Catch2 for
meta purposes, e.g. using `%debug` as the filename opens stream that meta purposes, e.g. using `%debug` as the filename opens stream that
@ -242,7 +242,7 @@ Catch2 currently recognizes 3 meta streams:
* `%stdout` - writes to stdout * `%stdout` - writes to stdout
* `%stderr` - writes to stderr * `%stderr` - writes to stderr
> Support for `%stdout` and `%stderr` was introduced in Catch2 X.Y.Z > Support for `%stdout` and `%stderr` was introduced in Catch2 3.0.1
<a id="naming-a-test-run"></a> <a id="naming-a-test-run"></a>
@ -290,7 +290,7 @@ There are currently two warnings implemented:
// not match any tests. // not match any tests.
``` ```
> `UnmatchedTestSpec` was introduced in Catch2 X.Y.Z. > `UnmatchedTestSpec` was introduced in Catch2 3.0.1.
<a id="reporting-timings"></a> <a id="reporting-timings"></a>
@ -388,7 +388,7 @@ either before running any tests, after running all tests - or both, depending on
## Skip all benchmarks ## Skip all benchmarks
<pre>--skip-benchmarks</pre> <pre>--skip-benchmarks</pre>
> [Introduced](https://github.com/catchorg/Catch2/issues/2408) in Catch X.Y.Z. > [Introduced](https://github.com/catchorg/Catch2/issues/2408) in Catch2 3.0.1.
This flag tells Catch2 to skip running all benchmarks. Benchmarks in this This flag tells Catch2 to skip running all benchmarks. Benchmarks in this
case mean code blocks in `BENCHMARK` and `BENCHMARK_ADVANCED` macros, not case mean code blocks in `BENCHMARK` and `BENCHMARK_ADVANCED` macros, not
@ -507,7 +507,7 @@ So, for example, tests within the file `~\Dev\MyProject\Ferrets.cpp` would be t
## Override output colouring ## Override output colouring
<pre>--colour-mode &lt;ansi|win32|none|default&gt;</pre> <pre>--colour-mode &lt;ansi|win32|none|default&gt;</pre>
> The `--colour-mode` option replaced the old `--colour` option in Catch2 X.Y.Z > The `--colour-mode` option replaced the old `--colour` option in Catch2 3.0.1
Catch2 support two different ways of colouring terminal output, and by Catch2 support two different ways of colouring terminal output, and by
@ -531,7 +531,7 @@ when writing to a file
## Test Sharding ## Test Sharding
<pre>--shard-count <#number of shards>, --shard-index <#shard index to run></pre> <pre>--shard-count <#number of shards>, --shard-index <#shard index to run></pre>
> [Introduced](https://github.com/catchorg/Catch2/pull/2257) in Catch2 X.Y.Z. > [Introduced](https://github.com/catchorg/Catch2/pull/2257) in Catch2 3.0.1.
When `--shard-count <#number of shards>` is used, the tests to execute will be split evenly in to the given number of sets, When `--shard-count <#number of shards>` is used, the tests to execute will be split evenly in to the given number of sets,
identified by indicies starting at 0. The tests in the set given by `--shard-index <#shard index to run>` will be executed. identified by indicies starting at 0. The tests in the set given by `--shard-index <#shard index to run>` will be executed.
@ -544,7 +544,7 @@ This is useful when you want to split test execution across multiple processes,
## Allow running the binary without tests ## Allow running the binary without tests
<pre>--allow-running-no-tests</pre> <pre>--allow-running-no-tests</pre>
> Introduced in Catch2 X.Y.Z. > Introduced in Catch2 3.0.1.
By default, Catch2 test binaries return non-0 exit code if no tests were By default, Catch2 test binaries return non-0 exit code if no tests were
run, e.g. if the binary was compiled with no tests, or the provided test run, e.g. if the binary was compiled with no tests, or the provided test

View File

@ -101,7 +101,7 @@ is equivalent with the out-of-the-box experience.
When `CATCH_CONFIG_BAZEL_SUPPORT` is defined, Catch2 will register a `JUnit` When `CATCH_CONFIG_BAZEL_SUPPORT` is defined, Catch2 will register a `JUnit`
reporter writing to a path pointed by `XML_OUTPUT_FILE` provided by Bazel. reporter writing to a path pointed by `XML_OUTPUT_FILE` provided by Bazel.
> `CATCH_CONFIG_BAZEL_SUPPORT` was [introduced](https://github.com/catchorg/Catch2/pull/2399) in Catch2 X.Y.Z. > `CATCH_CONFIG_BAZEL_SUPPORT` was [introduced](https://github.com/catchorg/Catch2/pull/2399) in Catch2 3.0.1.
## C++11 toggles ## C++11 toggles

View File

@ -248,7 +248,7 @@ Note that `DerivedException` in the example above has to derive from
### Generic range Matchers ### Generic range Matchers
> Generic range matchers were introduced in Catch2 X.Y.Z > Generic range matchers were introduced in Catch2 3.0.1
Catch2 also provides some matchers that use the new style matchers Catch2 also provides some matchers that use the new style matchers
definitions to handle generic range-like types. These are: definitions to handle generic range-like types. These are:
@ -350,7 +350,7 @@ style matchers arbitrarily.
## Writing custom matchers (new style) ## Writing custom matchers (new style)
> New style matchers were introduced in Catch2 X.Y.Z > New style matchers were introduced in Catch2 3.0.1
To create a new-style matcher, you have to create your own type that To create a new-style matcher, you have to create your own type that
derives from `Catch::Matchers::MatcherGenericBase`. Your type has to derives from `Catch::Matchers::MatcherGenericBase`. Your type has to

View File

@ -15,7 +15,7 @@ stringification machinery to the _expr_ and records the result. As with
evaluates to `true`. `CHECKED_ELSE( expr )` work similarly, but the block evaluates to `true`. `CHECKED_ELSE( expr )` work similarly, but the block
is entered only if the _expr_ evaluated to `false`. is entered only if the _expr_ evaluated to `false`.
> `CHECKED_X` macros were changed to not count as failure in Catch2 X.Y.Z. > `CHECKED_X` macros were changed to not count as failure in Catch2 3.0.1.
Example: Example:
```cpp ```cpp
@ -77,7 +77,7 @@ TEST_CASE("STATIC_REQUIRE showcase", "[traits]") {
} }
``` ```
> `STATIC_CHECK` was [introduced](https://github.com/catchorg/Catch2/pull/2318) in Catch2 X.Y.Z. > `STATIC_CHECK` was [introduced](https://github.com/catchorg/Catch2/pull/2318) in Catch2 3.0.1.
`STATIC_CHECK( expr )` is equivalent to `STATIC_REQUIRE( expr )`, with the `STATIC_CHECK( expr )` is equivalent to `STATIC_REQUIRE( expr )`, with the
difference that when `CATCH_CONFIG_RUNTIME_STATIC_REQUIRE` is defined, it difference that when `CATCH_CONFIG_RUNTIME_STATIC_REQUIRE` is defined, it

View File

@ -2,7 +2,7 @@
# Release notes # Release notes
**Contents**<br> **Contents**<br>
[3.0.1 (in progress)](#301-in-progress)<br> [3.0.1](#301)<br>
[2.13.7](#2137)<br> [2.13.7](#2137)<br>
[2.13.6](#2136)<br> [2.13.6](#2136)<br>
[2.13.5](#2135)<br> [2.13.5](#2135)<br>
@ -49,7 +49,7 @@
[Even Older versions](#even-older-versions)<br> [Even Older versions](#even-older-versions)<br>
## 3.0.1 (in progress) ## 3.0.1
**Catch2 now uses statically compiled library as its distribution model. **Catch2 now uses statically compiled library as its distribution model.
This also means that to get all of Catch2's functionality in a test file, This also means that to get all of Catch2's functionality in a test file,
@ -206,6 +206,7 @@ v3 releases.
* The cumulative reporter base stores benchmark results alongside assertion results * The cumulative reporter base stores benchmark results alongside assertion results
* Catch2's SE handling should no longer interferes with ASan on Windows (#2334) * Catch2's SE handling should no longer interferes with ASan on Windows (#2334)
* Fixed Windows console colour handling for tests that redirect stdout (#2345) * Fixed Windows console colour handling for tests that redirect stdout (#2345)
* Fixed issue with the `random` generators returning the same value over and over again
### Other changes ### Other changes
@ -230,6 +231,7 @@ v3 releases.
* `-DCATCH_CONFIG_ANDROID_LOGWRITE=OFF` does nothing (the define will not exist) * `-DCATCH_CONFIG_ANDROID_LOGWRITE=OFF` does nothing (the define will not exist)
## 2.13.7 ## 2.13.7
### Fixes ### Fixes

View File

@ -56,7 +56,7 @@ are handled by a different event.
### `testCasePartial` events ### `testCasePartial` events
> Introduced in Catch2 X.Y.Z > Introduced in Catch2 3.0.1
```cpp ```cpp
void testCasePartialStarting( TestCaseInfo const& testInfo, uint64_t partNumber ); void testCasePartialStarting( TestCaseInfo const& testInfo, uint64_t partNumber );
@ -135,7 +135,7 @@ benchmarking itself fails.
## Listings events ## Listings events
> Introduced in Catch2 X.Y.Z. > Introduced in Catch2 3.0.1.
Listings events are events that correspond to the test binary being Listings events are events that correspond to the test binary being
invoked with `--list-foo` flag. invoked with `--list-foo` flag.

View File

@ -30,7 +30,7 @@ reporters](#multiple-reporters) to avoid any surprises from doing so.
<a id="multiple-reporters"></a> <a id="multiple-reporters"></a>
## Using multiple reporters ## Using multiple reporters
> Support for having multiple parallel reporters was [introduced](https://github.com/catchorg/Catch2/pull/2183) in Catch2 X.Y.Z > Support for having multiple parallel reporters was [introduced](https://github.com/catchorg/Catch2/pull/2183) in Catch2 3.0.1
Catch2 supports using multiple reporters at the same time while having Catch2 supports using multiple reporters at the same time while having
them write into different destinations. The two main uses of this are them write into different destinations. The two main uses of this are
@ -169,7 +169,7 @@ Currently there are two customization options:
### Per-reporter configuration ### Per-reporter configuration
> Per-reporter configuration was introduced in Catch2 X.Y.Z > Per-reporter configuration was introduced in Catch2 3.0.1
Catch2 supports some configuration to happen per reporter. The configuration Catch2 supports some configuration to happen per reporter. The configuration
options fall into one of two categories: options fall into one of two categories:

View File

@ -5,8 +5,8 @@
// SPDX-License-Identifier: BSL-1.0 // SPDX-License-Identifier: BSL-1.0
// Catch v3.0.0-preview.5 // Catch v3.0.1
// Generated: 2022-04-20 23:45:15.004945 // Generated: 2022-05-17 22:08:47.054486
// ---------------------------------------------------------- // ----------------------------------------------------------
// This file is an amalgamation of multiple different files. // This file is an amalgamation of multiple different files.
// You probably shouldn't edit it directly. // You probably shouldn't edit it directly.
@ -145,6 +145,15 @@ namespace Catch {
namespace Benchmark { namespace Benchmark {
namespace Detail { namespace Detail {
#if defined( __GNUC__ ) || defined( __clang__ )
# pragma GCC diagnostic push
# pragma GCC diagnostic ignored "-Wfloat-equal"
#endif
bool directCompare( double lhs, double rhs ) { return lhs == rhs; }
#if defined( __GNUC__ ) || defined( __clang__ )
# pragma GCC diagnostic pop
#endif
double weighted_average_quantile(int k, int q, std::vector<double>::iterator first, std::vector<double>::iterator last) { double weighted_average_quantile(int k, int q, std::vector<double>::iterator first, std::vector<double>::iterator last) {
auto count = last - first; auto count = last - first;
double idx = (count - 1) * k / static_cast<double>(q); double idx = (count - 1) * k / static_cast<double>(q);
@ -152,7 +161,9 @@ namespace Catch {
double g = idx - j; double g = idx - j;
std::nth_element(first, first + j, last); std::nth_element(first, first + j, last);
auto xj = first[j]; auto xj = first[j];
if (g == 0) return xj; if ( directCompare( g, 0 ) ) {
return xj;
}
auto xj1 = *std::min_element(first + (j + 1), last); auto xj1 = *std::min_element(first + (j + 1), last);
return xj + g * (xj1 - xj); return xj + g * (xj1 - xj);
@ -594,6 +605,7 @@ namespace Catch {
bool Config::listTests() const { return m_data.listTests; } bool Config::listTests() const { return m_data.listTests; }
bool Config::listTags() const { return m_data.listTags; } bool Config::listTags() const { return m_data.listTags; }
bool Config::listReporters() const { return m_data.listReporters; } bool Config::listReporters() const { return m_data.listReporters; }
bool Config::listListeners() const { return m_data.listListeners; }
std::vector<std::string> const& Config::getTestsOrTags() const { return m_data.testsOrTags; } std::vector<std::string> const& Config::getTestsOrTags() const { return m_data.testsOrTags; }
std::vector<std::string> const& Config::getSectionsToRun() const { return m_data.sectionsToRun; } std::vector<std::string> const& Config::getSectionsToRun() const { return m_data.sectionsToRun; }
@ -635,6 +647,7 @@ namespace Catch {
bool Config::showInvisibles() const { return m_data.showInvisibles; } bool Config::showInvisibles() const { return m_data.showInvisibles; }
Verbosity Config::verbosity() const { return m_data.verbosity; } Verbosity Config::verbosity() const { return m_data.verbosity; }
bool Config::skipBenchmarks() const { return m_data.skipBenchmarks; }
bool Config::benchmarkNoAnalysis() const { return m_data.benchmarkNoAnalysis; } bool Config::benchmarkNoAnalysis() const { return m_data.benchmarkNoAnalysis; }
unsigned int Config::benchmarkSamples() const { return m_data.benchmarkSamples; } unsigned int Config::benchmarkSamples() const { return m_data.benchmarkSamples; }
double Config::benchmarkConfidenceInterval() const { return m_data.benchmarkConfidenceInterval; } double Config::benchmarkConfidenceInterval() const { return m_data.benchmarkConfidenceInterval; }
@ -1215,7 +1228,7 @@ namespace Catch {
else if( tag == "!nonportable"_sr ) else if( tag == "!nonportable"_sr )
return TestCaseProperties::NonPortable; return TestCaseProperties::NonPortable;
else if( tag == "!benchmark"_sr ) else if( tag == "!benchmark"_sr )
return static_cast<TestCaseProperties>(TestCaseProperties::Benchmark | TestCaseProperties::IsHidden ); return TestCaseProperties::Benchmark | TestCaseProperties::IsHidden;
else else
return TestCaseProperties::None; return TestCaseProperties::None;
} }
@ -1860,13 +1873,19 @@ namespace Catch {
} }
Version const& libraryVersion() { Version const& libraryVersion() {
static Version version( 3, 0, 0, "preview", 5 ); static Version version( 3, 0, 1, "", 0 );
return version; return version;
} }
} }
std::uint32_t Catch::Generators::Detail::getSeed() { return sharedRng()(); }
/** \file /** \file
* This is a special TU that combines what would otherwise be a very * This is a special TU that combines what would otherwise be a very
* small generator-related TUs into one bigger TU. * small generator-related TUs into one bigger TU.
@ -2001,6 +2020,32 @@ namespace Catch {
#include <string>
namespace Catch {
namespace Generators {
bool GeneratorUntypedBase::countedNext() {
auto ret = next();
if ( ret ) {
m_stringReprCache.clear();
++m_currentElementIndex;
}
return ret;
}
StringRef GeneratorUntypedBase::currentElementAsString() const {
if ( m_stringReprCache.empty() ) {
m_stringReprCache = stringifyImpl();
}
return m_stringReprCache;
}
} // namespace Generators
} // namespace Catch
#include <algorithm> #include <algorithm>
#include <cassert> #include <cassert>
#include <iomanip> #include <iomanip>
@ -2412,7 +2457,7 @@ namespace Catch {
return Detail::InternalParseResult::runtimeError( return Detail::InternalParseResult::runtimeError(
"Expected argument following " + "Expected argument following " +
token.token); token.token);
auto result = valueRef->setValue(argToken.token); const auto result = valueRef->setValue(argToken.token);
if (!result) if (!result)
return Detail::InternalParseResult(result); return Detail::InternalParseResult(result);
if (result.value() == if (result.value() ==
@ -3109,7 +3154,10 @@ namespace Catch {
( "list all/matching tags" ) ( "list all/matching tags" )
| Opt( config.listReporters ) | Opt( config.listReporters )
["--list-reporters"] ["--list-reporters"]
( "list all reporters" ) ( "list all available reporters" )
| Opt( config.listListeners )
["--list-listeners"]
( "list all listeners" )
| Opt( setTestOrder, "decl|lex|rand" ) | Opt( setTestOrder, "decl|lex|rand" )
["--order"] ["--order"]
( "test case order (defaults to decl)" ) ( "test case order (defaults to decl)" )
@ -3125,6 +3173,9 @@ namespace Catch {
| Opt( setWaitForKeypress, "never|start|exit|both" ) | Opt( setWaitForKeypress, "never|start|exit|both" )
["--wait-for-keypress"] ["--wait-for-keypress"]
( "waits for a keypress before exiting" ) ( "waits for a keypress before exiting" )
| Opt( config.skipBenchmarks)
["--skip-benchmarks"]
( "disable running benchmarks")
| Opt( config.benchmarkSamples, "samples" ) | Opt( config.benchmarkSamples, "samples" )
["--benchmark-samples"] ["--benchmark-samples"]
( "number of samples to collect (default: 100)" ) ( "number of samples to collect (default: 100)" )
@ -3230,7 +3281,6 @@ namespace Catch {
class NoColourImpl : public ColourImpl { class NoColourImpl : public ColourImpl {
public: public:
NoColourImpl( IStream* stream ): ColourImpl( stream ) {} NoColourImpl( IStream* stream ): ColourImpl( stream ) {}
static bool useColourOnPlatform() { return true; }
private: private:
void use( Colour::Code ) const override {} void use( Colour::Code ) const override {}
@ -3257,7 +3307,7 @@ namespace {
originalBackgroundAttributes = csbiInfo.wAttributes & ~( FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE | FOREGROUND_INTENSITY ); originalBackgroundAttributes = csbiInfo.wAttributes & ~( FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE | FOREGROUND_INTENSITY );
} }
static bool useColourOnPlatform(IStream const& stream) { static bool useImplementationForStream(IStream const& stream) {
// Win32 text colour APIs can only be used on console streams // Win32 text colour APIs can only be used on console streams
// We cannot check that the output hasn't been redirected, // We cannot check that the output hasn't been redirected,
// so we just check that the original stream is console stream. // so we just check that the original stream is console stream.
@ -3316,7 +3366,7 @@ namespace {
public: public:
ANSIColourImpl( IStream* stream ): ColourImpl( stream ) {} ANSIColourImpl( IStream* stream ): ColourImpl( stream ) {}
static bool useColourOnPlatform(IStream const& stream) { static bool useImplementationForStream(IStream const& stream) {
// This is kinda messy due to trying to support a bunch of // This is kinda messy due to trying to support a bunch of
// different platforms at once. // different platforms at once.
// The basic idea is that if we are asked to do autodetection (as // The basic idea is that if we are asked to do autodetection (as
@ -3390,13 +3440,13 @@ namespace Catch {
// todo: check win32 eligibility under ifdef, otherwise ansi // todo: check win32 eligibility under ifdef, otherwise ansi
if ( implSelection == ColourMode::PlatformDefault) { if ( implSelection == ColourMode::PlatformDefault) {
#if defined (CATCH_CONFIG_COLOUR_WIN32) #if defined (CATCH_CONFIG_COLOUR_WIN32)
if ( Win32ColourImpl::useColourOnPlatform( *stream ) ) { if ( Win32ColourImpl::useImplementationForStream( *stream ) ) {
return Detail::make_unique<Win32ColourImpl>( stream ); return Detail::make_unique<Win32ColourImpl>( stream );
} else { } else {
return Detail::make_unique<NoColourImpl>( stream ); return Detail::make_unique<NoColourImpl>( stream );
} }
#endif #endif
if ( ANSIColourImpl::useColourOnPlatform( *stream ) ) { if ( ANSIColourImpl::useImplementationForStream( *stream ) ) {
return Detail::make_unique<ANSIColourImpl>( stream ); return Detail::make_unique<ANSIColourImpl>( stream );
} }
return Detail::make_unique<NoColourImpl>( stream ); return Detail::make_unique<NoColourImpl>( stream );
@ -3475,7 +3525,7 @@ namespace Catch {
Context::~Context() = default; Context::~Context() = default;
SimplePcg32& rng() { SimplePcg32& sharedRng() {
static SimplePcg32 s_rng; static SimplePcg32 s_rng;
return s_rng; return s_rng;
} }
@ -4079,7 +4129,7 @@ namespace Detail {
setp( data, data + sizeof(data) ); setp( data, data + sizeof(data) );
} }
~StreamBufImpl() noexcept { ~StreamBufImpl() noexcept override {
StreamBufImpl::sync(); StreamBufImpl::sync();
} }
@ -4250,6 +4300,19 @@ namespace Catch {
reporter.listReporters(descriptions); reporter.listReporters(descriptions);
} }
void listListeners(IEventListener& reporter) {
std::vector<ListenerDescription> descriptions;
auto const& factories =
getRegistryHub().getReporterRegistry().getListeners();
descriptions.reserve( factories.size() );
for ( auto const& fac : factories ) {
descriptions.push_back( { fac->getName(), fac->getDescription() } );
}
reporter.listListeners( descriptions );
}
} // end anonymous namespace } // end anonymous namespace
void TagInfo::add( StringRef spelling ) { void TagInfo::add( StringRef spelling ) {
@ -4287,6 +4350,10 @@ namespace Catch {
listed = true; listed = true;
listReporters(reporter); listReporters(reporter);
} }
if ( config.listListeners() ) {
listed = true;
listListeners( reporter );
}
return listed; return listed;
} }
@ -4297,7 +4364,7 @@ namespace Catch {
namespace Catch { namespace Catch {
CATCH_INTERNAL_START_WARNINGS_SUPPRESSION CATCH_INTERNAL_START_WARNINGS_SUPPRESSION
CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS
LeakDetector leakDetector; static LeakDetector leakDetector;
CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION
} }
@ -4581,7 +4648,8 @@ namespace Catch {
void ReporterRegistry::registerReporter( std::string const& name, IReporterFactoryPtr factory ) { void ReporterRegistry::registerReporter( std::string const& name, IReporterFactoryPtr factory ) {
CATCH_ENFORCE( name.find( "::" ) == name.npos, CATCH_ENFORCE( name.find( "::" ) == name.npos,
"'::' is not allowed in reporter name: '" + name + '\'' ); "'::' is not allowed in reporter name: '" + name + '\'' );
m_factories.emplace(name, CATCH_MOVE(factory)); auto ret = m_factories.emplace(name, CATCH_MOVE(factory));
CATCH_ENFORCE( ret.second, "reporter using '" + name + "' as name was already registered" );
} }
void ReporterRegistry::registerListener( void ReporterRegistry::registerListener(
Detail::unique_ptr<EventListenerFactory> factory ) { Detail::unique_ptr<EventListenerFactory> factory ) {
@ -4851,7 +4919,7 @@ namespace Catch {
GeneratorTracker( TestCaseTracking::NameAndLocation const& nameAndLocation, TrackerContext& ctx, ITracker* parent ) GeneratorTracker( TestCaseTracking::NameAndLocation const& nameAndLocation, TrackerContext& ctx, ITracker* parent )
: TrackerBase( nameAndLocation, ctx, parent ) : TrackerBase( nameAndLocation, ctx, parent )
{} {}
~GeneratorTracker(); ~GeneratorTracker() override;
static GeneratorTracker& acquire( TrackerContext& ctx, TestCaseTracking::NameAndLocation const& nameAndLocation ) { static GeneratorTracker& acquire( TrackerContext& ctx, TestCaseTracking::NameAndLocation const& nameAndLocation ) {
GeneratorTracker* tracker; GeneratorTracker* tracker;
@ -4962,7 +5030,7 @@ namespace Catch {
// this generator is still waiting for any child to start. // this generator is still waiting for any child to start.
if ( should_wait_for_child || if ( should_wait_for_child ||
( m_runState == CompletedSuccessfully && ( m_runState == CompletedSuccessfully &&
m_generator->next() ) ) { m_generator->countedNext() ) ) {
m_children.clear(); m_children.clear();
m_runState = Executing; m_runState = Executing;
} }
@ -5012,6 +5080,39 @@ namespace Catch {
assert(rootTracker.isSectionTracker()); assert(rootTracker.isSectionTracker());
static_cast<SectionTracker&>(rootTracker).addInitialFilters(m_config->getSectionsToRun()); static_cast<SectionTracker&>(rootTracker).addInitialFilters(m_config->getSectionsToRun());
// We intentionally only seed the internal RNG once per test case,
// before it is first invoked. The reason for that is a complex
// interplay of generator/section implementation details and the
// Random*Generator types.
//
// The issue boils down to us needing to seed the Random*Generators
// with different seed each, so that they return different sequences
// of random numbers. We do this by giving them a number from the
// shared RNG instance as their seed.
//
// However, this runs into an issue if the reseeding happens each
// time the test case is entered (as opposed to first time only),
// because multiple generators could get the same seed, e.g. in
// ```cpp
// TEST_CASE() {
// auto i = GENERATE(take(10, random(0, 100));
// SECTION("A") {
// auto j = GENERATE(take(10, random(0, 100));
// }
// SECTION("B") {
// auto k = GENERATE(take(10, random(0, 100));
// }
// }
// ```
// `i` and `j` would properly return values from different sequences,
// but `i` and `k` would return the same sequence, because their seed
// would be the same.
// (The reason their seeds would be the same is that the generator
// for k would be initialized when the test case is entered the second
// time, after the shared RNG instance was reset to the same value
// it had when the generator for i was initialized.)
seedRng( *m_config );
uint64_t testRuns = 0; uint64_t testRuns = 0;
do { do {
m_trackerContext.startCycle(); m_trackerContext.startCycle();
@ -5241,8 +5342,6 @@ namespace Catch {
m_shouldReportUnexpected = true; m_shouldReportUnexpected = true;
m_lastAssertionInfo = { "TEST_CASE"_sr, testCaseInfo.lineInfo, StringRef(), ResultDisposition::Normal }; m_lastAssertionInfo = { "TEST_CASE"_sr, testCaseInfo.lineInfo, StringRef(), ResultDisposition::Normal };
seedRng(*m_config);
Timer timer; Timer timer;
CATCH_TRY { CATCH_TRY {
if (m_reporter->getPreferences().shouldRedirectStdOut) { if (m_reporter->getPreferences().shouldRedirectStdOut) {
@ -5417,10 +5516,7 @@ namespace Catch {
} }
void seedRng(IConfig const& config) { void seedRng(IConfig const& config) {
if (config.rngSeed() != 0) { sharedRng().seed(config.rngSeed());
std::srand(config.rngSeed());
rng().seed(config.rngSeed());
}
} }
unsigned int rngSeed() { unsigned int rngSeed() {
@ -5642,7 +5738,7 @@ namespace Catch {
namespace Catch { namespace Catch {
StringRef::StringRef( char const* rawChars ) noexcept StringRef::StringRef( char const* rawChars ) noexcept
: StringRef( rawChars, static_cast<StringRef::size_type>(std::strlen(rawChars) ) ) : StringRef( rawChars, std::strlen(rawChars) )
{} {}
auto StringRef::operator == ( StringRef other ) const noexcept -> bool { auto StringRef::operator == ( StringRef other ) const noexcept -> bool {
@ -7213,14 +7309,26 @@ namespace Detail {
ret << " (["; ret << " ([";
if (m_type == Detail::FloatingPointKind::Double) { if (m_type == Detail::FloatingPointKind::Double) {
write(ret, step(m_target, static_cast<double>(-INFINITY), m_ulps)); write( ret,
step( m_target,
-std::numeric_limits<double>::infinity(),
m_ulps ) );
ret << ", "; ret << ", ";
write(ret, step(m_target, static_cast<double>( INFINITY), m_ulps)); write( ret,
step( m_target,
std::numeric_limits<double>::infinity(),
m_ulps ) );
} else { } else {
// We have to cast INFINITY to float because of MinGW, see #1782 // We have to cast INFINITY to float because of MinGW, see #1782
write(ret, step(static_cast<float>(m_target), static_cast<float>(-INFINITY), m_ulps)); write( ret,
step( static_cast<float>( m_target ),
-std::numeric_limits<float>::infinity(),
m_ulps ) );
ret << ", "; ret << ", ";
write(ret, step(static_cast<float>(m_target), static_cast<float>( INFINITY), m_ulps)); write( ret,
step( static_cast<float>( m_target ),
std::numeric_limits<float>::infinity(),
m_ulps ) );
} }
ret << "])"; ret << "])";
@ -7706,6 +7814,33 @@ namespace Catch {
out << '\n' << std::flush; out << '\n' << std::flush;
} }
void defaultListListeners( std::ostream& out,
std::vector<ListenerDescription> const& descriptions ) {
const auto maxNameLen =
std::max_element( descriptions.begin(),
descriptions.end(),
[]( ListenerDescription const& lhs,
ListenerDescription const& rhs ) {
return lhs.name.size() < rhs.name.size();
} )
->name.size();
out << "Registered listeners:\n";
for ( auto const& desc : descriptions ) {
out << TextFlow::Column( static_cast<std::string>( desc.name ) +
':' )
.indent( 2 )
.width( maxNameLen + 5 ) +
TextFlow::Column( desc.description )
.initialIndent( 0 )
.indent( 2 )
.width( CATCH_CONFIG_CONSOLE_WIDTH - maxNameLen - 8 )
<< '\n';
}
out << '\n' << std::flush;
}
void defaultListTags( std::ostream& out, void defaultListTags( std::ostream& out,
std::vector<TagInfo> const& tags, std::vector<TagInfo> const& tags,
bool isFiltered ) { bool isFiltered ) {
@ -7786,6 +7921,8 @@ namespace Catch {
void EventListenerBase::assertionEnded( AssertionStats const& ) {} void EventListenerBase::assertionEnded( AssertionStats const& ) {}
void EventListenerBase::listReporters( void EventListenerBase::listReporters(
std::vector<ReporterDescription> const& ) {} std::vector<ReporterDescription> const& ) {}
void EventListenerBase::listListeners(
std::vector<ListenerDescription> const& ) {}
void EventListenerBase::listTests( std::vector<TestCaseHandle> const& ) {} void EventListenerBase::listTests( std::vector<TestCaseHandle> const& ) {}
void EventListenerBase::listTags( std::vector<TagInfo> const& ) {} void EventListenerBase::listTags( std::vector<TagInfo> const& ) {}
void EventListenerBase::noMatchingTestCases( StringRef ) {} void EventListenerBase::noMatchingTestCases( StringRef ) {}
@ -7822,6 +7959,11 @@ namespace Catch {
defaultListReporters(m_stream, descriptions, m_config->verbosity()); defaultListReporters(m_stream, descriptions, m_config->verbosity());
} }
void ReporterBase::listListeners(
std::vector<ListenerDescription> const& descriptions ) {
defaultListListeners( m_stream, descriptions );
}
void ReporterBase::listTests(std::vector<TestCaseHandle> const& tests) { void ReporterBase::listTests(std::vector<TestCaseHandle> const& tests) {
defaultListTests(m_stream, defaultListTests(m_stream,
m_colour.get(), m_colour.get(),
@ -9415,6 +9557,13 @@ namespace Catch {
} }
} }
void MultiReporter::listListeners(
std::vector<ListenerDescription> const& descriptions ) {
for ( auto& reporterish : m_reporterLikes ) {
reporterish->listListeners( descriptions );
}
}
void MultiReporter::listTests(std::vector<TestCaseHandle> const& tests) { void MultiReporter::listTests(std::vector<TestCaseHandle> const& tests) {
for (auto& reporterish : m_reporterLikes) { for (auto& reporterish : m_reporterLikes) {
reporterish->listTests(tests); reporterish->listTests(tests);
@ -9432,6 +9581,29 @@ namespace Catch {
namespace Catch {
namespace Detail {
void registerReporterImpl( std::string const& name,
IReporterFactoryPtr reporterPtr ) {
CATCH_TRY {
getMutableRegistryHub().registerReporter(
name, CATCH_MOVE( reporterPtr ) );
}
CATCH_CATCH_ALL {
// Do not throw when constructing global objects, instead
// register the exception to be processed later
getMutableRegistryHub().registerStartupException();
}
}
} // namespace Detail
} // namespace Catch
#include <map> #include <map>
namespace Catch { namespace Catch {
@ -9689,11 +9861,6 @@ namespace Catch {
} }
private: private:
void printSourceInfo() const {
stream << colourImpl->guardColour( tapDimColour )
<< result.getSourceInfo() << ':';
}
void printResultType(StringRef passOrFail) const { void printResultType(StringRef passOrFail) const {
if (!passOrFail.empty()) { if (!passOrFail.empty()) {
stream << passOrFail << ' ' << counter << " -"; stream << passOrFail << ' ' << counter << " -";
@ -10009,7 +10176,8 @@ namespace Catch {
m_xml.writeStylesheetRef( stylesheetRef ); m_xml.writeStylesheetRef( stylesheetRef );
m_xml.startElement("Catch2TestRun") m_xml.startElement("Catch2TestRun")
.writeAttribute("name"_sr, m_config->name()) .writeAttribute("name"_sr, m_config->name())
.writeAttribute("rng-seed"_sr, m_config->rngSeed()); .writeAttribute("rng-seed"_sr, m_config->rngSeed())
.writeAttribute("catch2-version"_sr, libraryVersion());
if (m_config->testSpec().hasFilters()) if (m_config->testSpec().hasFilters())
m_xml.writeAttribute( "filters"_sr, serializeFilters( m_config->getTestsOrTags() ) ); m_xml.writeAttribute( "filters"_sr, serializeFilters( m_config->getTestsOrTags() ) );
} }
@ -10212,6 +10380,19 @@ namespace Catch {
} }
} }
void XmlReporter::listListeners(std::vector<ListenerDescription> const& descriptions) {
auto outerTag = m_xml.scopedElement( "RegisteredListeners" );
for ( auto const& listener : descriptions ) {
auto inner = m_xml.scopedElement( "Listener" );
m_xml.startElement( "Name", XmlFormatting::Indent )
.writeText( listener.name, XmlFormatting::None )
.endElement( XmlFormatting::Newline );
m_xml.startElement( "Description", XmlFormatting::Indent )
.writeText( listener.description, XmlFormatting::None )
.endElement( XmlFormatting::Newline );
}
}
void XmlReporter::listTests(std::vector<TestCaseHandle> const& tests) { void XmlReporter::listTests(std::vector<TestCaseHandle> const& tests) {
auto outerTag = m_xml.scopedElement("MatchingTests"); auto outerTag = m_xml.scopedElement("MatchingTests");
for (auto const& test : tests) { for (auto const& test : tests) {

View File

@ -5,8 +5,8 @@
// SPDX-License-Identifier: BSL-1.0 // SPDX-License-Identifier: BSL-1.0
// Catch v3.0.0-preview.5 // Catch v3.0.1
// Generated: 2022-04-20 23:45:13.582550 // Generated: 2022-05-17 22:08:46.674860
// ---------------------------------------------------------- // ----------------------------------------------------------
// This file is an amalgamation of multiple different files. // This file is an amalgamation of multiple different files.
// You probably shouldn't edit it directly. // You probably shouldn't edit it directly.
@ -274,6 +274,7 @@ namespace Catch {
virtual std::vector<std::string> const& getSectionsToRun() const = 0; virtual std::vector<std::string> const& getSectionsToRun() const = 0;
virtual Verbosity verbosity() const = 0; virtual Verbosity verbosity() const = 0;
virtual bool skipBenchmarks() const = 0;
virtual bool benchmarkNoAnalysis() const = 0; virtual bool benchmarkNoAnalysis() const = 0;
virtual unsigned int benchmarkSamples() const = 0; virtual unsigned int benchmarkSamples() const = 0;
virtual double benchmarkConfidenceInterval() const = 0; virtual double benchmarkConfidenceInterval() const = 0;
@ -688,7 +689,7 @@ namespace Catch {
class IMutableContext : public IContext { class IMutableContext : public IContext {
public: public:
virtual ~IMutableContext(); // = default ~IMutableContext() override; // = default
virtual void setResultCapture( IResultCapture* resultCapture ) = 0; virtual void setResultCapture( IResultCapture* resultCapture ) = 0;
virtual void setConfig( IConfig const* config ) = 0; virtual void setConfig( IConfig const* config ) = 0;
@ -715,7 +716,7 @@ namespace Catch {
void cleanUpContext(); void cleanUpContext();
class SimplePcg32; class SimplePcg32;
SimplePcg32& rng(); SimplePcg32& sharedRng();
} }
#endif // CATCH_CONTEXT_HPP_INCLUDED #endif // CATCH_CONTEXT_HPP_INCLUDED
@ -1287,6 +1288,7 @@ namespace Catch {
namespace Catch { namespace Catch {
struct ReporterDescription; struct ReporterDescription;
struct ListenerDescription;
struct TagInfo; struct TagInfo;
struct TestCaseInfo; struct TestCaseInfo;
class TestCaseHandle; class TestCaseHandle;
@ -1509,11 +1511,12 @@ namespace Catch {
//! Writes out information about provided reporters using reporter-specific format //! Writes out information about provided reporters using reporter-specific format
virtual void listReporters(std::vector<ReporterDescription> const& descriptions) = 0; virtual void listReporters(std::vector<ReporterDescription> const& descriptions) = 0;
//! Writes out the provided listeners descriptions using reporter-specific format
virtual void listListeners(std::vector<ListenerDescription> const& descriptions) = 0;
//! Writes out information about provided tests using reporter-specific format //! Writes out information about provided tests using reporter-specific format
virtual void listTests(std::vector<TestCaseHandle> const& tests) = 0; virtual void listTests(std::vector<TestCaseHandle> const& tests) = 0;
//! Writes out information about the provided tags using reporter-specific format //! Writes out information about the provided tags using reporter-specific format
virtual void listTags(std::vector<TagInfo> const& tags) = 0; virtual void listTags(std::vector<TagInfo> const& tags) = 0;
}; };
using IEventListenerPtr = Detail::unique_ptr<IEventListener>; using IEventListenerPtr = Detail::unique_ptr<IEventListener>;
@ -2226,6 +2229,10 @@ namespace Catch {
namespace Detail { namespace Detail {
using sample = std::vector<double>; using sample = std::vector<double>;
// Used when we know we want == comparison of two doubles
// to centralize warning suppression
bool directCompare( double lhs, double rhs );
double weighted_average_quantile(int k, int q, std::vector<double>::iterator first, std::vector<double>::iterator last); double weighted_average_quantile(int k, int q, std::vector<double>::iterator first, std::vector<double>::iterator last);
template <typename Iterator> template <typename Iterator>
@ -2256,7 +2263,7 @@ namespace Catch {
double mean(Iterator first, Iterator last) { double mean(Iterator first, Iterator last) {
auto count = last - first; auto count = last - first;
double sum = std::accumulate(first, last, 0.); double sum = std::accumulate(first, last, 0.);
return sum / count; return sum / static_cast<double>(count);
} }
template <typename Estimator, typename Iterator> template <typename Estimator, typename Iterator>
@ -2302,15 +2309,17 @@ namespace Catch {
}); });
double accel = sum_cubes / (6 * std::pow(sum_squares, 1.5)); double accel = sum_cubes / (6 * std::pow(sum_squares, 1.5));
int n = static_cast<int>(resample.size()); long n = static_cast<long>(resample.size());
double prob_n = std::count_if(resample.begin(), resample.end(), [point](double x) { return x < point; }) / static_cast<double>(n); double prob_n = std::count_if(resample.begin(), resample.end(), [point](double x) { return x < point; }) / static_cast<double>(n);
// degenerate case with uniform samples // degenerate case with uniform samples
if (prob_n == 0) return { point, point, point, confidence_level }; if ( directCompare( prob_n, 0. ) ) {
return { point, point, point, confidence_level };
}
double bias = normal_quantile(prob_n); double bias = normal_quantile(prob_n);
double z1 = normal_quantile((1. - confidence_level) / 2.); double z1 = normal_quantile((1. - confidence_level) / 2.);
auto cumn = [n]( double x ) -> int { auto cumn = [n]( double x ) -> long {
return std::lround( normal_cdf( x ) * n ); return std::lround( normal_cdf( x ) * n );
}; };
auto a = [bias, accel](double b) { return bias + b / (1. - accel * b); }; auto a = [bias, accel](double b) { return bias + b / (1. - accel * b); };
@ -2318,7 +2327,7 @@ namespace Catch {
double b2 = bias - z1; double b2 = bias - z1;
double a1 = a(b1); double a1 = a(b1);
double a2 = a(b2); double a2 = a(b2);
auto lo = static_cast<size_t>((std::max)(cumn(a1), 0)); auto lo = static_cast<size_t>((std::max)(cumn(a1), 0l));
auto hi = static_cast<size_t>((std::min)(cumn(a2), n - 1)); auto hi = static_cast<size_t>((std::min)(cumn(a2), n - 1));
return { point, resample[lo], resample[hi], confidence_level }; return { point, resample[lo], resample[hi], confidence_level };
@ -2619,8 +2628,11 @@ namespace Catch {
// sets lambda to be used in fun *and* executes benchmark! // sets lambda to be used in fun *and* executes benchmark!
template <typename Fun, std::enable_if_t<!Detail::is_related<Fun, Benchmark>::value, int> = 0> template <typename Fun, std::enable_if_t<!Detail::is_related<Fun, Benchmark>::value, int> = 0>
Benchmark & operator=(Fun func) { Benchmark & operator=(Fun func) {
auto const* cfg = getCurrentContext().getConfig();
if (!cfg->skipBenchmarks()) {
fun = Detail::BenchmarkFunction(func); fun = Detail::BenchmarkFunction(func);
run(); run();
}
return *this; return *this;
} }
@ -2679,9 +2691,7 @@ namespace Catch {
template <typename T, bool Destruct> template <typename T, bool Destruct>
struct ObjectStorage struct ObjectStorage
{ {
using TStorage = std::aligned_storage_t<sizeof(T), std::alignment_of<T>::value>; ObjectStorage() = default;
ObjectStorage() : data() {}
ObjectStorage(const ObjectStorage& other) ObjectStorage(const ObjectStorage& other)
{ {
@ -2690,7 +2700,7 @@ namespace Catch {
ObjectStorage(ObjectStorage&& other) ObjectStorage(ObjectStorage&& other)
{ {
new(&data) T(CATCH_MOVE(other.stored_object())); new(data) T(CATCH_MOVE(other.stored_object()));
} }
~ObjectStorage() { destruct_on_exit<T>(); } ~ObjectStorage() { destruct_on_exit<T>(); }
@ -2698,7 +2708,7 @@ namespace Catch {
template <typename... Args> template <typename... Args>
void construct(Args&&... args) void construct(Args&&... args)
{ {
new (&data) T(CATCH_FORWARD(args)...); new (data) T(CATCH_FORWARD(args)...);
} }
template <bool AllowManualDestruction = !Destruct> template <bool AllowManualDestruction = !Destruct>
@ -2710,21 +2720,21 @@ namespace Catch {
private: private:
// If this is a constructor benchmark, destruct the underlying object // If this is a constructor benchmark, destruct the underlying object
template <typename U> template <typename U>
void destruct_on_exit(std::enable_if_t<Destruct, U>* = 0) { destruct<true>(); } void destruct_on_exit(std::enable_if_t<Destruct, U>* = nullptr) { destruct<true>(); }
// Otherwise, don't // Otherwise, don't
template <typename U> template <typename U>
void destruct_on_exit(std::enable_if_t<!Destruct, U>* = 0) { } void destruct_on_exit(std::enable_if_t<!Destruct, U>* = nullptr) { }
T& stored_object() { T& stored_object() {
return *static_cast<T*>(static_cast<void*>(&data)); return *static_cast<T*>(static_cast<void*>(data));
} }
T const& stored_object() const { T const& stored_object() const {
return *static_cast<T*>(static_cast<void*>(&data)); return *static_cast<T*>(static_cast<void*>(data));
} }
TStorage data; alignas( T ) unsigned char data[sizeof( T )]{};
}; };
} // namespace Detail } // namespace Detail
@ -4147,6 +4157,7 @@ namespace Catch {
bool listTests = false; bool listTests = false;
bool listTags = false; bool listTags = false;
bool listReporters = false; bool listReporters = false;
bool listListeners = false;
bool showSuccessfulTests = false; bool showSuccessfulTests = false;
bool shouldDebugBreak = false; bool shouldDebugBreak = false;
@ -4163,6 +4174,7 @@ namespace Catch {
unsigned int shardCount = 1; unsigned int shardCount = 1;
unsigned int shardIndex = 0; unsigned int shardIndex = 0;
bool skipBenchmarks = false;
bool benchmarkNoAnalysis = false; bool benchmarkNoAnalysis = false;
unsigned int benchmarkSamples = 100; unsigned int benchmarkSamples = 100;
double benchmarkConfidenceInterval = 0.95; double benchmarkConfidenceInterval = 0.95;
@ -4197,6 +4209,7 @@ namespace Catch {
bool listTests() const; bool listTests() const;
bool listTags() const; bool listTags() const;
bool listReporters() const; bool listReporters() const;
bool listListeners() const;
std::vector<ReporterSpec> const& getReporterSpecs() const; std::vector<ReporterSpec> const& getReporterSpecs() const;
std::vector<ProcessedReporterSpec> const& std::vector<ProcessedReporterSpec> const&
@ -4228,6 +4241,7 @@ namespace Catch {
int abortAfter() const override; int abortAfter() const override;
bool showInvisibles() const override; bool showInvisibles() const override;
Verbosity verbosity() const override; Verbosity verbosity() const override;
bool skipBenchmarks() const override;
bool benchmarkNoAnalysis() const override; bool benchmarkNoAnalysis() const override;
unsigned int benchmarkSamples() const override; unsigned int benchmarkSamples() const override;
double benchmarkConfidenceInterval() const override; double benchmarkConfidenceInterval() const override;
@ -6993,6 +7007,7 @@ namespace Catch {
#endif // CATCH_TRANSLATE_EXCEPTION_HPP_INCLUDED #endif // CATCH_TRANSLATE_EXCEPTION_HPP_INCLUDED
#ifndef CATCH_VERSION_HPP_INCLUDED #ifndef CATCH_VERSION_HPP_INCLUDED
#define CATCH_VERSION_HPP_INCLUDED #define CATCH_VERSION_HPP_INCLUDED
@ -7032,7 +7047,7 @@ namespace Catch {
#define CATCH_VERSION_MAJOR 3 #define CATCH_VERSION_MAJOR 3
#define CATCH_VERSION_MINOR 0 #define CATCH_VERSION_MINOR 0
#define CATCH_VERSION_PATCH 0 #define CATCH_VERSION_PATCH 1
#endif // CATCH_VERSION_MACROS_HPP_INCLUDED #endif // CATCH_VERSION_MACROS_HPP_INCLUDED
@ -7090,10 +7105,30 @@ namespace Catch {
#define CATCH_INTERFACES_GENERATORTRACKER_HPP_INCLUDED #define CATCH_INTERFACES_GENERATORTRACKER_HPP_INCLUDED
#include <string>
namespace Catch { namespace Catch {
namespace Generators { namespace Generators {
class GeneratorUntypedBase { class GeneratorUntypedBase {
// Caches result from `toStringImpl`, assume that when it is an
// empty string, the cache is invalidated.
mutable std::string m_stringReprCache;
// Counts based on `next` returning true
std::size_t m_currentElementIndex = 0;
/**
* Attempts to move the generator to the next element
*
* Returns true iff the move succeeded (and a valid element
* can be retrieved).
*/
virtual bool next() = 0;
//! Customization point for `currentElementAsString`
virtual std::string stringifyImpl() const = 0;
public: public:
GeneratorUntypedBase() = default; GeneratorUntypedBase() = default;
// Generation of copy ops is deprecated (and Clang will complain) // Generation of copy ops is deprecated (and Clang will complain)
@ -7103,11 +7138,34 @@ namespace Catch {
virtual ~GeneratorUntypedBase(); // = default; virtual ~GeneratorUntypedBase(); // = default;
// Attempts to move the generator to the next element /**
// * Attempts to move the generator to the next element
// Returns true iff the move succeeded (and a valid element *
// can be retrieved). * Serves as a non-virtual interface to `next`, so that the
virtual bool next() = 0; * top level interface can provide sanity checking and shared
* features.
*
* As with `next`, returns true iff the move succeeded and
* the generator has new valid element to provide.
*/
bool countedNext();
std::size_t currentElementIndex() const { return m_currentElementIndex; }
/**
* Returns generator's current element as user-friendly string.
*
* By default returns string equivalent to calling
* `Catch::Detail::stringify` on the current element, but generators
* can customize their implementation as needed.
*
* Not thread-safe due to internal caching.
*
* The returned ref is valid only until the generator instance
* is destructed, or it moves onto the next element, whichever
* comes first.
*/
StringRef currentElementAsString() const;
}; };
using GeneratorBasePtr = Catch::Detail::unique_ptr<GeneratorUntypedBase>; using GeneratorBasePtr = Catch::Detail::unique_ptr<GeneratorUntypedBase>;
@ -7142,6 +7200,10 @@ namespace Detail {
template<typename T> template<typename T>
class IGenerator : public GeneratorUntypedBase { class IGenerator : public GeneratorUntypedBase {
std::string stringifyImpl() const override {
return ::Catch::Detail::stringify( get() );
}
public: public:
~IGenerator() override = default; ~IGenerator() override = default;
IGenerator() = default; IGenerator() = default;
@ -7174,7 +7236,7 @@ namespace Detail {
return m_generator->get(); return m_generator->get();
} }
bool next() { bool next() {
return m_generator->next(); return m_generator->countedNext();
} }
}; };
@ -7641,16 +7703,21 @@ namespace Catch {
namespace Catch { namespace Catch {
namespace Generators { namespace Generators {
namespace Detail {
// Returns a suitable seed for a random floating generator based off
// the primary internal rng. It does so by taking current value from
// the rng and returning it as the seed.
std::uint32_t getSeed();
}
template <typename Float> template <typename Float>
class RandomFloatingGenerator final : public IGenerator<Float> { class RandomFloatingGenerator final : public IGenerator<Float> {
Catch::SimplePcg32& m_rng; Catch::SimplePcg32 m_rng;
std::uniform_real_distribution<Float> m_dist; std::uniform_real_distribution<Float> m_dist;
Float m_current_number; Float m_current_number;
public: public:
RandomFloatingGenerator( Float a, Float b, std::uint32_t seed ):
RandomFloatingGenerator(Float a, Float b): m_rng(seed),
m_rng(rng()),
m_dist(a, b) { m_dist(a, b) {
static_cast<void>(next()); static_cast<void>(next());
} }
@ -7666,13 +7733,12 @@ public:
template <typename Integer> template <typename Integer>
class RandomIntegerGenerator final : public IGenerator<Integer> { class RandomIntegerGenerator final : public IGenerator<Integer> {
Catch::SimplePcg32& m_rng; Catch::SimplePcg32 m_rng;
std::uniform_int_distribution<Integer> m_dist; std::uniform_int_distribution<Integer> m_dist;
Integer m_current_number; Integer m_current_number;
public: public:
RandomIntegerGenerator( Integer a, Integer b, std::uint32_t seed ):
RandomIntegerGenerator(Integer a, Integer b): m_rng(seed),
m_rng(rng()),
m_dist(a, b) { m_dist(a, b) {
static_cast<void>(next()); static_cast<void>(next());
} }
@ -7693,7 +7759,7 @@ std::enable_if_t<std::is_integral<T>::value && !std::is_same<T, bool>::value,
GeneratorWrapper<T>> GeneratorWrapper<T>>
random(T a, T b) { random(T a, T b) {
return GeneratorWrapper<T>( return GeneratorWrapper<T>(
Catch::Detail::make_unique<RandomIntegerGenerator<T>>(a, b) Catch::Detail::make_unique<RandomIntegerGenerator<T>>(a, b, Detail::getSeed())
); );
} }
@ -7702,7 +7768,7 @@ std::enable_if_t<std::is_floating_point<T>::value,
GeneratorWrapper<T>> GeneratorWrapper<T>>
random(T a, T b) { random(T a, T b) {
return GeneratorWrapper<T>( return GeneratorWrapper<T>(
Catch::Detail::make_unique<RandomFloatingGenerator<T>>(a, b) Catch::Detail::make_unique<RandomFloatingGenerator<T>>(a, b, Detail::getSeed())
); );
} }
@ -7867,6 +7933,9 @@ namespace Catch {
public: public:
virtual ~EventListenerFactory(); // = default virtual ~EventListenerFactory(); // = default
virtual IEventListenerPtr create( IConfig const* config ) const = 0; virtual IEventListenerPtr create( IConfig const* config ) const = 0;
//! Return a meaningful name for the listener, e.g. its type name
virtual StringRef getName() const = 0;
//! Return listener's description if available
virtual std::string getDescription() const = 0; virtual std::string getDescription() const = 0;
}; };
} // namespace Catch } // namespace Catch
@ -7901,6 +7970,7 @@ namespace Catch {
} // namespace Catch } // namespace Catch
#endif // CATCH_CASE_INSENSITIVE_COMPARISONS_HPP_INCLUDED #endif // CATCH_CASE_INSENSITIVE_COMPARISONS_HPP_INCLUDED
#include <string> #include <string>
#include <vector> #include <vector>
#include <map> #include <map>
@ -8033,6 +8103,7 @@ namespace Catch {
#endif // CATCH_CONSOLE_WIDTH_HPP_INCLUDED #endif // CATCH_CONSOLE_WIDTH_HPP_INCLUDED
#ifndef CATCH_CONTAINER_NONMEMBERS_HPP_INCLUDED #ifndef CATCH_CONTAINER_NONMEMBERS_HPP_INCLUDED
#define CATCH_CONTAINER_NONMEMBERS_HPP_INCLUDED #define CATCH_CONTAINER_NONMEMBERS_HPP_INCLUDED
@ -8125,7 +8196,7 @@ namespace Catch {
#if defined(__i386__) || defined(__x86_64__) #if defined(__i386__) || defined(__x86_64__)
#define CATCH_TRAP() __asm__("int $3\n" : : ) /* NOLINT */ #define CATCH_TRAP() __asm__("int $3\n" : : ) /* NOLINT */
#elif defined(__aarch64__) #elif defined(__aarch64__)
#define CATCH_TRAP() __asm__(".inst 0xd4200000") #define CATCH_TRAP() __asm__(".inst 0xd43e0000")
#endif #endif
#elif defined(CATCH_PLATFORM_IPHONE) #elif defined(CATCH_PLATFORM_IPHONE)
@ -8367,6 +8438,7 @@ namespace Catch {
#endif // CATCH_POLYFILLS_HPP_INCLUDED #endif // CATCH_POLYFILLS_HPP_INCLUDED
#include <cassert>
#include <cmath> #include <cmath>
#include <cstdint> #include <cstdint>
#include <utility> #include <utility>
@ -8381,6 +8453,15 @@ namespace Catch {
} // end namespace Detail } // end namespace Detail
#if defined( __GNUC__ ) || defined( __clang__ )
# pragma GCC diagnostic push
// We do a bunch of direct compensations of floating point numbers,
// because we know what we are doing and actually do want the direct
// comparison behaviour.
# pragma GCC diagnostic ignored "-Wfloat-equal"
#endif
/** /**
* Calculates the ULP distance between two floating point numbers * Calculates the ULP distance between two floating point numbers
* *
@ -8440,6 +8521,11 @@ namespace Catch {
return lc - rc; return lc - rc;
} }
#if defined( __GNUC__ ) || defined( __clang__ )
# pragma GCC diagnostic pop
#endif
} // end namespace Catch } // end namespace Catch
#endif // CATCH_FLOATING_POINT_HELPERS_HPP_INCLUDED #endif // CATCH_FLOATING_POINT_HELPERS_HPP_INCLUDED
@ -8523,6 +8609,10 @@ namespace Catch {
struct ReporterDescription { struct ReporterDescription {
std::string name, description; std::string name, description;
}; };
struct ListenerDescription {
StringRef name;
std::string description;
};
struct TagInfo { struct TagInfo {
void add(StringRef spelling); void add(StringRef spelling);
@ -10074,7 +10164,7 @@ namespace Matchers {
class MatcherGenericBase : public MatcherUntypedBase { class MatcherGenericBase : public MatcherUntypedBase {
public: public:
MatcherGenericBase() = default; MatcherGenericBase() = default;
virtual ~MatcherGenericBase(); // = default; ~MatcherGenericBase() override; // = default;
MatcherGenericBase(MatcherGenericBase&) = default; MatcherGenericBase(MatcherGenericBase&) = default;
MatcherGenericBase(MatcherGenericBase&&) = default; MatcherGenericBase(MatcherGenericBase&&) = default;
@ -11128,6 +11218,14 @@ namespace Catch {
*/ */
void listReporters( void listReporters(
std::vector<ReporterDescription> const& descriptions ) override; std::vector<ReporterDescription> const& descriptions ) override;
/**
* Provides a simple default listing of listeners
*
* Looks similarly to listing of reporters, but with listener type
* instead of reporter name.
*/
void listListeners(
std::vector<ListenerDescription> const& descriptions ) override;
/** /**
* Provides a simple default listing of tests. * Provides a simple default listing of tests.
* *
@ -11495,6 +11593,8 @@ namespace Catch {
void listReporters( void listReporters(
std::vector<ReporterDescription> const& descriptions ) override; std::vector<ReporterDescription> const& descriptions ) override;
void listListeners(
std::vector<ListenerDescription> const& descriptions ) override;
void listTests( std::vector<TestCaseHandle> const& tests ) override; void listTests( std::vector<TestCaseHandle> const& tests ) override;
void listTags( std::vector<TagInfo> const& tagInfos ) override; void listTags( std::vector<TagInfo> const& tagInfos ) override;
@ -11559,6 +11659,13 @@ namespace Catch {
std::vector<ReporterDescription> const& descriptions, std::vector<ReporterDescription> const& descriptions,
Verbosity verbosity ); Verbosity verbosity );
/**
* Lists listeners descriptions to the provided stream in user-friendly
* format
*/
void defaultListListeners( std::ostream& out,
std::vector<ListenerDescription> const& descriptions );
/** /**
* Lists tag information to the provided stream in user-friendly format * Lists tag information to the provided stream in user-friendly format
* *
@ -11692,6 +11799,7 @@ namespace Catch {
void skipTest( TestCaseInfo const& testInfo ) override; void skipTest( TestCaseInfo const& testInfo ) override;
void listReporters(std::vector<ReporterDescription> const& descriptions) override; void listReporters(std::vector<ReporterDescription> const& descriptions) override;
void listListeners(std::vector<ListenerDescription> const& descriptions) override;
void listTests(std::vector<TestCaseHandle> const& tests) override; void listTests(std::vector<TestCaseHandle> const& tests) override;
void listTags(std::vector<TagInfo> const& tags) override; void listTags(std::vector<TagInfo> const& tags) override;
@ -11707,8 +11815,28 @@ namespace Catch {
#define CATCH_REPORTER_REGISTRARS_HPP_INCLUDED #define CATCH_REPORTER_REGISTRARS_HPP_INCLUDED
#include <type_traits>
namespace Catch { namespace Catch {
namespace Detail {
template <typename T, typename = void>
struct has_description : std::false_type {};
template <typename T>
struct has_description<
T,
void_t<decltype( T::getDescription() )>>
: std::true_type {};
//! Indirection for reporter registration, so that the error handling is
//! independent on the reporter's concrete type
void registerReporterImpl( std::string const& name,
IReporterFactoryPtr reporterPtr );
} // namespace Detail
class IEventListener; class IEventListener;
using IEventListenerPtr = Detail::unique_ptr<IEventListener>; using IEventListenerPtr = Detail::unique_ptr<IEventListener>;
@ -11729,7 +11857,8 @@ namespace Catch {
class ReporterRegistrar { class ReporterRegistrar {
public: public:
explicit ReporterRegistrar( std::string const& name ) { explicit ReporterRegistrar( std::string const& name ) {
getMutableRegistryHub().registerReporter( name, Detail::make_unique<ReporterFactory<T>>() ); registerReporterImpl( name,
Detail::make_unique<ReporterFactory<T>>() );
} }
}; };
@ -11737,20 +11866,36 @@ namespace Catch {
class ListenerRegistrar { class ListenerRegistrar {
class TypedListenerFactory : public EventListenerFactory { class TypedListenerFactory : public EventListenerFactory {
StringRef m_listenerName;
IEventListenerPtr std::string getDescriptionImpl( std::true_type ) const {
create( IConfig const* config ) const override { return T::getDescription();
}
std::string getDescriptionImpl( std::false_type ) const {
return "(No description provided)";
}
public:
TypedListenerFactory( StringRef listenerName ):
m_listenerName( listenerName ) {}
IEventListenerPtr create( IConfig const* config ) const override {
return Detail::make_unique<T>( config ); return Detail::make_unique<T>( config );
} }
StringRef getName() const override {
return m_listenerName;
}
std::string getDescription() const override { std::string getDescription() const override {
return std::string(); return getDescriptionImpl( Detail::has_description<T>{} );
} }
}; };
public: public:
ListenerRegistrar(StringRef listenerName) {
ListenerRegistrar() { getMutableRegistryHub().registerListener( Detail::make_unique<TypedListenerFactory>(listenerName) );
getMutableRegistryHub().registerListener( Detail::make_unique<TypedListenerFactory>() );
} }
}; };
} }
@ -11760,14 +11905,21 @@ namespace Catch {
# define CATCH_REGISTER_REPORTER( name, reporterType ) \ # define CATCH_REGISTER_REPORTER( name, reporterType ) \
CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \ CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \
CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \ CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
namespace{ Catch::ReporterRegistrar<reporterType> catch_internal_RegistrarFor##reporterType( name ); } \ namespace { \
Catch::ReporterRegistrar<reporterType> INTERNAL_CATCH_UNIQUE_NAME( \
catch_internal_RegistrarFor )( name ); \
} \
CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION
# define CATCH_REGISTER_LISTENER( listenerType ) \ # define CATCH_REGISTER_LISTENER( listenerType ) \
CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \ CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \
CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \ CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
namespace{ Catch::ListenerRegistrar<listenerType> catch_internal_RegistrarFor##listenerType; } \ namespace { \
Catch::ListenerRegistrar<listenerType> INTERNAL_CATCH_UNIQUE_NAME( \
catch_internal_RegistrarFor )( #listenerType ); \
} \
CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION
#else // CATCH_CONFIG_DISABLE #else // CATCH_CONFIG_DISABLE
#define CATCH_REGISTER_REPORTER(name, reporterType) #define CATCH_REGISTER_REPORTER(name, reporterType)
@ -11969,6 +12121,7 @@ namespace Catch {
void benchmarkFailed( StringRef error ) override; void benchmarkFailed( StringRef error ) override;
void listReporters(std::vector<ReporterDescription> const& descriptions) override; void listReporters(std::vector<ReporterDescription> const& descriptions) override;
void listListeners(std::vector<ListenerDescription> const& descriptions) override;
void listTests(std::vector<TestCaseHandle> const& tests) override; void listTests(std::vector<TestCaseHandle> const& tests) override;
void listTags(std::vector<TagInfo> const& tags) override; void listTags(std::vector<TagInfo> const& tags) override;

View File

@ -36,7 +36,7 @@ namespace Catch {
} }
Version const& libraryVersion() { Version const& libraryVersion() {
static Version version( 3, 0, 0, "preview", 5 ); static Version version( 3, 0, 1, "", 0 );
return version; return version;
} }

View File

@ -10,6 +10,6 @@
#define CATCH_VERSION_MAJOR 3 #define CATCH_VERSION_MAJOR 3
#define CATCH_VERSION_MINOR 0 #define CATCH_VERSION_MINOR 0
#define CATCH_VERSION_PATCH 0 #define CATCH_VERSION_PATCH 1
#endif // CATCH_VERSION_MACROS_HPP_INCLUDED #endif // CATCH_VERSION_MACROS_HPP_INCLUDED