Merge branch 'devel' into docs_includes

This commit is contained in:
Nandan V 2022-10-18 09:03:45 +00:00 committed by GitHub
commit ea37a0c965
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
27 changed files with 511 additions and 223 deletions

View File

@ -4,7 +4,11 @@ on: [push, pull_request]
jobs: jobs:
build: build:
runs-on: macos-12 # macos-12 updated to a toolchain that crashes when linking the
# test binary. This seems to be a known bug in that version,
# and will eventually get fixed in an update. After that, we can go
# back to newer macos images.
runs-on: macos-11
strategy: strategy:
matrix: matrix:
cxx: cxx:

View File

@ -8,9 +8,10 @@
include(CheckCXXCompilerFlag) include(CheckCXXCompilerFlag)
function(add_cxx_flag_if_supported_to_targets flagname targets) function(add_cxx_flag_if_supported_to_targets flagname targets)
check_cxx_compiler_flag("${flagname}" HAVE_FLAG_${flagname}) string(MAKE_C_IDENTIFIER ${flagname} flag_identifier )
check_cxx_compiler_flag("${flagname}" HAVE_FLAG_${flag_identifier})
if (HAVE_FLAG_${flagname}) if (HAVE_FLAG_${flag_identifier})
foreach(target ${targets}) foreach(target ${targets})
target_compile_options(${target} PUBLIC ${flagname}) target_compile_options(${target} PUBLIC ${flagname})
endforeach() endforeach()
@ -112,9 +113,8 @@ endfunction()
# Adds flags required for reproducible build to the target # Adds flags required for reproducible build to the target
# Currently only supports GCC and Clang # Currently only supports GCC and Clang
function(add_build_reproducibility_settings target) function(add_build_reproducibility_settings target)
# Make the build reproducible on versions of g++ and clang that supports -ffile-prefix-map # Make the build reproducible on versions of g++ and clang that supports -ffile-prefix-map
if(("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU" AND NOT ${CMAKE_CXX_COMPILER_VERSION} VERSION_LESS 8) OR if((CMAKE_CXX_COMPILER_ID STREQUAL "GNU") OR (CMAKE_CXX_COMPILER_ID MATCHES "Clang"))
("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang" AND NOT ${CMAKE_CXX_COMPILER_VERSION} VERSION_LESS 10)) add_cxx_flag_if_supported_to_targets("-ffile-prefix-map=${CATCH_DIR}/=" "${target}")
target_compile_options(${target} PRIVATE "-ffile-prefix-map=${CATCH_DIR}=.")
endif() endif()
endfunction() endfunction()

View File

@ -31,7 +31,7 @@ if (CMAKE_BINARY_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR)
endif() endif()
project(Catch2 project(Catch2
VERSION 3.1.0 # CML version placeholder, don't delete VERSION 3.1.1 # CML version placeholder, don't delete
LANGUAGES CXX LANGUAGES CXX
# HOMEPAGE_URL is not supported until CMake version 3.12, which # HOMEPAGE_URL is not supported until CMake version 3.12, which
# we do not target yet. # we do not target yet.

View File

@ -11,31 +11,77 @@
[![Join the chat in Discord: https://discord.gg/4CWS9zD](https://img.shields.io/badge/Discord-Chat!-brightgreen.svg)](https://discord.gg/4CWS9zD) [![Join the chat in Discord: https://discord.gg/4CWS9zD](https://img.shields.io/badge/Discord-Chat!-brightgreen.svg)](https://discord.gg/4CWS9zD)
## What's the Catch2? ## What is Catch2?
Catch2 is mainly a unit testing framework for C++, but it also Catch2 is mainly a unit testing framework for C++, but it also
provides basic micro-benchmarking features, and simple BDD macros. provides basic micro-benchmarking features, and simple BDD macros.
Catch2's main advantage is that using it is both simple and natural. Catch2's main advantage is that using it is both simple and natural.
Tests autoregister themselves and do not have to be named with valid Test names do not have to be valid identifiers, assertions look like
identifiers, assertions look like normal C++ code, and sections provide normal C++ boolean expressions, and sections provide a nice and local way
a nice way to share set-up and tear-down code in tests. to share set-up and tear-down code in tests.
**Example unit test**
```cpp
#include <catch2/catch_test_macros.hpp>
## Catch2 v3 is being developed! #include <cstdint>
You are on the `devel` branch, where the next major version, v3, of uint32_t factorial( uint32_t number ) {
Catch2 is being developed. As it is a significant rework, you will return number <= 1 ? number : factorial(number-1) * number;
find that parts of this documentation are likely still stuck on v2. }
For stable (and documentation-matching) version of Catch2, [go to the TEST_CASE( "Factorials are computed", "[factorial]" ) {
`v2.x` branch](https://github.com/catchorg/Catch2/tree/v2.x). REQUIRE( factorial( 1) == 1 );
REQUIRE( factorial( 2) == 2 );
REQUIRE( factorial( 3) == 6 );
REQUIRE( factorial(10) == 3'628'800 );
}
```
**Example microbenchmark**
```cpp
#include <catch2/benchmark/catch_benchmark.hpp>
#include <cstdint>
uint64_t fibonacci(uint64_t number) {
return number < 2 ? 1 : fibonacci(number - 1) + fibonacci(number - 2);
}
TEST_CASE("Benchmark Fibonacci", "[!benchmark]") {
REQUIRE(Fibonacci(5) == 5);
REQUIRE(Fibonacci(20) == 6'765);
BENCHMARK("Fibonacci 20") {
return Fibonacci(20);
};
REQUIRE(Fibonacci(25) == 75'025);
BENCHMARK("Fibonacci 25") {
return Fibonacci(25);
};
}
```
## Catch2 v3 has been released!
You are on the `devel` branch, where the v3 version is being developed.
v3 brings a bunch of significant changes, the big one being that Catch2
is no longer a single-header library. Catch2 now behaves as a normal
library, with multiple headers and separately compiled implementation.
The documentation is slowly being updated to take these changes into
account, but this work is currently still ongoing.
For migrating from the v2 releases to v3, you should look at [our For migrating from the v2 releases to v3, you should look at [our
documentation](docs/migrate-v2-to-v3.md#top). It provides a simple documentation](docs/migrate-v2-to-v3.md#top). It provides a simple
guidelines on getting started, and collects most common migration guidelines on getting started, and collects most common migration
problems. problems.
For the previous major version of Catch2 [look into the `v2.x` branch
here on GitHub](https://github.com/catchorg/Catch2/tree/v2.x).
## How to use it ## How to use it
This documentation comprises these three parts: This documentation comprises these three parts:

View File

@ -4,34 +4,35 @@
To get the most out of Catch2, start with the [tutorial](tutorial.md#top). To get the most out of Catch2, start with the [tutorial](tutorial.md#top).
Once you're up and running consider the following reference material. Once you're up and running consider the following reference material.
Writing tests: **Writing tests:**
* [Assertion macros](assertions.md#top) * [Assertion macros](assertions.md#top)
* [Matchers](matchers.md#top) * [Matchers (asserting complex properties)](matchers.md#top)
* [Comparing floating point numbers](comparing-floating-point-numbers.md#top)
* [Logging macros](logging.md#top) * [Logging macros](logging.md#top)
* [Test cases and sections](test-cases-and-sections.md#top) * [Test cases and sections](test-cases-and-sections.md#top)
* [Test fixtures](test-fixtures.md#top) * [Test fixtures](test-fixtures.md#top)
* [Reporters](reporters.md#top) * [Reporters (output customization)](reporters.md#top)
* [Event Listeners](event-listeners.md#top) * [Event Listeners](event-listeners.md#top)
* [Data Generators](generators.md#top) * [Data Generators (value parameterized tests)](generators.md#top)
* [Other macros](other-macros.md#top) * [Other macros](other-macros.md#top)
* [Micro benchmarking](benchmarks.md#top) * [Micro benchmarking](benchmarks.md#top)
Fine tuning: **Fine tuning:**
* [Supplying your own main()](own-main.md#top) * [Supplying your own main()](own-main.md#top)
* [Compile-time configuration](configuration.md#top) * [Compile-time configuration](configuration.md#top)
* [String Conversions](tostring.md#top) * [String Conversions](tostring.md#top)
Running: **Running:**
* [Command line](command-line.md#top) * [Command line](command-line.md#top)
Odds and ends: **Odds and ends:**
* [Frequently Asked Questions (FAQ)](faq.md#top) * [Frequently Asked Questions (FAQ)](faq.md#top)
* [Best practices and other tips](usage-tips.md#top) * [Best practices and other tips](usage-tips.md#top)
* [CMake integration](cmake-integration.md#top) * [CMake integration](cmake-integration.md#top)
* [CI and other miscellaneous pieces](ci-and-misc.md#top) * [CI and other miscellaneous pieces](ci-and-misc.md#top)
* [Known limitations](limitations.md#top) * [Known limitations](limitations.md#top)
Other: **Other:**
* [Why Catch2?](why-catch.md#top) * [Why Catch2?](why-catch.md#top)
* [Migrating from v2 to v3](migrate-v2-to-v3.md#top) * [Migrating from v2 to v3](migrate-v2-to-v3.md#top)
* [Open Source Projects using Catch2](opensource-users.md#top) * [Open Source Projects using Catch2](opensource-users.md#top)

View File

@ -3,6 +3,7 @@
**Contents**<br> **Contents**<br>
[Natural Expressions](#natural-expressions)<br> [Natural Expressions](#natural-expressions)<br>
[Floating point comparisons](#floating-point-comparisons)<br>
[Exceptions](#exceptions)<br> [Exceptions](#exceptions)<br>
[Matcher expressions](#matcher-expressions)<br> [Matcher expressions](#matcher-expressions)<br>
[Thread Safety](#thread-safety)<br> [Thread Safety](#thread-safety)<br>
@ -34,81 +35,62 @@ CHECK( thisReturnsTrue() );
REQUIRE( i == 42 ); REQUIRE( i == 42 );
``` ```
Expressions prefixed with `!` cannot be decomposed. If you have a type
that is convertible to bool and you want to assert that it evaluates to
false, use the two forms below:
* **REQUIRE_FALSE(** _expression_ **)** and * **REQUIRE_FALSE(** _expression_ **)** and
* **CHECK_FALSE(** _expression_ **)** * **CHECK_FALSE(** _expression_ **)**
Evaluates the expression and records the _logical NOT_ of the result. If an exception is thrown it is caught, reported, and counted as a failure. Note that there is no reason to use these forms for plain bool variables,
(these forms exist as a workaround for the fact that ! prefixed expressions cannot be decomposed). because there is no added value in decomposing them.
Example: Example:
```cpp
Status ret = someFunction();
REQUIRE_FALSE(ret); // ret must evaluate to false, and Catch2 will print
// out the value of ret if possibly
``` ```
REQUIRE_FALSE( thisReturnsFalse() );
```
Do note that "overly complex" expressions cannot be decomposed and thus will not compile. This is done partly for practical reasons (to keep the underlying expression template machinery to minimum) and partly for philosophical reasons (assertions should be simple and deterministic).
Examples:
* `CHECK(a == 1 && b == 2);`
This expression is too complex because of the `&&` operator. If you want to check that 2 or more properties hold, you can either put the expression into parenthesis, which stops decomposition from working, or you need to decompose the expression into two assertions: `CHECK( a == 1 ); CHECK( b == 2);`
* `CHECK( a == 2 || b == 1 );`
This expression is too complex because of the `||` operator. If you want to check that one of several properties hold, you can put the expression into parenthesis (unlike with `&&`, expression decomposition into several `CHECK`s is not possible).
### Floating point comparisons ### Floating point comparisons
```cpp ```cpp
#include <catch2/catch_approx.hpp> #include <catch2/catch_approx.hpp>
``` ```
When comparing floating point numbers - especially if at least one of them has been computed - great care must be taken to allow for rounding errors and inexact representations. ### Other limitations
Catch provides a way to perform tolerant comparisons of floating point values through use of a wrapper class called `Approx`. `Approx` can be used on either side of a comparison expression. It overloads the comparisons operators to take a tolerance into account. Here's a simple example: Note that expressions containing either of the binary logical operators,
`&&` or `||`, cannot be decomposed and will not compile. The reason behind
this is that it is impossible to overload `&&` and `||` in a way that
keeps their short-circuiting semantics, and expression decomposition
relies on overloaded operators to work.
```cpp Simple example of an issue with overloading binary logical operators
REQUIRE( performComputation() == Approx( 2.1 ) ); is a common pointer idiom, `p && p->foo == 2`. Using the built-in `&&`
``` operator, `p` is only dereferenced if it is not null. With overloaded
`&&`, `p` is always dereferenced, thus causing a segfault if
`p == nullptr`.
Catch also provides a user-defined literal for `Approx`; `_a`. It resides in If you want to test expression that contains `&&` or `||`, you have two
the `Catch::literals` namespace and can be used like so: options.
```cpp
using namespace Catch::literals;
REQUIRE( performComputation() == 2.1_a );
```
`Approx` is constructed with defaults that should cover most simple cases. 1) Enclose it in parentheses. Parentheses force evaluation of the expression
For the more complex cases, `Approx` provides 3 customization points: before the expression decomposition can touch it, and thus it cannot
be used.
* __epsilon__ - epsilon serves to set the coefficient by which a result 2) Rewrite the expression. `REQUIRE(a == 1 && b == 2)` can always be split
can differ from `Approx`'s value before it is rejected. into `REQUIRE(a == 1); REQUIRE(b == 2);`. Alternatively, if this is a
_By default set to `std::numeric_limits<float>::epsilon()*100`._ common pattern in your tests, think about using [Matchers](#matcher-expressions).
* __margin__ - margin serves to set the the absolute value by which instead. There is no simple rewrite rule for `||`, but I generally
a result can differ from `Approx`'s value before it is rejected. believe that if you have `||` in your test expression, you should rethink
_By default set to `0.0`._ your tests.
* __scale__ - scale is used to change the magnitude of `Approx` for relative check.
_By default set to `0.0`._
#### epsilon example
```cpp
Approx target = Approx(100).epsilon(0.01);
100.0 == target; // Obviously true
200.0 == target; // Obviously still false
100.5 == target; // True, because we set target to allow up to 1% difference
```
#### margin example ## Floating point comparisons
```cpp
Approx target = Approx(100).margin(5);
100.0 == target; // Obviously true
200.0 == target; // Obviously still false
104.0 == target; // True, because we set target to allow absolute difference of at most 5
```
#### scale Comparing floating point numbers is complex, and [so it has its own
Scale can be useful if the computation leading to the result worked documentation page](comparing-floating-point-numbers.md#top).
on different scale than is used by the results. Since allowed difference
between Approx's value and compared value is based primarily on Approx's value
(the allowed difference is computed as
`(Approx::scale + Approx::value) * epsilon`), the resulting comparison could
need rescaling to be correct.
## Exceptions ## Exceptions

View File

@ -548,7 +548,8 @@ starting at 0. The tests in the set given by
`--shard-index <#shard index to run>` will be executed. The default shard `--shard-index <#shard index to run>` will be executed. The default shard
count is `1`, and the default index to run is `0`. count is `1`, and the default index to run is `0`.
_It is an error to specify a shard index greater than the number of shards._ _Shard index must be less than number of shards. As the name suggests,
it is treated as an index of the shard to run._
Sharding is useful when you want to split test execution across multiple Sharding is useful when you want to split test execution across multiple
processes, as is done with the [Bazel test sharding](https://docs.bazel.build/versions/main/test-encyclopedia.html#test-sharding). processes, as is done with the [Bazel test sharding](https://docs.bazel.build/versions/main/test-encyclopedia.html#test-sharding).

View File

@ -0,0 +1,192 @@
<a id="top"></a>
# Comparing floating point numbers with Catch2
If you are not deeply familiar with them, floating point numbers can be
unintuitive. This also applies to comparing floating point numbers for
(in)equality.
This page assumes that you have some understanding of both FP, and the
meaning of different kinds of comparisons, and only goes over what
functionality Catch2 provides to help you with comparing floating point
numbers. If you do not have this understanding, we recommend that you first
study up on floating point numbers and their comparisons, e.g. by [reading
this blog post](https://codingnest.com/the-little-things-comparing-floating-point-numbers/).
## Floating point matchers
```
#include <catch2/matchers/catch_matchers_floating.hpp
```
[Matchers](matchers.md#top) are the preferred way of comparing floating
point numbers in Catch2. We provide 3 of them:
* `WithinAbs(double target, double margin)`,
* `WithinRel(FloatingPoint target, FloatingPoint eps)`, and
* `WithinULP(FloatingPoint target, uint64_t maxUlpDiff)`.
> `WithinRel` matcher was introduced in Catch2 2.10.0
As with all matchers, you can combine multiple floating point matchers
in a single assertion. For example, to check that some computation matches
a known good value within 0.1% or is close enough (no different to 5
decimal places) to zero, we would write this assertion:
```cpp
REQUIRE_THAT( computation(input),
Catch::Matchers::WithinRel(expected, 0.001)
|| Catch::Matchers::WithinAbs(0, 0.000001) );
```
### WithinAbs
`WithinAbs` creates a matcher that accepts floating point numbers whose
difference with `target` is less-or-equal to the `margin`. Since `float`
can be converted to `double` without losing precision, only `double`
overload exists.
```cpp
REQUIRE_THAT(1.0, WithinAbs(1.2, 0.2));
REQUIRE_THAT(0.f, !WithinAbs(1.0, 0.5));
// Notice that infinity == infinity for WithinAbs
REQUIRE_THAT(INFINITY, WithinAbs(INFINITY, 0));
```
### WithinRel
`WithinRel` creates a matcher that accepts floating point numbers that
are _approximately equal_ to the `target` with a tolerance of `eps.`
Specifically, it matches if
`|arg - target| <= eps * max(|arg|, |target|)` holds. If you do not
specify `eps`, `std::numeric_limits<FloatingPoint>::epsilon * 100`
is used as the default.
```cpp
// Notice that WithinRel comparison is symmetric, unlike Approx's.
REQUIRE_THAT(1.0, WithinRel(1.1, 0.1));
REQUIRE_THAT(1.1, WithinRel(1.0, 0.1));
// Notice that inifnity == infinity for WithinRel
REQUIRE_THAT(INFINITY, WithinRel(INFINITY));
```
### WithinULP
`WithinULP` creates a matcher that accepts floating point numbers that
are no more than `maxUlpDiff`
[ULPs](https://en.wikipedia.org/wiki/Unit_in_the_last_place)
away from the `target` value. The short version of what this means
is that there is no more than `maxUlpDiff - 1` representable floating
point numbers between the argument for matching and the `target` value.
When using the ULP matcher in Catch2, it is important to keep in mind
that Catch2 interprets ULP distance slightly differently than
e.g. `std::nextafter` does.
Catch2's ULP calculation obeys these relations:
* `ulpDistance(-x, x) == 2 * ulpDistance(x, 0)`
* `ulpDistance(-0, 0) == 0` (due to the above)
* `ulpDistance(DBL_MAX, INFINITY) == 1`
* `ulpDistancE(NaN, x) == infinity`
**Important**: The WithinULP matcher requires the platform to use the
[IEEE-754](https://en.wikipedia.org/wiki/IEEE_754) representation for
floating point numbers.
```cpp
REQUIRE_THAT( -0.f, WithinULP( 0.f, 0 ) );
```
## `Approx`
```
#include <catch2/catch_approx.hpp>
```
**We strongly recommend against using `Approx` when writing new code.**
You should be using floating point matchers instead.
Catch2 provides one more way to handle floating point comparisons. It is
`Approx`, a special type with overloaded comparison operators, that can
be used in standard assertions, e.g.
```cpp
REQUIRE(0.99999 == Catch::Approx(1));
```
`Approx` supports four comparison operators, `==`, `!=`, `<=`, `>=`, and can
also be used with strong typedefs over `double`s. It can be used for both
relative and margin comparisons by using its three customization points.
Note that the semantics of this is always that of an _or_, so if either
the relative or absolute margin comparison passes, then the whole comparison
passes.
The downside to `Approx` is that it has a couple of issues that we cannot
fix without breaking backwards compatibility. Because Catch2 also provides
complete set of matchers that implement different floating point comparison
methods, `Approx` is left as-is, is considered deprecated, and should
not be used in new code.
The issues are
* All internal computation is done in `double`s, leading to slightly
different results if the inputs were floats.
* `Approx`'s relative margin comparison is not symmetric. This means
that `Approx( 10 ).epsilon(0.1) != 11.1` but `Approx( 11.1 ).epsilon(0.1) == 10`.
* By default, `Approx` only uses relative margin comparison. This means
that `Approx(0) == X` only passes for `X == 0`.
### Approx details
If you still want/need to know more about `Approx`, read on.
Catch2 provides a UDL for `Approx`; `_a`. It resides in the `Catch::literals`
namespace, and can be used like this:
```cpp
using namespace Catch::literals;
REQUIRE( performComputation() == 2.1_a );
```
`Approx` has three customization points for the comparison:
* **epsilon** - epsilon sets the coefficient by which a result
can differ from `Approx`'s value before it is rejected.
_Defaults to `std::numeric_limits<float>::epsilon()*100`._
```cpp
Approx target = Approx(100).epsilon(0.01);
100.0 == target; // Obviously true
200.0 == target; // Obviously still false
100.5 == target; // True, because we set target to allow up to 1% difference
```
* **margin** - margin sets the absolute value by which
a result can differ from `Approx`'s value before it is rejected.
_Defaults to `0.0`._
```cpp
Approx target = Approx(100).margin(5);
100.0 == target; // Obviously true
200.0 == target; // Obviously still false
104.0 == target; // True, because we set target to allow absolute difference of at most 5
```
* **scale** - scale is used to change the magnitude of `Approx` for the relative check.
_By default, set to `0.0`._
Scale could be useful if the computation leading to the result worked
on a different scale than is used by the results. Approx's scale is added
to Approx's value when computing the allowed relative margin from the
Approx's value.
---
[Home](Readme.md#top)

View File

@ -153,49 +153,8 @@ are:
> `WithinRel` matcher was introduced in Catch2 2.10.0 > `WithinRel` matcher was introduced in Catch2 2.10.0
For more details, read [the docs on comparing floating point
`WithinAbs` creates a matcher that accepts floating point numbers whose numbers](comparing-floating-point-numbers.md#floating-point-matchers).
difference with `target` is less than the `margin`.
`WithinULP` creates a matcher that accepts floating point numbers that
are no more than `maxUlpDiff`
[ULPs](https://en.wikipedia.org/wiki/Unit_in_the_last_place)
away from the `target` value. The short version of what this means
is that there is no more than `maxUlpDiff - 1` representable floating
point numbers between the argument for matching and the `target` value.
**Important**: The WithinULP matcher requires the platform to use the
[IEEE-754](https://en.wikipedia.org/wiki/IEEE_754) representation for
floating point numbers.
`WithinRel` creates a matcher that accepts floating point numbers that
are _approximately equal_ with the `target` with tolerance of `eps.`
Specifically, it matches if
`|arg - target| <= eps * max(|arg|, |target|)` holds. If you do not
specify `eps`, `std::numeric_limits<FloatingPoint>::epsilon * 100`
is used as the default.
In practice, you will often want to combine multiple of these matchers,
together for an assertion, because all 3 options have edge cases where
they behave differently than you would expect. As an example, under
the `WithinRel` matcher, a `0.` only ever matches a `0.` (or `-0.`),
regardless of the relative tolerance specified. Thus, if you want to
handle numbers that are "close enough to 0 to be 0", you have to combine
it with the `WithinAbs` matcher.
For example, to check that our computation matches known good value
within 0.1%, or is close enough (no different to 5 decimal places)
to zero, we would write this assertion:
```cpp
REQUIRE_THAT( computation(input),
Catch::Matchers::WithinRel(expected, 0.001)
|| Catch::Matchers::WithinAbs(0, 0.000001) );
```
> floating point matchers live in `catch2/matchers/catch_matchers_floating.hpp`
### Miscellaneous matchers ### Miscellaneous matchers

View File

@ -2,6 +2,7 @@
# Release notes # Release notes
**Contents**<br> **Contents**<br>
[3.1.1](#311)<br>
[3.1.0](#310)<br> [3.1.0](#310)<br>
[3.0.1](#301)<br> [3.0.1](#301)<br>
[2.13.7](#2137)<br> [2.13.7](#2137)<br>
@ -50,6 +51,39 @@
[Even Older versions](#even-older-versions)<br> [Even Older versions](#even-older-versions)<br>
## 3.1.1
### Improvements
* Added `Catch::getSeed` function that user code can call to retrieve current rng-seed
* Better detection of compiler support for `-ffile-prefix-map` (#2517)
* Catch2's shared libraries now have `SOVERSION` set (#2516)
* `catch2/catch_all.hpp` convenience header no longer transitively includes `windows.h` (#2432, #2526)
### Fixes
* Fixed compilation on Universal Windows Platform
* Fixed compilation on VxWorks (#2515)
* Fixed compilation on Cygwin (#2540)
* Remove unused variable in reporter registration (#2538)
* Fixed some symbol visibility issues with dynamic library on Windows (#2527)
* Suppressed `-Wuseless-cast` warnings in `REQUIRE_THROWS*` macros (#2520, #2521)
* This was triggered when the potentially throwing expression evaluates to `void`
* Fixed "warning: storage class is not first" with `nvc++` (#2533)
* Fixed handling of `DL_PATHS` argument to `catch_discover_tests` on MacOS (#2483)
* Suppressed `*-avoid-c-arrays` clang-tidy warning in `TEMPLATE_TEST_CASE` (#2095, #2536)
### Miscellaneous
* Fixed CMake install step for Catch2 build as dynamic library (#2485)
* Raised minimum CMake version to 3.10 (#2523)
* Expect the minimum CMake version to increase once more in next few releases.
* Whole bunch of doc updates and fixes
* #1444, #2497, #2547, #2549, and more
* Added support for building Catch2 with Meson (#2530, #2539)
## 3.1.0 ## 3.1.0
### Improvements ### Improvements

View File

@ -3,7 +3,7 @@
## Defining test fixtures ## Defining test fixtures
Although Catch allows you to group tests together as sections within a test case, it can still be convenient, sometimes, to group them using a more traditional test fixture. Catch fully supports this too. You define the test fixture as a simple structure: Although Catch allows you to group tests together as [sections within a test case](test-cases-and-sections.md), it can still be convenient, sometimes, to group them using a more traditional test fixture. Catch fully supports this too. You define the test fixture as a simple structure:
```c++ ```c++
class UniqueTestsFixture { class UniqueTestsFixture {

View File

@ -5,8 +5,8 @@
// SPDX-License-Identifier: BSL-1.0 // SPDX-License-Identifier: BSL-1.0
// Catch v3.1.0 // Catch v3.1.1
// Generated: 2022-07-17 20:14:05.885021 // Generated: 2022-10-17 18:47:22.400176
// ---------------------------------------------------------- // ----------------------------------------------------------
// 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.
@ -15,6 +15,28 @@
#include "catch_amalgamated.hpp" #include "catch_amalgamated.hpp"
#ifndef CATCH_WINDOWS_H_PROXY_HPP_INCLUDED
#define CATCH_WINDOWS_H_PROXY_HPP_INCLUDED
#if defined(CATCH_PLATFORM_WINDOWS)
// We might end up with the define made globally through the compiler,
// and we don't want to trigger warnings for this
#if !defined(NOMINMAX)
# define NOMINMAX
#endif
#if !defined(WIN32_LEAN_AND_MEAN)
# define WIN32_LEAN_AND_MEAN
#endif
#include <windows.h>
#endif // defined(CATCH_PLATFORM_WINDOWS)
#endif // CATCH_WINDOWS_H_PROXY_HPP_INCLUDED
namespace Catch { namespace Catch {
@ -488,8 +510,11 @@ namespace Catch {
namespace { namespace {
bool provideBazelReporterOutput() { bool provideBazelReporterOutput() {
#ifdef CATCH_CONFIG_BAZEL_SUPPORT #if defined(CATCH_CONFIG_BAZEL_SUPPORT)
return true; return true;
#elif defined(CATCH_PLATFORM_WINDOWS_UWP)
// UWP does not support environment variables
return false;
#else #else
# if defined( _MSC_VER ) # if defined( _MSC_VER )
@ -554,6 +579,7 @@ namespace Catch {
} ); } );
} }
#if !defined(CATCH_PLATFORM_WINDOWS_UWP)
if(provideBazelReporterOutput()){ if(provideBazelReporterOutput()){
// Register a JUnit reporter for Bazel. Bazel sets an environment // Register a JUnit reporter for Bazel. Bazel sets an environment
// variable with the path to XML output. If this file is written to // variable with the path to XML output. If this file is written to
@ -575,7 +601,7 @@ namespace Catch {
{ "junit", std::string( bazelOutputFilePtr ), {}, {} } ); { "junit", std::string( bazelOutputFilePtr ), {}, {} } );
} }
} }
#endif
// We now fixup the reporter specs to handle default output spec, // We now fixup the reporter specs to handle default output spec,
// default colour spec, etc // default colour spec, etc
@ -659,6 +685,16 @@ namespace Catch {
namespace Catch {
std::uint32_t getSeed() {
return getCurrentContext().getConfig()->rngSeed();
}
}
#include <cassert> #include <cassert>
#include <stack> #include <stack>
@ -882,7 +918,6 @@ namespace Catch {
multi->addListener(listener->create(config)); multi->addListener(listener->create(config));
} }
std::size_t reporterIdx = 0;
for ( auto const& reporterSpec : config->getProcessedReporterSpecs() ) { for ( auto const& reporterSpec : config->getProcessedReporterSpecs() ) {
multi->addReporter( createReporter( multi->addReporter( createReporter(
reporterSpec.name, reporterSpec.name,
@ -890,7 +925,6 @@ namespace Catch {
makeStream( reporterSpec.outputFilename ), makeStream( reporterSpec.outputFilename ),
reporterSpec.colourMode, reporterSpec.colourMode,
reporterSpec.customOptions ) ) ); reporterSpec.customOptions ) ) );
reporterIdx++;
} }
return multi; return multi;
@ -1890,7 +1924,7 @@ namespace Catch {
} }
Version const& libraryVersion() { Version const& libraryVersion() {
static Version version( 3, 1, 0, "", 0 ); static Version version( 3, 1, 1, "", 0 );
return version; return version;
} }
@ -3957,6 +3991,7 @@ namespace Detail {
FileStream( std::string const& filename ) { FileStream( std::string const& filename ) {
m_ofs.open( filename.c_str() ); m_ofs.open( filename.c_str() );
CATCH_ENFORCE( !m_ofs.fail(), "Unable to open file: '" << filename << '\'' ); CATCH_ENFORCE( !m_ofs.fail(), "Unable to open file: '" << filename << '\'' );
m_ofs << std::unitbuf;
} }
~FileStream() override = default; ~FileStream() override = default;
public: // IStream public: // IStream
@ -7878,7 +7913,7 @@ private:
<< serializeFilters( m_config->getTestsOrTags() ) << serializeFilters( m_config->getTestsOrTags() )
<< '\n'; << '\n';
} }
m_stream << "RNG seed: " << m_config->rngSeed() << '\n'; m_stream << "RNG seed: " << getSeed() << '\n';
} }
void CompactReporter::assertionEnded( AssertionStats const& _assertionStats ) { void CompactReporter::assertionEnded( AssertionStats const& _assertionStats ) {
@ -8399,7 +8434,7 @@ void ConsoleReporter::testRunStarting(TestRunInfo const& _testInfo) {
m_stream << m_colour->guardColour( Colour::BrightYellow ) << "Filters: " m_stream << m_colour->guardColour( Colour::BrightYellow ) << "Filters: "
<< serializeFilters( m_config->getTestsOrTags() ) << '\n'; << serializeFilters( m_config->getTestsOrTags() ) << '\n';
} }
m_stream << "Randomness seeded to: " << m_config->rngSeed() << '\n'; m_stream << "Randomness seeded to: " << getSeed() << '\n';
} }
void ConsoleReporter::lazyPrint() { void ConsoleReporter::lazyPrint() {

View File

@ -5,8 +5,8 @@
// SPDX-License-Identifier: BSL-1.0 // SPDX-License-Identifier: BSL-1.0
// Catch v3.1.0 // Catch v3.1.1
// Generated: 2022-07-17 20:14:04.055157 // Generated: 2022-10-17 18:47:20.510385
// ---------------------------------------------------------- // ----------------------------------------------------------
// 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.
@ -326,6 +326,10 @@ namespace Catch {
#elif defined(WIN32) || defined(__WIN32__) || defined(_WIN32) || defined(_MSC_VER) || defined(__MINGW32__) #elif defined(WIN32) || defined(__WIN32__) || defined(_WIN32) || defined(_MSC_VER) || defined(__MINGW32__)
# define CATCH_PLATFORM_WINDOWS # define CATCH_PLATFORM_WINDOWS
# if defined( WINAPI_FAMILY ) && ( WINAPI_FAMILY == WINAPI_FAMILY_APP )
# define CATCH_PLATFORM_WINDOWS_UWP
# endif
#endif #endif
#endif // CATCH_PLATFORM_HPP_INCLUDED #endif // CATCH_PLATFORM_HPP_INCLUDED
@ -356,6 +360,9 @@ namespace Catch {
# define CATCH_INTERNAL_SUPPRESS_UNUSED_VARIABLE_WARNINGS \ # define CATCH_INTERNAL_SUPPRESS_UNUSED_VARIABLE_WARNINGS \
_Pragma( "GCC diagnostic ignored \"-Wunused-variable\"" ) _Pragma( "GCC diagnostic ignored \"-Wunused-variable\"" )
# define CATCH_INTERNAL_SUPPRESS_USELESS_CAST_WARNINGS \
_Pragma( "GCC diagnostic ignored \"-Wuseless-cast\"" )
# define CATCH_INTERNAL_IGNORE_BUT_WARN(...) (void)__builtin_constant_p(__VA_ARGS__) # define CATCH_INTERNAL_IGNORE_BUT_WARN(...) (void)__builtin_constant_p(__VA_ARGS__)
#endif #endif
@ -477,7 +484,7 @@ namespace Catch {
// Universal Windows platform does not support SEH // Universal Windows platform does not support SEH
// Or console colours (or console at all...) // Or console colours (or console at all...)
# if defined(WINAPI_FAMILY) && (WINAPI_FAMILY == WINAPI_FAMILY_APP) # if defined(CATCH_PLATFORM_WINDOWS_UWP)
# define CATCH_INTERNAL_CONFIG_NO_COLOUR_WIN32 # define CATCH_INTERNAL_CONFIG_NO_COLOUR_WIN32
# else # else
# define CATCH_INTERNAL_CONFIG_WINDOWS_SEH # define CATCH_INTERNAL_CONFIG_WINDOWS_SEH
@ -638,6 +645,9 @@ namespace Catch {
#if !defined(CATCH_INTERNAL_SUPPRESS_UNUSED_VARIABLE_WARNINGS) #if !defined(CATCH_INTERNAL_SUPPRESS_UNUSED_VARIABLE_WARNINGS)
# define CATCH_INTERNAL_SUPPRESS_UNUSED_VARIABLE_WARNINGS # define CATCH_INTERNAL_SUPPRESS_UNUSED_VARIABLE_WARNINGS
#endif #endif
#if !defined(CATCH_INTERNAL_SUPPRESS_USELESS_CAST_WARNINGS)
# define CATCH_INTERNAL_SUPPRESS_USELESS_CAST_WARNINGS
#endif
#if !defined(CATCH_INTERNAL_SUPPRESS_ZERO_VARIADIC_WARNINGS) #if !defined(CATCH_INTERNAL_SUPPRESS_ZERO_VARIADIC_WARNINGS)
# define CATCH_INTERNAL_SUPPRESS_ZERO_VARIADIC_WARNINGS # define CATCH_INTERNAL_SUPPRESS_ZERO_VARIADIC_WARNINGS
#endif #endif
@ -679,6 +689,16 @@ namespace Catch {
# define CATCH_CONFIG_COLOUR_WIN32 # define CATCH_CONFIG_COLOUR_WIN32
#endif #endif
#if defined( CATCH_CONFIG_SHARED_LIBRARY ) && defined( _MSC_VER ) && \
!defined( CATCH_CONFIG_STATIC )
# ifdef Catch2_EXPORTS
# define CATCH_EXPORT //__declspec( dllexport ) // not needed
# else
# define CATCH_EXPORT __declspec( dllimport )
# endif
#else
# define CATCH_EXPORT
#endif
#endif // CATCH_COMPILER_CAPABILITIES_HPP_INCLUDED #endif // CATCH_COMPILER_CAPABILITIES_HPP_INCLUDED
@ -686,6 +706,7 @@ namespace Catch {
#ifndef CATCH_CONTEXT_HPP_INCLUDED #ifndef CATCH_CONTEXT_HPP_INCLUDED
#define CATCH_CONTEXT_HPP_INCLUDED #define CATCH_CONTEXT_HPP_INCLUDED
namespace Catch { namespace Catch {
class IResultCapture; class IResultCapture;
@ -706,7 +727,7 @@ namespace Catch {
virtual void setConfig( IConfig const* config ) = 0; virtual void setConfig( IConfig const* config ) = 0;
private: private:
static IMutableContext *currentContext; CATCH_EXPORT static IMutableContext* currentContext;
friend IMutableContext& getCurrentMutableContext(); friend IMutableContext& getCurrentMutableContext();
friend void cleanUpContext(); friend void cleanUpContext();
static void createContext(); static void createContext();
@ -1716,9 +1737,9 @@ namespace Catch {
template <typename> struct true_given : std::true_type {}; template <typename> struct true_given : std::true_type {};
struct is_callable_tester { struct is_callable_tester {
template <typename Fun, typename... Args> template <typename Fun, typename... Args>
true_given<decltype(std::declval<Fun>()(std::declval<Args>()...))> static test(int); static true_given<decltype(std::declval<Fun>()(std::declval<Args>()...))> test(int);
template <typename...> template <typename...>
std::false_type static test(...); static std::false_type test(...);
}; };
template <typename T> template <typename T>
@ -2737,14 +2758,18 @@ namespace Catch {
template <typename U> template <typename U>
void destruct_on_exit(std::enable_if_t<!Destruct, U>* = nullptr) { } void destruct_on_exit(std::enable_if_t<!Destruct, U>* = nullptr) { }
T& stored_object() { #if defined( __GNUC__ ) && __GNUC__ <= 6
return *static_cast<T*>(static_cast<void*>(data)); # pragma GCC diagnostic push
} # pragma GCC diagnostic ignored "-Wstrict-aliasing"
#endif
T& stored_object() { return *reinterpret_cast<T*>( data ); }
T const& stored_object() const { T const& stored_object() const {
return *static_cast<T const*>(static_cast<void const*>(data)); return *reinterpret_cast<T const*>( data );
} }
#if defined( __GNUC__ ) && __GNUC__ <= 6
# pragma GCC diagnostic pop
#endif
alignas( T ) unsigned char data[sizeof( T )]{}; alignas( T ) unsigned char data[sizeof( T )]{};
}; };
@ -2776,7 +2801,6 @@ namespace Catch {
#include <cstddef> #include <cstddef>
#include <type_traits> #include <type_traits>
#include <string> #include <string>
#include <string.h>
@ -2939,6 +2963,13 @@ namespace Catch {
namespace Detail { namespace Detail {
inline std::size_t catch_strnlen(const char *str, std::size_t n) {
auto ret = std::char_traits<char>::find(str, n, '\0');
if (ret != nullptr) {
return static_cast<std::size_t>(ret - str);
}
return n;
}
constexpr StringRef unprintableString = "{?}"_sr; constexpr StringRef unprintableString = "{?}"_sr;
@ -3106,28 +3137,24 @@ namespace Catch {
template<size_t SZ> template<size_t SZ>
struct StringMaker<char[SZ]> { struct StringMaker<char[SZ]> {
static std::string convert(char const* str) { static std::string convert(char const* str) {
// Note that `strnlen` is not actually part of standard C++,
// but both POSIX and Windows cstdlib provide it.
return Detail::convertIntoString( return Detail::convertIntoString(
StringRef( str, strnlen( str, SZ ) ) ); StringRef( str, Detail::catch_strnlen( str, SZ ) ) );
} }
}; };
template<size_t SZ> template<size_t SZ>
struct StringMaker<signed char[SZ]> { struct StringMaker<signed char[SZ]> {
static std::string convert(signed char const* str) { static std::string convert(signed char const* str) {
// See the plain `char const*` overload
auto reinterpreted = reinterpret_cast<char const*>(str); auto reinterpreted = reinterpret_cast<char const*>(str);
return Detail::convertIntoString( return Detail::convertIntoString(
StringRef(reinterpreted, strnlen(reinterpreted, SZ))); StringRef(reinterpreted, Detail::catch_strnlen(reinterpreted, SZ)));
} }
}; };
template<size_t SZ> template<size_t SZ>
struct StringMaker<unsigned char[SZ]> { struct StringMaker<unsigned char[SZ]> {
static std::string convert(unsigned char const* str) { static std::string convert(unsigned char const* str) {
// See the plain `char const*` overload
auto reinterpreted = reinterpret_cast<char const*>(str); auto reinterpreted = reinterpret_cast<char const*>(str);
return Detail::convertIntoString( return Detail::convertIntoString(
StringRef(reinterpreted, strnlen(reinterpreted, SZ))); StringRef(reinterpreted, Detail::catch_strnlen(reinterpreted, SZ)));
} }
}; };
@ -3194,13 +3221,13 @@ namespace Catch {
template<> template<>
struct StringMaker<float> { struct StringMaker<float> {
static std::string convert(float value); static std::string convert(float value);
static int precision; CATCH_EXPORT static int precision;
}; };
template<> template<>
struct StringMaker<double> { struct StringMaker<double> {
static std::string convert(double value); static std::string convert(double value);
static int precision; CATCH_EXPORT static int precision;
}; };
template <typename T> template <typename T>
@ -4271,6 +4298,19 @@ namespace Catch {
#endif // CATCH_CONFIG_HPP_INCLUDED #endif // CATCH_CONFIG_HPP_INCLUDED
#ifndef CATCH_GET_RANDOM_SEED_HPP_INCLUDED
#define CATCH_GET_RANDOM_SEED_HPP_INCLUDED
#include <cstdint>
namespace Catch {
//! Returns Catch2's current RNG seed.
std::uint32_t getSeed();
}
#endif // CATCH_GET_RANDOM_SEED_HPP_INCLUDED
#ifndef CATCH_MESSAGE_HPP_INCLUDED #ifndef CATCH_MESSAGE_HPP_INCLUDED
#define CATCH_MESSAGE_HPP_INCLUDED #define CATCH_MESSAGE_HPP_INCLUDED
@ -5642,7 +5682,10 @@ namespace Catch {
do { \ do { \
Catch::AssertionHandler catchAssertionHandler( macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(__VA_ARGS__), resultDisposition ); \ Catch::AssertionHandler catchAssertionHandler( macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(__VA_ARGS__), resultDisposition ); \
try { \ try { \
CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \
CATCH_INTERNAL_SUPPRESS_USELESS_CAST_WARNINGS \
static_cast<void>(__VA_ARGS__); \ static_cast<void>(__VA_ARGS__); \
CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION \
catchAssertionHandler.handleExceptionNotThrownAsExpected(); \ catchAssertionHandler.handleExceptionNotThrownAsExpected(); \
} \ } \
catch( ... ) { \ catch( ... ) { \
@ -5657,7 +5700,10 @@ namespace Catch {
Catch::AssertionHandler catchAssertionHandler( macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(__VA_ARGS__), resultDisposition); \ Catch::AssertionHandler catchAssertionHandler( macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(__VA_ARGS__), resultDisposition); \
if( catchAssertionHandler.allowThrows() ) \ if( catchAssertionHandler.allowThrows() ) \
try { \ try { \
CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \
CATCH_INTERNAL_SUPPRESS_USELESS_CAST_WARNINGS \
static_cast<void>(__VA_ARGS__); \ static_cast<void>(__VA_ARGS__); \
CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION \
catchAssertionHandler.handleUnexpectedExceptionNotThrown(); \ catchAssertionHandler.handleUnexpectedExceptionNotThrown(); \
} \ } \
catch( ... ) { \ catch( ... ) { \
@ -5674,7 +5720,10 @@ namespace Catch {
Catch::AssertionHandler catchAssertionHandler( macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(expr) ", " CATCH_INTERNAL_STRINGIFY(exceptionType), resultDisposition ); \ Catch::AssertionHandler catchAssertionHandler( macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(expr) ", " CATCH_INTERNAL_STRINGIFY(exceptionType), resultDisposition ); \
if( catchAssertionHandler.allowThrows() ) \ if( catchAssertionHandler.allowThrows() ) \
try { \ try { \
CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \
CATCH_INTERNAL_SUPPRESS_USELESS_CAST_WARNINGS \
static_cast<void>(expr); \ static_cast<void>(expr); \
CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION \
catchAssertionHandler.handleUnexpectedExceptionNotThrown(); \ catchAssertionHandler.handleUnexpectedExceptionNotThrown(); \
} \ } \
catch( exceptionType const& ) { \ catch( exceptionType const& ) { \
@ -5697,7 +5746,10 @@ namespace Catch {
Catch::AssertionHandler catchAssertionHandler( macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(__VA_ARGS__) ", " CATCH_INTERNAL_STRINGIFY(matcher), resultDisposition ); \ Catch::AssertionHandler catchAssertionHandler( macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(__VA_ARGS__) ", " CATCH_INTERNAL_STRINGIFY(matcher), resultDisposition ); \
if( catchAssertionHandler.allowThrows() ) \ if( catchAssertionHandler.allowThrows() ) \
try { \ try { \
CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \
CATCH_INTERNAL_SUPPRESS_USELESS_CAST_WARNINGS \
static_cast<void>(__VA_ARGS__); \ static_cast<void>(__VA_ARGS__); \
CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION \
catchAssertionHandler.handleUnexpectedExceptionNotThrown(); \ catchAssertionHandler.handleUnexpectedExceptionNotThrown(); \
} \ } \
catch( ... ) { \ catch( ... ) { \
@ -6447,12 +6499,12 @@ struct AutoReg : Detail::NonCopyable {
struct TestName{\ struct TestName{\
TestName(){\ TestName(){\
size_t index = 0; \ size_t index = 0; \
constexpr char const* tmpl_types[] = {CATCH_REC_LIST(INTERNAL_CATCH_STRINGIZE_WITHOUT_PARENS, __VA_ARGS__)};\ constexpr char const* tmpl_types[] = {CATCH_REC_LIST(INTERNAL_CATCH_STRINGIZE_WITHOUT_PARENS, __VA_ARGS__)}; /* NOLINT(cppcoreguidelines-avoid-c-arrays,modernize-avoid-c-arrays,hicpp-avoid-c-arrays) */\
using expander = size_t[];\ using expander = size_t[]; /* NOLINT(cppcoreguidelines-avoid-c-arrays,modernize-avoid-c-arrays,hicpp-avoid-c-arrays) */\
(void)expander{(reg_test(Types{}, Catch::NameAndTags{ Name " - " + std::string(tmpl_types[index]), Tags } ), index++)... };/* NOLINT */ \ (void)expander{(reg_test(Types{}, Catch::NameAndTags{ Name " - " + std::string(tmpl_types[index]), Tags } ), index++)... };/* NOLINT */ \
}\ }\
};\ };\
static int INTERNAL_CATCH_UNIQUE_NAME( globalRegistrar ) = [](){\ static const int INTERNAL_CATCH_UNIQUE_NAME( globalRegistrar ) = [](){\
TestName<INTERNAL_CATCH_MAKE_TYPE_LISTS_FROM_TYPES(__VA_ARGS__)>();\ TestName<INTERNAL_CATCH_MAKE_TYPE_LISTS_FROM_TYPES(__VA_ARGS__)>();\
return 0;\ return 0;\
}();\ }();\
@ -7063,7 +7115,7 @@ namespace Catch {
#define CATCH_VERSION_MAJOR 3 #define CATCH_VERSION_MAJOR 3
#define CATCH_VERSION_MINOR 1 #define CATCH_VERSION_MINOR 1
#define CATCH_VERSION_PATCH 0 #define CATCH_VERSION_PATCH 1
#endif // CATCH_VERSION_MACROS_HPP_INCLUDED #endif // CATCH_VERSION_MACROS_HPP_INCLUDED
@ -9122,6 +9174,7 @@ namespace Catch {
#include <cmath> #include <cmath>
#include <algorithm>
namespace Catch { namespace Catch {
@ -9673,32 +9726,6 @@ namespace Catch {
#endif // CATCH_UNCAUGHT_EXCEPTIONS_HPP_INCLUDED #endif // CATCH_UNCAUGHT_EXCEPTIONS_HPP_INCLUDED
#ifndef CATCH_WINDOWS_H_PROXY_HPP_INCLUDED
#define CATCH_WINDOWS_H_PROXY_HPP_INCLUDED
#if defined(CATCH_PLATFORM_WINDOWS)
// We might end up with the define made globally through the compiler,
// and we don't want to trigger warnings for this
#if !defined(NOMINMAX)
# define NOMINMAX
#endif
#if !defined(WIN32_LEAN_AND_MEAN)
# define WIN32_LEAN_AND_MEAN
#endif
#ifdef __AFXDLL
#include <AfxWin.h>
#else
#include <windows.h>
#endif
#endif // defined(CATCH_PLATFORM_WINDOWS)
#endif // CATCH_WINDOWS_H_PROXY_HPP_INCLUDED
#ifndef CATCH_XMLWRITER_HPP_INCLUDED #ifndef CATCH_XMLWRITER_HPP_INCLUDED
#define CATCH_XMLWRITER_HPP_INCLUDED #define CATCH_XMLWRITER_HPP_INCLUDED

View File

@ -8,7 +8,7 @@
project( project(
'catch2', 'catch2',
'cpp', 'cpp',
version: '3.1.0', # CML version placeholder, don't delete version: '3.1.1', # CML version placeholder, don't delete
license: 'BSL-1.0', license: 'BSL-1.0',
meson_version: '>=0.49.0', meson_version: '>=0.49.0',
) )

View File

@ -301,7 +301,10 @@ if (ANDROID)
target_link_libraries(Catch2 INTERFACE log) target_link_libraries(Catch2 INTERFACE log)
endif() endif()
set_target_properties(Catch2 PROPERTIES DEBUG_POSTFIX "d") set_target_properties(Catch2 PROPERTIES
DEBUG_POSTFIX "d"
VERSION ${PROJECT_VERSION}
SOVERSION ${PROJECT_VERSION})
# depend on bunch of C++11 and C++14 features to have C++14 enabled by default # depend on bunch of C++11 and C++14 features to have C++14 enabled by default
target_compile_features(Catch2 target_compile_features(Catch2
@ -350,6 +353,8 @@ target_link_libraries(Catch2WithMain PUBLIC Catch2)
set_target_properties(Catch2WithMain set_target_properties(Catch2WithMain
PROPERTIES PROPERTIES
OUTPUT_NAME "Catch2Main" OUTPUT_NAME "Catch2Main"
VERSION ${PROJECT_VERSION}
SOVERSION ${PROJECT_VERSION}
) )
set_target_properties(Catch2WithMain PROPERTIES DEBUG_POSTFIX "d") set_target_properties(Catch2WithMain PROPERTIES DEBUG_POSTFIX "d")

View File

@ -43,7 +43,7 @@ namespace Catch {
inline std::size_t catch_strnlen(const char *str, std::size_t n) { inline std::size_t catch_strnlen(const char *str, std::size_t n) {
auto ret = std::char_traits<char>::find(str, n, '\0'); auto ret = std::char_traits<char>::find(str, n, '\0');
if (ret != nullptr) { if (ret != nullptr) {
return ret - str; return static_cast<std::size_t>(ret - str);
} }
return n; return n;
} }

View File

@ -36,7 +36,7 @@ namespace Catch {
} }
Version const& libraryVersion() { Version const& libraryVersion() {
static Version version( 3, 1, 0, "", 0 ); static Version version( 3, 1, 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 1 #define CATCH_VERSION_MINOR 1
#define CATCH_VERSION_PATCH 0 #define CATCH_VERSION_PATCH 1
#endif // CATCH_VERSION_MACROS_HPP_INCLUDED #endif // CATCH_VERSION_MACROS_HPP_INCLUDED

View File

@ -16,21 +16,23 @@
namespace { namespace {
std::uint64_t Fibonacci(std::uint64_t number) { std::uint64_t Fibonacci(std::uint64_t number) {
return number < 2 ? 1 : Fibonacci(number - 1) + Fibonacci(number - 2); return number < 2 ? number : Fibonacci(number - 1) + Fibonacci(number - 2);
} }
} }
TEST_CASE("Benchmark Fibonacci", "[!benchmark]") { TEST_CASE("Benchmark Fibonacci", "[!benchmark]") {
CHECK(Fibonacci(0) == 1); CHECK(Fibonacci(0) == 0);
// some more asserts.. // some more asserts..
CHECK(Fibonacci(5) == 8); CHECK(Fibonacci(5) == 5);
// some more asserts.. // some more asserts..
BENCHMARK("Fibonacci 20") { REQUIRE( Fibonacci( 20 ) == 6'765 );
BENCHMARK( "Fibonacci 20" ) {
return Fibonacci(20); return Fibonacci(20);
}; };
BENCHMARK("Fibonacci 25") { REQUIRE( Fibonacci( 25 ) == 75'025 );
BENCHMARK( "Fibonacci 25" ) {
return Fibonacci(25); return Fibonacci(25);
}; };