mirror of
https://github.com/catchorg/Catch2.git
synced 2025-09-20 03:25:40 +02:00
Compare commits
86 Commits
Author | SHA1 | Date | |
---|---|---|---|
![]() |
5f94c8dafb | ||
![]() |
695a356f93 | ||
![]() |
020b655635 | ||
![]() |
5561d0342d | ||
![]() |
3a15315a37 | ||
![]() |
b7b346c3e5 | ||
![]() |
9e09d79946 | ||
![]() |
7048c2c269 | ||
![]() |
6f77d59b16 | ||
![]() |
022b61ff92 | ||
![]() |
87b5bf77bc | ||
![]() |
81d52c4a5f | ||
![]() |
200b8b6fc0 | ||
![]() |
e70fd2a4b9 | ||
![]() |
36170d60ca | ||
![]() |
917e92c162 | ||
![]() |
f54950744f | ||
![]() |
b3b07215d1 | ||
![]() |
2652bb86e3 | ||
![]() |
1715b6b923 | ||
![]() |
f20a9dbc6e | ||
![]() |
273c3f85eb | ||
![]() |
6a3d0dc176 | ||
![]() |
ccb1f70629 | ||
![]() |
4a5bc0f39a | ||
![]() |
f96e89e016 | ||
![]() |
481f54b357 | ||
![]() |
2d172dc688 | ||
![]() |
587a20b312 | ||
![]() |
bff44f8b01 | ||
![]() |
4ea74ff966 | ||
![]() |
d10b9bd02e | ||
![]() |
55794e9b27 | ||
![]() |
fa6211bfc2 | ||
![]() |
4e90f910dc | ||
![]() |
0c59cc83cf | ||
![]() |
e4004e0adb | ||
![]() |
6c9a255dc2 | ||
![]() |
9a8963133f | ||
![]() |
cfba9dce97 | ||
![]() |
a537ccae22 | ||
![]() |
e1c9d5569d | ||
![]() |
d512decaac | ||
![]() |
f23f96883a | ||
![]() |
d7b8c3ace3 | ||
![]() |
32733e08c0 | ||
![]() |
930f49a641 | ||
![]() |
c409dccee5 | ||
![]() |
95bfb33167 | ||
![]() |
59d2d08c0f | ||
![]() |
fa6d52e2a3 | ||
![]() |
5ac348cd6e | ||
![]() |
776a4686c7 | ||
![]() |
3136c4fb6a | ||
![]() |
74e0e737a6 | ||
![]() |
0685216175 | ||
![]() |
fc320f6b8f | ||
![]() |
5290d4bedc | ||
![]() |
7ada02e21e | ||
![]() |
849f2848bd | ||
![]() |
2fbd66c51c | ||
![]() |
51b29ced1a | ||
![]() |
9a558171d8 | ||
![]() |
c5c688820c | ||
![]() |
6a08225863 | ||
![]() |
4327baba40 | ||
![]() |
50cc14c94c | ||
![]() |
87b745da66 | ||
![]() |
7d0b205564 | ||
![]() |
8fb1219013 | ||
![]() |
23c80bcc92 | ||
![]() |
a2c8dce85c | ||
![]() |
1e379de9d7 | ||
![]() |
4eea438b73 | ||
![]() |
407ee0af2f | ||
![]() |
060a41ec7b | ||
![]() |
90825a4f7a | ||
![]() |
9e8ae7d470 | ||
![]() |
84856844e1 | ||
![]() |
01ef7076f5 | ||
![]() |
ae14a47360 | ||
![]() |
f2b23db6d1 | ||
![]() |
1aa98c76ac | ||
![]() |
3195c242c2 | ||
![]() |
31906d83ec | ||
![]() |
91fa55303b |
@@ -6,12 +6,16 @@ if(NOT DEFINED PROJECT_NAME)
|
|||||||
set(NOT_SUBPROJECT ON)
|
set(NOT_SUBPROJECT ON)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
project(Catch2 LANGUAGES CXX VERSION 2.10.0)
|
# Catch2's build breaks if done in-tree. You probably should not build
|
||||||
|
# things in tree anyway, but we can allow projects that include Catch2
|
||||||
if (CMAKE_BINARY_DIR STREQUAL CMAKE_SOURCE_DIR)
|
# as a subproject to build in-tree as long as it is not in our tree.
|
||||||
|
if (CMAKE_BINARY_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR)
|
||||||
message(FATAL_ERROR "Building in-source is not supported! Create a build dir and remove ${CMAKE_SOURCE_DIR}/CMakeCache.txt")
|
message(FATAL_ERROR "Building in-source is not supported! Create a build dir and remove ${CMAKE_SOURCE_DIR}/CMakeCache.txt")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
|
||||||
|
project(Catch2 LANGUAGES CXX VERSION 2.11.2)
|
||||||
|
|
||||||
# Provide path for scripts
|
# Provide path for scripts
|
||||||
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/CMake")
|
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/CMake")
|
||||||
|
|
||||||
|
@@ -5,11 +5,11 @@
|
|||||||
[](https://travis-ci.org/catchorg/Catch2)
|
[](https://travis-ci.org/catchorg/Catch2)
|
||||||
[](https://ci.appveyor.com/project/catchorg/catch2)
|
[](https://ci.appveyor.com/project/catchorg/catch2)
|
||||||
[](https://codecov.io/gh/catchorg/Catch2)
|
[](https://codecov.io/gh/catchorg/Catch2)
|
||||||
[](https://wandbox.org/permlink/00GdTUbFWaV3bNah)
|
[](https://wandbox.org/permlink/ZI5SYb7JE1UJhAKP)
|
||||||
[](https://discord.gg/4CWS9zD)
|
[](https://discord.gg/4CWS9zD)
|
||||||
|
|
||||||
|
|
||||||
<a href="https://github.com/catchorg/Catch2/releases/download/v2.10.0/catch.hpp">The latest version of the single header can be downloaded directly using this link</a>
|
<a href="https://github.com/catchorg/Catch2/releases/download/v2.11.2/catch.hpp">The latest version of the single header can be downloaded directly using this link</a>
|
||||||
|
|
||||||
## Catch2 is released!
|
## Catch2 is released!
|
||||||
|
|
||||||
|
@@ -1,6 +1,11 @@
|
|||||||
# version string format -- This will be overwritten later anyway
|
# version string format -- This will be overwritten later anyway
|
||||||
version: "{build}"
|
version: "{build}"
|
||||||
|
|
||||||
|
# We need a more up to date pip because Python 2.7 is EOL soon
|
||||||
|
init:
|
||||||
|
- set PATH=C:\Python35\Scripts;%PATH%
|
||||||
|
|
||||||
|
|
||||||
branches:
|
branches:
|
||||||
except:
|
except:
|
||||||
- /dev-travis.+/
|
- /dev-travis.+/
|
||||||
@@ -62,7 +67,7 @@ matrix:
|
|||||||
|
|
||||||
|
|
||||||
install:
|
install:
|
||||||
- ps: if (($env:CONFIGURATION) -eq "Debug" -And ($env:coverage) -eq "1" ) { python -m pip --disable-pip-version-check install codecov }
|
- ps: if (($env:CONFIGURATION) -eq "Debug" -And ($env:coverage) -eq "1" ) { pip --disable-pip-version-check install codecov }
|
||||||
- ps: if (($env:CONFIGURATION) -eq "Debug" -And ($env:coverage) -eq "1" ) { .\misc\installOpenCppCoverage.ps1 }
|
- ps: if (($env:CONFIGURATION) -eq "Debug" -And ($env:coverage) -eq "1" ) { .\misc\installOpenCppCoverage.ps1 }
|
||||||
|
|
||||||
# Win32 and x64 are CMake-compatible solution platform names.
|
# Win32 and x64 are CMake-compatible solution platform names.
|
||||||
|
@@ -14,6 +14,7 @@ coverage:
|
|||||||
- "**/catch_reporter_tap.hpp"
|
- "**/catch_reporter_tap.hpp"
|
||||||
- "**/catch_reporter_automake.hpp"
|
- "**/catch_reporter_automake.hpp"
|
||||||
- "**/catch_reporter_teamcity.hpp"
|
- "**/catch_reporter_teamcity.hpp"
|
||||||
|
- "**/catch_reporter_sonarqube.hpp"
|
||||||
- "**/external/clara.hpp"
|
- "**/external/clara.hpp"
|
||||||
|
|
||||||
|
|
||||||
|
@@ -35,6 +35,7 @@ FAQ:
|
|||||||
Other:
|
Other:
|
||||||
* [Why Catch?](why-catch.md#top)
|
* [Why Catch?](why-catch.md#top)
|
||||||
* [Open Source Projects using Catch](opensource-users.md#top)
|
* [Open Source Projects using Catch](opensource-users.md#top)
|
||||||
|
* [Commercial Projects using Catch](commercial-users.md#top)
|
||||||
* [Contributing](contributing.md#top)
|
* [Contributing](contributing.md#top)
|
||||||
* [Release Notes](release-notes.md#top)
|
* [Release Notes](release-notes.md#top)
|
||||||
* [Deprecations and incoming changes](deprecations.md#top)
|
* [Deprecations and incoming changes](deprecations.md#top)
|
||||||
|
@@ -189,19 +189,17 @@ construct and destroy objects without dynamic allocation and in a way that lets
|
|||||||
you measure construction and destruction separately.
|
you measure construction and destruction separately.
|
||||||
|
|
||||||
```c++
|
```c++
|
||||||
BENCHMARK_ADVANCED("construct")(Catch::Benchmark::Chronometer meter)
|
BENCHMARK_ADVANCED("construct")(Catch::Benchmark::Chronometer meter) {
|
||||||
{
|
|
||||||
std::vector<Catch::Benchmark::storage_for<std::string>> storage(meter.runs());
|
std::vector<Catch::Benchmark::storage_for<std::string>> storage(meter.runs());
|
||||||
meter.measure([&](int i) { storage[i].construct("thing"); });
|
meter.measure([&](int i) { storage[i].construct("thing"); });
|
||||||
})
|
};
|
||||||
|
|
||||||
BENCHMARK_ADVANCED("destroy", [](Catch::Benchmark::Chronometer meter)
|
BENCHMARK_ADVANCED("destroy")(Catch::Benchmark::Chronometer meter) {
|
||||||
{
|
|
||||||
std::vector<Catch::Benchmark::destructable_object<std::string>> storage(meter.runs());
|
std::vector<Catch::Benchmark::destructable_object<std::string>> storage(meter.runs());
|
||||||
for(auto&& o : storage)
|
for(auto&& o : storage)
|
||||||
o.construct("thing");
|
o.construct("thing");
|
||||||
meter.measure([&](int i) { storage[i].destruct(); });
|
meter.measure([&](int i) { storage[i].destruct(); });
|
||||||
})
|
};
|
||||||
```
|
```
|
||||||
|
|
||||||
`Catch::Benchmark::storage_for<T>` objects are just pieces of raw storage suitable for `T`
|
`Catch::Benchmark::storage_for<T>` objects are just pieces of raw storage suitable for `T`
|
||||||
|
@@ -12,7 +12,7 @@ Build Systems may refer to low-level tools, like CMake, or larger systems that r
|
|||||||
|
|
||||||
## Continuous Integration systems
|
## Continuous Integration systems
|
||||||
|
|
||||||
Probably the most important aspect to using Catch with a build server is the use of different reporters. Catch comes bundled with three reporters that should cover the majority of build servers out there - although adding more for better integration with some is always a possibility (currently we also offer TeamCity, TAP and Automake reporters).
|
Probably the most important aspect to using Catch with a build server is the use of different reporters. Catch comes bundled with three reporters that should cover the majority of build servers out there - although adding more for better integration with some is always a possibility (currently we also offer TeamCity, TAP, Automake and SonarQube reporters).
|
||||||
|
|
||||||
Two of these reporters are built in (XML and JUnit) and the third (TeamCity) is included as a separate header. It's possible that the other two may be split out in the future too - as that would make the core of Catch smaller for those that don't need them.
|
Two of these reporters are built in (XML and JUnit) and the third (TeamCity) is included as a separate header. It's possible that the other two may be split out in the future too - as that would make the core of Catch smaller for those that don't need them.
|
||||||
|
|
||||||
@@ -65,6 +65,10 @@ The Automake Reporter writes out the [meta tags](https://www.gnu.org/software/au
|
|||||||
|
|
||||||
Because of the incremental nature of Catch's test suites and ability to run specific tests, our implementation of TAP reporter writes out the number of tests in a suite last.
|
Because of the incremental nature of Catch's test suites and ability to run specific tests, our implementation of TAP reporter writes out the number of tests in a suite last.
|
||||||
|
|
||||||
|
### SonarQube Reporter
|
||||||
|
```-r sonarqube```
|
||||||
|
[SonarQube Generic Test Data](https://docs.sonarqube.org/latest/analysis/generic-test/) XML format for tests metrics.
|
||||||
|
|
||||||
## Low-level tools
|
## Low-level tools
|
||||||
|
|
||||||
### Precompiled headers (PCHs)
|
### Precompiled headers (PCHs)
|
||||||
|
@@ -24,6 +24,7 @@
|
|||||||
[Specify the number of resamples for bootstrapping](#specify-the-number-of-resamples-for-bootstrapping)<br>
|
[Specify the number of resamples for bootstrapping](#specify-the-number-of-resamples-for-bootstrapping)<br>
|
||||||
[Specify the confidence-interval for bootstrapping](#specify-the-confidence-interval-for-bootstrapping)<br>
|
[Specify the confidence-interval for bootstrapping](#specify-the-confidence-interval-for-bootstrapping)<br>
|
||||||
[Disable statistical analysis of collected benchmark samples](#disable-statistical-analysis-of-collected-benchmark-samples)<br>
|
[Disable statistical analysis of collected benchmark samples](#disable-statistical-analysis-of-collected-benchmark-samples)<br>
|
||||||
|
[Specify the amount of time in milliseconds spent on warming up each test](#specify-the-amount-of-time-in-milliseconds-spent-on-warming-up-each-test)<br>
|
||||||
[Usage](#usage)<br>
|
[Usage](#usage)<br>
|
||||||
[Specify the section to run](#specify-the-section-to-run)<br>
|
[Specify the section to run](#specify-the-section-to-run)<br>
|
||||||
[Filenames as tags](#filenames-as-tags)<br>
|
[Filenames as tags](#filenames-as-tags)<br>
|
||||||
@@ -64,6 +65,7 @@ Click one of the following links to take you straight to that option - or scroll
|
|||||||
<a href="#benchmark-resamples"> ` --benchmark-resamples`</a><br />
|
<a href="#benchmark-resamples"> ` --benchmark-resamples`</a><br />
|
||||||
<a href="#benchmark-confidence-interval"> ` --benchmark-confidence-interval`</a><br />
|
<a href="#benchmark-confidence-interval"> ` --benchmark-confidence-interval`</a><br />
|
||||||
<a href="#benchmark-no-analysis"> ` --benchmark-no-analysis`</a><br />
|
<a href="#benchmark-no-analysis"> ` --benchmark-no-analysis`</a><br />
|
||||||
|
<a href="#benchmark-warmup-time"> ` --benchmark-warmup-time`</a><br />
|
||||||
<a href="#use-colour"> ` --use-colour`</a><br />
|
<a href="#use-colour"> ` --use-colour`</a><br />
|
||||||
|
|
||||||
</br>
|
</br>
|
||||||
@@ -99,6 +101,7 @@ exclude:notThis Matches all tests except, 'notThis'
|
|||||||
~*private* Matches all tests except those that contain 'private'
|
~*private* Matches all tests except those that contain 'private'
|
||||||
a* ~ab* abc Matches all tests that start with 'a', except those that
|
a* ~ab* abc Matches all tests that start with 'a', except those that
|
||||||
start with 'ab', except 'abc', which is included
|
start with 'ab', except 'abc', which is included
|
||||||
|
-# [#somefile] Matches all tests from the file 'somefile.cpp'
|
||||||
</pre>
|
</pre>
|
||||||
|
|
||||||
Names within square brackets are interpreted as tags.
|
Names within square brackets are interpreted as tags.
|
||||||
@@ -268,7 +271,7 @@ See [The LibIdentify repo for more information and examples](https://github.com/
|
|||||||
|
|
||||||
<a id="wait-for-keypress"></a>
|
<a id="wait-for-keypress"></a>
|
||||||
## Wait for key before continuing
|
## Wait for key before continuing
|
||||||
<pre>--wait-for-keypress <start|exit|both></pre>
|
<pre>--wait-for-keypress <never|start|exit|both></pre>
|
||||||
|
|
||||||
Will cause the executable to print a message and wait until the return/ enter key is pressed before continuing -
|
Will cause the executable to print a message and wait until the return/ enter key is pressed before continuing -
|
||||||
either before running any tests, after running all tests - or both, depending on the argument.
|
either before running any tests, after running all tests - or both, depending on the argument.
|
||||||
@@ -316,6 +319,14 @@ Must be between 0 and 1 and defaults to 0.95.
|
|||||||
When this flag is specified no bootstrapping or any other statistical analysis is performed.
|
When this flag is specified no bootstrapping or any other statistical analysis is performed.
|
||||||
Instead the user code is only measured and the plain mean from the samples is reported.
|
Instead the user code is only measured and the plain mean from the samples is reported.
|
||||||
|
|
||||||
|
<a id="benchmark-warmup-time"></a>
|
||||||
|
## Specify the amount of time in milliseconds spent on warming up each test
|
||||||
|
<pre>--benchmark-warmup-time</pre>
|
||||||
|
|
||||||
|
> [Introduced](https://github.com/catchorg/Catch2/pull/1844) in Catch 2.11.2.
|
||||||
|
|
||||||
|
Configure the amount of time spent warming up each test.
|
||||||
|
|
||||||
<a id="usage"></a>
|
<a id="usage"></a>
|
||||||
## Usage
|
## Usage
|
||||||
<pre>-h, -?, --help</pre>
|
<pre>-h, -?, --help</pre>
|
||||||
|
@@ -18,3 +18,5 @@ fact then please let us know - either directly, via a PR or
|
|||||||
- [Inscopix Inc.](https://www.inscopix.com/)
|
- [Inscopix Inc.](https://www.inscopix.com/)
|
||||||
- [Makimo](https://makimo.pl/)
|
- [Makimo](https://makimo.pl/)
|
||||||
- [UX3D](https://ux3d.io)
|
- [UX3D](https://ux3d.io)
|
||||||
|
- [King](https://king.com)
|
||||||
|
|
||||||
|
@@ -16,6 +16,7 @@
|
|||||||
[Windows header clutter](#windows-header-clutter)<br>
|
[Windows header clutter](#windows-header-clutter)<br>
|
||||||
[Enabling stringification](#enabling-stringification)<br>
|
[Enabling stringification](#enabling-stringification)<br>
|
||||||
[Disabling exceptions](#disabling-exceptions)<br>
|
[Disabling exceptions](#disabling-exceptions)<br>
|
||||||
|
[Overriding Catch's debug break (`-b`)](#overriding-catchs-debug-break--b)<br>
|
||||||
|
|
||||||
Catch is designed to "just work" as much as possible. For most people the only configuration needed is telling Catch which source file should host all the implementation code (```CATCH_CONFIG_MAIN```).
|
Catch is designed to "just work" as much as possible. For most people the only configuration needed is telling Catch which source file should host all the implementation code (```CATCH_CONFIG_MAIN```).
|
||||||
|
|
||||||
@@ -257,6 +258,18 @@ namespace Catch {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## Overriding Catch's debug break (`-b`)
|
||||||
|
|
||||||
|
> [Introduced](https://github.com/catchorg/Catch2/pull/1846) in Catch 2.11.2.
|
||||||
|
|
||||||
|
You can override Catch2's break-into-debugger code by defining the
|
||||||
|
`CATCH_BREAK_INTO_DEBUGGER()` macro. This can be used if e.g. Catch2 does
|
||||||
|
not know your platform, or your platform is misdetected.
|
||||||
|
|
||||||
|
The macro will be used as is, that is, `CATCH_BREAK_INTO_DEBUGGER();`
|
||||||
|
must compile and must break into debugger.
|
||||||
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
[Home](Readme.md#top)
|
[Home](Readme.md#top)
|
||||||
|
@@ -70,6 +70,10 @@ locally takes just a few minutes.
|
|||||||
$ cd debug-build
|
$ cd debug-build
|
||||||
$ ctest -j 2 --output-on-failure
|
$ ctest -j 2 --output-on-failure
|
||||||
```
|
```
|
||||||
|
__Note:__ When running your tests with multi-configuration generators like
|
||||||
|
Visual Studio, you might get errors "Test not available without configuration."
|
||||||
|
You then have to pick one configuration (e.g. ` -C Debug`) in the `ctest` call.
|
||||||
|
|
||||||
If you added new tests, approval tests are very likely to fail. If they
|
If you added new tests, approval tests are very likely to fail. If they
|
||||||
do not, it means that your changes weren't run as part of them. This
|
do not, it means that your changes weren't run as part of them. This
|
||||||
_might_ be intentional, but usually is not.
|
_might_ be intentional, but usually is not.
|
||||||
|
@@ -45,6 +45,34 @@ There should be no reason to ever have an empty `SourceLineInfo`, so the
|
|||||||
method will be removed.
|
method will be removed.
|
||||||
|
|
||||||
|
|
||||||
|
### Composing lvalues of already composed matchers
|
||||||
|
|
||||||
|
Because a significant bug in this use case has persisted for 2+ years
|
||||||
|
without a bug report, and to simplify the implementation, code that
|
||||||
|
composes lvalues of composed matchers will not compile. That is,
|
||||||
|
this code will no longer work:
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
auto m1 = Contains("string");
|
||||||
|
auto m2 = Contains("random");
|
||||||
|
auto composed1 = m1 || m2;
|
||||||
|
auto m3 = Contains("different");
|
||||||
|
auto composed2 = composed1 || m3;
|
||||||
|
REQUIRE_THAT(foo(), !composed1);
|
||||||
|
REQUIRE_THAT(foo(), composed2);
|
||||||
|
```
|
||||||
|
|
||||||
|
Instead you will have to write this:
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
auto m1 = Contains("string");
|
||||||
|
auto m2 = Contains("random");
|
||||||
|
auto m3 = Contains("different");
|
||||||
|
REQUIRE_THAT(foo(), !(m1 || m2));
|
||||||
|
REQUIRE_THAT(foo(), m1 || m2 || m3);
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
## Planned changes
|
## Planned changes
|
||||||
|
|
||||||
|
|
||||||
@@ -93,6 +121,17 @@ positively match a testspec.
|
|||||||
The API for Catch2's console colour will be changed to take an extra
|
The API for Catch2's console colour will be changed to take an extra
|
||||||
argument, the stream to which the colour code should be applied.
|
argument, the stream to which the colour code should be applied.
|
||||||
|
|
||||||
|
|
||||||
|
### Type erasure in the `PredicateMatcher`
|
||||||
|
|
||||||
|
Currently, the `PredicateMatcher` uses `std::function` for type erasure,
|
||||||
|
so that type of the matcher is always `PredicateMatcher<T>`, regardless
|
||||||
|
of the type of the predicate. Because of the high compilation overhead
|
||||||
|
of `std::function`, and the fact that the type erasure is used only rarely,
|
||||||
|
`PredicateMatcher` will no longer be type erased in the future. Instead,
|
||||||
|
the predicate type will be made part of the PredicateMatcher's type.
|
||||||
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
[Home](Readme.md#top)
|
[Home](Readme.md#top)
|
||||||
|
@@ -49,7 +49,7 @@ a test case,
|
|||||||
* 4 specific purpose generators
|
* 4 specific purpose generators
|
||||||
* `RandomIntegerGenerator<Integral>` -- generates random Integrals from range
|
* `RandomIntegerGenerator<Integral>` -- generates random Integrals from range
|
||||||
* `RandomFloatGenerator<Float>` -- generates random Floats from range
|
* `RandomFloatGenerator<Float>` -- generates random Floats from range
|
||||||
* `RangeGenerator<T>` -- generates all values inside a specific range
|
* `RangeGenerator<T>` -- generates all values inside an arithmetic range
|
||||||
* `IteratorGenerator<T>` -- copies and returns values from an iterator range
|
* `IteratorGenerator<T>` -- copies and returns values from an iterator range
|
||||||
|
|
||||||
> `ChunkGenerator<T>`, `RandomIntegerGenerator<Integral>`, `RandomFloatGenerator<Float>` and `RangeGenerator<T>` were introduced in Catch 2.7.0.
|
> `ChunkGenerator<T>`, `RandomIntegerGenerator<Integral>`, `RandomFloatGenerator<Float>` and `RangeGenerator<T>` were introduced in Catch 2.7.0.
|
||||||
@@ -69,8 +69,8 @@ type, making their usage much nicer. These are
|
|||||||
* `map<T>(func, GeneratorWrapper<U>&&)` for `MapGenerator<T, U, Func>` (map `U` to `T`)
|
* `map<T>(func, GeneratorWrapper<U>&&)` for `MapGenerator<T, U, Func>` (map `U` to `T`)
|
||||||
* `chunk(chunk-size, GeneratorWrapper<T>&&)` for `ChunkGenerator<T>`
|
* `chunk(chunk-size, GeneratorWrapper<T>&&)` for `ChunkGenerator<T>`
|
||||||
* `random(IntegerOrFloat a, IntegerOrFloat b)` for `RandomIntegerGenerator` or `RandomFloatGenerator`
|
* `random(IntegerOrFloat a, IntegerOrFloat b)` for `RandomIntegerGenerator` or `RandomFloatGenerator`
|
||||||
* `range(start, end)` for `RangeGenerator<T>` with a step size of `1`
|
* `range(Arithemtic start, Arithmetic end)` for `RangeGenerator<Arithmetic>` with a step size of `1`
|
||||||
* `range(start, end, step)` for `RangeGenerator<T>` with a custom step size
|
* `range(Arithmetic start, Arithmetic end, Arithmetic step)` for `RangeGenerator<Arithmetic>` with a custom step size
|
||||||
* `from_range(InputIterator from, InputIterator to)` for `IteratorGenerator<T>`
|
* `from_range(InputIterator from, InputIterator to)` for `IteratorGenerator<T>`
|
||||||
* `from_range(Container const&)` for `IteratorGenerator<T>`
|
* `from_range(Container const&)` for `IteratorGenerator<T>`
|
||||||
|
|
||||||
@@ -78,6 +78,8 @@ type, making their usage much nicer. These are
|
|||||||
|
|
||||||
> `from_range` has been introduced in Catch 2.10.0
|
> `from_range` has been introduced in Catch 2.10.0
|
||||||
|
|
||||||
|
> `range()` for floating point numbers has been introduced in Catch 2.11.0
|
||||||
|
|
||||||
And can be used as shown in the example below to create a generator
|
And can be used as shown in the example below to create a generator
|
||||||
that returns 100 odd random number:
|
that returns 100 odd random number:
|
||||||
|
|
||||||
|
@@ -45,6 +45,15 @@ the `REQUIRE` family of macros), Catch2 does not know that there are no
|
|||||||
more sections in that test case and must run the test case again.
|
more sections in that test case and must run the test case again.
|
||||||
|
|
||||||
|
|
||||||
|
### MinGW/CygWin compilation (linking) is extremely slow
|
||||||
|
|
||||||
|
Compiling Catch2 with MinGW can be exceedingly slow, especially during
|
||||||
|
the linking step. As far as we can tell, this is caused by deficiencies
|
||||||
|
in its default linker. If you can tell MinGW to instead use lld, via
|
||||||
|
`-fuse-ld=lld`, the link time should drop down to reasonable length
|
||||||
|
again.
|
||||||
|
|
||||||
|
|
||||||
## Features
|
## Features
|
||||||
This section outlines some missing features, what is their status and their possible workarounds.
|
This section outlines some missing features, what is their status and their possible workarounds.
|
||||||
|
|
||||||
|
@@ -35,6 +35,22 @@ REQUIRE_THAT( str,
|
|||||||
(StartsWith( "Big data" ) && !Contains( "web scale" ) ) );
|
(StartsWith( "Big data" ) && !Contains( "web scale" ) ) );
|
||||||
```
|
```
|
||||||
|
|
||||||
|
_The combining operators do not take ownership of the matcher objects.
|
||||||
|
This means that if you store the combined object, you have to ensure that
|
||||||
|
the matcher objects outlive its last use. What this means is that code
|
||||||
|
like this leads to a use-after-free and (hopefully) a crash:_
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
TEST_CASE("Bugs, bugs, bugs", "[Bug]"){
|
||||||
|
std::string str = "Bugs as a service";
|
||||||
|
|
||||||
|
auto match_expression = Catch::EndsWith( "as a service" ) ||
|
||||||
|
(Catch::StartsWith( "Big data" ) && !Catch::Contains( "web scale" ) );
|
||||||
|
REQUIRE_THAT(str, match_expression);
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
## Built in matchers
|
## Built in matchers
|
||||||
Catch2 provides some matchers by default. They can be found in the
|
Catch2 provides some matchers by default. They can be found in the
|
||||||
`Catch::Matchers::foo` namespace and are imported into the `Catch`
|
`Catch::Matchers::foo` namespace and are imported into the `Catch`
|
||||||
|
@@ -53,9 +53,6 @@ Open source Oracle Tuxedo-like XATMI middleware for C and C++.
|
|||||||
### [Inja](https://github.com/pantor/inja)
|
### [Inja](https://github.com/pantor/inja)
|
||||||
A header-only template engine for modern C++.
|
A header-only template engine for modern C++.
|
||||||
|
|
||||||
### [JSON for Modern C++](https://github.com/nlohmann/json)
|
|
||||||
A, single-header, JSON parsing library that takes advantage of what C++ has to offer.
|
|
||||||
|
|
||||||
### [libcluon](https://github.com/chrberger/libcluon)
|
### [libcluon](https://github.com/chrberger/libcluon)
|
||||||
A single-header-only library written in C++14 to glue distributed software components (UDP, TCP, shared memory) supporting natively Protobuf, LCM/ZCM, MsgPack, and JSON for dynamic message transformations in-between.
|
A single-header-only library written in C++14 to glue distributed software components (UDP, TCP, shared memory) supporting natively Protobuf, LCM/ZCM, MsgPack, and JSON for dynamic message transformations in-between.
|
||||||
|
|
||||||
|
@@ -2,6 +2,11 @@
|
|||||||
|
|
||||||
# Release notes
|
# Release notes
|
||||||
**Contents**<br>
|
**Contents**<br>
|
||||||
|
[2.11.2](#2112)<br>
|
||||||
|
[2.11.1](#2111)<br>
|
||||||
|
[2.11.0](#2110)<br>
|
||||||
|
[2.10.2](#2102)<br>
|
||||||
|
[2.10.1](#2101)<br>
|
||||||
[2.10.0](#2100)<br>
|
[2.10.0](#2100)<br>
|
||||||
[2.9.2](#292)<br>
|
[2.9.2](#292)<br>
|
||||||
[2.9.1](#291)<br>
|
[2.9.1](#291)<br>
|
||||||
@@ -29,6 +34,89 @@
|
|||||||
[Even Older versions](#even-older-versions)<br>
|
[Even Older versions](#even-older-versions)<br>
|
||||||
|
|
||||||
|
|
||||||
|
## 2.11.2
|
||||||
|
|
||||||
|
### Improvements
|
||||||
|
* GCC and Clang now issue warnings for suspicious code in assertions (#1880)
|
||||||
|
* E.g. `REQUIRE( int != unsigned int )` will now issue mixed signedness comparison warning
|
||||||
|
* This has always worked on MSVC, but it now also works for GCC and current Clang versions
|
||||||
|
* Colorization of "Test filters" output should be more robust now
|
||||||
|
* `--wait-for-keypress` now also accepts `never` as an option (#1866)
|
||||||
|
* Reporters no longer round-off nanoseconds when reporting benchmarking results (#1876)
|
||||||
|
* Catch2's debug break now supports iOS while using Thumb instruction set (#1862)
|
||||||
|
* It is now possible to customize benchmark's warm-up time when running the test binary (#1844)
|
||||||
|
* `--benchmark-warmup-time {ms}`
|
||||||
|
* User can now specify how Catch2 should break into debugger (#1846)
|
||||||
|
|
||||||
|
### Fixes
|
||||||
|
* Fixes missing `<random>` include in benchmarking (#1831)
|
||||||
|
* Fixed missing `<iterator>` include in benchmarking (#1874)
|
||||||
|
* Hidden test cases are now also tagged with `[!hide]` as per documentation (#1847)
|
||||||
|
* Detection of whether libc provides `std::nextafter` has been improved (#1854)
|
||||||
|
* Detection of `wmain` no longer incorrectly looks for `WIN32` macro (#1849)
|
||||||
|
* Now it just detects Windows platform
|
||||||
|
* Composing already-composed matchers no longer modifies the partially-composed matcher expression
|
||||||
|
* This bug has been present for the last ~2 years and nobody reported it
|
||||||
|
|
||||||
|
|
||||||
|
## 2.11.1
|
||||||
|
|
||||||
|
### Improvements
|
||||||
|
* Breaking into debugger is supported on iOS (#1817)
|
||||||
|
* `google-build-using-namespace` clang-tidy warning is suppressed (#1799)
|
||||||
|
|
||||||
|
### Fixes
|
||||||
|
* Clang on Windows is no longer assumed to implement MSVC's traditional preprocessor (#1806)
|
||||||
|
* `ObjectStorage` now behaves properly in `const` contexts (#1820)
|
||||||
|
* `GENERATE_COPY(a, b)` now compiles properly (#1809, #1815)
|
||||||
|
* Some more cleanups in the benchmarking support
|
||||||
|
|
||||||
|
|
||||||
|
## 2.11.0
|
||||||
|
|
||||||
|
### Improvements
|
||||||
|
* JUnit reporter output now contains more details in case of failure (#1347, #1719)
|
||||||
|
* Added SonarQube Test Data reporter (#1738)
|
||||||
|
* It is in a separate header, just like the TAP, Automake, and TeamCity reporters
|
||||||
|
* `range` generator now allows floating point numbers (#1776)
|
||||||
|
* Reworked part of internals to increase throughput
|
||||||
|
|
||||||
|
|
||||||
|
### Fixes
|
||||||
|
* The single header version should contain full benchmarking support (#1800)
|
||||||
|
* `[.foo]` is now properly parsed as `[.][foo]` when used on the command line (#1798)
|
||||||
|
* Fixed compilation of benchmarking on platforms where `steady_clock::period` is not `std::nano` (#1794)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## 2.10.2
|
||||||
|
|
||||||
|
### Improvements
|
||||||
|
* Catch2 will now compile on platform where `INFINITY` is double (#1782)
|
||||||
|
|
||||||
|
|
||||||
|
### Fixes
|
||||||
|
* Warning suppressed during listener registration will no longer leak
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## 2.10.1
|
||||||
|
|
||||||
|
### Improvements
|
||||||
|
* Catch2 now guards itself against `min` and `max` macros from `windows.h` (#1772)
|
||||||
|
* Templated tests will now compile with ICC (#1748)
|
||||||
|
* `WithinULP` matcher now uses scientific notation for stringification (#1760)
|
||||||
|
|
||||||
|
|
||||||
|
### Fixes
|
||||||
|
* Templated tests no longer trigger `-Wunused-templates` (#1762)
|
||||||
|
* Suppressed clang-analyzer false positive in context getter (#1230, #1735)
|
||||||
|
|
||||||
|
|
||||||
|
### Miscellaneous
|
||||||
|
* CMake no longer prohibits in-tree build when Catch2 is used as a subproject (#1773, #1774)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## 2.10.0
|
## 2.10.0
|
||||||
|
|
||||||
|
@@ -42,8 +42,8 @@ Tag version and release title should be same as the new version,
|
|||||||
description should contain the release notes for the current release.
|
description should contain the release notes for the current release.
|
||||||
Single header version of `catch.hpp` *needs* to be attached as a binary,
|
Single header version of `catch.hpp` *needs* to be attached as a binary,
|
||||||
as that is where the official download link links to. Preferably
|
as that is where the official download link links to. Preferably
|
||||||
it should use linux line endings. All non-bundled reporters (Automake,
|
it should use linux line endings. All non-bundled reporters (Automake, TAP,
|
||||||
TAP, TeamCity) should also be attached as binaries, as they might be
|
TeamCity, SonarQube) should also be attached as binaries, as they might be
|
||||||
dependent on a specific version of the single-include header.
|
dependent on a specific version of the single-include header.
|
||||||
|
|
||||||
Since 2.5.0, the release tag and the "binaries" (headers) should be PGP
|
Since 2.5.0, the release tag and the "binaries" (headers) should be PGP
|
||||||
@@ -67,6 +67,7 @@ $ gpg2 --armor --output catch.hpp.asc --detach-sig catch.hpp
|
|||||||
$ gpg2 --armor --output catch_reporter_automake.hpp.asc --detach-sig catch_reporter_automake.hpp
|
$ gpg2 --armor --output catch_reporter_automake.hpp.asc --detach-sig catch_reporter_automake.hpp
|
||||||
$ gpg2 --armor --output catch_reporter_teamcity.hpp.asc --detach-sig catch_reporter_teamcity.hpp
|
$ gpg2 --armor --output catch_reporter_teamcity.hpp.asc --detach-sig catch_reporter_teamcity.hpp
|
||||||
$ gpg2 --armor --output catch_reporter_tap.hpp.asc --detach-sig catch_reporter_tap.hpp
|
$ gpg2 --armor --output catch_reporter_tap.hpp.asc --detach-sig catch_reporter_tap.hpp
|
||||||
|
$ gpg2 --armor --output catch_reporter_sonarqube.hpp.asc --detach-sig catch_reporter_sonarqube.hpp
|
||||||
```
|
```
|
||||||
|
|
||||||
_GPG does not support signing multiple files in single invocation._
|
_GPG does not support signing multiple files in single invocation._
|
||||||
|
@@ -29,6 +29,7 @@ Do this in one source file - the same one you have `CATCH_CONFIG_MAIN` or `CATCH
|
|||||||
Use this when building as part of a TeamCity build to see results as they happen ([code example](../examples/207-Rpt-TeamCityReporter.cpp)).
|
Use this when building as part of a TeamCity build to see results as they happen ([code example](../examples/207-Rpt-TeamCityReporter.cpp)).
|
||||||
* `tap` writes in the TAP ([Test Anything Protocol](https://en.wikipedia.org/wiki/Test_Anything_Protocol)) format.
|
* `tap` writes in the TAP ([Test Anything Protocol](https://en.wikipedia.org/wiki/Test_Anything_Protocol)) format.
|
||||||
* `automake` writes in a format that correspond to [automake .trs](https://www.gnu.org/software/automake/manual/html_node/Log-files-generation-and-test-results-recording.html) files
|
* `automake` writes in a format that correspond to [automake .trs](https://www.gnu.org/software/automake/manual/html_node/Log-files-generation-and-test-results-recording.html) files
|
||||||
|
* `sonarqube` writes the [SonarQube Generic Test Data](https://docs.sonarqube.org/latest/analysis/generic-test/) XML format.
|
||||||
|
|
||||||
You see what reporters are available from the command line by running with `--list-reporters`.
|
You see what reporters are available from the command line by running with `--list-reporters`.
|
||||||
|
|
||||||
|
@@ -22,7 +22,7 @@ But functions and methods can also be written inline in header files. The downsi
|
|||||||
|
|
||||||
Because Catch is implemented *entirely* in headers you might think that the whole of Catch must be compiled into every translation unit that uses it! Actually it's not quite as bad as that. Catch mitigates this situation by effectively maintaining the traditional separation between the implementation code and declarations. Internally the implementation code is protected by ```#ifdef```s and is conditionally compiled into only one translation unit. This translation unit is that one that ```#define```s ```CATCH_CONFIG_MAIN``` or ```CATCH_CONFIG_RUNNER```. Let's call this the main source file.
|
Because Catch is implemented *entirely* in headers you might think that the whole of Catch must be compiled into every translation unit that uses it! Actually it's not quite as bad as that. Catch mitigates this situation by effectively maintaining the traditional separation between the implementation code and declarations. Internally the implementation code is protected by ```#ifdef```s and is conditionally compiled into only one translation unit. This translation unit is that one that ```#define```s ```CATCH_CONFIG_MAIN``` or ```CATCH_CONFIG_RUNNER```. Let's call this the main source file.
|
||||||
|
|
||||||
As a result the main source file *does* compile the whole of Catch every time! So it makes sense to dedicate this file to *only* ```#define```-ing the identifier and ```#include```-ing Catch (and implementing the runner code, if you're doing that). Keep all your test cases in other files. This way you won't pay the recompilation cost for the whole of Catch
|
As a result the main source file *does* compile the whole of Catch every time! So it makes sense to dedicate this file to *only* ```#define```-ing the identifier and ```#include```-ing Catch (and implementing the runner code, if you're doing that). Keep all your test cases in other files. This way you won't pay the recompilation cost for the whole of Catch.
|
||||||
|
|
||||||
## Practical example
|
## Practical example
|
||||||
Assume you have the `Factorial` function from the [tutorial](tutorial.md#top) in `factorial.cpp` (with forward declaration in `factorial.h`) and want to test it and keep the compile times down when adding new tests. Then you should have 2 files, `tests-main.cpp` and `tests-factorial.cpp`:
|
Assume you have the `Factorial` function from the [tutorial](tutorial.md#top) in `factorial.cpp` (with forward declaration in `factorial.h`) and want to test it and keep the compile times down when adding new tests. Then you should have 2 files, `tests-main.cpp` and `tests-factorial.cpp`:
|
||||||
|
@@ -106,7 +106,7 @@ Of course there are still more issues to deal with. For example we'll hit proble
|
|||||||
Although this was a simple test it's been enough to demonstrate a few things about how Catch is used. Let's take a moment to consider those before we move on.
|
Although this was a simple test it's been enough to demonstrate a few things about how Catch is used. Let's take a moment to consider those before we move on.
|
||||||
|
|
||||||
1. All we did was ```#define``` one identifier and ```#include``` one header and we got everything - even an implementation of ```main()``` that will [respond to command line arguments](command-line.md#top). You can only use that ```#define``` in one implementation file, for (hopefully) obvious reasons. Once you have more than one file with unit tests in you'll just ```#include "catch.hpp"``` and go. Usually it's a good idea to have a dedicated implementation file that just has ```#define CATCH_CONFIG_MAIN``` and ```#include "catch.hpp"```. You can also provide your own implementation of main and drive Catch yourself (see [Supplying-your-own-main()](own-main.md#top)).
|
1. All we did was ```#define``` one identifier and ```#include``` one header and we got everything - even an implementation of ```main()``` that will [respond to command line arguments](command-line.md#top). You can only use that ```#define``` in one implementation file, for (hopefully) obvious reasons. Once you have more than one file with unit tests in you'll just ```#include "catch.hpp"``` and go. Usually it's a good idea to have a dedicated implementation file that just has ```#define CATCH_CONFIG_MAIN``` and ```#include "catch.hpp"```. You can also provide your own implementation of main and drive Catch yourself (see [Supplying-your-own-main()](own-main.md#top)).
|
||||||
2. We introduce test cases with the ```TEST_CASE``` macro. This macro takes one or two arguments - a free form test name and, optionally, one or more tags (for more see <a href="#test-cases-and-sections">Test cases and Sections</a>, ). The test name must be unique. You can run sets of tests by specifying a wildcarded test name or a tag expression. See the [command line docs](command-line.md#top) for more information on running tests.
|
2. We introduce test cases with the ```TEST_CASE``` macro. This macro takes one or two arguments - a free form test name and, optionally, one or more tags (for more see <a href="#test-cases-and-sections">Test cases and Sections</a>). The test name must be unique. You can run sets of tests by specifying a wildcarded test name or a tag expression. See the [command line docs](command-line.md#top) for more information on running tests.
|
||||||
3. The name and tags arguments are just strings. We haven't had to declare a function or method - or explicitly register the test case anywhere. Behind the scenes a function with a generated name is defined for you, and automatically registered using static registry classes. By abstracting the function name away we can name our tests without the constraints of identifier names.
|
3. The name and tags arguments are just strings. We haven't had to declare a function or method - or explicitly register the test case anywhere. Behind the scenes a function with a generated name is defined for you, and automatically registered using static registry classes. By abstracting the function name away we can name our tests without the constraints of identifier names.
|
||||||
4. We write our individual test assertions using the ```REQUIRE``` macro. Rather than a separate macro for each type of condition we express the condition naturally using C/C++ syntax. Behind the scenes a simple set of expression templates captures the left-hand-side and right-hand-side of the expression so we can display the values in our test report. As we'll see later there _are_ other assertion macros - but because of this technique the number of them is drastically reduced.
|
4. We write our individual test assertions using the ```REQUIRE``` macro. Rather than a separate macro for each type of condition we express the condition naturally using C/C++ syntax. Behind the scenes a simple set of expression templates captures the left-hand-side and right-hand-side of the expression so we can display the values in our test report. As we'll see later there _are_ other assertion macros - but because of this technique the number of them is drastically reduced.
|
||||||
|
|
||||||
|
@@ -24,7 +24,7 @@ std::string ws(int const level) {
|
|||||||
template< typename T >
|
template< typename T >
|
||||||
std::ostream& operator<<( std::ostream& os, std::vector<T> const& v ) {
|
std::ostream& operator<<( std::ostream& os, std::vector<T> const& v ) {
|
||||||
os << "{ ";
|
os << "{ ";
|
||||||
for ( auto x : v )
|
for ( const auto& x : v )
|
||||||
os << x << ", ";
|
os << x << ", ";
|
||||||
return os << "}";
|
return os << "}";
|
||||||
}
|
}
|
||||||
@@ -57,7 +57,7 @@ void print( std::ostream& os, int const level, Catch::MessageInfo const& info )
|
|||||||
|
|
||||||
void print( std::ostream& os, int const level, std::string const& title, std::vector<Catch::MessageInfo> const& v ) {
|
void print( std::ostream& os, int const level, std::string const& title, std::vector<Catch::MessageInfo> const& v ) {
|
||||||
os << ws(level ) << title << ":\n";
|
os << ws(level ) << title << ":\n";
|
||||||
for ( auto x : v )
|
for ( const auto& x : v )
|
||||||
{
|
{
|
||||||
os << ws(level+1) << "{\n";
|
os << ws(level+1) << "{\n";
|
||||||
print( os, level+2, x );
|
print( os, level+2, x );
|
||||||
|
@@ -10,12 +10,13 @@
|
|||||||
#define CATCH_CONFIG_MAIN
|
#define CATCH_CONFIG_MAIN
|
||||||
#include <catch2/catch.hpp>
|
#include <catch2/catch.hpp>
|
||||||
|
|
||||||
|
|
||||||
class out_buff : public std::stringbuf {
|
class out_buff : public std::stringbuf {
|
||||||
std::FILE* m_stream;
|
std::FILE* m_stream;
|
||||||
public:
|
public:
|
||||||
out_buff(std::FILE* stream):m_stream(stream) {}
|
out_buff(std::FILE* stream):m_stream(stream) {}
|
||||||
~out_buff() { pubsync(); }
|
~out_buff();
|
||||||
int sync() {
|
int sync() override {
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
for (unsigned char c : str()) {
|
for (unsigned char c : str()) {
|
||||||
if (putc(c, m_stream) == EOF) {
|
if (putc(c, m_stream) == EOF) {
|
||||||
@@ -29,6 +30,12 @@ public:
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
out_buff::~out_buff() { pubsync(); }
|
||||||
|
|
||||||
|
#if defined(__clang__)
|
||||||
|
#pragma clang diagnostic ignored "-Wexit-time-destructors" // static variables in cout/cerr/clog
|
||||||
|
#endif
|
||||||
|
|
||||||
namespace Catch {
|
namespace Catch {
|
||||||
std::ostream& cout() {
|
std::ostream& cout() {
|
||||||
static std::ostream ret(new out_buff(stdout));
|
static std::ostream ret(new out_buff(stdout));
|
||||||
|
@@ -22,15 +22,17 @@ public:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string const& get() const override {
|
std::string const& get() const override;
|
||||||
return m_line;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool next() override {
|
bool next() override {
|
||||||
return !!std::getline(m_stream, m_line);
|
return !!std::getline(m_stream, m_line);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
std::string const& LineGenerator::get() const {
|
||||||
|
return m_line;
|
||||||
|
}
|
||||||
|
|
||||||
// This helper function provides a nicer UX when instantiating the generator
|
// This helper function provides a nicer UX when instantiating the generator
|
||||||
// Notice that it returns an instance of GeneratorWrapper<std::string>, which
|
// Notice that it returns an instance of GeneratorWrapper<std::string>, which
|
||||||
// is a value-wrapper around std::unique_ptr<IGenerator<std::string>>.
|
// is a value-wrapper around std::unique_ptr<IGenerator<std::string>>.
|
||||||
|
@@ -10,8 +10,8 @@
|
|||||||
#define TWOBLUECUBES_CATCH_HPP_INCLUDED
|
#define TWOBLUECUBES_CATCH_HPP_INCLUDED
|
||||||
|
|
||||||
#define CATCH_VERSION_MAJOR 2
|
#define CATCH_VERSION_MAJOR 2
|
||||||
#define CATCH_VERSION_MINOR 10
|
#define CATCH_VERSION_MINOR 11
|
||||||
#define CATCH_VERSION_PATCH 0
|
#define CATCH_VERSION_PATCH 2
|
||||||
|
|
||||||
#ifdef __clang__
|
#ifdef __clang__
|
||||||
# pragma clang system_header
|
# pragma clang system_header
|
||||||
@@ -80,7 +80,7 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(CATCH_CONFIG_ENABLE_BENCHMARKING)
|
#if defined(CATCH_CONFIG_ENABLE_BENCHMARKING)
|
||||||
#include "internal/benchmark/catch_benchmark.hpp"
|
#include "internal/benchmark/catch_benchmarking_all.hpp"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif // ! CATCH_CONFIG_IMPL_ONLY
|
#endif // ! CATCH_CONFIG_IMPL_ONLY
|
||||||
|
@@ -44,10 +44,10 @@ namespace Catch {
|
|||||||
template <typename Clock>
|
template <typename Clock>
|
||||||
ExecutionPlan<FloatDuration<Clock>> prepare(const IConfig &cfg, Environment<FloatDuration<Clock>> env) const {
|
ExecutionPlan<FloatDuration<Clock>> prepare(const IConfig &cfg, Environment<FloatDuration<Clock>> env) const {
|
||||||
auto min_time = env.clock_resolution.mean * Detail::minimum_ticks;
|
auto min_time = env.clock_resolution.mean * Detail::minimum_ticks;
|
||||||
auto run_time = std::max(min_time, std::chrono::duration_cast<decltype(min_time)>(Detail::warmup_time));
|
auto run_time = std::max(min_time, std::chrono::duration_cast<decltype(min_time)>(cfg.benchmarkWarmupTime()));
|
||||||
auto&& test = Detail::run_for_at_least<Clock>(std::chrono::duration_cast<ClockDuration<Clock>>(run_time), 1, fun);
|
auto&& test = Detail::run_for_at_least<Clock>(std::chrono::duration_cast<ClockDuration<Clock>>(run_time), 1, fun);
|
||||||
int new_iters = static_cast<int>(std::ceil(min_time * test.iterations / test.elapsed));
|
int new_iters = static_cast<int>(std::ceil(min_time * test.iterations / test.elapsed));
|
||||||
return { new_iters, test.elapsed / test.iterations * new_iters * cfg.benchmarkSamples(), fun, std::chrono::duration_cast<FloatDuration<Clock>>(Detail::warmup_time), Detail::warmup_iterations };
|
return { new_iters, test.elapsed / test.iterations * new_iters * cfg.benchmarkSamples(), fun, std::chrono::duration_cast<FloatDuration<Clock>>(cfg.benchmarkWarmupTime()), Detail::warmup_iterations };
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename Clock = default_clock>
|
template <typename Clock = default_clock>
|
||||||
@@ -79,7 +79,7 @@ namespace Catch {
|
|||||||
});
|
});
|
||||||
|
|
||||||
auto analysis = Detail::analyse(*cfg, env, samples.begin(), samples.end());
|
auto analysis = Detail::analyse(*cfg, env, samples.begin(), samples.end());
|
||||||
BenchmarkStats<std::chrono::duration<double, std::nano>> stats{ info, analysis.samples, analysis.mean, analysis.standard_deviation, analysis.outliers, analysis.outlier_variance };
|
BenchmarkStats<FloatDuration<Clock>> stats{ info, analysis.samples, analysis.mean, analysis.standard_deviation, analysis.outliers, analysis.outlier_variance };
|
||||||
getResultCapture().benchmarkEnded(stats);
|
getResultCapture().benchmarkEnded(stats);
|
||||||
|
|
||||||
} CATCH_CATCH_ALL{
|
} CATCH_CATCH_ALL{
|
||||||
|
29
include/internal/benchmark/catch_benchmarking_all.hpp
Normal file
29
include/internal/benchmark/catch_benchmarking_all.hpp
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
/*
|
||||||
|
* Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||||
|
* file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
// A proxy header that includes all of the benchmarking headers to allow
|
||||||
|
// concise include of the benchmarking features. You should prefer the
|
||||||
|
// individual includes in standard use.
|
||||||
|
|
||||||
|
#include "catch_benchmark.hpp"
|
||||||
|
#include "catch_chronometer.hpp"
|
||||||
|
#include "catch_clock.hpp"
|
||||||
|
#include "catch_constructor.hpp"
|
||||||
|
#include "catch_environment.hpp"
|
||||||
|
#include "catch_estimate.hpp"
|
||||||
|
#include "catch_execution_plan.hpp"
|
||||||
|
#include "catch_optimizer.hpp"
|
||||||
|
#include "catch_outlier_classification.hpp"
|
||||||
|
#include "catch_sample_analysis.hpp"
|
||||||
|
#include "detail/catch_analyse.hpp"
|
||||||
|
#include "detail/catch_benchmark_function.hpp"
|
||||||
|
#include "detail/catch_complete_invoke.hpp"
|
||||||
|
#include "detail/catch_estimate_clock.hpp"
|
||||||
|
#include "detail/catch_measure.hpp"
|
||||||
|
#include "detail/catch_repeat.hpp"
|
||||||
|
#include "detail/catch_run_for_at_least.hpp"
|
||||||
|
#include "detail/catch_stats.hpp"
|
||||||
|
#include "detail/catch_timing.hpp"
|
@@ -14,6 +14,7 @@
|
|||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
|
|
||||||
namespace Catch {
|
namespace Catch {
|
||||||
|
namespace Benchmark {
|
||||||
namespace Detail {
|
namespace Detail {
|
||||||
template <typename T, bool Destruct>
|
template <typename T, bool Destruct>
|
||||||
struct ObjectStorage
|
struct ObjectStorage
|
||||||
@@ -54,11 +55,15 @@ namespace Catch {
|
|||||||
template <typename U>
|
template <typename U>
|
||||||
void destruct_on_exit(typename std::enable_if<!Destruct, U>::type* = 0) { }
|
void destruct_on_exit(typename std::enable_if<!Destruct, U>::type* = 0) { }
|
||||||
|
|
||||||
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 {
|
||||||
|
return *static_cast<T*>(static_cast<void*>(&data));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
TStorage data;
|
TStorage data;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -69,5 +74,6 @@ namespace Catch {
|
|||||||
template <typename T>
|
template <typename T>
|
||||||
using destructable_object = Detail::ObjectStorage<T, false>;
|
using destructable_object = Detail::ObjectStorage<T, false>;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#endif // TWOBLUECUBES_CATCH_CONSTRUCTOR_HPP_INCLUDED
|
#endif // TWOBLUECUBES_CATCH_CONSTRUCTOR_HPP_INCLUDED
|
||||||
|
@@ -176,9 +176,10 @@ namespace Catch {
|
|||||||
|
|
||||||
|
|
||||||
bootstrap_analysis analyse_samples(double confidence_level, int n_resamples, std::vector<double>::iterator first, std::vector<double>::iterator last) {
|
bootstrap_analysis analyse_samples(double confidence_level, int n_resamples, std::vector<double>::iterator first, std::vector<double>::iterator last) {
|
||||||
|
CATCH_INTERNAL_START_WARNINGS_SUPPRESSION
|
||||||
CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS
|
CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS
|
||||||
static std::random_device entropy;
|
static std::random_device entropy;
|
||||||
CATCH_INTERNAL_UNSUPPRESS_GLOBALS_WARNINGS
|
CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION
|
||||||
|
|
||||||
auto n = static_cast<int>(last - first); // seriously, one can't use integral types without hell in C++
|
auto n = static_cast<int>(last - first); // seriously, one can't use integral types without hell in C++
|
||||||
|
|
||||||
|
@@ -18,11 +18,13 @@
|
|||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <functional>
|
#include <functional>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
#include <iterator>
|
||||||
#include <numeric>
|
#include <numeric>
|
||||||
#include <tuple>
|
#include <tuple>
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
#include <cstddef>
|
#include <cstddef>
|
||||||
|
#include <random>
|
||||||
|
|
||||||
namespace Catch {
|
namespace Catch {
|
||||||
namespace Benchmark {
|
namespace Benchmark {
|
||||||
|
@@ -41,15 +41,17 @@
|
|||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
#define INTERNAL_CATCH_TEST( macroName, resultDisposition, ... ) \
|
#define INTERNAL_CATCH_TEST( macroName, resultDisposition, ... ) \
|
||||||
do { \
|
do { \
|
||||||
|
/* The expression should not be evaluated, but warnings should hopefully be checked */ \
|
||||||
|
CATCH_INTERNAL_IGNORE_BUT_WARN(__VA_ARGS__); \
|
||||||
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 ); \
|
||||||
INTERNAL_CATCH_TRY { \
|
INTERNAL_CATCH_TRY { \
|
||||||
|
CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \
|
||||||
CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS \
|
CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS \
|
||||||
catchAssertionHandler.handleExpr( Catch::Decomposer() <= __VA_ARGS__ ); \
|
catchAssertionHandler.handleExpr( Catch::Decomposer() <= __VA_ARGS__ ); \
|
||||||
CATCH_INTERNAL_UNSUPPRESS_PARENTHESES_WARNINGS \
|
CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION \
|
||||||
} INTERNAL_CATCH_CATCH( catchAssertionHandler ) \
|
} INTERNAL_CATCH_CATCH( catchAssertionHandler ) \
|
||||||
INTERNAL_CATCH_REACT( catchAssertionHandler ) \
|
INTERNAL_CATCH_REACT( catchAssertionHandler ) \
|
||||||
} while( (void)0, (false) && static_cast<bool>( !!(__VA_ARGS__) ) ) // the expression here is never evaluated at runtime but it forces the compiler to give it a look
|
} while( false )
|
||||||
// The double negation silences MSVC's C4800 warning, the static_cast forces short-circuit evaluation if the type has overloaded &&.
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
#define INTERNAL_CATCH_IF( macroName, resultDisposition, ... ) \
|
#define INTERNAL_CATCH_IF( macroName, resultDisposition, ... ) \
|
||||||
|
@@ -49,9 +49,14 @@ namespace Catch {
|
|||||||
if( !line.empty() && !startsWith( line, '#' ) ) {
|
if( !line.empty() && !startsWith( line, '#' ) ) {
|
||||||
if( !startsWith( line, '"' ) )
|
if( !startsWith( line, '"' ) )
|
||||||
line = '"' + line + '"';
|
line = '"' + line + '"';
|
||||||
config.testsOrTags.push_back( line + ',' );
|
config.testsOrTags.push_back( line );
|
||||||
|
config.testsOrTags.emplace_back( "," );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
//Remove comma in the end
|
||||||
|
if(!config.testsOrTags.empty())
|
||||||
|
config.testsOrTags.erase( config.testsOrTags.end()-1 );
|
||||||
|
|
||||||
return ParserResult::ok( ParseResultType::Matched );
|
return ParserResult::ok( ParseResultType::Matched );
|
||||||
};
|
};
|
||||||
auto const setTestOrder = [&]( std::string const& order ) {
|
auto const setTestOrder = [&]( std::string const& order ) {
|
||||||
@@ -86,14 +91,16 @@ namespace Catch {
|
|||||||
};
|
};
|
||||||
auto const setWaitForKeypress = [&]( std::string const& keypress ) {
|
auto const setWaitForKeypress = [&]( std::string const& keypress ) {
|
||||||
auto keypressLc = toLower( keypress );
|
auto keypressLc = toLower( keypress );
|
||||||
if( keypressLc == "start" )
|
if (keypressLc == "never")
|
||||||
|
config.waitForKeypress = WaitForKeypress::Never;
|
||||||
|
else if( keypressLc == "start" )
|
||||||
config.waitForKeypress = WaitForKeypress::BeforeStart;
|
config.waitForKeypress = WaitForKeypress::BeforeStart;
|
||||||
else if( keypressLc == "exit" )
|
else if( keypressLc == "exit" )
|
||||||
config.waitForKeypress = WaitForKeypress::BeforeExit;
|
config.waitForKeypress = WaitForKeypress::BeforeExit;
|
||||||
else if( keypressLc == "both" )
|
else if( keypressLc == "both" )
|
||||||
config.waitForKeypress = WaitForKeypress::BeforeStartAndExit;
|
config.waitForKeypress = WaitForKeypress::BeforeStartAndExit;
|
||||||
else
|
else
|
||||||
return ParserResult::runtimeError( "keypress argument must be one of: start, exit or both. '" + keypress + "' not recognised" );
|
return ParserResult::runtimeError( "keypress argument must be one of: never, start, exit or both. '" + keypress + "' not recognised" );
|
||||||
return ParserResult::ok( ParseResultType::Matched );
|
return ParserResult::ok( ParseResultType::Matched );
|
||||||
};
|
};
|
||||||
auto const setVerbosity = [&]( std::string const& verbosity ) {
|
auto const setVerbosity = [&]( std::string const& verbosity ) {
|
||||||
@@ -193,7 +200,7 @@ namespace Catch {
|
|||||||
| Opt( config.libIdentify )
|
| Opt( config.libIdentify )
|
||||||
["--libidentify"]
|
["--libidentify"]
|
||||||
( "report name and version according to libidentify standard" )
|
( "report name and version according to libidentify standard" )
|
||||||
| Opt( setWaitForKeypress, "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.benchmarkSamples, "samples" )
|
| Opt( config.benchmarkSamples, "samples" )
|
||||||
@@ -208,6 +215,9 @@ namespace Catch {
|
|||||||
| Opt( config.benchmarkNoAnalysis )
|
| Opt( config.benchmarkNoAnalysis )
|
||||||
["--benchmark-no-analysis"]
|
["--benchmark-no-analysis"]
|
||||||
( "perform only measurements; do not perform any analysis" )
|
( "perform only measurements; do not perform any analysis" )
|
||||||
|
| Opt( config.benchmarkWarmupTime, "benchmarkWarmupTime" )
|
||||||
|
["--benchmark-warmup-time"]
|
||||||
|
( "amount of time in milliseconds spent on warming up each test (default: 100)" )
|
||||||
| Arg( config.testsOrTags, "test name|pattern|tags" )
|
| Arg( config.testsOrTags, "test name|pattern|tags" )
|
||||||
( "which test or tests to use" );
|
( "which test or tests to use" );
|
||||||
|
|
||||||
|
@@ -43,32 +43,39 @@
|
|||||||
# define CATCH_INTERNAL_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS
|
# define CATCH_INTERNAL_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef __clang__
|
// We have to avoid both ICC and Clang, because they try to mask themselves
|
||||||
|
// as gcc, and we want only GCC in this block
|
||||||
|
#if defined(__GNUC__) && !defined(__clang__) && !defined(__ICC)
|
||||||
|
# define CATCH_INTERNAL_START_WARNINGS_SUPPRESSION _Pragma( "GCC diagnostic push" )
|
||||||
|
# define CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION _Pragma( "GCC diagnostic pop" )
|
||||||
|
|
||||||
|
# define CATCH_INTERNAL_IGNORE_BUT_WARN(...) (void)__builtin_constant_p(__VA_ARGS__)
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(__clang__)
|
||||||
|
|
||||||
|
# define CATCH_INTERNAL_START_WARNINGS_SUPPRESSION _Pragma( "clang diagnostic push" )
|
||||||
|
# define CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION _Pragma( "clang diagnostic pop" )
|
||||||
|
|
||||||
|
# define CATCH_INTERNAL_IGNORE_BUT_WARN(...) (void)__builtin_constant_p(__VA_ARGS__)
|
||||||
|
|
||||||
|
|
||||||
# define CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
|
# define CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
|
||||||
_Pragma( "clang diagnostic push" ) \
|
|
||||||
_Pragma( "clang diagnostic ignored \"-Wexit-time-destructors\"" ) \
|
_Pragma( "clang diagnostic ignored \"-Wexit-time-destructors\"" ) \
|
||||||
_Pragma( "clang diagnostic ignored \"-Wglobal-constructors\"")
|
_Pragma( "clang diagnostic ignored \"-Wglobal-constructors\"")
|
||||||
# define CATCH_INTERNAL_UNSUPPRESS_GLOBALS_WARNINGS \
|
|
||||||
_Pragma( "clang diagnostic pop" )
|
|
||||||
|
|
||||||
# define CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS \
|
# define CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS \
|
||||||
_Pragma( "clang diagnostic push" ) \
|
|
||||||
_Pragma( "clang diagnostic ignored \"-Wparentheses\"" )
|
_Pragma( "clang diagnostic ignored \"-Wparentheses\"" )
|
||||||
# define CATCH_INTERNAL_UNSUPPRESS_PARENTHESES_WARNINGS \
|
|
||||||
_Pragma( "clang diagnostic pop" )
|
|
||||||
|
|
||||||
# define CATCH_INTERNAL_SUPPRESS_UNUSED_WARNINGS \
|
# define CATCH_INTERNAL_SUPPRESS_UNUSED_WARNINGS \
|
||||||
_Pragma( "clang diagnostic push" ) \
|
|
||||||
_Pragma( "clang diagnostic ignored \"-Wunused-variable\"" )
|
_Pragma( "clang diagnostic ignored \"-Wunused-variable\"" )
|
||||||
# define CATCH_INTERNAL_UNSUPPRESS_UNUSED_WARNINGS \
|
|
||||||
_Pragma( "clang diagnostic pop" )
|
|
||||||
|
|
||||||
# define CATCH_INTERNAL_SUPPRESS_ZERO_VARIADIC_WARNINGS \
|
# define CATCH_INTERNAL_SUPPRESS_ZERO_VARIADIC_WARNINGS \
|
||||||
_Pragma( "clang diagnostic push" ) \
|
|
||||||
_Pragma( "clang diagnostic ignored \"-Wgnu-zero-variadic-macro-arguments\"" )
|
_Pragma( "clang diagnostic ignored \"-Wgnu-zero-variadic-macro-arguments\"" )
|
||||||
# define CATCH_INTERNAL_UNSUPPRESS_ZERO_VARIADIC_WARNINGS \
|
|
||||||
_Pragma( "clang diagnostic pop" )
|
# define CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS \
|
||||||
|
_Pragma( "clang diagnostic ignored \"-Wunused-template\"" )
|
||||||
|
|
||||||
#endif // __clang__
|
#endif // __clang__
|
||||||
|
|
||||||
@@ -128,8 +135,12 @@
|
|||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
// Visual C++
|
// Visual C++
|
||||||
#ifdef _MSC_VER
|
#if defined(_MSC_VER)
|
||||||
|
|
||||||
|
# define CATCH_INTERNAL_START_WARNINGS_SUPPRESSION __pragma( warning(push) )
|
||||||
|
# define CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION __pragma( warning(pop) )
|
||||||
|
|
||||||
|
# define CATCH_INTERNAL_IGNORE_BUT_WARN(...) (void)sizeof(__VA_ARGS__)
|
||||||
|
|
||||||
# if _MSC_VER >= 1900 // Visual Studio 2015 or newer
|
# if _MSC_VER >= 1900 // Visual Studio 2015 or newer
|
||||||
# define CATCH_INTERNAL_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS
|
# define CATCH_INTERNAL_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS
|
||||||
@@ -146,9 +157,12 @@
|
|||||||
// MSVC traditional preprocessor needs some workaround for __VA_ARGS__
|
// MSVC traditional preprocessor needs some workaround for __VA_ARGS__
|
||||||
// _MSVC_TRADITIONAL == 0 means new conformant preprocessor
|
// _MSVC_TRADITIONAL == 0 means new conformant preprocessor
|
||||||
// _MSVC_TRADITIONAL == 1 means old traditional non-conformant preprocessor
|
// _MSVC_TRADITIONAL == 1 means old traditional non-conformant preprocessor
|
||||||
|
# if !defined(__clang__) // Handle Clang masquerading for msvc
|
||||||
# if !defined(_MSVC_TRADITIONAL) || (defined(_MSVC_TRADITIONAL) && _MSVC_TRADITIONAL)
|
# if !defined(_MSVC_TRADITIONAL) || (defined(_MSVC_TRADITIONAL) && _MSVC_TRADITIONAL)
|
||||||
# define CATCH_INTERNAL_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
|
# define CATCH_INTERNAL_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
|
||||||
# endif
|
# endif // MSVC_TRADITIONAL
|
||||||
|
# endif // __clang__
|
||||||
|
|
||||||
#endif // _MSC_VER
|
#endif // _MSC_VER
|
||||||
|
|
||||||
#if defined(_REENTRANT) || defined(_MSC_VER)
|
#if defined(_REENTRANT) || defined(_MSC_VER)
|
||||||
@@ -197,7 +211,7 @@
|
|||||||
#define CATCH_CONFIG_COLOUR_NONE
|
#define CATCH_CONFIG_COLOUR_NONE
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(__UCLIBC__)
|
#if !defined(_GLIBCXX_USE_C99_MATH_TR1)
|
||||||
#define CATCH_INTERNAL_CONFIG_GLOBAL_NEXTAFTER
|
#define CATCH_INTERNAL_CONFIG_GLOBAL_NEXTAFTER
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -304,21 +318,42 @@
|
|||||||
# define CATCH_CONFIG_GLOBAL_NEXTAFTER
|
# define CATCH_CONFIG_GLOBAL_NEXTAFTER
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
// Even if we do not think the compiler has that warning, we still have
|
||||||
|
// to provide a macro that can be used by the code.
|
||||||
|
#if !defined(CATCH_INTERNAL_START_WARNINGS_SUPPRESSION)
|
||||||
|
# define CATCH_INTERNAL_START_WARNINGS_SUPPRESSION
|
||||||
|
#endif
|
||||||
|
#if !defined(CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION)
|
||||||
|
# define CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION
|
||||||
|
#endif
|
||||||
#if !defined(CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS)
|
#if !defined(CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS)
|
||||||
# define CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS
|
# define CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS
|
||||||
# define CATCH_INTERNAL_UNSUPPRESS_PARENTHESES_WARNINGS
|
|
||||||
#endif
|
#endif
|
||||||
#if !defined(CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS)
|
#if !defined(CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS)
|
||||||
# define CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS
|
# define CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS
|
||||||
# define CATCH_INTERNAL_UNSUPPRESS_GLOBALS_WARNINGS
|
|
||||||
#endif
|
#endif
|
||||||
#if !defined(CATCH_INTERNAL_SUPPRESS_UNUSED_WARNINGS)
|
#if !defined(CATCH_INTERNAL_SUPPRESS_UNUSED_WARNINGS)
|
||||||
# define CATCH_INTERNAL_SUPPRESS_UNUSED_WARNINGS
|
# define CATCH_INTERNAL_SUPPRESS_UNUSED_WARNINGS
|
||||||
# define CATCH_INTERNAL_UNSUPPRESS_UNUSED_WARNINGS
|
|
||||||
#endif
|
#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
|
||||||
# define CATCH_INTERNAL_UNSUPPRESS_ZERO_VARIADIC_WARNINGS
|
#endif
|
||||||
|
|
||||||
|
// The goal of this macro is to avoid evaluation of the arguments, but
|
||||||
|
// still have the compiler warn on problems inside...
|
||||||
|
#if !defined(CATCH_INTERNAL_IGNORE_BUT_WARN)
|
||||||
|
# define CATCH_INTERNAL_IGNORE_BUT_WARN(...)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(__APPLE__) && defined(__apple_build_version__) && (__clang_major__ < 10)
|
||||||
|
# undef CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS
|
||||||
|
#elif defined(__clang__) && (__clang_major__ < 5)
|
||||||
|
# undef CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if !defined(CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS)
|
||||||
|
# define CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(CATCH_CONFIG_DISABLE_EXCEPTIONS)
|
#if defined(CATCH_CONFIG_DISABLE_EXCEPTIONS)
|
||||||
|
@@ -76,6 +76,7 @@ namespace Catch {
|
|||||||
int Config::benchmarkSamples() const { return m_data.benchmarkSamples; }
|
int Config::benchmarkSamples() const { return m_data.benchmarkSamples; }
|
||||||
double Config::benchmarkConfidenceInterval() const { return m_data.benchmarkConfidenceInterval; }
|
double Config::benchmarkConfidenceInterval() const { return m_data.benchmarkConfidenceInterval; }
|
||||||
unsigned int Config::benchmarkResamples() const { return m_data.benchmarkResamples; }
|
unsigned int Config::benchmarkResamples() const { return m_data.benchmarkResamples; }
|
||||||
|
std::chrono::milliseconds Config::benchmarkWarmupTime() const { return std::chrono::milliseconds(m_data.benchmarkWarmupTime); }
|
||||||
|
|
||||||
IStream const* Config::openStream() {
|
IStream const* Config::openStream() {
|
||||||
return Catch::makeStream(m_data.outputFilename);
|
return Catch::makeStream(m_data.outputFilename);
|
||||||
|
@@ -47,6 +47,7 @@ namespace Catch {
|
|||||||
unsigned int benchmarkSamples = 100;
|
unsigned int benchmarkSamples = 100;
|
||||||
double benchmarkConfidenceInterval = 0.95;
|
double benchmarkConfidenceInterval = 0.95;
|
||||||
unsigned int benchmarkResamples = 100000;
|
unsigned int benchmarkResamples = 100000;
|
||||||
|
std::chrono::milliseconds::rep benchmarkWarmupTime = 100;
|
||||||
|
|
||||||
Verbosity verbosity = Verbosity::Normal;
|
Verbosity verbosity = Verbosity::Normal;
|
||||||
WarnAbout::What warnings = WarnAbout::Nothing;
|
WarnAbout::What warnings = WarnAbout::Nothing;
|
||||||
@@ -113,6 +114,7 @@ namespace Catch {
|
|||||||
int benchmarkSamples() const override;
|
int benchmarkSamples() const override;
|
||||||
double benchmarkConfidenceInterval() const override;
|
double benchmarkConfidenceInterval() const override;
|
||||||
unsigned int benchmarkResamples() const override;
|
unsigned int benchmarkResamples() const override;
|
||||||
|
std::chrono::milliseconds benchmarkWarmupTime() const override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
@@ -34,7 +34,7 @@ namespace Catch {
|
|||||||
};
|
};
|
||||||
|
|
||||||
struct NoColourImpl : IColourImpl {
|
struct NoColourImpl : IColourImpl {
|
||||||
void use( Colour::Code ) {}
|
void use( Colour::Code ) override {}
|
||||||
|
|
||||||
static IColourImpl* instance() {
|
static IColourImpl* instance() {
|
||||||
static NoColourImpl s_instance;
|
static NoColourImpl s_instance;
|
||||||
@@ -167,7 +167,7 @@ namespace {
|
|||||||
|
|
||||||
bool useColourOnPlatform() {
|
bool useColourOnPlatform() {
|
||||||
return
|
return
|
||||||
#ifdef CATCH_PLATFORM_MAC
|
#if defined(CATCH_PLATFORM_MAC) || defined(CATCH_PLATFORM_IPHONE)
|
||||||
!isDebuggerActive() &&
|
!isDebuggerActive() &&
|
||||||
#endif
|
#endif
|
||||||
#if !(defined(__DJGPP__) && defined(__STRICT_ANSI__))
|
#if !(defined(__DJGPP__) && defined(__STRICT_ANSI__))
|
||||||
@@ -208,13 +208,13 @@ namespace Catch {
|
|||||||
namespace Catch {
|
namespace Catch {
|
||||||
|
|
||||||
Colour::Colour( Code _colourCode ) { use( _colourCode ); }
|
Colour::Colour( Code _colourCode ) { use( _colourCode ); }
|
||||||
Colour::Colour( Colour&& rhs ) noexcept {
|
Colour::Colour( Colour&& other ) noexcept {
|
||||||
m_moved = rhs.m_moved;
|
m_moved = other.m_moved;
|
||||||
rhs.m_moved = true;
|
other.m_moved = true;
|
||||||
}
|
}
|
||||||
Colour& Colour::operator=( Colour&& rhs ) noexcept {
|
Colour& Colour::operator=( Colour&& other ) noexcept {
|
||||||
m_moved = rhs.m_moved;
|
m_moved = other.m_moved;
|
||||||
rhs.m_moved = true;
|
other.m_moved = true;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -226,7 +226,7 @@ namespace Catch {
|
|||||||
// However, under some conditions it does happen (see #1626),
|
// However, under some conditions it does happen (see #1626),
|
||||||
// and this change is small enough that we can let practicality
|
// and this change is small enough that we can let practicality
|
||||||
// triumph over purity in this case.
|
// triumph over purity in this case.
|
||||||
if (impl != NULL) {
|
if (impl != nullptr) {
|
||||||
impl->use( _colourCode );
|
impl->use( _colourCode );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -46,6 +46,7 @@ namespace Catch {
|
|||||||
{
|
{
|
||||||
if( !IMutableContext::currentContext )
|
if( !IMutableContext::currentContext )
|
||||||
IMutableContext::createContext();
|
IMutableContext::createContext();
|
||||||
|
// NOLINTNEXTLINE(clang-analyzer-core.uninitialized.UndefReturn)
|
||||||
return *IMutableContext::currentContext;
|
return *IMutableContext::currentContext;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -12,7 +12,7 @@
|
|||||||
#include "catch_stream.h"
|
#include "catch_stream.h"
|
||||||
#include "catch_platform.h"
|
#include "catch_platform.h"
|
||||||
|
|
||||||
#ifdef CATCH_PLATFORM_MAC
|
#if defined(CATCH_PLATFORM_MAC) || defined(CATCH_PLATFORM_IPHONE)
|
||||||
|
|
||||||
# include <assert.h>
|
# include <assert.h>
|
||||||
# include <stdbool.h>
|
# include <stdbool.h>
|
||||||
|
@@ -19,6 +19,19 @@ namespace Catch {
|
|||||||
|
|
||||||
#define CATCH_TRAP() __asm__("int $3\n" : : ) /* NOLINT */
|
#define CATCH_TRAP() __asm__("int $3\n" : : ) /* NOLINT */
|
||||||
|
|
||||||
|
#elif defined(CATCH_PLATFORM_IPHONE)
|
||||||
|
|
||||||
|
// use inline assembler
|
||||||
|
#if defined(__i386__) || defined(__x86_64__)
|
||||||
|
#define CATCH_TRAP() __asm__("int $3")
|
||||||
|
#elif defined(__aarch64__)
|
||||||
|
#define CATCH_TRAP() __asm__(".inst 0xd4200000")
|
||||||
|
#elif defined(__arm__) && !defined(__thumb__)
|
||||||
|
#define CATCH_TRAP() __asm__(".inst 0xe7f001f0")
|
||||||
|
#elif defined(__arm__) && defined(__thumb__)
|
||||||
|
#define CATCH_TRAP() __asm__(".inst 0xde01")
|
||||||
|
#endif
|
||||||
|
|
||||||
#elif defined(CATCH_PLATFORM_LINUX)
|
#elif defined(CATCH_PLATFORM_LINUX)
|
||||||
// If we can use inline assembler, do it because this allows us to break
|
// If we can use inline assembler, do it because this allows us to break
|
||||||
// directly at the location of the failing check instead of breaking inside
|
// directly at the location of the failing check instead of breaking inside
|
||||||
@@ -37,10 +50,12 @@ namespace Catch {
|
|||||||
#define CATCH_TRAP() DebugBreak()
|
#define CATCH_TRAP() DebugBreak()
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifndef CATCH_BREAK_INTO_DEBUGGER
|
||||||
#ifdef CATCH_TRAP
|
#ifdef CATCH_TRAP
|
||||||
#define CATCH_BREAK_INTO_DEBUGGER() []{ if( Catch::isDebuggerActive() ) { CATCH_TRAP(); } }()
|
#define CATCH_BREAK_INTO_DEBUGGER() []{ if( Catch::isDebuggerActive() ) { CATCH_TRAP(); } }()
|
||||||
#else
|
#else
|
||||||
#define CATCH_BREAK_INTO_DEBUGGER() []{}()
|
#define CATCH_BREAK_INTO_DEBUGGER() []{}()
|
||||||
#endif
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif // TWOBLUECUBES_CATCH_DEBUGGER_H_INCLUDED
|
#endif // TWOBLUECUBES_CATCH_DEBUGGER_H_INCLUDED
|
||||||
|
@@ -9,10 +9,11 @@
|
|||||||
#define TWOBLUECUBES_CATCH_DEFAULT_MAIN_HPP_INCLUDED
|
#define TWOBLUECUBES_CATCH_DEFAULT_MAIN_HPP_INCLUDED
|
||||||
|
|
||||||
#include "catch_session.h"
|
#include "catch_session.h"
|
||||||
|
#include "catch_platform.h"
|
||||||
|
|
||||||
#ifndef __OBJC__
|
#ifndef __OBJC__
|
||||||
|
|
||||||
#if defined(CATCH_CONFIG_WCHAR) && defined(WIN32) && defined(_UNICODE) && !defined(DO_NOT_USE_WMAIN)
|
#if defined(CATCH_CONFIG_WCHAR) && defined(CATCH_PLATFORM_WINDOWS) && defined(_UNICODE) && !defined(DO_NOT_USE_WMAIN)
|
||||||
// Standard C/C++ Win32 Unicode wmain entry point
|
// Standard C/C++ Win32 Unicode wmain entry point
|
||||||
extern "C" int wmain (int argc, wchar_t * argv[], wchar_t * []) {
|
extern "C" int wmain (int argc, wchar_t * argv[], wchar_t * []) {
|
||||||
#else
|
#else
|
||||||
|
@@ -60,7 +60,7 @@ namespace Catch {
|
|||||||
assert( valueNames.size() == values.size() );
|
assert( valueNames.size() == values.size() );
|
||||||
std::size_t i = 0;
|
std::size_t i = 0;
|
||||||
for( auto value : values )
|
for( auto value : values )
|
||||||
enumInfo->m_values.push_back({ value, valueNames[i++] });
|
enumInfo->m_values.emplace_back(value, valueNames[i++]);
|
||||||
|
|
||||||
return enumInfo;
|
return enumInfo;
|
||||||
}
|
}
|
||||||
|
@@ -57,7 +57,6 @@ namespace Generators {
|
|||||||
class SingleValueGenerator final : public IGenerator<T> {
|
class SingleValueGenerator final : public IGenerator<T> {
|
||||||
T m_value;
|
T m_value;
|
||||||
public:
|
public:
|
||||||
SingleValueGenerator(T const& value) : m_value( value ) {}
|
|
||||||
SingleValueGenerator(T&& value) : m_value(std::move(value)) {}
|
SingleValueGenerator(T&& value) : m_value(std::move(value)) {}
|
||||||
|
|
||||||
T const& get() const override {
|
T const& get() const override {
|
||||||
@@ -120,21 +119,21 @@ namespace Generators {
|
|||||||
m_generators.emplace_back(std::move(generator));
|
m_generators.emplace_back(std::move(generator));
|
||||||
}
|
}
|
||||||
void populate(T&& val) {
|
void populate(T&& val) {
|
||||||
m_generators.emplace_back(value(std::move(val)));
|
m_generators.emplace_back(value(std::forward<T>(val)));
|
||||||
}
|
}
|
||||||
template<typename U>
|
template<typename U>
|
||||||
void populate(U&& val) {
|
void populate(U&& val) {
|
||||||
populate(T(std::move(val)));
|
populate(T(std::forward<U>(val)));
|
||||||
}
|
}
|
||||||
template<typename U, typename... Gs>
|
template<typename U, typename... Gs>
|
||||||
void populate(U&& valueOrGenerator, Gs... moreGenerators) {
|
void populate(U&& valueOrGenerator, Gs &&... moreGenerators) {
|
||||||
populate(std::forward<U>(valueOrGenerator));
|
populate(std::forward<U>(valueOrGenerator));
|
||||||
populate(std::forward<Gs>(moreGenerators)...);
|
populate(std::forward<Gs>(moreGenerators)...);
|
||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
template <typename... Gs>
|
template <typename... Gs>
|
||||||
Generators(Gs... moreGenerators) {
|
Generators(Gs &&... moreGenerators) {
|
||||||
m_generators.reserve(sizeof...(Gs));
|
m_generators.reserve(sizeof...(Gs));
|
||||||
populate(std::forward<Gs>(moreGenerators)...);
|
populate(std::forward<Gs>(moreGenerators)...);
|
||||||
}
|
}
|
||||||
@@ -166,7 +165,7 @@ namespace Generators {
|
|||||||
struct as {};
|
struct as {};
|
||||||
|
|
||||||
template<typename T, typename... Gs>
|
template<typename T, typename... Gs>
|
||||||
auto makeGenerators( GeneratorWrapper<T>&& generator, Gs... moreGenerators ) -> Generators<T> {
|
auto makeGenerators( GeneratorWrapper<T>&& generator, Gs &&... moreGenerators ) -> Generators<T> {
|
||||||
return Generators<T>(std::move(generator), std::forward<Gs>(moreGenerators)...);
|
return Generators<T>(std::move(generator), std::forward<Gs>(moreGenerators)...);
|
||||||
}
|
}
|
||||||
template<typename T>
|
template<typename T>
|
||||||
@@ -174,11 +173,11 @@ namespace Generators {
|
|||||||
return Generators<T>(std::move(generator));
|
return Generators<T>(std::move(generator));
|
||||||
}
|
}
|
||||||
template<typename T, typename... Gs>
|
template<typename T, typename... Gs>
|
||||||
auto makeGenerators( T&& val, Gs... moreGenerators ) -> Generators<T> {
|
auto makeGenerators( T&& val, Gs &&... moreGenerators ) -> Generators<T> {
|
||||||
return makeGenerators( value( std::forward<T>( val ) ), std::forward<Gs>( moreGenerators )... );
|
return makeGenerators( value( std::forward<T>( val ) ), std::forward<Gs>( moreGenerators )... );
|
||||||
}
|
}
|
||||||
template<typename T, typename U, typename... Gs>
|
template<typename T, typename U, typename... Gs>
|
||||||
auto makeGenerators( as<T>, U&& val, Gs... moreGenerators ) -> Generators<T> {
|
auto makeGenerators( as<T>, U&& val, Gs &&... moreGenerators ) -> Generators<T> {
|
||||||
return makeGenerators( value( T( std::forward<U>( val ) ) ), std::forward<Gs>( moreGenerators )... );
|
return makeGenerators( value( T( std::forward<U>( val ) ) ), std::forward<Gs>( moreGenerators )... );
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -204,10 +203,10 @@ namespace Generators {
|
|||||||
} // namespace Catch
|
} // namespace Catch
|
||||||
|
|
||||||
#define GENERATE( ... ) \
|
#define GENERATE( ... ) \
|
||||||
Catch::Generators::generate( CATCH_INTERNAL_LINEINFO, [ ]{ using namespace Catch::Generators; return makeGenerators( __VA_ARGS__ ); } )
|
Catch::Generators::generate( CATCH_INTERNAL_LINEINFO, [ ]{ using namespace Catch::Generators; return makeGenerators( __VA_ARGS__ ); } ) //NOLINT(google-build-using-namespace)
|
||||||
#define GENERATE_COPY( ... ) \
|
#define GENERATE_COPY( ... ) \
|
||||||
Catch::Generators::generate( CATCH_INTERNAL_LINEINFO, [=]{ using namespace Catch::Generators; return makeGenerators( __VA_ARGS__ ); } )
|
Catch::Generators::generate( CATCH_INTERNAL_LINEINFO, [=]{ using namespace Catch::Generators; return makeGenerators( __VA_ARGS__ ); } ) //NOLINT(google-build-using-namespace)
|
||||||
#define GENERATE_REF( ... ) \
|
#define GENERATE_REF( ... ) \
|
||||||
Catch::Generators::generate( CATCH_INTERNAL_LINEINFO, [&]{ using namespace Catch::Generators; return makeGenerators( __VA_ARGS__ ); } )
|
Catch::Generators::generate( CATCH_INTERNAL_LINEINFO, [&]{ using namespace Catch::Generators; return makeGenerators( __VA_ARGS__ ); } ) //NOLINT(google-build-using-namespace)
|
||||||
|
|
||||||
#endif // TWOBLUECUBES_CATCH_GENERATORS_HPP_INCLUDED
|
#endif // TWOBLUECUBES_CATCH_GENERATORS_HPP_INCLUDED
|
||||||
|
@@ -8,6 +8,7 @@
|
|||||||
#define TWOBLUECUBES_CATCH_GENERATORS_GENERIC_HPP_INCLUDED
|
#define TWOBLUECUBES_CATCH_GENERATORS_GENERIC_HPP_INCLUDED
|
||||||
|
|
||||||
#include "catch_generators.hpp"
|
#include "catch_generators.hpp"
|
||||||
|
#include "catch_meta.hpp"
|
||||||
|
|
||||||
namespace Catch {
|
namespace Catch {
|
||||||
namespace Generators {
|
namespace Generators {
|
||||||
@@ -172,18 +173,7 @@ namespace Generators {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
#if defined(__cpp_lib_is_invocable) && __cpp_lib_is_invocable >= 201703
|
template <typename Func, typename U, typename T = FunctionReturnType<Func, U>>
|
||||||
// std::result_of is deprecated in C++17 and removed in C++20. Hence, it is
|
|
||||||
// replaced with std::invoke_result here. Also *_t format is preferred over
|
|
||||||
// typename *::type format.
|
|
||||||
template <typename Func, typename U>
|
|
||||||
using MapFunctionReturnType = std::remove_reference_t<std::remove_cv_t<std::invoke_result_t<Func, U>>>;
|
|
||||||
#else
|
|
||||||
template <typename Func, typename U>
|
|
||||||
using MapFunctionReturnType = typename std::remove_reference<typename std::remove_cv<typename std::result_of<Func(U)>::type>::type>::type;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
template <typename Func, typename U, typename T = MapFunctionReturnType<Func, U>>
|
|
||||||
GeneratorWrapper<T> map(Func&& function, GeneratorWrapper<U>&& generator) {
|
GeneratorWrapper<T> map(Func&& function, GeneratorWrapper<U>&& generator) {
|
||||||
return GeneratorWrapper<T>(
|
return GeneratorWrapper<T>(
|
||||||
pf::make_unique<MapGenerator<T, U, Func>>(std::forward<Func>(function), std::move(generator))
|
pf::make_unique<MapGenerator<T, U, Func>>(std::forward<Func>(function), std::move(generator))
|
||||||
|
@@ -117,7 +117,7 @@ public:
|
|||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
GeneratorWrapper<T> range(T const& start, T const& end, T const& step) {
|
GeneratorWrapper<T> range(T const& start, T const& end, T const& step) {
|
||||||
static_assert(std::is_integral<T>::value && !std::is_same<T, bool>::value, "Type must be an integer");
|
static_assert(std::is_arithmetic<T>::value && !std::is_same<T, bool>::value, "Type must be numeric");
|
||||||
return GeneratorWrapper<T>(pf::make_unique<RangeGenerator<T>>(start, end, step));
|
return GeneratorWrapper<T>(pf::make_unique<RangeGenerator<T>>(start, end, step));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -11,6 +11,7 @@
|
|||||||
#include "catch_common.h"
|
#include "catch_common.h"
|
||||||
#include "catch_option.hpp"
|
#include "catch_option.hpp"
|
||||||
|
|
||||||
|
#include <chrono>
|
||||||
#include <iosfwd>
|
#include <iosfwd>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
@@ -81,6 +82,7 @@ namespace Catch {
|
|||||||
virtual int benchmarkSamples() const = 0;
|
virtual int benchmarkSamples() const = 0;
|
||||||
virtual double benchmarkConfidenceInterval() const = 0;
|
virtual double benchmarkConfidenceInterval() const = 0;
|
||||||
virtual unsigned int benchmarkResamples() const = 0;
|
virtual unsigned int benchmarkResamples() const = 0;
|
||||||
|
virtual std::chrono::milliseconds benchmarkWarmupTime() const = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
using IConfigPtr = std::shared_ptr<IConfig const>;
|
using IConfigPtr = std::shared_ptr<IConfig const>;
|
||||||
|
@@ -73,9 +73,10 @@ namespace Catch {
|
|||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
#define INTERNAL_CATCH_TRANSLATE_EXCEPTION2( translatorName, signature ) \
|
#define INTERNAL_CATCH_TRANSLATE_EXCEPTION2( translatorName, signature ) \
|
||||||
static std::string translatorName( signature ); \
|
static std::string translatorName( signature ); \
|
||||||
|
CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \
|
||||||
CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
|
CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
|
||||||
namespace{ Catch::ExceptionTranslatorRegistrar INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionRegistrar )( &translatorName ); } \
|
namespace{ Catch::ExceptionTranslatorRegistrar INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionRegistrar )( &translatorName ); } \
|
||||||
CATCH_INTERNAL_UNSUPPRESS_GLOBALS_WARNINGS \
|
CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION \
|
||||||
static std::string translatorName( signature )
|
static std::string translatorName( signature )
|
||||||
|
|
||||||
#define INTERNAL_CATCH_TRANSLATE_EXCEPTION( signature ) INTERNAL_CATCH_TRANSLATE_EXCEPTION2( INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionTranslator ), signature )
|
#define INTERNAL_CATCH_TRANSLATE_EXCEPTION( signature ) INTERNAL_CATCH_TRANSLATE_EXCEPTION2( INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionTranslator ), signature )
|
||||||
|
@@ -214,6 +214,8 @@ namespace Catch {
|
|||||||
|
|
||||||
virtual void noMatchingTestCases( std::string const& spec ) = 0;
|
virtual void noMatchingTestCases( std::string const& spec ) = 0;
|
||||||
|
|
||||||
|
virtual void reportInvalidArguments(std::string const&) {}
|
||||||
|
|
||||||
virtual void testRunStarting( TestRunInfo const& testRunInfo ) = 0;
|
virtual void testRunStarting( TestRunInfo const& testRunInfo ) = 0;
|
||||||
virtual void testGroupStarting( GroupInfo const& groupInfo ) = 0;
|
virtual void testGroupStarting( GroupInfo const& groupInfo ) = 0;
|
||||||
|
|
||||||
|
@@ -28,7 +28,7 @@
|
|||||||
namespace Catch {
|
namespace Catch {
|
||||||
|
|
||||||
std::size_t listTests( Config const& config ) {
|
std::size_t listTests( Config const& config ) {
|
||||||
TestSpec testSpec = config.testSpec();
|
TestSpec const& testSpec = config.testSpec();
|
||||||
if( config.hasTestFilters() )
|
if( config.hasTestFilters() )
|
||||||
Catch::cout() << "Matching test cases:\n";
|
Catch::cout() << "Matching test cases:\n";
|
||||||
else {
|
else {
|
||||||
@@ -62,7 +62,7 @@ namespace Catch {
|
|||||||
}
|
}
|
||||||
|
|
||||||
std::size_t listTestsNamesOnly( Config const& config ) {
|
std::size_t listTestsNamesOnly( Config const& config ) {
|
||||||
TestSpec testSpec = config.testSpec();
|
TestSpec const& testSpec = config.testSpec();
|
||||||
std::size_t matchedTests = 0;
|
std::size_t matchedTests = 0;
|
||||||
std::vector<TestCase> matchedTestCases = filterTests( getAllTestCasesSorted( config ), testSpec, config );
|
std::vector<TestCase> matchedTestCases = filterTests( getAllTestCasesSorted( config ), testSpec, config );
|
||||||
for( auto const& testCaseInfo : matchedTestCases ) {
|
for( auto const& testCaseInfo : matchedTestCases ) {
|
||||||
@@ -100,7 +100,7 @@ namespace Catch {
|
|||||||
}
|
}
|
||||||
|
|
||||||
std::size_t listTags( Config const& config ) {
|
std::size_t listTags( Config const& config ) {
|
||||||
TestSpec testSpec = config.testSpec();
|
TestSpec const& testSpec = config.testSpec();
|
||||||
if( config.hasTestFilters() )
|
if( config.hasTestFilters() )
|
||||||
Catch::cout() << "Tags for matching test cases:\n";
|
Catch::cout() << "Tags for matching test cases:\n";
|
||||||
else {
|
else {
|
||||||
|
@@ -91,9 +91,10 @@ namespace Matchers {
|
|||||||
return description;
|
return description;
|
||||||
}
|
}
|
||||||
|
|
||||||
MatchAllOf<ArgT>& operator && ( MatcherBase<ArgT> const& other ) {
|
MatchAllOf<ArgT> operator && ( MatcherBase<ArgT> const& other ) {
|
||||||
m_matchers.push_back( &other );
|
auto copy(*this);
|
||||||
return *this;
|
copy.m_matchers.push_back( &other );
|
||||||
|
return copy;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<MatcherBase<ArgT> const*> m_matchers;
|
std::vector<MatcherBase<ArgT> const*> m_matchers;
|
||||||
@@ -124,9 +125,10 @@ namespace Matchers {
|
|||||||
return description;
|
return description;
|
||||||
}
|
}
|
||||||
|
|
||||||
MatchAnyOf<ArgT>& operator || ( MatcherBase<ArgT> const& other ) {
|
MatchAnyOf<ArgT> operator || ( MatcherBase<ArgT> const& other ) {
|
||||||
m_matchers.push_back( &other );
|
auto copy(*this);
|
||||||
return *this;
|
copy.m_matchers.push_back( &other );
|
||||||
|
return copy;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<MatcherBase<ArgT> const*> m_matchers;
|
std::vector<MatcherBase<ArgT> const*> m_matchers;
|
||||||
|
@@ -59,16 +59,8 @@ namespace {
|
|||||||
return static_cast<uint64_t>(ulpDiff) <= maxUlpDiff;
|
return static_cast<uint64_t>(ulpDiff) <= maxUlpDiff;
|
||||||
}
|
}
|
||||||
|
|
||||||
} //end anonymous namespace
|
|
||||||
|
|
||||||
#if defined(CATCH_CONFIG_GLOBAL_NEXTAFTER)
|
#if defined(CATCH_CONFIG_GLOBAL_NEXTAFTER)
|
||||||
|
|
||||||
#if defined(__clang__)
|
|
||||||
#pragma clang diagnostic push
|
|
||||||
// The long double overload is currently unused
|
|
||||||
#pragma clang diagnostic ignored "-Wunused-function"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
float nextafter(float x, float y) {
|
float nextafter(float x, float y) {
|
||||||
return ::nextafterf(x, y);
|
return ::nextafterf(x, y);
|
||||||
}
|
}
|
||||||
@@ -77,18 +69,8 @@ namespace {
|
|||||||
return ::nextafter(x, y);
|
return ::nextafter(x, y);
|
||||||
}
|
}
|
||||||
|
|
||||||
long double nextafter(long double x, long double y) {
|
|
||||||
return ::nextafterl(x, y);
|
|
||||||
}
|
|
||||||
|
|
||||||
#if defined(__clang__)
|
|
||||||
#pragma clang diagnostic pop
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif // ^^^ CATCH_CONFIG_GLOBAL_NEXTAFTER ^^^
|
#endif // ^^^ CATCH_CONFIG_GLOBAL_NEXTAFTER ^^^
|
||||||
|
|
||||||
namespace {
|
|
||||||
|
|
||||||
template <typename FP>
|
template <typename FP>
|
||||||
FP step(FP start, FP direction, uint64_t steps) {
|
FP step(FP start, FP direction, uint64_t steps) {
|
||||||
for (uint64_t i = 0; i < steps; ++i) {
|
for (uint64_t i = 0; i < steps; ++i) {
|
||||||
@@ -101,14 +83,17 @@ FP step(FP start, FP direction, uint64_t steps) {
|
|||||||
return start;
|
return start;
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace {
|
|
||||||
|
|
||||||
// Performs equivalent check of std::fabs(lhs - rhs) <= margin
|
// Performs equivalent check of std::fabs(lhs - rhs) <= margin
|
||||||
// But without the subtraction to allow for INFINITY in comparison
|
// But without the subtraction to allow for INFINITY in comparison
|
||||||
bool marginComparison(double lhs, double rhs, double margin) {
|
bool marginComparison(double lhs, double rhs, double margin) {
|
||||||
return (lhs + margin >= rhs) && (rhs + margin >= lhs);
|
return (lhs + margin >= rhs) && (rhs + margin >= lhs);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <typename FloatingPoint>
|
||||||
|
void write(std::ostream& out, FloatingPoint num) {
|
||||||
|
out << std::scientific
|
||||||
|
<< std::setprecision(std::numeric_limits<FloatingPoint>::max_digits10 - 1)
|
||||||
|
<< num;
|
||||||
}
|
}
|
||||||
|
|
||||||
} // end anonymous namespace
|
} // end anonymous namespace
|
||||||
@@ -142,7 +127,7 @@ namespace Floating {
|
|||||||
WithinUlpsMatcher::WithinUlpsMatcher(double target, uint64_t ulps, FloatingPointKind baseType)
|
WithinUlpsMatcher::WithinUlpsMatcher(double target, uint64_t ulps, FloatingPointKind baseType)
|
||||||
:m_target{ target }, m_ulps{ ulps }, m_type{ baseType } {
|
:m_target{ target }, m_ulps{ ulps }, m_type{ baseType } {
|
||||||
CATCH_ENFORCE(m_type == FloatingPointKind::Double
|
CATCH_ENFORCE(m_type == FloatingPointKind::Double
|
||||||
|| m_ulps < std::numeric_limits<uint32_t>::max(),
|
|| m_ulps < (std::numeric_limits<uint32_t>::max)(),
|
||||||
"Provided ULP is impossibly large for a float comparison.");
|
"Provided ULP is impossibly large for a float comparison.");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -170,27 +155,29 @@ namespace Floating {
|
|||||||
std::string WithinUlpsMatcher::describe() const {
|
std::string WithinUlpsMatcher::describe() const {
|
||||||
std::stringstream ret;
|
std::stringstream ret;
|
||||||
|
|
||||||
ret << "is within " << m_ulps << " ULPs of " << ::Catch::Detail::stringify(m_target);
|
ret << "is within " << m_ulps << " ULPs of ";
|
||||||
|
|
||||||
if (m_type == FloatingPointKind::Float) {
|
if (m_type == FloatingPointKind::Float) {
|
||||||
|
write(ret, static_cast<float>(m_target));
|
||||||
ret << 'f';
|
ret << 'f';
|
||||||
|
} else {
|
||||||
|
write(ret, m_target);
|
||||||
}
|
}
|
||||||
|
|
||||||
ret << " ([";
|
ret << " ([";
|
||||||
ret << std::fixed << std::setprecision(std::numeric_limits<double>::max_digits10);
|
|
||||||
if (m_type == FloatingPointKind::Double) {
|
if (m_type == FloatingPointKind::Double) {
|
||||||
ret << step(m_target, static_cast<double>(-INFINITY), m_ulps)
|
write(ret, step(m_target, static_cast<double>(-INFINITY), m_ulps));
|
||||||
<< ", "
|
ret << ", ";
|
||||||
<< step(m_target, static_cast<double>(INFINITY), m_ulps);
|
write(ret, step(m_target, static_cast<double>( INFINITY), m_ulps));
|
||||||
} else {
|
} else {
|
||||||
ret << step<float>(static_cast<float>(m_target), -INFINITY, m_ulps)
|
// 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));
|
||||||
<< step<float>(static_cast<float>(m_target), INFINITY, m_ulps);
|
ret << ", ";
|
||||||
|
write(ret, step(static_cast<float>(m_target), static_cast<float>( INFINITY), m_ulps));
|
||||||
}
|
}
|
||||||
ret << "])";
|
ret << "])";
|
||||||
|
|
||||||
return ret.str();
|
return ret.str();
|
||||||
//return "is within " + Catch::to_string(m_ulps) + " ULPs of " + ::Catch::Detail::stringify(m_target) + ((m_type == FloatingPointKind::Float)? "f" : "");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
WithinRelMatcher::WithinRelMatcher(double target, double epsilon):
|
WithinRelMatcher::WithinRelMatcher(double target, double epsilon):
|
||||||
@@ -201,7 +188,7 @@ namespace Floating {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool WithinRelMatcher::match(double const& matchee) const {
|
bool WithinRelMatcher::match(double const& matchee) const {
|
||||||
const auto relMargin = m_epsilon * std::max(std::fabs(matchee), std::fabs(m_target));
|
const auto relMargin = m_epsilon * (std::max)(std::fabs(matchee), std::fabs(m_target));
|
||||||
return marginComparison(matchee, m_target,
|
return marginComparison(matchee, m_target,
|
||||||
std::isinf(relMargin)? 0 : relMargin);
|
std::isinf(relMargin)? 0 : relMargin);
|
||||||
}
|
}
|
||||||
|
@@ -111,7 +111,7 @@ namespace Catch {
|
|||||||
pos = skipq(pos, c);
|
pos = skipq(pos, c);
|
||||||
break;
|
break;
|
||||||
case ',':
|
case ',':
|
||||||
if (start != pos && openings.size() == 0) {
|
if (start != pos && openings.empty()) {
|
||||||
m_messages.emplace_back(macroName, lineInfo, resultType);
|
m_messages.emplace_back(macroName, lineInfo, resultType);
|
||||||
m_messages.back().message = static_cast<std::string>(trimmed(start, pos));
|
m_messages.back().message = static_cast<std::string>(trimmed(start, pos));
|
||||||
m_messages.back().message += " := ";
|
m_messages.back().message += " := ";
|
||||||
@@ -119,7 +119,7 @@ namespace Catch {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
assert(openings.size() == 0 && "Mismatched openings");
|
assert(openings.empty() && "Mismatched openings");
|
||||||
m_messages.emplace_back(macroName, lineInfo, resultType);
|
m_messages.emplace_back(macroName, lineInfo, resultType);
|
||||||
m_messages.back().message = static_cast<std::string>(trimmed(start, names.size() - 1));
|
m_messages.back().message = static_cast<std::string>(trimmed(start, names.size() - 1));
|
||||||
m_messages.back().message += " := ";
|
m_messages.back().message += " := ";
|
||||||
|
@@ -29,6 +29,18 @@ struct is_callable;
|
|||||||
template <typename Fun, typename... Args>
|
template <typename Fun, typename... Args>
|
||||||
struct is_callable<Fun(Args...)> : decltype(is_callable_tester::test<Fun, Args...>(0)) {};
|
struct is_callable<Fun(Args...)> : decltype(is_callable_tester::test<Fun, Args...>(0)) {};
|
||||||
|
|
||||||
|
|
||||||
|
#if defined(__cpp_lib_is_invocable) && __cpp_lib_is_invocable >= 201703
|
||||||
|
// std::result_of is deprecated in C++17 and removed in C++20. Hence, it is
|
||||||
|
// replaced with std::invoke_result here. Also *_t format is preferred over
|
||||||
|
// typename *::type format.
|
||||||
|
template <typename Func, typename U>
|
||||||
|
using FunctionReturnType = std::remove_reference_t<std::remove_cv_t<std::invoke_result_t<Func, U>>>;
|
||||||
|
#else
|
||||||
|
template <typename Func, typename U>
|
||||||
|
using FunctionReturnType = typename std::remove_reference<typename std::remove_cv<typename std::result_of<Func(U)>::type>::type>::type;
|
||||||
|
#endif
|
||||||
|
|
||||||
} // namespace Catch
|
} // namespace Catch
|
||||||
|
|
||||||
namespace mpl_{
|
namespace mpl_{
|
||||||
|
@@ -102,35 +102,49 @@
|
|||||||
template<typename...> struct TypeList {};\
|
template<typename...> struct TypeList {};\
|
||||||
template<typename...Ts>\
|
template<typename...Ts>\
|
||||||
constexpr auto get_wrapper() noexcept -> TypeList<Ts...> { return {}; }\
|
constexpr auto get_wrapper() noexcept -> TypeList<Ts...> { return {}; }\
|
||||||
|
template<template<typename...> class...> struct TemplateTypeList{};\
|
||||||
|
template<template<typename...> class...Cs>\
|
||||||
|
constexpr auto get_wrapper() noexcept -> TemplateTypeList<Cs...> { return {}; }\
|
||||||
|
template<typename...>\
|
||||||
|
struct append;\
|
||||||
|
template<typename...>\
|
||||||
|
struct rewrap;\
|
||||||
|
template<template<typename...> class, typename...>\
|
||||||
|
struct create;\
|
||||||
|
template<template<typename...> class, typename>\
|
||||||
|
struct convert;\
|
||||||
\
|
\
|
||||||
template<template<typename...> class L1, typename...E1, template<typename...> class L2, typename...E2> \
|
template<typename T> \
|
||||||
constexpr auto append(L1<E1...>, L2<E2...>) noexcept -> L1<E1...,E2...> { return {}; }\
|
struct append<T> { using type = T; };\
|
||||||
template< template<typename...> class L1, typename...E1, template<typename...> class L2, typename...E2, typename...Rest>\
|
template< template<typename...> class L1, typename...E1, template<typename...> class L2, typename...E2, typename...Rest>\
|
||||||
constexpr auto append(L1<E1...>, L2<E2...>, Rest...) noexcept -> decltype(append(L1<E1...,E2...>{}, Rest{}...)) { return {}; }\
|
struct append<L1<E1...>, L2<E2...>, Rest...> { using type = typename append<L1<E1...,E2...>, Rest...>::type; };\
|
||||||
template< template<typename...> class L1, typename...E1, typename...Rest>\
|
template< template<typename...> class L1, typename...E1, typename...Rest>\
|
||||||
constexpr auto append(L1<E1...>, TypeList<mpl_::na>, Rest...) noexcept -> L1<E1...> { return {}; }\
|
struct append<L1<E1...>, TypeList<mpl_::na>, Rest...> { using type = L1<E1...>; };\
|
||||||
\
|
\
|
||||||
template< template<typename...> class Container, template<typename...> class List, typename...elems>\
|
template< template<typename...> class Container, template<typename...> class List, typename...elems>\
|
||||||
constexpr auto rewrap(List<elems...>) noexcept -> TypeList<Container<elems...>> { return {}; }\
|
struct rewrap<TemplateTypeList<Container>, List<elems...>> { using type = TypeList<Container<elems...>>; };\
|
||||||
template< template<typename...> class Container, template<typename...> class List, class...Elems, typename...Elements>\
|
template< template<typename...> class Container, template<typename...> class List, class...Elems, typename...Elements>\
|
||||||
constexpr auto rewrap(List<Elems...>,Elements...) noexcept -> decltype(append(TypeList<Container<Elems...>>{}, rewrap<Container>(Elements{}...))) { return {}; }\
|
struct rewrap<TemplateTypeList<Container>, List<Elems...>, Elements...> { using type = typename append<TypeList<Container<Elems...>>, typename rewrap<TemplateTypeList<Container>, Elements...>::type>::type; };\
|
||||||
\
|
\
|
||||||
template<template <typename...> class Final, template< typename...> class...Containers, typename...Types>\
|
template<template <typename...> class Final, template< typename...> class...Containers, typename...Types>\
|
||||||
constexpr auto create(TypeList<Types...>) noexcept -> decltype(append(Final<>{}, rewrap<Containers>(Types{}...)...)) { return {}; }\
|
struct create<Final, TemplateTypeList<Containers...>, TypeList<Types...>> { using type = typename append<Final<>, typename rewrap<TemplateTypeList<Containers>, Types...>::type...>::type; };\
|
||||||
template<template <typename...> class Final, template <typename...> class List, typename...Ts>\
|
template<template <typename...> class Final, template <typename...> class List, typename...Ts>\
|
||||||
constexpr auto convert(const List<Ts...>& ) noexcept -> decltype(append(Final<>{},TypeList<Ts>{}...)) { return {}; }
|
struct convert<Final, List<Ts...>> { using type = typename append<Final<>,TypeList<Ts>...>::type; };
|
||||||
|
|
||||||
#define INTERNAL_CATCH_NTTP_1(signature, ...)\
|
#define INTERNAL_CATCH_NTTP_1(signature, ...)\
|
||||||
template<INTERNAL_CATCH_REMOVE_PARENS(signature)> struct Nttp{};\
|
template<INTERNAL_CATCH_REMOVE_PARENS(signature)> struct Nttp{};\
|
||||||
template<INTERNAL_CATCH_REMOVE_PARENS(signature)>\
|
template<INTERNAL_CATCH_REMOVE_PARENS(signature)>\
|
||||||
constexpr auto get_wrapper() noexcept -> Nttp<__VA_ARGS__> { return {}; } \
|
constexpr auto get_wrapper() noexcept -> Nttp<__VA_ARGS__> { return {}; } \
|
||||||
|
template<template<INTERNAL_CATCH_REMOVE_PARENS(signature)> class...> struct NttpTemplateTypeList{};\
|
||||||
|
template<template<INTERNAL_CATCH_REMOVE_PARENS(signature)> class...Cs>\
|
||||||
|
constexpr auto get_wrapper() noexcept -> NttpTemplateTypeList<Cs...> { return {}; } \
|
||||||
\
|
\
|
||||||
template< template<INTERNAL_CATCH_REMOVE_PARENS(signature)> class Container, template<INTERNAL_CATCH_REMOVE_PARENS(signature)> class List, INTERNAL_CATCH_REMOVE_PARENS(signature)>\
|
template< template<INTERNAL_CATCH_REMOVE_PARENS(signature)> class Container, template<INTERNAL_CATCH_REMOVE_PARENS(signature)> class List, INTERNAL_CATCH_REMOVE_PARENS(signature)>\
|
||||||
constexpr auto rewrap(List<__VA_ARGS__>) noexcept -> TypeList<Container<__VA_ARGS__>> { return {}; }\
|
struct rewrap<NttpTemplateTypeList<Container>, List<__VA_ARGS__>> { using type = TypeList<Container<__VA_ARGS__>>; };\
|
||||||
template< template<INTERNAL_CATCH_REMOVE_PARENS(signature)> class Container, template<INTERNAL_CATCH_REMOVE_PARENS(signature)> class List, INTERNAL_CATCH_REMOVE_PARENS(signature), typename...Elements>\
|
template< template<INTERNAL_CATCH_REMOVE_PARENS(signature)> class Container, template<INTERNAL_CATCH_REMOVE_PARENS(signature)> class List, INTERNAL_CATCH_REMOVE_PARENS(signature), typename...Elements>\
|
||||||
constexpr auto rewrap(List<__VA_ARGS__>,Elements...elems) noexcept -> decltype(append(TypeList<Container<__VA_ARGS__>>{}, rewrap<Container>(elems...))) { return {}; }\
|
struct rewrap<NttpTemplateTypeList<Container>, List<__VA_ARGS__>, Elements...> { using type = typename append<TypeList<Container<__VA_ARGS__>>, typename rewrap<NttpTemplateTypeList<Container>, Elements...>::type>::type; };\
|
||||||
template<template <typename...> class Final, template<INTERNAL_CATCH_REMOVE_PARENS(signature)> class...Containers, typename...Types>\
|
template<template <typename...> class Final, template<INTERNAL_CATCH_REMOVE_PARENS(signature)> class...Containers, typename...Types>\
|
||||||
constexpr auto create(TypeList<Types...>) noexcept -> decltype(append(Final<>{}, rewrap<Containers>(Types{}...)...)) { return {}; }
|
struct create<Final, NttpTemplateTypeList<Containers...>, TypeList<Types...>> { using type = typename append<Final<>, typename rewrap<NttpTemplateTypeList<Containers>, Types...>::type...>::type; };
|
||||||
|
|
||||||
#define INTERNAL_CATCH_DECLARE_SIG_TEST0(TestName)
|
#define INTERNAL_CATCH_DECLARE_SIG_TEST0(TestName)
|
||||||
#define INTERNAL_CATCH_DECLARE_SIG_TEST1(TestName, signature)\
|
#define INTERNAL_CATCH_DECLARE_SIG_TEST1(TestName, signature)\
|
||||||
|
@@ -20,10 +20,10 @@ namespace Catch {
|
|||||||
using state_type = std::uint64_t;
|
using state_type = std::uint64_t;
|
||||||
public:
|
public:
|
||||||
using result_type = std::uint32_t;
|
using result_type = std::uint32_t;
|
||||||
static constexpr result_type min() {
|
static constexpr result_type (min)() {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
static constexpr result_type max() {
|
static constexpr result_type (max)() {
|
||||||
return static_cast<result_type>(-1);
|
return static_cast<result_type>(-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -58,14 +58,16 @@ namespace Catch {
|
|||||||
#if !defined(CATCH_CONFIG_DISABLE)
|
#if !defined(CATCH_CONFIG_DISABLE)
|
||||||
|
|
||||||
#define CATCH_REGISTER_REPORTER( name, reporterType ) \
|
#define CATCH_REGISTER_REPORTER( name, reporterType ) \
|
||||||
|
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> catch_internal_RegistrarFor##reporterType( name ); } \
|
||||||
CATCH_INTERNAL_UNSUPPRESS_GLOBALS_WARNINGS
|
CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION
|
||||||
|
|
||||||
#define CATCH_REGISTER_LISTENER( listenerType ) \
|
#define CATCH_REGISTER_LISTENER( listenerType ) \
|
||||||
|
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> catch_internal_RegistrarFor##listenerType; } \
|
||||||
CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS
|
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)
|
||||||
|
@@ -37,13 +37,15 @@ namespace Catch {
|
|||||||
} // end namespace Catch
|
} // end namespace Catch
|
||||||
|
|
||||||
#define INTERNAL_CATCH_SECTION( ... ) \
|
#define INTERNAL_CATCH_SECTION( ... ) \
|
||||||
|
CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \
|
||||||
CATCH_INTERNAL_SUPPRESS_UNUSED_WARNINGS \
|
CATCH_INTERNAL_SUPPRESS_UNUSED_WARNINGS \
|
||||||
if( Catch::Section const& INTERNAL_CATCH_UNIQUE_NAME( catch_internal_Section ) = Catch::SectionInfo( CATCH_INTERNAL_LINEINFO, __VA_ARGS__ ) ) \
|
if( Catch::Section const& INTERNAL_CATCH_UNIQUE_NAME( catch_internal_Section ) = Catch::SectionInfo( CATCH_INTERNAL_LINEINFO, __VA_ARGS__ ) ) \
|
||||||
CATCH_INTERNAL_UNSUPPRESS_UNUSED_WARNINGS
|
CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION
|
||||||
|
|
||||||
#define INTERNAL_CATCH_DYNAMIC_SECTION( ... ) \
|
#define INTERNAL_CATCH_DYNAMIC_SECTION( ... ) \
|
||||||
|
CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \
|
||||||
CATCH_INTERNAL_SUPPRESS_UNUSED_WARNINGS \
|
CATCH_INTERNAL_SUPPRESS_UNUSED_WARNINGS \
|
||||||
if( Catch::Section const& INTERNAL_CATCH_UNIQUE_NAME( catch_internal_Section ) = Catch::SectionInfo( CATCH_INTERNAL_LINEINFO, (Catch::ReusableStringStream() << __VA_ARGS__).str() ) ) \
|
if( Catch::Section const& INTERNAL_CATCH_UNIQUE_NAME( catch_internal_Section ) = Catch::SectionInfo( CATCH_INTERNAL_LINEINFO, (Catch::ReusableStringStream() << __VA_ARGS__).str() ) ) \
|
||||||
CATCH_INTERNAL_UNSUPPRESS_UNUSED_WARNINGS
|
CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION
|
||||||
|
|
||||||
#endif // TWOBLUECUBES_CATCH_SECTION_H_INCLUDED
|
#endif // TWOBLUECUBES_CATCH_SECTION_H_INCLUDED
|
||||||
|
@@ -68,8 +68,9 @@ namespace Catch {
|
|||||||
{
|
{
|
||||||
auto const& allTestCases = getAllTestCasesSorted(*m_config);
|
auto const& allTestCases = getAllTestCasesSorted(*m_config);
|
||||||
m_matches = m_config->testSpec().matchesByFilter(allTestCases, *m_config);
|
m_matches = m_config->testSpec().matchesByFilter(allTestCases, *m_config);
|
||||||
|
auto const& invalidArgs = m_config->testSpec().getInvalidArgs();
|
||||||
|
|
||||||
if (m_matches.empty()) {
|
if (m_matches.empty() && invalidArgs.empty()) {
|
||||||
for (auto const& test : allTestCases)
|
for (auto const& test : allTestCases)
|
||||||
if (!test.isHidden())
|
if (!test.isHidden())
|
||||||
m_tests.emplace(&test);
|
m_tests.emplace(&test);
|
||||||
@@ -80,6 +81,7 @@ namespace Catch {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Totals execute() {
|
Totals execute() {
|
||||||
|
auto const& invalidArgs = m_config->testSpec().getInvalidArgs();
|
||||||
Totals totals;
|
Totals totals;
|
||||||
m_context.testGroupStarting(m_config->name(), 1, 1);
|
m_context.testGroupStarting(m_config->name(), 1, 1);
|
||||||
for (auto const& testCase : m_tests) {
|
for (auto const& testCase : m_tests) {
|
||||||
@@ -95,6 +97,12 @@ namespace Catch {
|
|||||||
totals.error = -1;
|
totals.error = -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!invalidArgs.empty()) {
|
||||||
|
for (auto const& invalidArg: invalidArgs)
|
||||||
|
m_context.reporter().reportInvalidArguments(invalidArg);
|
||||||
|
}
|
||||||
|
|
||||||
m_context.testGroupEnded(m_config->name(), totals, 1, 1);
|
m_context.testGroupEnded(m_config->name(), totals, 1, 1);
|
||||||
return totals;
|
return totals;
|
||||||
}
|
}
|
||||||
@@ -212,11 +220,11 @@ namespace Catch {
|
|||||||
char **utf8Argv = new char *[ argc ];
|
char **utf8Argv = new char *[ argc ];
|
||||||
|
|
||||||
for ( int i = 0; i < argc; ++i ) {
|
for ( int i = 0; i < argc; ++i ) {
|
||||||
int bufSize = WideCharToMultiByte( CP_UTF8, 0, argv[i], -1, NULL, 0, NULL, NULL );
|
int bufSize = WideCharToMultiByte( CP_UTF8, 0, argv[i], -1, nullptr, 0, nullptr, nullptr );
|
||||||
|
|
||||||
utf8Argv[ i ] = new char[ bufSize ];
|
utf8Argv[ i ] = new char[ bufSize ];
|
||||||
|
|
||||||
WideCharToMultiByte( CP_UTF8, 0, argv[i], -1, utf8Argv[i], bufSize, NULL, NULL );
|
WideCharToMultiByte( CP_UTF8, 0, argv[i], -1, utf8Argv[i], bufSize, nullptr, nullptr );
|
||||||
}
|
}
|
||||||
|
|
||||||
int returnCode = applyCommandLine( argc, utf8Argv );
|
int returnCode = applyCommandLine( argc, utf8Argv );
|
||||||
|
@@ -9,6 +9,8 @@
|
|||||||
#ifndef TWOBLUECUBES_CATCH_STREAM_H_INCLUDED
|
#ifndef TWOBLUECUBES_CATCH_STREAM_H_INCLUDED
|
||||||
#define TWOBLUECUBES_CATCH_STREAM_H_INCLUDED
|
#define TWOBLUECUBES_CATCH_STREAM_H_INCLUDED
|
||||||
|
|
||||||
|
#include "catch_common.h"
|
||||||
|
|
||||||
#include <iosfwd>
|
#include <iosfwd>
|
||||||
#include <cstddef>
|
#include <cstddef>
|
||||||
#include <ostream>
|
#include <ostream>
|
||||||
@@ -28,7 +30,7 @@ namespace Catch {
|
|||||||
|
|
||||||
auto makeStream( StringRef const &filename ) -> IStream const*;
|
auto makeStream( StringRef const &filename ) -> IStream const*;
|
||||||
|
|
||||||
class ReusableStringStream {
|
class ReusableStringStream : NonCopyable {
|
||||||
std::size_t m_index;
|
std::size_t m_index;
|
||||||
std::ostream* m_oss;
|
std::ostream* m_oss;
|
||||||
public:
|
public:
|
||||||
|
@@ -5,14 +5,10 @@
|
|||||||
* file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
* file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include "catch_enforce.h"
|
||||||
#if defined(__clang__)
|
|
||||||
# pragma clang diagnostic push
|
|
||||||
# pragma clang diagnostic ignored "-Wexit-time-destructors"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include "catch_stringref.h"
|
#include "catch_stringref.h"
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
#include <ostream>
|
#include <ostream>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
@@ -22,63 +18,33 @@ namespace Catch {
|
|||||||
: StringRef( rawChars, static_cast<StringRef::size_type>(std::strlen(rawChars) ) )
|
: StringRef( rawChars, static_cast<StringRef::size_type>(std::strlen(rawChars) ) )
|
||||||
{}
|
{}
|
||||||
|
|
||||||
void StringRef::swap( StringRef& other ) noexcept {
|
|
||||||
std::swap( m_start, other.m_start );
|
|
||||||
std::swap( m_size, other.m_size );
|
|
||||||
std::swap( m_data, other.m_data );
|
|
||||||
}
|
|
||||||
|
|
||||||
auto StringRef::c_str() const -> char const* {
|
auto StringRef::c_str() const -> char const* {
|
||||||
if( !isSubstring() )
|
CATCH_ENFORCE(isNullTerminated(), "Called StringRef::c_str() on a non-null-terminated instance");
|
||||||
return m_start;
|
return m_start;
|
||||||
|
|
||||||
const_cast<StringRef *>( this )->takeOwnership();
|
|
||||||
return m_data;
|
|
||||||
}
|
}
|
||||||
auto StringRef::currentData() const noexcept -> char const* {
|
auto StringRef::data() const noexcept -> char const* {
|
||||||
return m_start;
|
return m_start;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto StringRef::isOwned() const noexcept -> bool {
|
|
||||||
return m_data != nullptr;
|
|
||||||
}
|
|
||||||
auto StringRef::isSubstring() const noexcept -> bool {
|
|
||||||
return m_start[m_size] != '\0';
|
|
||||||
}
|
|
||||||
|
|
||||||
void StringRef::takeOwnership() {
|
|
||||||
if( !isOwned() ) {
|
|
||||||
m_data = new char[m_size+1];
|
|
||||||
memcpy( m_data, m_start, m_size );
|
|
||||||
m_data[m_size] = '\0';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
auto StringRef::substr( size_type start, size_type size ) const noexcept -> StringRef {
|
auto StringRef::substr( size_type start, size_type size ) const noexcept -> StringRef {
|
||||||
if( start < m_size )
|
if (start < m_size) {
|
||||||
return StringRef( m_start+start, size );
|
return StringRef(m_start + start, (std::min)(m_size - start, size));
|
||||||
else
|
} else {
|
||||||
return StringRef();
|
return StringRef();
|
||||||
}
|
}
|
||||||
auto StringRef::operator == ( StringRef const& other ) const noexcept -> bool {
|
|
||||||
return
|
|
||||||
size() == other.size() &&
|
|
||||||
(std::strncmp( m_start, other.m_start, size() ) == 0);
|
|
||||||
}
|
}
|
||||||
auto StringRef::operator != ( StringRef const& other ) const noexcept -> bool {
|
auto StringRef::operator == ( StringRef const& other ) const noexcept -> bool {
|
||||||
return !operator==( other );
|
return m_size == other.m_size
|
||||||
|
&& (std::memcmp( m_start, other.m_start, m_size ) == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto operator << ( std::ostream& os, StringRef const& str ) -> std::ostream& {
|
auto operator << ( std::ostream& os, StringRef const& str ) -> std::ostream& {
|
||||||
return os.write(str.currentData(), str.size());
|
return os.write(str.data(), str.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
auto operator+=( std::string& lhs, StringRef const& rhs ) -> std::string& {
|
auto operator+=( std::string& lhs, StringRef const& rhs ) -> std::string& {
|
||||||
lhs.append(rhs.currentData(), rhs.size());
|
lhs.append(rhs.data(), rhs.size());
|
||||||
return lhs;
|
return lhs;
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace Catch
|
} // namespace Catch
|
||||||
|
|
||||||
#if defined(__clang__)
|
|
||||||
# pragma clang diagnostic pop
|
|
||||||
#endif
|
|
||||||
|
@@ -16,49 +16,24 @@ namespace Catch {
|
|||||||
|
|
||||||
/// A non-owning string class (similar to the forthcoming std::string_view)
|
/// A non-owning string class (similar to the forthcoming std::string_view)
|
||||||
/// Note that, because a StringRef may be a substring of another string,
|
/// Note that, because a StringRef may be a substring of another string,
|
||||||
/// it may not be null terminated. c_str() must return a null terminated
|
/// it may not be null terminated.
|
||||||
/// string, however, and so the StringRef will internally take ownership
|
|
||||||
/// (taking a copy), if necessary. In theory this ownership is not externally
|
|
||||||
/// visible - but it does mean (substring) StringRefs should not be shared between
|
|
||||||
/// threads.
|
|
||||||
class StringRef {
|
class StringRef {
|
||||||
public:
|
public:
|
||||||
using size_type = std::size_t;
|
using size_type = std::size_t;
|
||||||
using const_iterator = const char*;
|
using const_iterator = const char*;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
friend struct StringRefTestAccess;
|
|
||||||
|
|
||||||
char const* m_start;
|
|
||||||
size_type m_size;
|
|
||||||
|
|
||||||
char* m_data = nullptr;
|
|
||||||
|
|
||||||
void takeOwnership();
|
|
||||||
|
|
||||||
static constexpr char const* const s_empty = "";
|
static constexpr char const* const s_empty = "";
|
||||||
|
|
||||||
public: // construction/ assignment
|
char const* m_start = s_empty;
|
||||||
StringRef() noexcept
|
size_type m_size = 0;
|
||||||
: StringRef( s_empty, 0 )
|
|
||||||
{}
|
|
||||||
|
|
||||||
StringRef( StringRef const& other ) noexcept
|
public: // construction
|
||||||
: m_start( other.m_start ),
|
constexpr StringRef() noexcept = default;
|
||||||
m_size( other.m_size )
|
|
||||||
{}
|
|
||||||
|
|
||||||
StringRef( StringRef&& other ) noexcept
|
|
||||||
: m_start( other.m_start ),
|
|
||||||
m_size( other.m_size ),
|
|
||||||
m_data( other.m_data )
|
|
||||||
{
|
|
||||||
other.m_data = nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
StringRef( char const* rawChars ) noexcept;
|
StringRef( char const* rawChars ) noexcept;
|
||||||
|
|
||||||
StringRef( char const* rawChars, size_type size ) noexcept
|
constexpr StringRef( char const* rawChars, size_type size ) noexcept
|
||||||
: m_start( rawChars ),
|
: m_start( rawChars ),
|
||||||
m_size( size )
|
m_size( size )
|
||||||
{}
|
{}
|
||||||
@@ -68,27 +43,15 @@ namespace Catch {
|
|||||||
m_size( stdString.size() )
|
m_size( stdString.size() )
|
||||||
{}
|
{}
|
||||||
|
|
||||||
~StringRef() noexcept {
|
|
||||||
delete[] m_data;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto operator = ( StringRef const &other ) noexcept -> StringRef& {
|
|
||||||
delete[] m_data;
|
|
||||||
m_data = nullptr;
|
|
||||||
m_start = other.m_start;
|
|
||||||
m_size = other.m_size;
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
explicit operator std::string() const {
|
explicit operator std::string() const {
|
||||||
return std::string(m_start, m_size);
|
return std::string(m_start, m_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
void swap( StringRef& other ) noexcept;
|
|
||||||
|
|
||||||
public: // operators
|
public: // operators
|
||||||
auto operator == ( StringRef const& other ) const noexcept -> bool;
|
auto operator == ( StringRef const& other ) const noexcept -> bool;
|
||||||
auto operator != ( StringRef const& other ) const noexcept -> bool;
|
auto operator != (StringRef const& other) const noexcept -> bool {
|
||||||
|
return !(*this == other);
|
||||||
|
}
|
||||||
|
|
||||||
auto operator[] ( size_type index ) const noexcept -> char {
|
auto operator[] ( size_type index ) const noexcept -> char {
|
||||||
assert(index < m_size);
|
assert(index < m_size);
|
||||||
@@ -96,42 +59,45 @@ namespace Catch {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public: // named queries
|
public: // named queries
|
||||||
auto empty() const noexcept -> bool {
|
constexpr auto empty() const noexcept -> bool {
|
||||||
return m_size == 0;
|
return m_size == 0;
|
||||||
}
|
}
|
||||||
auto size() const noexcept -> size_type {
|
constexpr auto size() const noexcept -> size_type {
|
||||||
return m_size;
|
return m_size;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Returns the current start pointer. If the StringRef is not
|
||||||
|
// null-terminated, throws std::domain_exception
|
||||||
auto c_str() const -> char const*;
|
auto c_str() const -> char const*;
|
||||||
|
|
||||||
public: // substrings and searches
|
public: // substrings and searches
|
||||||
auto substr( size_type start, size_type size ) const noexcept -> StringRef;
|
// Returns a substring of [start, start + length).
|
||||||
|
// If start + length > size(), then the substring is [start, size()).
|
||||||
|
// If start > size(), then the substring is empty.
|
||||||
|
auto substr( size_type start, size_type length ) const noexcept -> StringRef;
|
||||||
|
|
||||||
// Returns the current start pointer.
|
// Returns the current start pointer. May not be null-terminated.
|
||||||
// Note that the pointer can change when if the StringRef is a substring
|
auto data() const noexcept -> char const*;
|
||||||
auto currentData() const noexcept -> char const*;
|
|
||||||
|
constexpr auto isNullTerminated() const noexcept -> bool {
|
||||||
|
return m_start[m_size] == '\0';
|
||||||
|
}
|
||||||
|
|
||||||
public: // iterators
|
public: // iterators
|
||||||
const_iterator begin() const { return m_start; }
|
constexpr const_iterator begin() const { return m_start; }
|
||||||
const_iterator end() const { return m_start + m_size; }
|
constexpr const_iterator end() const { return m_start + m_size; }
|
||||||
|
|
||||||
private: // ownership queries - may not be consistent between calls
|
|
||||||
auto isOwned() const noexcept -> bool;
|
|
||||||
auto isSubstring() const noexcept -> bool;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
auto operator += ( std::string& lhs, StringRef const& sr ) -> std::string&;
|
auto operator += ( std::string& lhs, StringRef const& sr ) -> std::string&;
|
||||||
auto operator << ( std::ostream& os, StringRef const& sr ) -> std::ostream&;
|
auto operator << ( std::ostream& os, StringRef const& sr ) -> std::ostream&;
|
||||||
|
|
||||||
|
|
||||||
inline auto operator "" _sr( char const* rawChars, std::size_t size ) noexcept -> StringRef {
|
constexpr auto operator "" _sr( char const* rawChars, std::size_t size ) noexcept -> StringRef {
|
||||||
return StringRef( rawChars, size );
|
return StringRef( rawChars, size );
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace Catch
|
} // namespace Catch
|
||||||
|
|
||||||
inline auto operator "" _catch_sr( char const* rawChars, std::size_t size ) noexcept -> Catch::StringRef {
|
constexpr auto operator "" _catch_sr( char const* rawChars, std::size_t size ) noexcept -> Catch::StringRef {
|
||||||
return Catch::StringRef( rawChars, size );
|
return Catch::StringRef( rawChars, size );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -18,8 +18,9 @@ namespace Catch {
|
|||||||
} // end namespace Catch
|
} // end namespace Catch
|
||||||
|
|
||||||
#define CATCH_REGISTER_TAG_ALIAS( alias, spec ) \
|
#define CATCH_REGISTER_TAG_ALIAS( alias, spec ) \
|
||||||
|
CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \
|
||||||
CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
|
CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
|
||||||
namespace{ Catch::RegistrarForTagAliases INTERNAL_CATCH_UNIQUE_NAME( AutoRegisterTagAlias )( alias, spec, CATCH_INTERNAL_LINEINFO ); } \
|
namespace{ Catch::RegistrarForTagAliases INTERNAL_CATCH_UNIQUE_NAME( AutoRegisterTagAlias )( alias, spec, CATCH_INTERNAL_LINEINFO ); } \
|
||||||
CATCH_INTERNAL_UNSUPPRESS_GLOBALS_WARNINGS
|
CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION
|
||||||
|
|
||||||
#endif // TWOBLUECUBES_CATCH_TAG_ALIAS_AUTOREGISTRAR_H_INCLUDED
|
#endif // TWOBLUECUBES_CATCH_TAG_ALIAS_AUTOREGISTRAR_H_INCLUDED
|
||||||
|
@@ -89,7 +89,8 @@ namespace Catch {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if( isHidden ) {
|
if( isHidden ) {
|
||||||
tags.push_back( "." );
|
// Add all "hidden" tags to make them behave identically
|
||||||
|
tags.insert( tags.end(), { ".", "!hide" } );
|
||||||
}
|
}
|
||||||
|
|
||||||
TestCaseInfo info( static_cast<std::string>(nameAndTags.name), _className, desc, tags, _lineInfo );
|
TestCaseInfo info( static_cast<std::string>(nameAndTags.name), _className, desc, tags, _lineInfo );
|
||||||
|
@@ -225,8 +225,8 @@ namespace TestCaseTracking {
|
|||||||
void SectionTracker::addInitialFilters( std::vector<std::string> const& filters ) {
|
void SectionTracker::addInitialFilters( std::vector<std::string> const& filters ) {
|
||||||
if( !filters.empty() ) {
|
if( !filters.empty() ) {
|
||||||
m_filters.reserve( m_filters.size() + filters.size() + 2 );
|
m_filters.reserve( m_filters.size() + filters.size() + 2 );
|
||||||
m_filters.push_back(""); // Root - should never be consulted
|
m_filters.emplace_back(""); // Root - should never be consulted
|
||||||
m_filters.push_back(""); // Test Case - not a section filter
|
m_filters.emplace_back(""); // Test Case - not a section filter
|
||||||
m_filters.insert( m_filters.end(), filters.begin(), filters.end() );
|
m_filters.insert( m_filters.end(), filters.begin(), filters.end() );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -105,21 +105,24 @@ struct AutoReg : NonCopyable {
|
|||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
#define INTERNAL_CATCH_TESTCASE2( TestName, ... ) \
|
#define INTERNAL_CATCH_TESTCASE2( TestName, ... ) \
|
||||||
static void TestName(); \
|
static void TestName(); \
|
||||||
|
CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \
|
||||||
CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
|
CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
|
||||||
namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( Catch::makeTestInvoker( &TestName ), CATCH_INTERNAL_LINEINFO, Catch::StringRef(), Catch::NameAndTags{ __VA_ARGS__ } ); } /* NOLINT */ \
|
namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( Catch::makeTestInvoker( &TestName ), CATCH_INTERNAL_LINEINFO, Catch::StringRef(), Catch::NameAndTags{ __VA_ARGS__ } ); } /* NOLINT */ \
|
||||||
CATCH_INTERNAL_UNSUPPRESS_GLOBALS_WARNINGS \
|
CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION \
|
||||||
static void TestName()
|
static void TestName()
|
||||||
#define INTERNAL_CATCH_TESTCASE( ... ) \
|
#define INTERNAL_CATCH_TESTCASE( ... ) \
|
||||||
INTERNAL_CATCH_TESTCASE2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ), __VA_ARGS__ )
|
INTERNAL_CATCH_TESTCASE2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ), __VA_ARGS__ )
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
#define INTERNAL_CATCH_METHOD_AS_TEST_CASE( QualifiedMethod, ... ) \
|
#define INTERNAL_CATCH_METHOD_AS_TEST_CASE( QualifiedMethod, ... ) \
|
||||||
|
CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \
|
||||||
CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
|
CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
|
||||||
namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( Catch::makeTestInvoker( &QualifiedMethod ), CATCH_INTERNAL_LINEINFO, "&" #QualifiedMethod, Catch::NameAndTags{ __VA_ARGS__ } ); } /* NOLINT */ \
|
namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( Catch::makeTestInvoker( &QualifiedMethod ), CATCH_INTERNAL_LINEINFO, "&" #QualifiedMethod, Catch::NameAndTags{ __VA_ARGS__ } ); } /* NOLINT */ \
|
||||||
CATCH_INTERNAL_UNSUPPRESS_GLOBALS_WARNINGS
|
CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
#define INTERNAL_CATCH_TEST_CASE_METHOD2( TestName, ClassName, ... )\
|
#define INTERNAL_CATCH_TEST_CASE_METHOD2( TestName, ClassName, ... )\
|
||||||
|
CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \
|
||||||
CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
|
CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
|
||||||
namespace{ \
|
namespace{ \
|
||||||
struct TestName : INTERNAL_CATCH_REMOVE_PARENS(ClassName) { \
|
struct TestName : INTERNAL_CATCH_REMOVE_PARENS(ClassName) { \
|
||||||
@@ -127,21 +130,24 @@ struct AutoReg : NonCopyable {
|
|||||||
}; \
|
}; \
|
||||||
Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar ) ( Catch::makeTestInvoker( &TestName::test ), CATCH_INTERNAL_LINEINFO, #ClassName, Catch::NameAndTags{ __VA_ARGS__ } ); /* NOLINT */ \
|
Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar ) ( Catch::makeTestInvoker( &TestName::test ), CATCH_INTERNAL_LINEINFO, #ClassName, Catch::NameAndTags{ __VA_ARGS__ } ); /* NOLINT */ \
|
||||||
} \
|
} \
|
||||||
CATCH_INTERNAL_UNSUPPRESS_GLOBALS_WARNINGS \
|
CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION \
|
||||||
void TestName::test()
|
void TestName::test()
|
||||||
#define INTERNAL_CATCH_TEST_CASE_METHOD( ClassName, ... ) \
|
#define INTERNAL_CATCH_TEST_CASE_METHOD( ClassName, ... ) \
|
||||||
INTERNAL_CATCH_TEST_CASE_METHOD2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ), ClassName, __VA_ARGS__ )
|
INTERNAL_CATCH_TEST_CASE_METHOD2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ), ClassName, __VA_ARGS__ )
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
#define INTERNAL_CATCH_REGISTER_TESTCASE( Function, ... ) \
|
#define INTERNAL_CATCH_REGISTER_TESTCASE( Function, ... ) \
|
||||||
|
CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \
|
||||||
CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
|
CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
|
||||||
Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( Catch::makeTestInvoker( Function ), CATCH_INTERNAL_LINEINFO, Catch::StringRef(), Catch::NameAndTags{ __VA_ARGS__ } ); /* NOLINT */ \
|
Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( Catch::makeTestInvoker( Function ), CATCH_INTERNAL_LINEINFO, Catch::StringRef(), Catch::NameAndTags{ __VA_ARGS__ } ); /* NOLINT */ \
|
||||||
CATCH_INTERNAL_UNSUPPRESS_GLOBALS_WARNINGS
|
CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
#define INTERNAL_CATCH_TEMPLATE_TEST_CASE_2(TestName, TestFunc, Name, Tags, Signature, ... )\
|
#define INTERNAL_CATCH_TEMPLATE_TEST_CASE_2(TestName, TestFunc, Name, Tags, Signature, ... )\
|
||||||
|
CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \
|
||||||
CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
|
CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
|
||||||
CATCH_INTERNAL_SUPPRESS_ZERO_VARIADIC_WARNINGS \
|
CATCH_INTERNAL_SUPPRESS_ZERO_VARIADIC_WARNINGS \
|
||||||
|
CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS \
|
||||||
INTERNAL_CATCH_DECLARE_SIG_TEST(TestFunc, INTERNAL_CATCH_REMOVE_PARENS(Signature));\
|
INTERNAL_CATCH_DECLARE_SIG_TEST(TestFunc, INTERNAL_CATCH_REMOVE_PARENS(Signature));\
|
||||||
namespace {\
|
namespace {\
|
||||||
namespace INTERNAL_CATCH_MAKE_NAMESPACE(TestName){\
|
namespace INTERNAL_CATCH_MAKE_NAMESPACE(TestName){\
|
||||||
@@ -163,8 +169,7 @@ struct AutoReg : NonCopyable {
|
|||||||
}();\
|
}();\
|
||||||
}\
|
}\
|
||||||
}\
|
}\
|
||||||
CATCH_INTERNAL_UNSUPPRESS_GLOBALS_WARNINGS \
|
CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION \
|
||||||
CATCH_INTERNAL_UNSUPPRESS_ZERO_VARIADIC_WARNINGS \
|
|
||||||
INTERNAL_CATCH_DEFINE_SIG_TEST(TestFunc,INTERNAL_CATCH_REMOVE_PARENS(Signature))
|
INTERNAL_CATCH_DEFINE_SIG_TEST(TestFunc,INTERNAL_CATCH_REMOVE_PARENS(Signature))
|
||||||
|
|
||||||
#ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
|
#ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
|
||||||
@@ -184,8 +189,10 @@ struct AutoReg : NonCopyable {
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE2(TestName, TestFuncName, Name, Tags, Signature, TmplTypes, TypesList) \
|
#define INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE2(TestName, TestFuncName, Name, Tags, Signature, TmplTypes, TypesList) \
|
||||||
|
CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \
|
||||||
CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
|
CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
|
||||||
CATCH_INTERNAL_SUPPRESS_ZERO_VARIADIC_WARNINGS \
|
CATCH_INTERNAL_SUPPRESS_ZERO_VARIADIC_WARNINGS \
|
||||||
|
CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS \
|
||||||
template<typename TestType> static void TestFuncName(); \
|
template<typename TestType> static void TestFuncName(); \
|
||||||
namespace {\
|
namespace {\
|
||||||
namespace INTERNAL_CATCH_MAKE_NAMESPACE(TestName) { \
|
namespace INTERNAL_CATCH_MAKE_NAMESPACE(TestName) { \
|
||||||
@@ -203,15 +210,14 @@ struct AutoReg : NonCopyable {
|
|||||||
} \
|
} \
|
||||||
}; \
|
}; \
|
||||||
static int INTERNAL_CATCH_UNIQUE_NAME( globalRegistrar ) = [](){ \
|
static int INTERNAL_CATCH_UNIQUE_NAME( globalRegistrar ) = [](){ \
|
||||||
using TestInit = decltype(create<TestName, INTERNAL_CATCH_REMOVE_PARENS(TmplTypes)>(TypeList<INTERNAL_CATCH_MAKE_TYPE_LISTS_FROM_TYPES(INTERNAL_CATCH_REMOVE_PARENS(TypesList))>{})); \
|
using TestInit = typename create<TestName, decltype(get_wrapper<INTERNAL_CATCH_REMOVE_PARENS(TmplTypes)>()), TypeList<INTERNAL_CATCH_MAKE_TYPE_LISTS_FROM_TYPES(INTERNAL_CATCH_REMOVE_PARENS(TypesList))>>::type; \
|
||||||
TestInit t; \
|
TestInit t; \
|
||||||
t.reg_tests(); \
|
t.reg_tests(); \
|
||||||
return 0; \
|
return 0; \
|
||||||
}(); \
|
}(); \
|
||||||
} \
|
} \
|
||||||
} \
|
} \
|
||||||
CATCH_INTERNAL_UNSUPPRESS_GLOBALS_WARNINGS \
|
CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION \
|
||||||
CATCH_INTERNAL_UNSUPPRESS_ZERO_VARIADIC_WARNINGS \
|
|
||||||
template<typename TestType> \
|
template<typename TestType> \
|
||||||
static void TestFuncName()
|
static void TestFuncName()
|
||||||
|
|
||||||
@@ -232,7 +238,9 @@ struct AutoReg : NonCopyable {
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define INTERNAL_CATCH_TEMPLATE_LIST_TEST_CASE_2(TestName, TestFunc, Name, Tags, TmplList)\
|
#define INTERNAL_CATCH_TEMPLATE_LIST_TEST_CASE_2(TestName, TestFunc, Name, Tags, TmplList)\
|
||||||
|
CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \
|
||||||
CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
|
CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
|
||||||
|
CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS \
|
||||||
template<typename TestType> static void TestFunc(); \
|
template<typename TestType> static void TestFunc(); \
|
||||||
namespace {\
|
namespace {\
|
||||||
namespace INTERNAL_CATCH_MAKE_NAMESPACE(TestName){\
|
namespace INTERNAL_CATCH_MAKE_NAMESPACE(TestName){\
|
||||||
@@ -246,13 +254,13 @@ struct AutoReg : NonCopyable {
|
|||||||
} \
|
} \
|
||||||
};\
|
};\
|
||||||
static int INTERNAL_CATCH_UNIQUE_NAME( globalRegistrar ) = [](){ \
|
static int INTERNAL_CATCH_UNIQUE_NAME( globalRegistrar ) = [](){ \
|
||||||
using TestInit = decltype(convert<TestName>(std::declval<TmplList>())); \
|
using TestInit = typename convert<TestName, TmplList>::type; \
|
||||||
TestInit t; \
|
TestInit t; \
|
||||||
t.reg_tests(); \
|
t.reg_tests(); \
|
||||||
return 0; \
|
return 0; \
|
||||||
}(); \
|
}(); \
|
||||||
}}\
|
}}\
|
||||||
CATCH_INTERNAL_UNSUPPRESS_GLOBALS_WARNINGS \
|
CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION \
|
||||||
template<typename TestType> \
|
template<typename TestType> \
|
||||||
static void TestFunc()
|
static void TestFunc()
|
||||||
|
|
||||||
@@ -261,8 +269,10 @@ struct AutoReg : NonCopyable {
|
|||||||
|
|
||||||
|
|
||||||
#define INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_2( TestNameClass, TestName, ClassName, Name, Tags, Signature, ... ) \
|
#define INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_2( TestNameClass, TestName, ClassName, Name, Tags, Signature, ... ) \
|
||||||
|
CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \
|
||||||
CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
|
CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
|
||||||
CATCH_INTERNAL_SUPPRESS_ZERO_VARIADIC_WARNINGS \
|
CATCH_INTERNAL_SUPPRESS_ZERO_VARIADIC_WARNINGS \
|
||||||
|
CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS \
|
||||||
namespace {\
|
namespace {\
|
||||||
namespace INTERNAL_CATCH_MAKE_NAMESPACE(TestName){ \
|
namespace INTERNAL_CATCH_MAKE_NAMESPACE(TestName){ \
|
||||||
INTERNAL_CATCH_TYPE_GEN\
|
INTERNAL_CATCH_TYPE_GEN\
|
||||||
@@ -284,8 +294,7 @@ struct AutoReg : NonCopyable {
|
|||||||
}();\
|
}();\
|
||||||
}\
|
}\
|
||||||
}\
|
}\
|
||||||
CATCH_INTERNAL_UNSUPPRESS_GLOBALS_WARNINGS\
|
CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION \
|
||||||
CATCH_INTERNAL_UNSUPPRESS_ZERO_VARIADIC_WARNINGS\
|
|
||||||
INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD(TestName, INTERNAL_CATCH_REMOVE_PARENS(Signature))
|
INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD(TestName, INTERNAL_CATCH_REMOVE_PARENS(Signature))
|
||||||
|
|
||||||
#ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
|
#ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
|
||||||
@@ -305,8 +314,10 @@ struct AutoReg : NonCopyable {
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD_2(TestNameClass, TestName, ClassName, Name, Tags, Signature, TmplTypes, TypesList)\
|
#define INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD_2(TestNameClass, TestName, ClassName, Name, Tags, Signature, TmplTypes, TypesList)\
|
||||||
|
CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \
|
||||||
CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
|
CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
|
||||||
CATCH_INTERNAL_SUPPRESS_ZERO_VARIADIC_WARNINGS \
|
CATCH_INTERNAL_SUPPRESS_ZERO_VARIADIC_WARNINGS \
|
||||||
|
CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS \
|
||||||
template<typename TestType> \
|
template<typename TestType> \
|
||||||
struct TestName : INTERNAL_CATCH_REMOVE_PARENS(ClassName <TestType>) { \
|
struct TestName : INTERNAL_CATCH_REMOVE_PARENS(ClassName <TestType>) { \
|
||||||
void test();\
|
void test();\
|
||||||
@@ -327,15 +338,14 @@ struct AutoReg : NonCopyable {
|
|||||||
}\
|
}\
|
||||||
};\
|
};\
|
||||||
static int INTERNAL_CATCH_UNIQUE_NAME( globalRegistrar ) = [](){\
|
static int INTERNAL_CATCH_UNIQUE_NAME( globalRegistrar ) = [](){\
|
||||||
using TestInit = decltype(create<TestNameClass, INTERNAL_CATCH_REMOVE_PARENS(TmplTypes)>(TypeList<INTERNAL_CATCH_MAKE_TYPE_LISTS_FROM_TYPES(INTERNAL_CATCH_REMOVE_PARENS(TypesList))>{}));\
|
using TestInit = typename create<TestNameClass, decltype(get_wrapper<INTERNAL_CATCH_REMOVE_PARENS(TmplTypes)>()), TypeList<INTERNAL_CATCH_MAKE_TYPE_LISTS_FROM_TYPES(INTERNAL_CATCH_REMOVE_PARENS(TypesList))>>::type;\
|
||||||
TestInit t;\
|
TestInit t;\
|
||||||
t.reg_tests();\
|
t.reg_tests();\
|
||||||
return 0;\
|
return 0;\
|
||||||
}(); \
|
}(); \
|
||||||
}\
|
}\
|
||||||
}\
|
}\
|
||||||
CATCH_INTERNAL_UNSUPPRESS_GLOBALS_WARNINGS \
|
CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION \
|
||||||
CATCH_INTERNAL_UNSUPPRESS_ZERO_VARIADIC_WARNINGS \
|
|
||||||
template<typename TestType> \
|
template<typename TestType> \
|
||||||
void TestName<TestType>::test()
|
void TestName<TestType>::test()
|
||||||
|
|
||||||
@@ -356,7 +366,9 @@ struct AutoReg : NonCopyable {
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define INTERNAL_CATCH_TEMPLATE_LIST_TEST_CASE_METHOD_2( TestNameClass, TestName, ClassName, Name, Tags, TmplList) \
|
#define INTERNAL_CATCH_TEMPLATE_LIST_TEST_CASE_METHOD_2( TestNameClass, TestName, ClassName, Name, Tags, TmplList) \
|
||||||
|
CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \
|
||||||
CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
|
CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
|
||||||
|
CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS \
|
||||||
template<typename TestType> \
|
template<typename TestType> \
|
||||||
struct TestName : INTERNAL_CATCH_REMOVE_PARENS(ClassName <TestType>) { \
|
struct TestName : INTERNAL_CATCH_REMOVE_PARENS(ClassName <TestType>) { \
|
||||||
void test();\
|
void test();\
|
||||||
@@ -373,13 +385,13 @@ struct AutoReg : NonCopyable {
|
|||||||
}\
|
}\
|
||||||
};\
|
};\
|
||||||
static int INTERNAL_CATCH_UNIQUE_NAME( globalRegistrar ) = [](){\
|
static int INTERNAL_CATCH_UNIQUE_NAME( globalRegistrar ) = [](){\
|
||||||
using TestInit = decltype(convert<TestNameClass>(std::declval<TmplList>()));\
|
using TestInit = typename convert<TestNameClass, TmplList>::type;\
|
||||||
TestInit t;\
|
TestInit t;\
|
||||||
t.reg_tests();\
|
t.reg_tests();\
|
||||||
return 0;\
|
return 0;\
|
||||||
}(); \
|
}(); \
|
||||||
}}\
|
}}\
|
||||||
CATCH_INTERNAL_UNSUPPRESS_GLOBALS_WARNINGS \
|
CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION \
|
||||||
template<typename TestType> \
|
template<typename TestType> \
|
||||||
void TestName<TestType>::test()
|
void TestName<TestType>::test()
|
||||||
|
|
||||||
|
@@ -92,4 +92,8 @@ namespace Catch {
|
|||||||
return matches;
|
return matches;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const TestSpec::vectorStrings& TestSpec::getInvalidArgs() const{
|
||||||
|
return (m_invalidArgs);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -73,14 +73,16 @@ namespace Catch {
|
|||||||
std::vector<TestCase const*> tests;
|
std::vector<TestCase const*> tests;
|
||||||
};
|
};
|
||||||
using Matches = std::vector<FilterMatch>;
|
using Matches = std::vector<FilterMatch>;
|
||||||
|
using vectorStrings = std::vector<std::string>;
|
||||||
|
|
||||||
bool hasFilters() const;
|
bool hasFilters() const;
|
||||||
bool matches( TestCaseInfo const& testCase ) const;
|
bool matches( TestCaseInfo const& testCase ) const;
|
||||||
Matches matchesByFilter( std::vector<TestCase> const& testCases, IConfig const& config ) const;
|
Matches matchesByFilter( std::vector<TestCase> const& testCases, IConfig const& config ) const;
|
||||||
|
const vectorStrings & getInvalidArgs() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::vector<Filter> m_filters;
|
std::vector<Filter> m_filters;
|
||||||
|
std::vector<std::string> m_invalidArgs;
|
||||||
friend class TestSpecParser;
|
friend class TestSpecParser;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@@ -20,8 +20,13 @@ namespace Catch {
|
|||||||
m_substring.reserve(m_arg.size());
|
m_substring.reserve(m_arg.size());
|
||||||
m_patternName.reserve(m_arg.size());
|
m_patternName.reserve(m_arg.size());
|
||||||
m_realPatternPos = 0;
|
m_realPatternPos = 0;
|
||||||
|
|
||||||
for( m_pos = 0; m_pos < m_arg.size(); ++m_pos )
|
for( m_pos = 0; m_pos < m_arg.size(); ++m_pos )
|
||||||
visitChar( m_arg[m_pos] );
|
//if visitChar fails
|
||||||
|
if( !visitChar( m_arg[m_pos] ) ){
|
||||||
|
m_testSpec.m_invalidArgs.push_back(arg);
|
||||||
|
break;
|
||||||
|
}
|
||||||
endMode();
|
endMode();
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
@@ -29,38 +34,32 @@ namespace Catch {
|
|||||||
addFilter();
|
addFilter();
|
||||||
return m_testSpec;
|
return m_testSpec;
|
||||||
}
|
}
|
||||||
void TestSpecParser::visitChar( char c ) {
|
bool TestSpecParser::visitChar( char c ) {
|
||||||
if( (m_mode != EscapedName) && (c == '\\') ) {
|
if( (m_mode != EscapedName) && (c == '\\') ) {
|
||||||
escape();
|
escape();
|
||||||
m_substring += c;
|
addCharToPattern(c);
|
||||||
m_patternName += c;
|
return true;
|
||||||
m_realPatternPos++;
|
|
||||||
return;
|
|
||||||
}else if((m_mode != EscapedName) && (c == ',') ) {
|
}else if((m_mode != EscapedName) && (c == ',') ) {
|
||||||
endMode();
|
return separate();
|
||||||
addFilter();
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
switch( m_mode ) {
|
switch( m_mode ) {
|
||||||
case None:
|
case None:
|
||||||
if( processNoneChar( c ) )
|
if( processNoneChar( c ) )
|
||||||
return;
|
return true;
|
||||||
break;
|
break;
|
||||||
case Name:
|
case Name:
|
||||||
processNameChar( c );
|
processNameChar( c );
|
||||||
break;
|
break;
|
||||||
case EscapedName:
|
case EscapedName:
|
||||||
endMode();
|
endMode();
|
||||||
m_substring += c;
|
addCharToPattern(c);
|
||||||
m_patternName += c;
|
return true;
|
||||||
m_realPatternPos++;
|
|
||||||
return;
|
|
||||||
default:
|
default:
|
||||||
case Tag:
|
case Tag:
|
||||||
case QuotedName:
|
case QuotedName:
|
||||||
if( processOtherChar( c ) )
|
if( processOtherChar( c ) )
|
||||||
return;
|
return true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -69,6 +68,7 @@ namespace Catch {
|
|||||||
m_patternName += c;
|
m_patternName += c;
|
||||||
m_realPatternPos++;
|
m_realPatternPos++;
|
||||||
}
|
}
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
// Two of the processing methods return true to signal the caller to return
|
// Two of the processing methods return true to signal the caller to return
|
||||||
// without adding the given character to the current pattern strings
|
// without adding the given character to the current pattern strings
|
||||||
@@ -113,9 +113,9 @@ namespace Catch {
|
|||||||
switch( m_mode ) {
|
switch( m_mode ) {
|
||||||
case Name:
|
case Name:
|
||||||
case QuotedName:
|
case QuotedName:
|
||||||
return addPattern<TestSpec::NamePattern>();
|
return addNamePattern();
|
||||||
case Tag:
|
case Tag:
|
||||||
return addPattern<TestSpec::TagPattern>();
|
return addTagPattern();
|
||||||
case EscapedName:
|
case EscapedName:
|
||||||
revertBackToLastMode();
|
revertBackToLastMode();
|
||||||
return;
|
return;
|
||||||
@@ -161,6 +161,76 @@ namespace Catch {
|
|||||||
m_mode = lastMode;
|
m_mode = lastMode;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool TestSpecParser::separate() {
|
||||||
|
if( (m_mode==QuotedName) || (m_mode==Tag) ){
|
||||||
|
//invalid argument, signal failure to previous scope.
|
||||||
|
m_mode = None;
|
||||||
|
m_pos = m_arg.size();
|
||||||
|
m_substring.clear();
|
||||||
|
m_patternName.clear();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
endMode();
|
||||||
|
addFilter();
|
||||||
|
return true; //success
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string TestSpecParser::preprocessPattern() {
|
||||||
|
std::string token = m_patternName;
|
||||||
|
for (std::size_t i = 0; i < m_escapeChars.size(); ++i)
|
||||||
|
token = token.substr(0, m_escapeChars[i] - i) + token.substr(m_escapeChars[i] - i + 1);
|
||||||
|
m_escapeChars.clear();
|
||||||
|
if (startsWith(token, "exclude:")) {
|
||||||
|
m_exclusion = true;
|
||||||
|
token = token.substr(8);
|
||||||
|
}
|
||||||
|
|
||||||
|
m_patternName.clear();
|
||||||
|
|
||||||
|
return token;
|
||||||
|
}
|
||||||
|
|
||||||
|
void TestSpecParser::addNamePattern() {
|
||||||
|
auto token = preprocessPattern();
|
||||||
|
|
||||||
|
if (!token.empty()) {
|
||||||
|
TestSpec::PatternPtr pattern = std::make_shared<TestSpec::NamePattern>(token, m_substring);
|
||||||
|
if (m_exclusion)
|
||||||
|
pattern = std::make_shared<TestSpec::ExcludedPattern>(pattern);
|
||||||
|
m_currentFilter.m_patterns.push_back(pattern);
|
||||||
|
}
|
||||||
|
m_substring.clear();
|
||||||
|
m_exclusion = false;
|
||||||
|
m_mode = None;
|
||||||
|
}
|
||||||
|
|
||||||
|
void TestSpecParser::addTagPattern() {
|
||||||
|
auto token = preprocessPattern();
|
||||||
|
|
||||||
|
if (!token.empty()) {
|
||||||
|
// If the tag pattern is the "hide and tag" shorthand (e.g. [.foo])
|
||||||
|
// we have to create a separate hide tag and shorten the real one
|
||||||
|
if (token.size() > 1 && token[0] == '.') {
|
||||||
|
token.erase(token.begin());
|
||||||
|
TestSpec::PatternPtr pattern = std::make_shared<TestSpec::TagPattern>(".", m_substring);
|
||||||
|
if (m_exclusion) {
|
||||||
|
pattern = std::make_shared<TestSpec::ExcludedPattern>(pattern);
|
||||||
|
}
|
||||||
|
m_currentFilter.m_patterns.push_back(pattern);
|
||||||
|
}
|
||||||
|
|
||||||
|
TestSpec::PatternPtr pattern = std::make_shared<TestSpec::TagPattern>(token, m_substring);
|
||||||
|
|
||||||
|
if (m_exclusion) {
|
||||||
|
pattern = std::make_shared<TestSpec::ExcludedPattern>(pattern);
|
||||||
|
}
|
||||||
|
m_currentFilter.m_patterns.push_back(pattern);
|
||||||
|
}
|
||||||
|
m_substring.clear();
|
||||||
|
m_exclusion = false;
|
||||||
|
m_mode = None;
|
||||||
|
}
|
||||||
|
|
||||||
TestSpec parseTestSpec( std::string const& arg ) {
|
TestSpec parseTestSpec( std::string const& arg ) {
|
||||||
return TestSpecParser( ITagAliasRegistry::get() ).parse( arg ).testSpec();
|
return TestSpecParser( ITagAliasRegistry::get() ).parse( arg ).testSpec();
|
||||||
}
|
}
|
||||||
|
@@ -41,7 +41,7 @@ namespace Catch {
|
|||||||
TestSpec testSpec();
|
TestSpec testSpec();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void visitChar( char c );
|
bool visitChar( char c );
|
||||||
void startNewMode( Mode mode );
|
void startNewMode( Mode mode );
|
||||||
bool processNoneChar( char c );
|
bool processNoneChar( char c );
|
||||||
void processNameChar( char c );
|
void processNameChar( char c );
|
||||||
@@ -51,30 +51,22 @@ namespace Catch {
|
|||||||
bool isControlChar( char c ) const;
|
bool isControlChar( char c ) const;
|
||||||
void saveLastMode();
|
void saveLastMode();
|
||||||
void revertBackToLastMode();
|
void revertBackToLastMode();
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
void addPattern() {
|
|
||||||
std::string token = m_patternName;
|
|
||||||
for( std::size_t i = 0; i < m_escapeChars.size(); ++i )
|
|
||||||
token = token.substr( 0, m_escapeChars[i] - i ) + token.substr( m_escapeChars[i] -i +1 );
|
|
||||||
m_escapeChars.clear();
|
|
||||||
if( startsWith( token, "exclude:" ) ) {
|
|
||||||
m_exclusion = true;
|
|
||||||
token = token.substr( 8 );
|
|
||||||
}
|
|
||||||
if( !token.empty() ) {
|
|
||||||
TestSpec::PatternPtr pattern = std::make_shared<T>( token, m_substring );
|
|
||||||
if( m_exclusion )
|
|
||||||
pattern = std::make_shared<TestSpec::ExcludedPattern>( pattern );
|
|
||||||
m_currentFilter.m_patterns.push_back( pattern );
|
|
||||||
}
|
|
||||||
m_substring.clear();
|
|
||||||
m_patternName.clear();
|
|
||||||
m_exclusion = false;
|
|
||||||
m_mode = None;
|
|
||||||
}
|
|
||||||
|
|
||||||
void addFilter();
|
void addFilter();
|
||||||
|
bool separate();
|
||||||
|
|
||||||
|
// Handles common preprocessing of the pattern for name/tag patterns
|
||||||
|
std::string preprocessPattern();
|
||||||
|
// Adds the current pattern as a test name
|
||||||
|
void addNamePattern();
|
||||||
|
// Adds the current pattern as a tag
|
||||||
|
void addTagPattern();
|
||||||
|
|
||||||
|
inline void addCharToPattern(char c) {
|
||||||
|
m_substring += c;
|
||||||
|
m_patternName += c;
|
||||||
|
m_realPatternPos++;
|
||||||
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
TestSpec parseTestSpec( std::string const& arg );
|
TestSpec parseTestSpec( std::string const& arg );
|
||||||
|
|
||||||
|
@@ -38,13 +38,11 @@ namespace Detail {
|
|||||||
enum Arch { Big, Little };
|
enum Arch { Big, Little };
|
||||||
|
|
||||||
static Arch which() {
|
static Arch which() {
|
||||||
union _{
|
int one = 1;
|
||||||
int asInt;
|
// If the lowest byte we read is non-zero, we can assume
|
||||||
char asChar[sizeof (int)];
|
// that little endian format is used.
|
||||||
} u;
|
auto value = *reinterpret_cast<char*>(&one);
|
||||||
|
return value ? Little : Big;
|
||||||
u.asInt = 1;
|
|
||||||
return ( u.asChar[sizeof(int)-1] == 1 ) ? Big : Little;
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@@ -37,7 +37,7 @@ namespace Catch {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Version const& libraryVersion() {
|
Version const& libraryVersion() {
|
||||||
static Version version( 2, 10, 0, "", 0 );
|
static Version version( 2, 11, 2, "", 0 );
|
||||||
return version;
|
return version;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -10,8 +10,7 @@
|
|||||||
#include "catch_enforce.h"
|
#include "catch_enforce.h"
|
||||||
|
|
||||||
#include <iomanip>
|
#include <iomanip>
|
||||||
|
#include <type_traits>
|
||||||
using uchar = unsigned char;
|
|
||||||
|
|
||||||
namespace Catch {
|
namespace Catch {
|
||||||
|
|
||||||
@@ -51,8 +50,31 @@ namespace {
|
|||||||
os.flags(f);
|
os.flags(f);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool shouldNewline(XmlFormatting fmt) {
|
||||||
|
return !!(static_cast<std::underlying_type<XmlFormatting>::type>(fmt & XmlFormatting::Newline));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool shouldIndent(XmlFormatting fmt) {
|
||||||
|
return !!(static_cast<std::underlying_type<XmlFormatting>::type>(fmt & XmlFormatting::Indent));
|
||||||
|
}
|
||||||
|
|
||||||
} // anonymous namespace
|
} // anonymous namespace
|
||||||
|
|
||||||
|
XmlFormatting operator | (XmlFormatting lhs, XmlFormatting rhs) {
|
||||||
|
return static_cast<XmlFormatting>(
|
||||||
|
static_cast<std::underlying_type<XmlFormatting>::type>(lhs) |
|
||||||
|
static_cast<std::underlying_type<XmlFormatting>::type>(rhs)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
XmlFormatting operator & (XmlFormatting lhs, XmlFormatting rhs) {
|
||||||
|
return static_cast<XmlFormatting>(
|
||||||
|
static_cast<std::underlying_type<XmlFormatting>::type>(lhs) &
|
||||||
|
static_cast<std::underlying_type<XmlFormatting>::type>(rhs)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
XmlEncode::XmlEncode( std::string const& str, ForWhat forWhat )
|
XmlEncode::XmlEncode( std::string const& str, ForWhat forWhat )
|
||||||
: m_str( str ),
|
: m_str( str ),
|
||||||
m_forWhat( forWhat )
|
m_forWhat( forWhat )
|
||||||
@@ -63,7 +85,7 @@ namespace {
|
|||||||
// (see: http://www.w3.org/TR/xml/#syntax)
|
// (see: http://www.w3.org/TR/xml/#syntax)
|
||||||
|
|
||||||
for( std::size_t idx = 0; idx < m_str.size(); ++ idx ) {
|
for( std::size_t idx = 0; idx < m_str.size(); ++ idx ) {
|
||||||
uchar c = m_str[idx];
|
unsigned char c = m_str[idx];
|
||||||
switch (c) {
|
switch (c) {
|
||||||
case '<': os << "<"; break;
|
case '<': os << "<"; break;
|
||||||
case '&': os << "&"; break;
|
case '&': os << "&"; break;
|
||||||
@@ -123,7 +145,7 @@ namespace {
|
|||||||
bool valid = true;
|
bool valid = true;
|
||||||
uint32_t value = headerValue(c);
|
uint32_t value = headerValue(c);
|
||||||
for (std::size_t n = 1; n < encBytes; ++n) {
|
for (std::size_t n = 1; n < encBytes; ++n) {
|
||||||
uchar nc = m_str[idx + n];
|
unsigned char nc = m_str[idx + n];
|
||||||
valid &= ((nc & 0xC0) == 0x80);
|
valid &= ((nc & 0xC0) == 0x80);
|
||||||
value = (value << 6) | (nc & 0x3F);
|
value = (value << 6) | (nc & 0x3F);
|
||||||
}
|
}
|
||||||
@@ -157,13 +179,17 @@ namespace {
|
|||||||
return os;
|
return os;
|
||||||
}
|
}
|
||||||
|
|
||||||
XmlWriter::ScopedElement::ScopedElement( XmlWriter* writer )
|
XmlWriter::ScopedElement::ScopedElement( XmlWriter* writer, XmlFormatting fmt )
|
||||||
: m_writer( writer )
|
: m_writer( writer ),
|
||||||
|
m_fmt(fmt)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
XmlWriter::ScopedElement::ScopedElement( ScopedElement&& other ) noexcept
|
XmlWriter::ScopedElement::ScopedElement( ScopedElement&& other ) noexcept
|
||||||
: m_writer( other.m_writer ){
|
: m_writer( other.m_writer ),
|
||||||
|
m_fmt(other.m_fmt)
|
||||||
|
{
|
||||||
other.m_writer = nullptr;
|
other.m_writer = nullptr;
|
||||||
|
other.m_fmt = XmlFormatting::None;
|
||||||
}
|
}
|
||||||
XmlWriter::ScopedElement& XmlWriter::ScopedElement::operator=( ScopedElement&& other ) noexcept {
|
XmlWriter::ScopedElement& XmlWriter::ScopedElement::operator=( ScopedElement&& other ) noexcept {
|
||||||
if ( m_writer ) {
|
if ( m_writer ) {
|
||||||
@@ -171,17 +197,20 @@ namespace {
|
|||||||
}
|
}
|
||||||
m_writer = other.m_writer;
|
m_writer = other.m_writer;
|
||||||
other.m_writer = nullptr;
|
other.m_writer = nullptr;
|
||||||
|
m_fmt = other.m_fmt;
|
||||||
|
other.m_fmt = XmlFormatting::None;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
XmlWriter::ScopedElement::~ScopedElement() {
|
XmlWriter::ScopedElement::~ScopedElement() {
|
||||||
if( m_writer )
|
if (m_writer) {
|
||||||
m_writer->endElement();
|
m_writer->endElement(m_fmt);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
XmlWriter::ScopedElement& XmlWriter::ScopedElement::writeText( std::string const& text, bool indent ) {
|
XmlWriter::ScopedElement& XmlWriter::ScopedElement::writeText( std::string const& text, XmlFormatting fmt ) {
|
||||||
m_writer->writeText( text, indent );
|
m_writer->writeText( text, fmt );
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -191,37 +220,47 @@ namespace {
|
|||||||
}
|
}
|
||||||
|
|
||||||
XmlWriter::~XmlWriter() {
|
XmlWriter::~XmlWriter() {
|
||||||
while( !m_tags.empty() )
|
while (!m_tags.empty()) {
|
||||||
endElement();
|
endElement();
|
||||||
}
|
}
|
||||||
|
newlineIfNecessary();
|
||||||
|
}
|
||||||
|
|
||||||
XmlWriter& XmlWriter::startElement( std::string const& name ) {
|
XmlWriter& XmlWriter::startElement( std::string const& name, XmlFormatting fmt ) {
|
||||||
ensureTagClosed();
|
ensureTagClosed();
|
||||||
newlineIfNecessary();
|
newlineIfNecessary();
|
||||||
m_os << m_indent << '<' << name;
|
if (shouldIndent(fmt)) {
|
||||||
m_tags.push_back( name );
|
m_os << m_indent;
|
||||||
m_indent += " ";
|
m_indent += " ";
|
||||||
|
}
|
||||||
|
m_os << '<' << name;
|
||||||
|
m_tags.push_back( name );
|
||||||
m_tagIsOpen = true;
|
m_tagIsOpen = true;
|
||||||
|
applyFormatting(fmt);
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
XmlWriter::ScopedElement XmlWriter::scopedElement( std::string const& name ) {
|
XmlWriter::ScopedElement XmlWriter::scopedElement( std::string const& name, XmlFormatting fmt ) {
|
||||||
ScopedElement scoped( this );
|
ScopedElement scoped( this, fmt );
|
||||||
startElement( name );
|
startElement( name, fmt );
|
||||||
return scoped;
|
return scoped;
|
||||||
}
|
}
|
||||||
|
|
||||||
XmlWriter& XmlWriter::endElement() {
|
XmlWriter& XmlWriter::endElement(XmlFormatting fmt) {
|
||||||
newlineIfNecessary();
|
|
||||||
m_indent = m_indent.substr(0, m_indent.size() - 2);
|
m_indent = m_indent.substr(0, m_indent.size() - 2);
|
||||||
|
|
||||||
if( m_tagIsOpen ) {
|
if( m_tagIsOpen ) {
|
||||||
m_os << "/>";
|
m_os << "/>";
|
||||||
m_tagIsOpen = false;
|
m_tagIsOpen = false;
|
||||||
|
} else {
|
||||||
|
newlineIfNecessary();
|
||||||
|
if (shouldIndent(fmt)) {
|
||||||
|
m_os << m_indent;
|
||||||
}
|
}
|
||||||
else {
|
m_os << "</" << m_tags.back() << ">";
|
||||||
m_os << m_indent << "</" << m_tags.back() << ">";
|
|
||||||
}
|
}
|
||||||
m_os << std::endl;
|
m_os << std::flush;
|
||||||
|
applyFormatting(fmt);
|
||||||
m_tags.pop_back();
|
m_tags.pop_back();
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
@@ -237,22 +276,26 @@ namespace {
|
|||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
XmlWriter& XmlWriter::writeText( std::string const& text, bool indent ) {
|
XmlWriter& XmlWriter::writeText( std::string const& text, XmlFormatting fmt) {
|
||||||
if( !text.empty() ){
|
if( !text.empty() ){
|
||||||
bool tagWasOpen = m_tagIsOpen;
|
bool tagWasOpen = m_tagIsOpen;
|
||||||
ensureTagClosed();
|
ensureTagClosed();
|
||||||
if( tagWasOpen && indent )
|
if (tagWasOpen && shouldIndent(fmt)) {
|
||||||
m_os << m_indent;
|
m_os << m_indent;
|
||||||
|
}
|
||||||
m_os << XmlEncode( text );
|
m_os << XmlEncode( text );
|
||||||
m_needsNewline = true;
|
applyFormatting(fmt);
|
||||||
}
|
}
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
XmlWriter& XmlWriter::writeComment( std::string const& text ) {
|
XmlWriter& XmlWriter::writeComment( std::string const& text, XmlFormatting fmt) {
|
||||||
ensureTagClosed();
|
ensureTagClosed();
|
||||||
m_os << m_indent << "<!--" << text << "-->";
|
if (shouldIndent(fmt)) {
|
||||||
m_needsNewline = true;
|
m_os << m_indent;
|
||||||
|
}
|
||||||
|
m_os << "<!--" << text << "-->";
|
||||||
|
applyFormatting(fmt);
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -268,11 +311,16 @@ namespace {
|
|||||||
|
|
||||||
void XmlWriter::ensureTagClosed() {
|
void XmlWriter::ensureTagClosed() {
|
||||||
if( m_tagIsOpen ) {
|
if( m_tagIsOpen ) {
|
||||||
m_os << ">" << std::endl;
|
m_os << '>' << std::flush;
|
||||||
|
newlineIfNecessary();
|
||||||
m_tagIsOpen = false;
|
m_tagIsOpen = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void XmlWriter::applyFormatting(XmlFormatting fmt) {
|
||||||
|
m_needsNewline = shouldNewline(fmt);
|
||||||
|
}
|
||||||
|
|
||||||
void XmlWriter::writeDeclaration() {
|
void XmlWriter::writeDeclaration() {
|
||||||
m_os << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n";
|
m_os << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n";
|
||||||
}
|
}
|
||||||
|
@@ -14,6 +14,14 @@
|
|||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
namespace Catch {
|
namespace Catch {
|
||||||
|
enum class XmlFormatting {
|
||||||
|
None = 0x00,
|
||||||
|
Indent = 0x01,
|
||||||
|
Newline = 0x02,
|
||||||
|
};
|
||||||
|
|
||||||
|
XmlFormatting operator | (XmlFormatting lhs, XmlFormatting rhs);
|
||||||
|
XmlFormatting operator & (XmlFormatting lhs, XmlFormatting rhs);
|
||||||
|
|
||||||
class XmlEncode {
|
class XmlEncode {
|
||||||
public:
|
public:
|
||||||
@@ -35,14 +43,14 @@ namespace Catch {
|
|||||||
|
|
||||||
class ScopedElement {
|
class ScopedElement {
|
||||||
public:
|
public:
|
||||||
ScopedElement( XmlWriter* writer );
|
ScopedElement( XmlWriter* writer, XmlFormatting fmt );
|
||||||
|
|
||||||
ScopedElement( ScopedElement&& other ) noexcept;
|
ScopedElement( ScopedElement&& other ) noexcept;
|
||||||
ScopedElement& operator=( ScopedElement&& other ) noexcept;
|
ScopedElement& operator=( ScopedElement&& other ) noexcept;
|
||||||
|
|
||||||
~ScopedElement();
|
~ScopedElement();
|
||||||
|
|
||||||
ScopedElement& writeText( std::string const& text, bool indent = true );
|
ScopedElement& writeText( std::string const& text, XmlFormatting fmt = XmlFormatting::Newline | XmlFormatting::Indent );
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
ScopedElement& writeAttribute( std::string const& name, T const& attribute ) {
|
ScopedElement& writeAttribute( std::string const& name, T const& attribute ) {
|
||||||
@@ -52,6 +60,7 @@ namespace Catch {
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
mutable XmlWriter* m_writer = nullptr;
|
mutable XmlWriter* m_writer = nullptr;
|
||||||
|
XmlFormatting m_fmt;
|
||||||
};
|
};
|
||||||
|
|
||||||
XmlWriter( std::ostream& os = Catch::cout() );
|
XmlWriter( std::ostream& os = Catch::cout() );
|
||||||
@@ -60,11 +69,11 @@ namespace Catch {
|
|||||||
XmlWriter( XmlWriter const& ) = delete;
|
XmlWriter( XmlWriter const& ) = delete;
|
||||||
XmlWriter& operator=( XmlWriter const& ) = delete;
|
XmlWriter& operator=( XmlWriter const& ) = delete;
|
||||||
|
|
||||||
XmlWriter& startElement( std::string const& name );
|
XmlWriter& startElement( std::string const& name, XmlFormatting fmt = XmlFormatting::Newline | XmlFormatting::Indent);
|
||||||
|
|
||||||
ScopedElement scopedElement( std::string const& name );
|
ScopedElement scopedElement( std::string const& name, XmlFormatting fmt = XmlFormatting::Newline | XmlFormatting::Indent);
|
||||||
|
|
||||||
XmlWriter& endElement();
|
XmlWriter& endElement(XmlFormatting fmt = XmlFormatting::Newline | XmlFormatting::Indent);
|
||||||
|
|
||||||
XmlWriter& writeAttribute( std::string const& name, std::string const& attribute );
|
XmlWriter& writeAttribute( std::string const& name, std::string const& attribute );
|
||||||
|
|
||||||
@@ -77,9 +86,9 @@ namespace Catch {
|
|||||||
return writeAttribute( name, rss.str() );
|
return writeAttribute( name, rss.str() );
|
||||||
}
|
}
|
||||||
|
|
||||||
XmlWriter& writeText( std::string const& text, bool indent = true );
|
XmlWriter& writeText( std::string const& text, XmlFormatting fmt = XmlFormatting::Newline | XmlFormatting::Indent);
|
||||||
|
|
||||||
XmlWriter& writeComment( std::string const& text );
|
XmlWriter& writeComment(std::string const& text, XmlFormatting fmt = XmlFormatting::Newline | XmlFormatting::Indent);
|
||||||
|
|
||||||
void writeStylesheetRef( std::string const& url );
|
void writeStylesheetRef( std::string const& url );
|
||||||
|
|
||||||
@@ -89,6 +98,8 @@ namespace Catch {
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
void applyFormatting(XmlFormatting fmt);
|
||||||
|
|
||||||
void writeDeclaration();
|
void writeDeclaration();
|
||||||
|
|
||||||
void newlineIfNecessary();
|
void newlineIfNecessary();
|
||||||
|
@@ -51,6 +51,8 @@ namespace Catch {
|
|||||||
|
|
||||||
void noMatchingTestCases(std::string const&) override {}
|
void noMatchingTestCases(std::string const&) override {}
|
||||||
|
|
||||||
|
void reportInvalidArguments(std::string const&) override {}
|
||||||
|
|
||||||
void testRunStarting(TestRunInfo const& _testRunInfo) override {
|
void testRunStarting(TestRunInfo const& _testRunInfo) override {
|
||||||
currentTestRunInfo = _testRunInfo;
|
currentTestRunInfo = _testRunInfo;
|
||||||
}
|
}
|
||||||
|
@@ -210,15 +210,11 @@ class Duration {
|
|||||||
static const uint64_t s_nanosecondsInASecond = 1000 * s_nanosecondsInAMillisecond;
|
static const uint64_t s_nanosecondsInASecond = 1000 * s_nanosecondsInAMillisecond;
|
||||||
static const uint64_t s_nanosecondsInAMinute = 60 * s_nanosecondsInASecond;
|
static const uint64_t s_nanosecondsInAMinute = 60 * s_nanosecondsInASecond;
|
||||||
|
|
||||||
uint64_t m_inNanoseconds;
|
double m_inNanoseconds;
|
||||||
Unit m_units;
|
Unit m_units;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit Duration(double inNanoseconds, Unit units = Unit::Auto)
|
explicit Duration(double inNanoseconds, Unit units = Unit::Auto)
|
||||||
: Duration(static_cast<uint64_t>(inNanoseconds), units) {
|
|
||||||
}
|
|
||||||
|
|
||||||
explicit Duration(uint64_t inNanoseconds, Unit units = Unit::Auto)
|
|
||||||
: m_inNanoseconds(inNanoseconds),
|
: m_inNanoseconds(inNanoseconds),
|
||||||
m_units(units) {
|
m_units(units) {
|
||||||
if (m_units == Unit::Auto) {
|
if (m_units == Unit::Auto) {
|
||||||
@@ -247,7 +243,7 @@ public:
|
|||||||
case Unit::Minutes:
|
case Unit::Minutes:
|
||||||
return m_inNanoseconds / static_cast<double>(s_nanosecondsInAMinute);
|
return m_inNanoseconds / static_cast<double>(s_nanosecondsInAMinute);
|
||||||
default:
|
default:
|
||||||
return static_cast<double>(m_inNanoseconds);
|
return m_inNanoseconds;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
auto unitsAsString() const -> std::string {
|
auto unitsAsString() const -> std::string {
|
||||||
@@ -383,6 +379,10 @@ void ConsoleReporter::noMatchingTestCases(std::string const& spec) {
|
|||||||
stream << "No test cases matched '" << spec << '\'' << std::endl;
|
stream << "No test cases matched '" << spec << '\'' << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ConsoleReporter::reportInvalidArguments(std::string const&arg){
|
||||||
|
stream << "Invalid Filter: " << arg << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
void ConsoleReporter::assertionStarting(AssertionInfo const&) {}
|
void ConsoleReporter::assertionStarting(AssertionInfo const&) {}
|
||||||
|
|
||||||
bool ConsoleReporter::assertionEnded(AssertionStats const& _assertionStats) {
|
bool ConsoleReporter::assertionEnded(AssertionStats const& _assertionStats) {
|
||||||
@@ -680,8 +680,10 @@ void ConsoleReporter::printSummaryDivider() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void ConsoleReporter::printTestFilters() {
|
void ConsoleReporter::printTestFilters() {
|
||||||
if (m_config->testSpec().hasFilters())
|
if (m_config->testSpec().hasFilters()) {
|
||||||
stream << Colour(Colour::BrightYellow) << "Filters: " << serializeFilters( m_config->getTestsOrTags() ) << '\n';
|
Colour guard(Colour::BrightYellow);
|
||||||
|
stream << "Filters: " << serializeFilters(m_config->getTestsOrTags()) << '\n';
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
CATCH_REGISTER_REPORTER("console", ConsoleReporter)
|
CATCH_REGISTER_REPORTER("console", ConsoleReporter)
|
||||||
|
@@ -32,6 +32,8 @@ namespace Catch {
|
|||||||
|
|
||||||
void noMatchingTestCases(std::string const& spec) override;
|
void noMatchingTestCases(std::string const& spec) override;
|
||||||
|
|
||||||
|
void reportInvalidArguments(std::string const&arg) override;
|
||||||
|
|
||||||
void assertionStarting(AssertionInfo const&) override;
|
void assertionStarting(AssertionInfo const&) override;
|
||||||
|
|
||||||
bool assertionEnded(AssertionStats const& _assertionStats) override;
|
bool assertionEnded(AssertionStats const& _assertionStats) override;
|
||||||
|
@@ -12,6 +12,7 @@
|
|||||||
|
|
||||||
#include "../internal/catch_tostring.h"
|
#include "../internal/catch_tostring.h"
|
||||||
#include "../internal/catch_reporter_registrars.hpp"
|
#include "../internal/catch_reporter_registrars.hpp"
|
||||||
|
#include "../internal/catch_text.h"
|
||||||
|
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
@@ -146,8 +147,8 @@ namespace Catch {
|
|||||||
for( auto const& child : groupNode.children )
|
for( auto const& child : groupNode.children )
|
||||||
writeTestCase( *child );
|
writeTestCase( *child );
|
||||||
|
|
||||||
xml.scopedElement( "system-out" ).writeText( trim( stdOutForSuite ), false );
|
xml.scopedElement( "system-out" ).writeText( trim( stdOutForSuite ), XmlFormatting::Newline );
|
||||||
xml.scopedElement( "system-err" ).writeText( trim( stdErrForSuite ), false );
|
xml.scopedElement( "system-err" ).writeText( trim( stdErrForSuite ), XmlFormatting::Newline );
|
||||||
}
|
}
|
||||||
|
|
||||||
void JunitReporter::writeTestCase( TestCaseNode const& testCaseNode ) {
|
void JunitReporter::writeTestCase( TestCaseNode const& testCaseNode ) {
|
||||||
@@ -196,9 +197,9 @@ namespace Catch {
|
|||||||
writeAssertions( sectionNode );
|
writeAssertions( sectionNode );
|
||||||
|
|
||||||
if( !sectionNode.stdOut.empty() )
|
if( !sectionNode.stdOut.empty() )
|
||||||
xml.scopedElement( "system-out" ).writeText( trim( sectionNode.stdOut ), false );
|
xml.scopedElement( "system-out" ).writeText( trim( sectionNode.stdOut ), XmlFormatting::Newline );
|
||||||
if( !sectionNode.stdErr.empty() )
|
if( !sectionNode.stdErr.empty() )
|
||||||
xml.scopedElement( "system-err" ).writeText( trim( sectionNode.stdErr ), false );
|
xml.scopedElement( "system-err" ).writeText( trim( sectionNode.stdErr ), XmlFormatting::Newline );
|
||||||
}
|
}
|
||||||
for( auto const& childNode : sectionNode.childSections )
|
for( auto const& childNode : sectionNode.childSections )
|
||||||
if( className.empty() )
|
if( className.empty() )
|
||||||
@@ -222,11 +223,7 @@ namespace Catch {
|
|||||||
elementName = "error";
|
elementName = "error";
|
||||||
break;
|
break;
|
||||||
case ResultWas::ExplicitFailure:
|
case ResultWas::ExplicitFailure:
|
||||||
elementName = "failure";
|
|
||||||
break;
|
|
||||||
case ResultWas::ExpressionFailed:
|
case ResultWas::ExpressionFailed:
|
||||||
elementName = "failure";
|
|
||||||
break;
|
|
||||||
case ResultWas::DidntThrowException:
|
case ResultWas::DidntThrowException:
|
||||||
elementName = "failure";
|
elementName = "failure";
|
||||||
break;
|
break;
|
||||||
@@ -244,10 +241,25 @@ namespace Catch {
|
|||||||
|
|
||||||
XmlWriter::ScopedElement e = xml.scopedElement( elementName );
|
XmlWriter::ScopedElement e = xml.scopedElement( elementName );
|
||||||
|
|
||||||
xml.writeAttribute( "message", result.getExpandedExpression() );
|
xml.writeAttribute( "message", result.getExpression() );
|
||||||
xml.writeAttribute( "type", result.getTestMacroName() );
|
xml.writeAttribute( "type", result.getTestMacroName() );
|
||||||
|
|
||||||
ReusableStringStream rss;
|
ReusableStringStream rss;
|
||||||
|
if (stats.totals.assertions.total() > 0) {
|
||||||
|
rss << "FAILED" << ":\n";
|
||||||
|
if (result.hasExpression()) {
|
||||||
|
rss << " ";
|
||||||
|
rss << result.getExpressionInMacro();
|
||||||
|
rss << '\n';
|
||||||
|
}
|
||||||
|
if (result.hasExpandedExpression()) {
|
||||||
|
rss << "with expansion:\n";
|
||||||
|
rss << Column(result.getExpandedExpression()).indent(2) << '\n';
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
rss << '\n';
|
||||||
|
}
|
||||||
|
|
||||||
if( !result.getMessage().empty() )
|
if( !result.getMessage().empty() )
|
||||||
rss << result.getMessage() << '\n';
|
rss << result.getMessage() << '\n';
|
||||||
for( auto const& msg : stats.infoMessages )
|
for( auto const& msg : stats.infoMessages )
|
||||||
@@ -255,7 +267,7 @@ namespace Catch {
|
|||||||
rss << msg.message << '\n';
|
rss << msg.message << '\n';
|
||||||
|
|
||||||
rss << "at " << result.getSourceInfo();
|
rss << "at " << result.getSourceInfo();
|
||||||
xml.writeText( rss.str(), false );
|
xml.writeText( rss.str(), XmlFormatting::Newline );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -42,6 +42,13 @@ namespace Catch {
|
|||||||
m_reporter->noMatchingTestCases( spec );
|
m_reporter->noMatchingTestCases( spec );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ListeningReporter::reportInvalidArguments(std::string const&arg){
|
||||||
|
for ( auto const& listener : m_listeners ) {
|
||||||
|
listener->reportInvalidArguments( arg );
|
||||||
|
}
|
||||||
|
m_reporter->reportInvalidArguments( arg );
|
||||||
|
}
|
||||||
|
|
||||||
#if defined(CATCH_CONFIG_ENABLE_BENCHMARKING)
|
#if defined(CATCH_CONFIG_ENABLE_BENCHMARKING)
|
||||||
void ListeningReporter::benchmarkPreparing( std::string const& name ) {
|
void ListeningReporter::benchmarkPreparing( std::string const& name ) {
|
||||||
for (auto const& listener : m_listeners) {
|
for (auto const& listener : m_listeners) {
|
||||||
|
@@ -29,6 +29,8 @@ namespace Catch {
|
|||||||
|
|
||||||
void noMatchingTestCases( std::string const& spec ) override;
|
void noMatchingTestCases( std::string const& spec ) override;
|
||||||
|
|
||||||
|
void reportInvalidArguments(std::string const&arg) override;
|
||||||
|
|
||||||
static std::set<Verbosity> getSupportedVerbosities();
|
static std::set<Verbosity> getSupportedVerbosities();
|
||||||
|
|
||||||
#if defined(CATCH_CONFIG_ENABLE_BENCHMARKING)
|
#if defined(CATCH_CONFIG_ENABLE_BENCHMARKING)
|
||||||
|
181
include/reporters/catch_reporter_sonarqube.hpp
Normal file
181
include/reporters/catch_reporter_sonarqube.hpp
Normal file
@@ -0,0 +1,181 @@
|
|||||||
|
/*
|
||||||
|
* Created by Daniel Garcia on 2018-12-04.
|
||||||
|
* Copyright Social Point SL. All rights reserved.
|
||||||
|
*
|
||||||
|
* Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||||
|
* file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||||
|
*/
|
||||||
|
#ifndef CATCH_REPORTER_SONARQUBE_HPP_INCLUDED
|
||||||
|
#define CATCH_REPORTER_SONARQUBE_HPP_INCLUDED
|
||||||
|
|
||||||
|
|
||||||
|
// Don't #include any Catch headers here - we can assume they are already
|
||||||
|
// included before this header.
|
||||||
|
// This is not good practice in general but is necessary in this case so this
|
||||||
|
// file can be distributed as a single header that works with the main
|
||||||
|
// Catch single header.
|
||||||
|
|
||||||
|
#include <map>
|
||||||
|
|
||||||
|
namespace Catch {
|
||||||
|
|
||||||
|
struct SonarQubeReporter : CumulativeReporterBase<SonarQubeReporter> {
|
||||||
|
|
||||||
|
SonarQubeReporter(ReporterConfig const& config)
|
||||||
|
: CumulativeReporterBase(config)
|
||||||
|
, xml(config.stream()) {
|
||||||
|
m_reporterPrefs.shouldRedirectStdOut = true;
|
||||||
|
m_reporterPrefs.shouldReportAllAssertions = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
~SonarQubeReporter() override;
|
||||||
|
|
||||||
|
static std::string getDescription() {
|
||||||
|
return "Reports test results in the Generic Test Data SonarQube XML format";
|
||||||
|
}
|
||||||
|
|
||||||
|
static std::set<Verbosity> getSupportedVerbosities() {
|
||||||
|
return { Verbosity::Normal };
|
||||||
|
}
|
||||||
|
|
||||||
|
void noMatchingTestCases(std::string const& /*spec*/) override {}
|
||||||
|
|
||||||
|
void testRunStarting(TestRunInfo const& testRunInfo) override {
|
||||||
|
CumulativeReporterBase::testRunStarting(testRunInfo);
|
||||||
|
xml.startElement("testExecutions");
|
||||||
|
xml.writeAttribute("version", "1");
|
||||||
|
}
|
||||||
|
|
||||||
|
void testGroupEnded(TestGroupStats const& testGroupStats) override {
|
||||||
|
CumulativeReporterBase::testGroupEnded(testGroupStats);
|
||||||
|
writeGroup(*m_testGroups.back());
|
||||||
|
}
|
||||||
|
|
||||||
|
void testRunEndedCumulative() override {
|
||||||
|
xml.endElement();
|
||||||
|
}
|
||||||
|
|
||||||
|
void writeGroup(TestGroupNode const& groupNode) {
|
||||||
|
std::map<std::string, TestGroupNode::ChildNodes> testsPerFile;
|
||||||
|
for(auto const& child : groupNode.children)
|
||||||
|
testsPerFile[child->value.testInfo.lineInfo.file].push_back(child);
|
||||||
|
|
||||||
|
for(auto const& kv : testsPerFile)
|
||||||
|
writeTestFile(kv.first.c_str(), kv.second);
|
||||||
|
}
|
||||||
|
|
||||||
|
void writeTestFile(const char* filename, TestGroupNode::ChildNodes const& testCaseNodes) {
|
||||||
|
XmlWriter::ScopedElement e = xml.scopedElement("file");
|
||||||
|
xml.writeAttribute("path", filename);
|
||||||
|
|
||||||
|
for(auto const& child : testCaseNodes)
|
||||||
|
writeTestCase(*child);
|
||||||
|
}
|
||||||
|
|
||||||
|
void writeTestCase(TestCaseNode const& testCaseNode) {
|
||||||
|
// All test cases have exactly one section - which represents the
|
||||||
|
// test case itself. That section may have 0-n nested sections
|
||||||
|
assert(testCaseNode.children.size() == 1);
|
||||||
|
SectionNode const& rootSection = *testCaseNode.children.front();
|
||||||
|
writeSection("", rootSection, testCaseNode.value.testInfo.okToFail());
|
||||||
|
}
|
||||||
|
|
||||||
|
void writeSection(std::string const& rootName, SectionNode const& sectionNode, bool okToFail) {
|
||||||
|
std::string name = trim(sectionNode.stats.sectionInfo.name);
|
||||||
|
if(!rootName.empty())
|
||||||
|
name = rootName + '/' + name;
|
||||||
|
|
||||||
|
if(!sectionNode.assertions.empty() || !sectionNode.stdOut.empty() || !sectionNode.stdErr.empty()) {
|
||||||
|
XmlWriter::ScopedElement e = xml.scopedElement("testCase");
|
||||||
|
xml.writeAttribute("name", name);
|
||||||
|
xml.writeAttribute("duration", static_cast<long>(sectionNode.stats.durationInSeconds * 1000));
|
||||||
|
|
||||||
|
writeAssertions(sectionNode, okToFail);
|
||||||
|
}
|
||||||
|
|
||||||
|
for(auto const& childNode : sectionNode.childSections)
|
||||||
|
writeSection(name, *childNode, okToFail);
|
||||||
|
}
|
||||||
|
|
||||||
|
void writeAssertions(SectionNode const& sectionNode, bool okToFail) {
|
||||||
|
for(auto const& assertion : sectionNode.assertions)
|
||||||
|
writeAssertion( assertion, okToFail);
|
||||||
|
}
|
||||||
|
|
||||||
|
void writeAssertion(AssertionStats const& stats, bool okToFail) {
|
||||||
|
AssertionResult const& result = stats.assertionResult;
|
||||||
|
if(!result.isOk()) {
|
||||||
|
std::string elementName;
|
||||||
|
if(okToFail) {
|
||||||
|
elementName = "skipped";
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
switch(result.getResultType()) {
|
||||||
|
case ResultWas::ThrewException:
|
||||||
|
case ResultWas::FatalErrorCondition:
|
||||||
|
elementName = "error";
|
||||||
|
break;
|
||||||
|
case ResultWas::ExplicitFailure:
|
||||||
|
elementName = "failure";
|
||||||
|
break;
|
||||||
|
case ResultWas::ExpressionFailed:
|
||||||
|
elementName = "failure";
|
||||||
|
break;
|
||||||
|
case ResultWas::DidntThrowException:
|
||||||
|
elementName = "failure";
|
||||||
|
break;
|
||||||
|
|
||||||
|
// We should never see these here:
|
||||||
|
case ResultWas::Info:
|
||||||
|
case ResultWas::Warning:
|
||||||
|
case ResultWas::Ok:
|
||||||
|
case ResultWas::Unknown:
|
||||||
|
case ResultWas::FailureBit:
|
||||||
|
case ResultWas::Exception:
|
||||||
|
elementName = "internalError";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
XmlWriter::ScopedElement e = xml.scopedElement(elementName);
|
||||||
|
|
||||||
|
ReusableStringStream messageRss;
|
||||||
|
messageRss << result.getTestMacroName() << "(" << result.getExpression() << ")";
|
||||||
|
xml.writeAttribute("message", messageRss.str());
|
||||||
|
|
||||||
|
ReusableStringStream textRss;
|
||||||
|
if (stats.totals.assertions.total() > 0) {
|
||||||
|
textRss << "FAILED:\n";
|
||||||
|
if (result.hasExpression()) {
|
||||||
|
textRss << "\t" << result.getExpressionInMacro() << "\n";
|
||||||
|
}
|
||||||
|
if (result.hasExpandedExpression()) {
|
||||||
|
textRss << "with expansion:\n\t" << result.getExpandedExpression() << "\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!result.getMessage().empty())
|
||||||
|
textRss << result.getMessage() << "\n";
|
||||||
|
|
||||||
|
for(auto const& msg : stats.infoMessages)
|
||||||
|
if(msg.type == ResultWas::Info)
|
||||||
|
textRss << msg.message << "\n";
|
||||||
|
|
||||||
|
textRss << "at " << result.getSourceInfo();
|
||||||
|
xml.writeText(textRss.str(), XmlFormatting::Newline);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
XmlWriter xml;
|
||||||
|
};
|
||||||
|
|
||||||
|
#ifdef CATCH_IMPL
|
||||||
|
SonarQubeReporter::~SonarQubeReporter() {}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
CATCH_REGISTER_REPORTER( "sonarqube", SonarQubeReporter )
|
||||||
|
|
||||||
|
} // end namespace Catch
|
||||||
|
|
||||||
|
#endif // CATCH_REPORTER_SONARQUBE_HPP_INCLUDED
|
@@ -193,9 +193,9 @@ namespace Catch {
|
|||||||
e.writeAttribute( "durationInSeconds", m_testCaseTimer.getElapsedSeconds() );
|
e.writeAttribute( "durationInSeconds", m_testCaseTimer.getElapsedSeconds() );
|
||||||
|
|
||||||
if( !testCaseStats.stdOut.empty() )
|
if( !testCaseStats.stdOut.empty() )
|
||||||
m_xml.scopedElement( "StdOut" ).writeText( trim( testCaseStats.stdOut ), false );
|
m_xml.scopedElement( "StdOut" ).writeText( trim( testCaseStats.stdOut ), XmlFormatting::Newline );
|
||||||
if( !testCaseStats.stdErr.empty() )
|
if( !testCaseStats.stdErr.empty() )
|
||||||
m_xml.scopedElement( "StdErr" ).writeText( trim( testCaseStats.stdErr ), false );
|
m_xml.scopedElement( "StdErr" ).writeText( trim( testCaseStats.stdErr ), XmlFormatting::Newline );
|
||||||
|
|
||||||
m_xml.endElement();
|
m_xml.endElement();
|
||||||
}
|
}
|
||||||
@@ -229,16 +229,16 @@ namespace Catch {
|
|||||||
m_xml.writeAttribute("samples", info.samples)
|
m_xml.writeAttribute("samples", info.samples)
|
||||||
.writeAttribute("resamples", info.resamples)
|
.writeAttribute("resamples", info.resamples)
|
||||||
.writeAttribute("iterations", info.iterations)
|
.writeAttribute("iterations", info.iterations)
|
||||||
.writeAttribute("clockResolution", static_cast<uint64_t>(info.clockResolution))
|
.writeAttribute("clockResolution", info.clockResolution)
|
||||||
.writeAttribute("estimatedDuration", static_cast<uint64_t>(info.estimatedDuration))
|
.writeAttribute("estimatedDuration", info.estimatedDuration)
|
||||||
.writeComment("All values in nano seconds");
|
.writeComment("All values in nano seconds");
|
||||||
}
|
}
|
||||||
|
|
||||||
void XmlReporter::benchmarkEnded(BenchmarkStats<> const& benchmarkStats) {
|
void XmlReporter::benchmarkEnded(BenchmarkStats<> const& benchmarkStats) {
|
||||||
m_xml.startElement("mean")
|
m_xml.startElement("mean")
|
||||||
.writeAttribute("value", static_cast<uint64_t>(benchmarkStats.mean.point.count()))
|
.writeAttribute("value", benchmarkStats.mean.point.count())
|
||||||
.writeAttribute("lowerBound", static_cast<uint64_t>(benchmarkStats.mean.lower_bound.count()))
|
.writeAttribute("lowerBound", benchmarkStats.mean.lower_bound.count())
|
||||||
.writeAttribute("upperBound", static_cast<uint64_t>(benchmarkStats.mean.upper_bound.count()))
|
.writeAttribute("upperBound", benchmarkStats.mean.upper_bound.count())
|
||||||
.writeAttribute("ci", benchmarkStats.mean.confidence_interval);
|
.writeAttribute("ci", benchmarkStats.mean.confidence_interval);
|
||||||
m_xml.endElement();
|
m_xml.endElement();
|
||||||
m_xml.startElement("standardDeviation")
|
m_xml.startElement("standardDeviation")
|
||||||
|
@@ -282,6 +282,7 @@ set(REPORTER_HEADERS
|
|||||||
${HEADER_DIR}/reporters/catch_reporter_tap.hpp
|
${HEADER_DIR}/reporters/catch_reporter_tap.hpp
|
||||||
${HEADER_DIR}/reporters/catch_reporter_teamcity.hpp
|
${HEADER_DIR}/reporters/catch_reporter_teamcity.hpp
|
||||||
${HEADER_DIR}/reporters/catch_reporter_xml.h
|
${HEADER_DIR}/reporters/catch_reporter_xml.h
|
||||||
|
${HEADER_DIR}/reporters/catch_reporter_sonarqube.hpp
|
||||||
)
|
)
|
||||||
set(REPORTER_SOURCES
|
set(REPORTER_SOURCES
|
||||||
${HEADER_DIR}/reporters/catch_reporter_bases.cpp
|
${HEADER_DIR}/reporters/catch_reporter_bases.cpp
|
||||||
@@ -435,11 +436,20 @@ set_tests_properties(FilenameAsTagsTest PROPERTIES PASS_REGULAR_EXPRESSION "\\[#
|
|||||||
add_test(NAME EscapeSpecialCharactersInTestNames COMMAND $<TARGET_FILE:SelfTest> "Test with special\\, characters \"in name")
|
add_test(NAME EscapeSpecialCharactersInTestNames COMMAND $<TARGET_FILE:SelfTest> "Test with special\\, characters \"in name")
|
||||||
set_tests_properties(EscapeSpecialCharactersInTestNames PROPERTIES PASS_REGULAR_EXPRESSION "1 assertion in 1 test case")
|
set_tests_properties(EscapeSpecialCharactersInTestNames PROPERTIES PASS_REGULAR_EXPRESSION "1 assertion in 1 test case")
|
||||||
|
|
||||||
add_test(NAME SpecialCharactersInTestNamesFromFile COMMAND $<TARGET_FILE:SelfTest> "-f ${CATCH_DIR}/projects/SelfTest/Misc/special-characters-in-file.input")
|
add_test(NAME TestsInFile::SimpleSpecs COMMAND $<TARGET_FILE:SelfTest> "-f ${CATCH_DIR}/projects/SelfTest/Misc/plain-old-tests.input")
|
||||||
set_tests_properties(SpecialCharactersInTestNamesFromFile PROPERTIES PASS_REGULAR_EXPRESSION "1 assertion in 1 test case")
|
set_tests_properties(TestsInFile::SimpleSpecs PROPERTIES PASS_REGULAR_EXPRESSION "6 assertions in 2 test cases")
|
||||||
|
|
||||||
add_test(NAME RunningTestsFromFile COMMAND $<TARGET_FILE:SelfTest> "-f ${CATCH_DIR}/projects/SelfTest/Misc/plain-old-tests.input")
|
add_test(NAME TestsInFile::EscapeSpecialCharacters COMMAND $<TARGET_FILE:SelfTest> "-f ${CATCH_DIR}/projects/SelfTest/Misc/special-characters-in-file.input")
|
||||||
set_tests_properties(RunningTestsFromFile PROPERTIES PASS_REGULAR_EXPRESSION "6 assertions in 2 test cases")
|
set_tests_properties(TestsInFile::EscapeSpecialCharacters PROPERTIES PASS_REGULAR_EXPRESSION "1 assertion in 1 test case")
|
||||||
|
|
||||||
|
# CTest does not allow us to create an AND of required regular expressions,
|
||||||
|
# so we have to split the test into 2 parts and look for parts of the expected
|
||||||
|
# output separately.
|
||||||
|
add_test(NAME TestsInFile::InvalidTestNames-1 COMMAND $<TARGET_FILE:SelfTest> "-f ${CATCH_DIR}/projects/SelfTest/Misc/invalid-test-names.input")
|
||||||
|
set_tests_properties(TestsInFile::InvalidTestNames-1 PROPERTIES PASS_REGULAR_EXPRESSION "Invalid Filter: \"Test with special, characters in \\\\\" name\"")
|
||||||
|
|
||||||
|
add_test(NAME TestsInFile::InvalidTestNames-2 COMMAND $<TARGET_FILE:SelfTest> "-f ${CATCH_DIR}/projects/SelfTest/Misc/invalid-test-names.input")
|
||||||
|
set_tests_properties(TestsInFile::InvalidTestNames-2 PROPERTIES PASS_REGULAR_EXPRESSION "No tests ran")
|
||||||
|
|
||||||
|
|
||||||
if (CATCH_USE_VALGRIND)
|
if (CATCH_USE_VALGRIND)
|
||||||
|
@@ -126,6 +126,24 @@ set_tests_properties(
|
|||||||
PASS_REGULAR_EXPRESSION "benchmark name samples iterations estimated"
|
PASS_REGULAR_EXPRESSION "benchmark name samples iterations estimated"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# This test touches windows.h, so it should only be compiled under msvc
|
||||||
|
if (MSVC)
|
||||||
|
# This test fails if it does not compile and succeeds otherwise
|
||||||
|
add_executable(WindowsHeader ${TESTS_DIR}/X90-WindowsHeaderInclusion.cpp)
|
||||||
|
set_property( TARGET WindowsHeader PROPERTY CXX_STANDARD 11 )
|
||||||
|
set_property( TARGET WindowsHeader PROPERTY CXX_STANDARD_REQUIRED ON )
|
||||||
|
set_property( TARGET WindowsHeader PROPERTY CXX_EXTENSIONS OFF )
|
||||||
|
target_include_directories( WindowsHeader PRIVATE ${SINGLE_INCLUDE_PATH} )
|
||||||
|
add_test(NAME WindowsHeader COMMAND WindowsHeader -r compact)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
add_executable(DebugBreakMacros ${TESTS_DIR}/X12-CustomDebugBreakMacro.cpp)
|
||||||
|
add_test(NAME DebugBreakMacros COMMAND DebugBreakMacros --break)
|
||||||
|
set_tests_properties(
|
||||||
|
DebugBreakMacros
|
||||||
|
PROPERTIES
|
||||||
|
PASS_REGULAR_EXPRESSION "Pretty please, break into debugger"
|
||||||
|
)
|
||||||
|
|
||||||
set( EXTRA_TEST_BINARIES
|
set( EXTRA_TEST_BINARIES
|
||||||
PrefixedMacros
|
PrefixedMacros
|
||||||
@@ -135,6 +153,7 @@ set( EXTRA_TEST_BINARIES
|
|||||||
FallbackStringifier
|
FallbackStringifier
|
||||||
DisableStringification
|
DisableStringification
|
||||||
BenchmarkingMacros
|
BenchmarkingMacros
|
||||||
|
DebugBreakMacros
|
||||||
)
|
)
|
||||||
|
|
||||||
# Shared config
|
# Shared config
|
||||||
@@ -145,3 +164,4 @@ foreach( test ${EXTRA_TEST_BINARIES} )
|
|||||||
target_include_directories( ${test} PRIVATE ${SINGLE_INCLUDE_PATH} )
|
target_include_directories( ${test} PRIVATE ${SINGLE_INCLUDE_PATH} )
|
||||||
endforeach()
|
endforeach()
|
||||||
|
|
||||||
|
|
||||||
|
17
projects/ExtraTests/X12-CustomDebugBreakMacro.cpp
Normal file
17
projects/ExtraTests/X12-CustomDebugBreakMacro.cpp
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
// X12-CustomDebugBreakMacro.cpp
|
||||||
|
// Test that user-defined `CATCH_BREAK_INTO_DEBUGGER` is respected and used.
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
void custom_debug_break() {
|
||||||
|
std::cerr << "Pretty please, break into debugger\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
#define CATCH_BREAK_INTO_DEBUGGER() custom_debug_break()
|
||||||
|
|
||||||
|
#define CATCH_CONFIG_MAIN
|
||||||
|
#include <catch2/catch.hpp>
|
||||||
|
|
||||||
|
TEST_CASE("Failing test that breaks into debugger", "[macros]") {
|
||||||
|
REQUIRE(1 == 2);
|
||||||
|
}
|
@@ -26,14 +26,6 @@ TEST_CASE("Benchmark factorial", "[benchmark]") {
|
|||||||
BENCHMARK("factorial 14") {
|
BENCHMARK("factorial 14") {
|
||||||
return factorial(14);
|
return factorial(14);
|
||||||
};
|
};
|
||||||
//
|
|
||||||
// BENCHMARK("factorial 20") {
|
|
||||||
// return factorial(20);
|
|
||||||
// };
|
|
||||||
//
|
|
||||||
// BENCHMARK("factorial 35") {
|
|
||||||
// return factorial(35);
|
|
||||||
// };
|
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("Benchmark containers", "[.][benchmark]") {
|
TEST_CASE("Benchmark containers", "[.][benchmark]") {
|
||||||
|
12
projects/ExtraTests/X90-WindowsHeaderInclusion.cpp
Normal file
12
projects/ExtraTests/X90-WindowsHeaderInclusion.cpp
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
// X90-WindowsHeaderInclusion.cpp
|
||||||
|
// Test that the Catch2 header compiles even after including windows.h
|
||||||
|
// without defining NOMINMAX first. As an FYI, if you do that, you are
|
||||||
|
// wrong.
|
||||||
|
|
||||||
|
#include <windows.h>
|
||||||
|
#define CATCH_CONFIG_MAIN
|
||||||
|
#include <catch2/catch.hpp>
|
||||||
|
|
||||||
|
TEST_CASE("Catch2 did survive compilation with windows.h", "[compile-test]") {
|
||||||
|
SUCCEED();
|
||||||
|
}
|
@@ -312,6 +312,8 @@ Condition.tests.cpp:<line number>: passed: 4 == ul for: 4 == 4
|
|||||||
Condition.tests.cpp:<line number>: passed: 5 == c for: 5 == 5
|
Condition.tests.cpp:<line number>: passed: 5 == c for: 5 == 5
|
||||||
Condition.tests.cpp:<line number>: passed: 6 == uc for: 6 == 6
|
Condition.tests.cpp:<line number>: passed: 6 == uc for: 6 == 6
|
||||||
Condition.tests.cpp:<line number>: passed: (std::numeric_limits<uint32_t>::max)() > ul for: 4294967295 (0x<hex digits>) > 4
|
Condition.tests.cpp:<line number>: passed: (std::numeric_limits<uint32_t>::max)() > ul for: 4294967295 (0x<hex digits>) > 4
|
||||||
|
Matchers.tests.cpp:<line number>: passed: testStringForMatching2(), !composed1 for: "some completely different text that contains one common word" not ( contains: "string" or contains: "random" )
|
||||||
|
Matchers.tests.cpp:<line number>: passed: testStringForMatching2(), composed2 for: "some completely different text that contains one common word" ( contains: "string" or contains: "random" or contains: "different" )
|
||||||
Matchers.tests.cpp:<line number>: failed: testStringForMatching(), Contains("not there", Catch::CaseSensitive::No) for: "this string contains 'abc' as a substring" contains: "not there" (case insensitive)
|
Matchers.tests.cpp:<line number>: failed: testStringForMatching(), Contains("not there", Catch::CaseSensitive::No) for: "this string contains 'abc' as a substring" contains: "not there" (case insensitive)
|
||||||
Matchers.tests.cpp:<line number>: failed: testStringForMatching(), Contains("STRING") for: "this string contains 'abc' as a substring" contains: "STRING"
|
Matchers.tests.cpp:<line number>: failed: testStringForMatching(), Contains("STRING") for: "this string contains 'abc' as a substring" contains: "STRING"
|
||||||
Generators.tests.cpp:<line number>: passed: elem % 2 == 1 for: 1 == 1
|
Generators.tests.cpp:<line number>: passed: elem % 2 == 1 for: 1 == 1
|
||||||
@@ -424,14 +426,15 @@ Matchers.tests.cpp:<line number>: passed: 11., !WithinAbs(10., 0.5) for: 11.0 no
|
|||||||
Matchers.tests.cpp:<line number>: passed: 10., !WithinAbs(11., 0.5) for: 10.0 not is within 0.5 of 11.0
|
Matchers.tests.cpp:<line number>: passed: 10., !WithinAbs(11., 0.5) for: 10.0 not is within 0.5 of 11.0
|
||||||
Matchers.tests.cpp:<line number>: passed: -10., WithinAbs(-10., 0.5) for: -10.0 is within 0.5 of -10.0
|
Matchers.tests.cpp:<line number>: passed: -10., WithinAbs(-10., 0.5) for: -10.0 is within 0.5 of -10.0
|
||||||
Matchers.tests.cpp:<line number>: passed: -10., WithinAbs(-9.6, 0.5) for: -10.0 is within 0.5 of -9.6
|
Matchers.tests.cpp:<line number>: passed: -10., WithinAbs(-9.6, 0.5) for: -10.0 is within 0.5 of -9.6
|
||||||
Matchers.tests.cpp:<line number>: passed: 1., WithinULP(1., 0) for: 1.0 is within 0 ULPs of 1.0 ([1.00000000000000000, 1.00000000000000000])
|
Matchers.tests.cpp:<line number>: passed: 1., WithinULP(1., 0) for: 1.0 is within 0 ULPs of 1.0000000000000000e+00 ([1.0000000000000000e+00, 1.0000000000000000e+00])
|
||||||
Matchers.tests.cpp:<line number>: passed: nextafter(1., 2.), WithinULP(1., 1) for: 1.0 is within 1 ULPs of 1.0 ([0.99999999999999989, 1.00000000000000022])
|
Matchers.tests.cpp:<line number>: passed: nextafter(1., 2.), WithinULP(1., 1) for: 1.0 is within 1 ULPs of 1.0000000000000000e+00 ([9.9999999999999989e-01, 1.0000000000000002e+00])
|
||||||
Matchers.tests.cpp:<line number>: passed: nextafter(1., 0.), WithinULP(1., 1) for: 1.0 is within 1 ULPs of 1.0 ([0.99999999999999989, 1.00000000000000022])
|
Matchers.tests.cpp:<line number>: passed: 0., WithinULP(nextafter(0., 1.), 1) for: 0.0 is within 1 ULPs of 4.9406564584124654e-324 ([0.0000000000000000e+00, 9.8813129168249309e-324])
|
||||||
Matchers.tests.cpp:<line number>: passed: nextafter(1., 2.), !WithinULP(1., 0) for: 1.0 not is within 0 ULPs of 1.0 ([1.00000000000000000, 1.00000000000000000])
|
Matchers.tests.cpp:<line number>: passed: 1., WithinULP(nextafter(1., 0.), 1) for: 1.0 is within 1 ULPs of 9.9999999999999989e-01 ([9.9999999999999978e-01, 1.0000000000000000e+00])
|
||||||
Matchers.tests.cpp:<line number>: passed: 1., WithinULP(1., 0) for: 1.0 is within 0 ULPs of 1.0 ([1.00000000000000000, 1.00000000000000000])
|
Matchers.tests.cpp:<line number>: passed: 1., !WithinULP(nextafter(1., 2.), 0) for: 1.0 not is within 0 ULPs of 1.0000000000000002e+00 ([1.0000000000000002e+00, 1.0000000000000002e+00])
|
||||||
Matchers.tests.cpp:<line number>: passed: -0., WithinULP(0., 0) for: -0.0 is within 0 ULPs of 0.0 ([0.00000000000000000, 0.00000000000000000])
|
Matchers.tests.cpp:<line number>: passed: 1., WithinULP(1., 0) for: 1.0 is within 0 ULPs of 1.0000000000000000e+00 ([1.0000000000000000e+00, 1.0000000000000000e+00])
|
||||||
Matchers.tests.cpp:<line number>: passed: 1., WithinAbs(1., 0.5) || WithinULP(2., 1) for: 1.0 ( is within 0.5 of 1.0 or is within 1 ULPs of 2.0 ([1.99999999999999978, 2.00000000000000044]) )
|
Matchers.tests.cpp:<line number>: passed: -0., WithinULP(0., 0) for: -0.0 is within 0 ULPs of 0.0000000000000000e+00 ([0.0000000000000000e+00, 0.0000000000000000e+00])
|
||||||
Matchers.tests.cpp:<line number>: passed: 1., WithinAbs(2., 0.5) || WithinULP(1., 0) for: 1.0 ( is within 0.5 of 2.0 or is within 0 ULPs of 1.0 ([1.00000000000000000, 1.00000000000000000]) )
|
Matchers.tests.cpp:<line number>: passed: 1., WithinAbs(1., 0.5) || WithinULP(2., 1) for: 1.0 ( is within 0.5 of 1.0 or is within 1 ULPs of 2.0000000000000000e+00 ([1.9999999999999998e+00, 2.0000000000000004e+00]) )
|
||||||
|
Matchers.tests.cpp:<line number>: passed: 1., WithinAbs(2., 0.5) || WithinULP(1., 0) for: 1.0 ( is within 0.5 of 2.0 or is within 0 ULPs of 1.0000000000000000e+00 ([1.0000000000000000e+00, 1.0000000000000000e+00]) )
|
||||||
Matchers.tests.cpp:<line number>: passed: 0.0001, WithinAbs(0., 0.001) || WithinRel(0., 0.1) for: 0.0001 ( is within 0.001 of 0.0 or and 0 are within 10% of each other )
|
Matchers.tests.cpp:<line number>: passed: 0.0001, WithinAbs(0., 0.001) || WithinRel(0., 0.1) for: 0.0001 ( is within 0.001 of 0.0 or and 0 are within 10% of each other )
|
||||||
Matchers.tests.cpp:<line number>: passed: WithinAbs(1., 0.)
|
Matchers.tests.cpp:<line number>: passed: WithinAbs(1., 0.)
|
||||||
Matchers.tests.cpp:<line number>: passed: WithinAbs(1., -1.), std::domain_error
|
Matchers.tests.cpp:<line number>: passed: WithinAbs(1., -1.), std::domain_error
|
||||||
@@ -453,14 +456,15 @@ Matchers.tests.cpp:<line number>: passed: 11.f, !WithinAbs(10.f, 0.5f) for: 11.0
|
|||||||
Matchers.tests.cpp:<line number>: passed: 10.f, !WithinAbs(11.f, 0.5f) for: 10.0f not is within 0.5 of 11.0
|
Matchers.tests.cpp:<line number>: passed: 10.f, !WithinAbs(11.f, 0.5f) for: 10.0f not is within 0.5 of 11.0
|
||||||
Matchers.tests.cpp:<line number>: passed: -10.f, WithinAbs(-10.f, 0.5f) for: -10.0f is within 0.5 of -10.0
|
Matchers.tests.cpp:<line number>: passed: -10.f, WithinAbs(-10.f, 0.5f) for: -10.0f is within 0.5 of -10.0
|
||||||
Matchers.tests.cpp:<line number>: passed: -10.f, WithinAbs(-9.6f, 0.5f) for: -10.0f is within 0.5 of -9.6000003815
|
Matchers.tests.cpp:<line number>: passed: -10.f, WithinAbs(-9.6f, 0.5f) for: -10.0f is within 0.5 of -9.6000003815
|
||||||
Matchers.tests.cpp:<line number>: passed: 1.f, WithinULP(1.f, 0) for: 1.0f is within 0 ULPs of 1.0f ([1.00000000000000000, 1.00000000000000000])
|
Matchers.tests.cpp:<line number>: passed: 1.f, WithinULP(1.f, 0) for: 1.0f is within 0 ULPs of 1.00000000e+00f ([1.00000000e+00, 1.00000000e+00])
|
||||||
Matchers.tests.cpp:<line number>: passed: nextafter(1.f, 2.f), WithinULP(1.f, 1) for: 1.0f is within 1 ULPs of 1.0f ([0.99999994039535522, 1.00000011920928955])
|
Matchers.tests.cpp:<line number>: passed: nextafter(1.f, 2.f), WithinULP(1.f, 1) for: 1.0f is within 1 ULPs of 1.00000000e+00f ([9.99999940e-01, 1.00000012e+00])
|
||||||
Matchers.tests.cpp:<line number>: passed: nextafter(1.f, 0.f), WithinULP(1.f, 1) for: 1.0f is within 1 ULPs of 1.0f ([0.99999994039535522, 1.00000011920928955])
|
Matchers.tests.cpp:<line number>: passed: 0.f, WithinULP(nextafter(0.f, 1.f), 1) for: 0.0f is within 1 ULPs of 1.40129846e-45f ([0.00000000e+00, 2.80259693e-45])
|
||||||
Matchers.tests.cpp:<line number>: passed: nextafter(1.f, 2.f), !WithinULP(1.f, 0) for: 1.0f not is within 0 ULPs of 1.0f ([1.00000000000000000, 1.00000000000000000])
|
Matchers.tests.cpp:<line number>: passed: 1.f, WithinULP(nextafter(1.f, 0.f), 1) for: 1.0f is within 1 ULPs of 9.99999940e-01f ([9.99999881e-01, 1.00000000e+00])
|
||||||
Matchers.tests.cpp:<line number>: passed: 1.f, WithinULP(1.f, 0) for: 1.0f is within 0 ULPs of 1.0f ([1.00000000000000000, 1.00000000000000000])
|
Matchers.tests.cpp:<line number>: passed: 1.f, !WithinULP(nextafter(1.f, 2.f), 0) for: 1.0f not is within 0 ULPs of 1.00000012e+00f ([1.00000012e+00, 1.00000012e+00])
|
||||||
Matchers.tests.cpp:<line number>: passed: -0.f, WithinULP(0.f, 0) for: -0.0f is within 0 ULPs of 0.0f ([0.00000000000000000, 0.00000000000000000])
|
Matchers.tests.cpp:<line number>: passed: 1.f, WithinULP(1.f, 0) for: 1.0f is within 0 ULPs of 1.00000000e+00f ([1.00000000e+00, 1.00000000e+00])
|
||||||
Matchers.tests.cpp:<line number>: passed: 1.f, WithinAbs(1.f, 0.5) || WithinULP(1.f, 1) for: 1.0f ( is within 0.5 of 1.0 or is within 1 ULPs of 1.0f ([0.99999994039535522, 1.00000011920928955]) )
|
Matchers.tests.cpp:<line number>: passed: -0.f, WithinULP(0.f, 0) for: -0.0f is within 0 ULPs of 0.00000000e+00f ([0.00000000e+00, 0.00000000e+00])
|
||||||
Matchers.tests.cpp:<line number>: passed: 1.f, WithinAbs(2.f, 0.5) || WithinULP(1.f, 0) for: 1.0f ( is within 0.5 of 2.0 or is within 0 ULPs of 1.0f ([1.00000000000000000, 1.00000000000000000]) )
|
Matchers.tests.cpp:<line number>: passed: 1.f, WithinAbs(1.f, 0.5) || WithinULP(1.f, 1) for: 1.0f ( is within 0.5 of 1.0 or is within 1 ULPs of 1.00000000e+00f ([9.99999940e-01, 1.00000012e+00]) )
|
||||||
|
Matchers.tests.cpp:<line number>: passed: 1.f, WithinAbs(2.f, 0.5) || WithinULP(1.f, 0) for: 1.0f ( is within 0.5 of 2.0 or is within 0 ULPs of 1.00000000e+00f ([1.00000000e+00, 1.00000000e+00]) )
|
||||||
Matchers.tests.cpp:<line number>: passed: 0.0001f, WithinAbs(0.f, 0.001f) || WithinRel(0.f, 0.1f) for: 0.0001f ( is within 0.001 of 0.0 or and 0 are within 10% of each other )
|
Matchers.tests.cpp:<line number>: passed: 0.0001f, WithinAbs(0.f, 0.001f) || WithinRel(0.f, 0.1f) for: 0.0001f ( is within 0.001 of 0.0 or and 0 are within 10% of each other )
|
||||||
Matchers.tests.cpp:<line number>: passed: WithinAbs(1.f, 0.f)
|
Matchers.tests.cpp:<line number>: passed: WithinAbs(1.f, 0.f)
|
||||||
Matchers.tests.cpp:<line number>: passed: WithinAbs(1.f, -1.f), std::domain_error
|
Matchers.tests.cpp:<line number>: passed: WithinAbs(1.f, -1.f), std::domain_error
|
||||||
@@ -629,6 +633,74 @@ GeneratorsImpl.tests.cpp:<line number>: passed: gen.get() == 2 for: 2 == 2
|
|||||||
GeneratorsImpl.tests.cpp:<line number>: passed: gen.next() for: true
|
GeneratorsImpl.tests.cpp:<line number>: passed: gen.next() for: true
|
||||||
GeneratorsImpl.tests.cpp:<line number>: passed: gen.get() == 5 for: 5 == 5
|
GeneratorsImpl.tests.cpp:<line number>: passed: gen.get() == 5 for: 5 == 5
|
||||||
GeneratorsImpl.tests.cpp:<line number>: passed: !(gen.next()) for: !false
|
GeneratorsImpl.tests.cpp:<line number>: passed: !(gen.next()) for: !false
|
||||||
|
GeneratorsImpl.tests.cpp:<line number>: passed: gen.get() == Approx(expected) for: -1.0 == Approx( -1.0 ) with 1 message: 'Current expected value is -1'
|
||||||
|
GeneratorsImpl.tests.cpp:<line number>: passed: gen.next() for: true with 1 message: 'Current expected value is -1'
|
||||||
|
GeneratorsImpl.tests.cpp:<line number>: passed: gen.get() == Approx(expected) for: -0.9 == Approx( -0.9 ) with 1 message: 'Current expected value is -0.9'
|
||||||
|
GeneratorsImpl.tests.cpp:<line number>: passed: gen.next() for: true with 1 message: 'Current expected value is -0.9'
|
||||||
|
GeneratorsImpl.tests.cpp:<line number>: passed: gen.get() == Approx(expected) for: -0.8 == Approx( -0.8 ) with 1 message: 'Current expected value is -0.8'
|
||||||
|
GeneratorsImpl.tests.cpp:<line number>: passed: gen.next() for: true with 1 message: 'Current expected value is -0.8'
|
||||||
|
GeneratorsImpl.tests.cpp:<line number>: passed: gen.get() == Approx(expected) for: -0.7 == Approx( -0.7 ) with 1 message: 'Current expected value is -0.7'
|
||||||
|
GeneratorsImpl.tests.cpp:<line number>: passed: gen.next() for: true with 1 message: 'Current expected value is -0.7'
|
||||||
|
GeneratorsImpl.tests.cpp:<line number>: passed: gen.get() == Approx(expected) for: -0.6 == Approx( -0.6 ) with 1 message: 'Current expected value is -0.6'
|
||||||
|
GeneratorsImpl.tests.cpp:<line number>: passed: gen.next() for: true with 1 message: 'Current expected value is -0.6'
|
||||||
|
GeneratorsImpl.tests.cpp:<line number>: passed: gen.get() == Approx(expected) for: -0.5 == Approx( -0.5 ) with 1 message: 'Current expected value is -0.5'
|
||||||
|
GeneratorsImpl.tests.cpp:<line number>: passed: gen.next() for: true with 1 message: 'Current expected value is -0.5'
|
||||||
|
GeneratorsImpl.tests.cpp:<line number>: passed: gen.get() == Approx(expected) for: -0.4 == Approx( -0.4 ) with 1 message: 'Current expected value is -0.4'
|
||||||
|
GeneratorsImpl.tests.cpp:<line number>: passed: gen.next() for: true with 1 message: 'Current expected value is -0.4'
|
||||||
|
GeneratorsImpl.tests.cpp:<line number>: passed: gen.get() == Approx(expected) for: -0.3 == Approx( -0.3 ) with 1 message: 'Current expected value is -0.3'
|
||||||
|
GeneratorsImpl.tests.cpp:<line number>: passed: gen.next() for: true with 1 message: 'Current expected value is -0.3'
|
||||||
|
GeneratorsImpl.tests.cpp:<line number>: passed: gen.get() == Approx(expected) for: -0.2 == Approx( -0.2 ) with 1 message: 'Current expected value is -0.2'
|
||||||
|
GeneratorsImpl.tests.cpp:<line number>: passed: gen.next() for: true with 1 message: 'Current expected value is -0.2'
|
||||||
|
GeneratorsImpl.tests.cpp:<line number>: passed: gen.get() == Approx(expected) for: -0.1 == Approx( -0.1 ) with 1 message: 'Current expected value is -0.1'
|
||||||
|
GeneratorsImpl.tests.cpp:<line number>: passed: gen.next() for: true with 1 message: 'Current expected value is -0.1'
|
||||||
|
GeneratorsImpl.tests.cpp:<line number>: passed: gen.get() == Approx(expected) for: -0.0 == Approx( -0.0 ) with 1 message: 'Current expected value is -1.38778e-16'
|
||||||
|
GeneratorsImpl.tests.cpp:<line number>: passed: gen.next() for: true with 1 message: 'Current expected value is -1.38778e-16'
|
||||||
|
GeneratorsImpl.tests.cpp:<line number>: passed: gen.get() == Approx(expected) for: 0.1 == Approx( 0.1 ) with 1 message: 'Current expected value is 0.1'
|
||||||
|
GeneratorsImpl.tests.cpp:<line number>: passed: gen.next() for: true with 1 message: 'Current expected value is 0.1'
|
||||||
|
GeneratorsImpl.tests.cpp:<line number>: passed: gen.get() == Approx(expected) for: 0.2 == Approx( 0.2 ) with 1 message: 'Current expected value is 0.2'
|
||||||
|
GeneratorsImpl.tests.cpp:<line number>: passed: gen.next() for: true with 1 message: 'Current expected value is 0.2'
|
||||||
|
GeneratorsImpl.tests.cpp:<line number>: passed: gen.get() == Approx(expected) for: 0.3 == Approx( 0.3 ) with 1 message: 'Current expected value is 0.3'
|
||||||
|
GeneratorsImpl.tests.cpp:<line number>: passed: gen.next() for: true with 1 message: 'Current expected value is 0.3'
|
||||||
|
GeneratorsImpl.tests.cpp:<line number>: passed: gen.get() == Approx(expected) for: 0.4 == Approx( 0.4 ) with 1 message: 'Current expected value is 0.4'
|
||||||
|
GeneratorsImpl.tests.cpp:<line number>: passed: gen.next() for: true with 1 message: 'Current expected value is 0.4'
|
||||||
|
GeneratorsImpl.tests.cpp:<line number>: passed: gen.get() == Approx(expected) for: 0.5 == Approx( 0.5 ) with 1 message: 'Current expected value is 0.5'
|
||||||
|
GeneratorsImpl.tests.cpp:<line number>: passed: gen.next() for: true with 1 message: 'Current expected value is 0.5'
|
||||||
|
GeneratorsImpl.tests.cpp:<line number>: passed: gen.get() == Approx(expected) for: 0.6 == Approx( 0.6 ) with 1 message: 'Current expected value is 0.6'
|
||||||
|
GeneratorsImpl.tests.cpp:<line number>: passed: gen.next() for: true with 1 message: 'Current expected value is 0.6'
|
||||||
|
GeneratorsImpl.tests.cpp:<line number>: passed: gen.get() == Approx(expected) for: 0.7 == Approx( 0.7 ) with 1 message: 'Current expected value is 0.7'
|
||||||
|
GeneratorsImpl.tests.cpp:<line number>: passed: gen.next() for: true with 1 message: 'Current expected value is 0.7'
|
||||||
|
GeneratorsImpl.tests.cpp:<line number>: passed: gen.get() == Approx(expected) for: 0.8 == Approx( 0.8 ) with 1 message: 'Current expected value is 0.8'
|
||||||
|
GeneratorsImpl.tests.cpp:<line number>: passed: gen.next() for: true with 1 message: 'Current expected value is 0.8'
|
||||||
|
GeneratorsImpl.tests.cpp:<line number>: passed: gen.get() == Approx(expected) for: 0.9 == Approx( 0.9 ) with 1 message: 'Current expected value is 0.9'
|
||||||
|
GeneratorsImpl.tests.cpp:<line number>: passed: gen.next() for: true with 1 message: 'Current expected value is 0.9'
|
||||||
|
GeneratorsImpl.tests.cpp:<line number>: passed: gen.get() == Approx( rangeEnd ) for: 1.0 == Approx( 1.0 )
|
||||||
|
GeneratorsImpl.tests.cpp:<line number>: passed: !(gen.next()) for: !false
|
||||||
|
GeneratorsImpl.tests.cpp:<line number>: passed: gen.get() == Approx(expected) for: -1.0 == Approx( -1.0 ) with 1 message: 'Current expected value is -1'
|
||||||
|
GeneratorsImpl.tests.cpp:<line number>: passed: gen.next() for: true with 1 message: 'Current expected value is -1'
|
||||||
|
GeneratorsImpl.tests.cpp:<line number>: passed: gen.get() == Approx(expected) for: -0.7 == Approx( -0.7 ) with 1 message: 'Current expected value is -0.7'
|
||||||
|
GeneratorsImpl.tests.cpp:<line number>: passed: gen.next() for: true with 1 message: 'Current expected value is -0.7'
|
||||||
|
GeneratorsImpl.tests.cpp:<line number>: passed: gen.get() == Approx(expected) for: -0.4 == Approx( -0.4 ) with 1 message: 'Current expected value is -0.4'
|
||||||
|
GeneratorsImpl.tests.cpp:<line number>: passed: gen.next() for: true with 1 message: 'Current expected value is -0.4'
|
||||||
|
GeneratorsImpl.tests.cpp:<line number>: passed: gen.get() == Approx(expected) for: -0.1 == Approx( -0.1 ) with 1 message: 'Current expected value is -0.1'
|
||||||
|
GeneratorsImpl.tests.cpp:<line number>: passed: gen.next() for: true with 1 message: 'Current expected value is -0.1'
|
||||||
|
GeneratorsImpl.tests.cpp:<line number>: passed: gen.get() == Approx(expected) for: 0.2 == Approx( 0.2 ) with 1 message: 'Current expected value is 0.2'
|
||||||
|
GeneratorsImpl.tests.cpp:<line number>: passed: gen.next() for: true with 1 message: 'Current expected value is 0.2'
|
||||||
|
GeneratorsImpl.tests.cpp:<line number>: passed: gen.get() == Approx(expected) for: 0.5 == Approx( 0.5 ) with 1 message: 'Current expected value is 0.5'
|
||||||
|
GeneratorsImpl.tests.cpp:<line number>: passed: gen.next() for: true with 1 message: 'Current expected value is 0.5'
|
||||||
|
GeneratorsImpl.tests.cpp:<line number>: passed: !(gen.next()) for: !false
|
||||||
|
GeneratorsImpl.tests.cpp:<line number>: passed: gen.get() == Approx(expected) for: -1.0 == Approx( -1.0 ) with 1 message: 'Current expected value is -1'
|
||||||
|
GeneratorsImpl.tests.cpp:<line number>: passed: gen.next() for: true with 1 message: 'Current expected value is -1'
|
||||||
|
GeneratorsImpl.tests.cpp:<line number>: passed: gen.get() == Approx(expected) for: -0.7 == Approx( -0.7 ) with 1 message: 'Current expected value is -0.7'
|
||||||
|
GeneratorsImpl.tests.cpp:<line number>: passed: gen.next() for: true with 1 message: 'Current expected value is -0.7'
|
||||||
|
GeneratorsImpl.tests.cpp:<line number>: passed: gen.get() == Approx(expected) for: -0.4 == Approx( -0.4 ) with 1 message: 'Current expected value is -0.4'
|
||||||
|
GeneratorsImpl.tests.cpp:<line number>: passed: gen.next() for: true with 1 message: 'Current expected value is -0.4'
|
||||||
|
GeneratorsImpl.tests.cpp:<line number>: passed: gen.get() == Approx(expected) for: -0.1 == Approx( -0.1 ) with 1 message: 'Current expected value is -0.1'
|
||||||
|
GeneratorsImpl.tests.cpp:<line number>: passed: gen.next() for: true with 1 message: 'Current expected value is -0.1'
|
||||||
|
GeneratorsImpl.tests.cpp:<line number>: passed: gen.get() == Approx(expected) for: 0.2 == Approx( 0.2 ) with 1 message: 'Current expected value is 0.2'
|
||||||
|
GeneratorsImpl.tests.cpp:<line number>: passed: gen.next() for: true with 1 message: 'Current expected value is 0.2'
|
||||||
|
GeneratorsImpl.tests.cpp:<line number>: passed: gen.get() == Approx(expected) for: 0.5 == Approx( 0.5 ) with 1 message: 'Current expected value is 0.5'
|
||||||
|
GeneratorsImpl.tests.cpp:<line number>: passed: gen.next() for: true with 1 message: 'Current expected value is 0.5'
|
||||||
|
GeneratorsImpl.tests.cpp:<line number>: passed: !(gen.next()) for: !false
|
||||||
GeneratorsImpl.tests.cpp:<line number>: passed: gen.get() == 5 for: 5 == 5
|
GeneratorsImpl.tests.cpp:<line number>: passed: gen.get() == 5 for: 5 == 5
|
||||||
GeneratorsImpl.tests.cpp:<line number>: passed: gen.next() for: true
|
GeneratorsImpl.tests.cpp:<line number>: passed: gen.next() for: true
|
||||||
GeneratorsImpl.tests.cpp:<line number>: passed: gen.get() == 2 for: 2 == 2
|
GeneratorsImpl.tests.cpp:<line number>: passed: gen.get() == 2 for: 2 == 2
|
||||||
@@ -957,6 +1029,12 @@ CmdLine.tests.cpp:<line number>: passed: spec.matches( fakeTestCase( " aardvark
|
|||||||
CmdLine.tests.cpp:<line number>: passed: spec.matches( fakeTestCase( " aardvark " ) ) for: true
|
CmdLine.tests.cpp:<line number>: passed: spec.matches( fakeTestCase( " aardvark " ) ) for: true
|
||||||
CmdLine.tests.cpp:<line number>: passed: spec.matches( fakeTestCase( "aardvark " ) ) for: true
|
CmdLine.tests.cpp:<line number>: passed: spec.matches( fakeTestCase( "aardvark " ) ) for: true
|
||||||
CmdLine.tests.cpp:<line number>: passed: spec.matches( fakeTestCase( "aardvark" ) ) for: true
|
CmdLine.tests.cpp:<line number>: passed: spec.matches( fakeTestCase( "aardvark" ) ) for: true
|
||||||
|
CmdLine.tests.cpp:<line number>: passed: spec.matches(fakeTestCase("hidden and foo", "[.][foo]")) for: true
|
||||||
|
CmdLine.tests.cpp:<line number>: passed: !(spec.matches(fakeTestCase("only foo", "[foo]"))) for: !false
|
||||||
|
CmdLine.tests.cpp:<line number>: passed: !(spec.matches(fakeTestCase("hidden and foo", "[.][foo]"))) for: !false
|
||||||
|
CmdLine.tests.cpp:<line number>: passed: !(spec.matches(fakeTestCase("only foo", "[foo]"))) for: !false
|
||||||
|
CmdLine.tests.cpp:<line number>: passed: !(spec.matches(fakeTestCase("only hidden", "[.]"))) for: !false
|
||||||
|
CmdLine.tests.cpp:<line number>: passed: spec.matches(fakeTestCase("neither foo nor hidden", "[bar]")) for: true
|
||||||
Condition.tests.cpp:<line number>: passed: p == 0 for: 0 == 0
|
Condition.tests.cpp:<line number>: passed: p == 0 for: 0 == 0
|
||||||
Condition.tests.cpp:<line number>: passed: p == pNULL for: 0 == 0
|
Condition.tests.cpp:<line number>: passed: p == pNULL for: 0 == 0
|
||||||
Condition.tests.cpp:<line number>: passed: p != 0 for: 0x<hex digits> != 0
|
Condition.tests.cpp:<line number>: passed: p != 0 for: 0x<hex digits> != 0
|
||||||
@@ -1010,6 +1088,16 @@ CmdLine.tests.cpp:<line number>: passed: cli.parse({"test", "-x", "2"}) for: {?}
|
|||||||
CmdLine.tests.cpp:<line number>: passed: config.abortAfter == 2 for: 2 == 2
|
CmdLine.tests.cpp:<line number>: passed: config.abortAfter == 2 for: 2 == 2
|
||||||
CmdLine.tests.cpp:<line number>: passed: !result for: true
|
CmdLine.tests.cpp:<line number>: passed: !result for: true
|
||||||
CmdLine.tests.cpp:<line number>: passed: result.errorMessage(), Contains("convert") && Contains("oops") for: "Unable to convert 'oops' to destination type" ( contains: "convert" and contains: "oops" )
|
CmdLine.tests.cpp:<line number>: passed: result.errorMessage(), Contains("convert") && Contains("oops") for: "Unable to convert 'oops' to destination type" ( contains: "convert" and contains: "oops" )
|
||||||
|
CmdLine.tests.cpp:<line number>: passed: cli.parse({"test", "--wait-for-keypress", std::get<0>(input)}) for: {?}
|
||||||
|
CmdLine.tests.cpp:<line number>: passed: config.waitForKeypress == std::get<1>(input) for: 0 == 0
|
||||||
|
CmdLine.tests.cpp:<line number>: passed: cli.parse({"test", "--wait-for-keypress", std::get<0>(input)}) for: {?}
|
||||||
|
CmdLine.tests.cpp:<line number>: passed: config.waitForKeypress == std::get<1>(input) for: 1 == 1
|
||||||
|
CmdLine.tests.cpp:<line number>: passed: cli.parse({"test", "--wait-for-keypress", std::get<0>(input)}) for: {?}
|
||||||
|
CmdLine.tests.cpp:<line number>: passed: config.waitForKeypress == std::get<1>(input) for: 2 == 2
|
||||||
|
CmdLine.tests.cpp:<line number>: passed: cli.parse({"test", "--wait-for-keypress", std::get<0>(input)}) for: {?}
|
||||||
|
CmdLine.tests.cpp:<line number>: passed: config.waitForKeypress == std::get<1>(input) for: 3 == 3
|
||||||
|
CmdLine.tests.cpp:<line number>: passed: !result for: true
|
||||||
|
CmdLine.tests.cpp:<line number>: passed: result.errorMessage(), Contains("never") && Contains("both") for: "keypress argument must be one of: never, start, exit or both. 'sometimes' not recognised" ( contains: "never" and contains: "both" )
|
||||||
CmdLine.tests.cpp:<line number>: passed: cli.parse({"test", "-e"}) for: {?}
|
CmdLine.tests.cpp:<line number>: passed: cli.parse({"test", "-e"}) for: {?}
|
||||||
CmdLine.tests.cpp:<line number>: passed: config.noThrow for: true
|
CmdLine.tests.cpp:<line number>: passed: config.noThrow for: true
|
||||||
CmdLine.tests.cpp:<line number>: passed: cli.parse({"test", "--nothrow"}) for: {?}
|
CmdLine.tests.cpp:<line number>: passed: cli.parse({"test", "--nothrow"}) for: {?}
|
||||||
@@ -1040,6 +1128,8 @@ CmdLine.tests.cpp:<line number>: passed: cli.parse({ "test", "--benchmark-confid
|
|||||||
CmdLine.tests.cpp:<line number>: passed: config.benchmarkConfidenceInterval == Catch::Detail::Approx(0.99) for: 0.99 == Approx( 0.99 )
|
CmdLine.tests.cpp:<line number>: passed: config.benchmarkConfidenceInterval == Catch::Detail::Approx(0.99) for: 0.99 == Approx( 0.99 )
|
||||||
CmdLine.tests.cpp:<line number>: passed: cli.parse({ "test", "--benchmark-no-analysis" }) for: {?}
|
CmdLine.tests.cpp:<line number>: passed: cli.parse({ "test", "--benchmark-no-analysis" }) for: {?}
|
||||||
CmdLine.tests.cpp:<line number>: passed: config.benchmarkNoAnalysis for: true
|
CmdLine.tests.cpp:<line number>: passed: config.benchmarkNoAnalysis for: true
|
||||||
|
CmdLine.tests.cpp:<line number>: passed: cli.parse({ "test", "--benchmark-warmup-time=10" }) for: {?}
|
||||||
|
CmdLine.tests.cpp:<line number>: passed: config.benchmarkWarmupTime == 10 for: 10 == 10
|
||||||
Misc.tests.cpp:<line number>: passed: std::tuple_size<TestType>::value >= 1 for: 3 >= 1
|
Misc.tests.cpp:<line number>: passed: std::tuple_size<TestType>::value >= 1 for: 3 >= 1
|
||||||
Misc.tests.cpp:<line number>: passed: std::tuple_size<TestType>::value >= 1 for: 2 >= 1
|
Misc.tests.cpp:<line number>: passed: std::tuple_size<TestType>::value >= 1 for: 2 >= 1
|
||||||
Misc.tests.cpp:<line number>: passed: std::tuple_size<TestType>::value >= 1 for: 1 >= 1
|
Misc.tests.cpp:<line number>: passed: std::tuple_size<TestType>::value >= 1 for: 1 >= 1
|
||||||
@@ -1093,37 +1183,32 @@ Matchers.tests.cpp:<line number>: passed: testStringForMatching(), EndsWith("sub
|
|||||||
Matchers.tests.cpp:<line number>: passed: testStringForMatching(), EndsWith(" SuBsTrInG", Catch::CaseSensitive::No) for: "this string contains 'abc' as a substring" ends with: " substring" (case insensitive)
|
Matchers.tests.cpp:<line number>: passed: testStringForMatching(), EndsWith(" SuBsTrInG", Catch::CaseSensitive::No) for: "this string contains 'abc' as a substring" ends with: " substring" (case insensitive)
|
||||||
String.tests.cpp:<line number>: passed: empty.empty() for: true
|
String.tests.cpp:<line number>: passed: empty.empty() for: true
|
||||||
String.tests.cpp:<line number>: passed: empty.size() == 0 for: 0 == 0
|
String.tests.cpp:<line number>: passed: empty.size() == 0 for: 0 == 0
|
||||||
|
String.tests.cpp:<line number>: passed: empty.isNullTerminated() for: true
|
||||||
String.tests.cpp:<line number>: passed: std::strcmp( empty.c_str(), "" ) == 0 for: 0 == 0
|
String.tests.cpp:<line number>: passed: std::strcmp( empty.c_str(), "" ) == 0 for: 0 == 0
|
||||||
String.tests.cpp:<line number>: passed: s.empty() == false for: false == false
|
String.tests.cpp:<line number>: passed: s.empty() == false for: false == false
|
||||||
String.tests.cpp:<line number>: passed: s.size() == 5 for: 5 == 5
|
String.tests.cpp:<line number>: passed: s.size() == 5 for: 5 == 5
|
||||||
String.tests.cpp:<line number>: passed: isSubstring( s ) == false for: false == false
|
String.tests.cpp:<line number>: passed: s.isNullTerminated() for: true
|
||||||
String.tests.cpp:<line number>: passed: std::strcmp( rawChars, "hello" ) == 0 for: 0 == 0
|
String.tests.cpp:<line number>: passed: std::strcmp( rawChars, "hello" ) == 0 for: 0 == 0
|
||||||
String.tests.cpp:<line number>: passed: isOwned( s ) == false for: false == false
|
String.tests.cpp:<line number>: passed: s.c_str()
|
||||||
String.tests.cpp:<line number>: passed: s.c_str() == rawChars for: "hello" == "hello"
|
String.tests.cpp:<line number>: passed: s.c_str() == rawChars for: "hello" == "hello"
|
||||||
String.tests.cpp:<line number>: passed: isOwned( s ) == false for: false == false
|
String.tests.cpp:<line number>: passed: s.data() == rawChars for: "hello" == "hello"
|
||||||
String.tests.cpp:<line number>: passed: original == "original"
|
String.tests.cpp:<line number>: passed: original == "original"
|
||||||
String.tests.cpp:<line number>: passed: isSubstring( original ) for: true
|
String.tests.cpp:<line number>: passed: !(original.isNullTerminated()) for: !false
|
||||||
String.tests.cpp:<line number>: passed: isOwned( original ) == false for: false == false
|
String.tests.cpp:<line number>: passed: original.c_str()
|
||||||
String.tests.cpp:<line number>: passed: isOwned( original ) for: true
|
String.tests.cpp:<line number>: passed: original.data()
|
||||||
String.tests.cpp:<line number>: passed: ss.empty() == false for: false == false
|
String.tests.cpp:<line number>: passed: ss.empty() == false for: false == false
|
||||||
String.tests.cpp:<line number>: passed: ss.size() == 5 for: 5 == 5
|
String.tests.cpp:<line number>: passed: ss.size() == 5 for: 5 == 5
|
||||||
String.tests.cpp:<line number>: passed: std::strcmp( ss.c_str(), "hello" ) == 0 for: 0 == 0
|
String.tests.cpp:<line number>: passed: std::strncmp( ss.data(), "hello", 5 ) == 0 for: 0 == 0
|
||||||
String.tests.cpp:<line number>: passed: ss == "hello" for: hello == "hello"
|
String.tests.cpp:<line number>: passed: ss == "hello" for: hello == "hello"
|
||||||
String.tests.cpp:<line number>: passed: isSubstring( ss ) for: true
|
|
||||||
String.tests.cpp:<line number>: passed: isOwned( ss ) == false for: false == false
|
|
||||||
String.tests.cpp:<line number>: passed: rawChars == s.currentData() for: "hello world!" == "hello world!"
|
|
||||||
String.tests.cpp:<line number>: passed: ss.c_str() != rawChars for: "hello" != "hello world!"
|
|
||||||
String.tests.cpp:<line number>: passed: isOwned( ss ) for: true
|
|
||||||
String.tests.cpp:<line number>: passed: isOwned(ss) == false for: false == false
|
|
||||||
String.tests.cpp:<line number>: passed: ss == "hello" for: hello == "hello"
|
|
||||||
String.tests.cpp:<line number>: passed: rawChars == ss.currentData() for: "hello world!" == "hello world!"
|
|
||||||
String.tests.cpp:<line number>: passed: ss.size() == 6 for: 6 == 6
|
String.tests.cpp:<line number>: passed: ss.size() == 6 for: 6 == 6
|
||||||
String.tests.cpp:<line number>: passed: std::strcmp( ss.c_str(), "world!" ) == 0 for: 0 == 0
|
String.tests.cpp:<line number>: passed: std::strcmp( ss.c_str(), "world!" ) == 0 for: 0 == 0
|
||||||
String.tests.cpp:<line number>: passed: s.c_str() == s2.c_str() for: "hello world!" == "hello world!"
|
String.tests.cpp:<line number>: passed: s.data() == s2.data() for: "hello world!" == "hello world!"
|
||||||
String.tests.cpp:<line number>: passed: s.c_str() != ss.c_str() for: "hello world!" != "hello"
|
String.tests.cpp:<line number>: passed: s.data() == ss.data() for: "hello world!" == "hello world!"
|
||||||
String.tests.cpp:<line number>: passed: s.substr(s.size() + 1, 123).empty() for: true
|
String.tests.cpp:<line number>: passed: s.substr(s.size() + 1, 123).empty() for: true
|
||||||
String.tests.cpp:<line number>: passed: StringRef("hello") == StringRef("hello") for: hello == hello
|
String.tests.cpp:<line number>: passed: std::strcmp(ss.c_str(), "world!") == 0 for: 0 == 0
|
||||||
String.tests.cpp:<line number>: passed: StringRef("hello") != StringRef("cello") for: hello != cello
|
String.tests.cpp:<line number>: passed: (char*)buffer1 != (char*)buffer2 for: "Hello" != "Hello"
|
||||||
|
String.tests.cpp:<line number>: passed: left == right for: Hello == Hello
|
||||||
|
String.tests.cpp:<line number>: passed: left != left.substr(0, 3) for: Hello != Hel
|
||||||
String.tests.cpp:<line number>: passed: sr == "a standard string" for: a standard string == "a standard string"
|
String.tests.cpp:<line number>: passed: sr == "a standard string" for: a standard string == "a standard string"
|
||||||
String.tests.cpp:<line number>: passed: sr.size() == stdStr.size() for: 17 == 17
|
String.tests.cpp:<line number>: passed: sr.size() == stdStr.size() for: 17 == 17
|
||||||
String.tests.cpp:<line number>: passed: sr == "a standard string" for: a standard string == "a standard string"
|
String.tests.cpp:<line number>: passed: sr == "a standard string" for: a standard string == "a standard string"
|
||||||
@@ -1134,6 +1219,17 @@ String.tests.cpp:<line number>: passed: stdStr == "a stringref" for: "a stringre
|
|||||||
String.tests.cpp:<line number>: passed: stdStr.size() == sr.size() for: 11 == 11
|
String.tests.cpp:<line number>: passed: stdStr.size() == sr.size() for: 11 == 11
|
||||||
String.tests.cpp:<line number>: passed: stdStr == "a stringref" for: "a stringref" == "a stringref"
|
String.tests.cpp:<line number>: passed: stdStr == "a stringref" for: "a stringref" == "a stringref"
|
||||||
String.tests.cpp:<line number>: passed: stdStr.size() == sr.size() for: 11 == 11
|
String.tests.cpp:<line number>: passed: stdStr.size() == sr.size() for: 11 == 11
|
||||||
|
String.tests.cpp:<line number>: passed: with 1 message: 'StringRef{}.size() == 0'
|
||||||
|
String.tests.cpp:<line number>: passed: with 1 message: 'StringRef{ "abc", 3 }.size() == 3'
|
||||||
|
String.tests.cpp:<line number>: passed: with 1 message: 'StringRef{ "abc", 3 }.isNullTerminated()'
|
||||||
|
String.tests.cpp:<line number>: passed: with 1 message: 'StringRef{ "abc", 2 }.size() == 2'
|
||||||
|
String.tests.cpp:<line number>: passed: with 1 message: '!(StringRef{ "abc", 2 }.isNullTerminated())'
|
||||||
|
String.tests.cpp:<line number>: passed: with 1 message: '!(sr1.empty())'
|
||||||
|
String.tests.cpp:<line number>: passed: with 1 message: 'sr1.size() == 3'
|
||||||
|
String.tests.cpp:<line number>: passed: with 1 message: 'sr1.isNullTerminated()'
|
||||||
|
String.tests.cpp:<line number>: passed: with 1 message: 'sr2.empty()'
|
||||||
|
String.tests.cpp:<line number>: passed: with 1 message: 'sr2.size() == 0'
|
||||||
|
String.tests.cpp:<line number>: passed: with 1 message: 'sr2.isNullTerminated()'
|
||||||
ToStringChrono.tests.cpp:<line number>: passed: minute == seconds for: 1 m == 60 s
|
ToStringChrono.tests.cpp:<line number>: passed: minute == seconds for: 1 m == 60 s
|
||||||
ToStringChrono.tests.cpp:<line number>: passed: hour != seconds for: 1 h != 60 s
|
ToStringChrono.tests.cpp:<line number>: passed: hour != seconds for: 1 h != 60 s
|
||||||
ToStringChrono.tests.cpp:<line number>: passed: micro != milli for: 1 us != 1 ms
|
ToStringChrono.tests.cpp:<line number>: passed: micro != milli for: 1 us != 1 ms
|
||||||
@@ -1485,48 +1581,9 @@ Xml.tests.cpp:<line number>: passed: encode( stringWithQuotes, Catch::XmlEncode:
|
|||||||
"don't "quote" me on that"
|
"don't "quote" me on that"
|
||||||
Xml.tests.cpp:<line number>: passed: encode( "[\x01]" ) == "[\\x01]" for: "[\x01]" == "[\x01]"
|
Xml.tests.cpp:<line number>: passed: encode( "[\x01]" ) == "[\\x01]" for: "[\x01]" == "[\x01]"
|
||||||
Xml.tests.cpp:<line number>: passed: encode( "[\x7F]" ) == "[\\x7F]" for: "[\x7F]" == "[\x7F]"
|
Xml.tests.cpp:<line number>: passed: encode( "[\x7F]" ) == "[\\x7F]" for: "[\x7F]" == "[\x7F]"
|
||||||
Xml.tests.cpp:<line number>: passed: encode(u8"Here be 👾") == u8"Here be 👾" for: "Here be 👾" == "Here be 👾"
|
Tag.tests.cpp:<line number>: passed: testcase.tags, VectorContains(std::string(".")) && VectorContains(std::string("!hide")) for: { "!hide", "." } ( Contains: "." and Contains: "!hide" )
|
||||||
Xml.tests.cpp:<line number>: passed: encode(u8"šš") == u8"šš" for: "šš" == "šš"
|
Tag.tests.cpp:<line number>: passed: testcase.tags, VectorContains(std::string(".")) && VectorContains(std::string("!hide")) for: { "!hide", "." } ( Contains: "." and Contains: "!hide" )
|
||||||
Xml.tests.cpp:<line number>: passed: encode("\xDF\xBF") == "\xDF\xBF" for: "߿" == "߿"
|
Tag.tests.cpp:<line number>: passed: testcase.tags, VectorContains(std::string(".")) && VectorContains(std::string("!hide")) for: { "!hide", ".", "foo" } ( Contains: "." and Contains: "!hide" )
|
||||||
Xml.tests.cpp:<line number>: passed: encode("\xE0\xA0\x80") == "\xE0\xA0\x80" for: "ࠀ" == "ࠀ"
|
|
||||||
Xml.tests.cpp:<line number>: passed: encode("\xED\x9F\xBF") == "\xED\x9F\xBF" for: "" == ""
|
|
||||||
Xml.tests.cpp:<line number>: passed: encode("\xEE\x80\x80") == "\xEE\x80\x80" for: "" == ""
|
|
||||||
Xml.tests.cpp:<line number>: passed: encode("\xEF\xBF\xBF") == "\xEF\xBF\xBF" for: "" == ""
|
|
||||||
Xml.tests.cpp:<line number>: passed: encode("\xF0\x90\x80\x80") == "\xF0\x90\x80\x80" for: "𐀀" == "𐀀"
|
|
||||||
Xml.tests.cpp:<line number>: passed: encode("\xF4\x8F\xBF\xBF") == "\xF4\x8F\xBF\xBF" for: "" == ""
|
|
||||||
Xml.tests.cpp:<line number>: passed: encode("Here \xFF be 👾") == u8"Here \\xFF be 👾" for: "Here \xFF be 👾" == "Here \xFF be 👾"
|
|
||||||
Xml.tests.cpp:<line number>: passed: encode("\xFF") == "\\xFF" for: "\xFF" == "\xFF"
|
|
||||||
Xml.tests.cpp:<line number>: passed: encode("\xC5\xC5\xA0") == u8"\\xC5Š" for: "\xC5Š" == "\xC5Š"
|
|
||||||
Xml.tests.cpp:<line number>: passed: encode("\xF4\x90\x80\x80") == u8"\\xF4\\x90\\x80\\x80" for: "\xF4\x90\x80\x80" == "\xF4\x90\x80\x80"
|
|
||||||
Xml.tests.cpp:<line number>: passed: encode("\xC0\x80") == u8"\\xC0\\x80" for: "\xC0\x80" == "\xC0\x80"
|
|
||||||
Xml.tests.cpp:<line number>: passed: encode("\xF0\x80\x80\x80") == u8"\\xF0\\x80\\x80\\x80" for: "\xF0\x80\x80\x80" == "\xF0\x80\x80\x80"
|
|
||||||
Xml.tests.cpp:<line number>: passed: encode("\xC1\xBF") == u8"\\xC1\\xBF" for: "\xC1\xBF" == "\xC1\xBF"
|
|
||||||
Xml.tests.cpp:<line number>: passed: encode("\xE0\x9F\xBF") == u8"\\xE0\\x9F\\xBF" for: "\xE0\x9F\xBF" == "\xE0\x9F\xBF"
|
|
||||||
Xml.tests.cpp:<line number>: passed: encode("\xF0\x8F\xBF\xBF") == u8"\\xF0\\x8F\\xBF\\xBF" for: "\xF0\x8F\xBF\xBF" == "\xF0\x8F\xBF\xBF"
|
|
||||||
Xml.tests.cpp:<line number>: passed: encode("\xED\xA0\x80") == "\xED\xA0\x80" for: "<22><><EFBFBD>" == "<22><><EFBFBD>"
|
|
||||||
Xml.tests.cpp:<line number>: passed: encode("\xED\xAF\xBF") == "\xED\xAF\xBF" for: "<22><><EFBFBD>" == "<22><><EFBFBD>"
|
|
||||||
Xml.tests.cpp:<line number>: passed: encode("\xED\xB0\x80") == "\xED\xB0\x80" for: "<22><><EFBFBD>" == "<22><><EFBFBD>"
|
|
||||||
Xml.tests.cpp:<line number>: passed: encode("\xED\xBF\xBF") == "\xED\xBF\xBF" for: "<22><><EFBFBD>" == "<22><><EFBFBD>"
|
|
||||||
Xml.tests.cpp:<line number>: passed: encode("\x80") == u8"\\x80" for: "\x80" == "\x80"
|
|
||||||
Xml.tests.cpp:<line number>: passed: encode("\x81") == u8"\\x81" for: "\x81" == "\x81"
|
|
||||||
Xml.tests.cpp:<line number>: passed: encode("\xBC") == u8"\\xBC" for: "\xBC" == "\xBC"
|
|
||||||
Xml.tests.cpp:<line number>: passed: encode("\xBF") == u8"\\xBF" for: "\xBF" == "\xBF"
|
|
||||||
Xml.tests.cpp:<line number>: passed: encode("\xF5\x80\x80\x80") == u8"\\xF5\\x80\\x80\\x80" for: "\xF5\x80\x80\x80" == "\xF5\x80\x80\x80"
|
|
||||||
Xml.tests.cpp:<line number>: passed: encode("\xF6\x80\x80\x80") == u8"\\xF6\\x80\\x80\\x80" for: "\xF6\x80\x80\x80" == "\xF6\x80\x80\x80"
|
|
||||||
Xml.tests.cpp:<line number>: passed: encode("\xF7\x80\x80\x80") == u8"\\xF7\\x80\\x80\\x80" for: "\xF7\x80\x80\x80" == "\xF7\x80\x80\x80"
|
|
||||||
Xml.tests.cpp:<line number>: passed: encode("\xDE") == u8"\\xDE" for: "\xDE" == "\xDE"
|
|
||||||
Xml.tests.cpp:<line number>: passed: encode("\xDF") == u8"\\xDF" for: "\xDF" == "\xDF"
|
|
||||||
Xml.tests.cpp:<line number>: passed: encode("\xE0") == u8"\\xE0" for: "\xE0" == "\xE0"
|
|
||||||
Xml.tests.cpp:<line number>: passed: encode("\xEF") == u8"\\xEF" for: "\xEF" == "\xEF"
|
|
||||||
Xml.tests.cpp:<line number>: passed: encode("\xF0") == u8"\\xF0" for: "\xF0" == "\xF0"
|
|
||||||
Xml.tests.cpp:<line number>: passed: encode("\xF4") == u8"\\xF4" for: "\xF4" == "\xF4"
|
|
||||||
Xml.tests.cpp:<line number>: passed: encode("\xE0\x80") == u8"\\xE0\\x80" for: "\xE0\x80" == "\xE0\x80"
|
|
||||||
Xml.tests.cpp:<line number>: passed: encode("\xE0\xBF") == u8"\\xE0\\xBF" for: "\xE0\xBF" == "\xE0\xBF"
|
|
||||||
Xml.tests.cpp:<line number>: passed: encode("\xE1\x80") == u8"\\xE1\\x80" for: "\xE1\x80" == "\xE1\x80"
|
|
||||||
Xml.tests.cpp:<line number>: passed: encode("\xF0\x80") == u8"\\xF0\\x80" for: "\xF0\x80" == "\xF0\x80"
|
|
||||||
Xml.tests.cpp:<line number>: passed: encode("\xF4\x80") == u8"\\xF4\\x80" for: "\xF4\x80" == "\xF4\x80"
|
|
||||||
Xml.tests.cpp:<line number>: passed: encode("\xF0\x80\x80") == u8"\\xF0\\x80\\x80" for: "\xF0\x80\x80" == "\xF0\x80\x80"
|
|
||||||
Xml.tests.cpp:<line number>: passed: encode("\xF4\x80\x80") == u8"\\xF4\\x80\\x80" for: "\xF4\x80\x80" == "\xF4\x80\x80"
|
|
||||||
ToStringVector.tests.cpp:<line number>: passed: Catch::Detail::stringify( empty ) == "{ }" for: "{ }" == "{ }"
|
ToStringVector.tests.cpp:<line number>: passed: Catch::Detail::stringify( empty ) == "{ }" for: "{ }" == "{ }"
|
||||||
ToStringVector.tests.cpp:<line number>: passed: Catch::Detail::stringify( oneValue ) == "{ 42 }" for: "{ 42 }" == "{ 42 }"
|
ToStringVector.tests.cpp:<line number>: passed: Catch::Detail::stringify( oneValue ) == "{ 42 }" for: "{ 42 }" == "{ 42 }"
|
||||||
ToStringVector.tests.cpp:<line number>: passed: Catch::Detail::stringify( twoValues ) == "{ 42, 250 }" for: "{ 42, 250 }" == "{ 42, 250 }"
|
ToStringVector.tests.cpp:<line number>: passed: Catch::Detail::stringify( twoValues ) == "{ 42, 250 }" for: "{ 42, 250 }" == "{ 42, 250 }"
|
||||||
@@ -1628,7 +1685,7 @@ StringManip.tests.cpp:<line number>: passed: Catch::replaceInPlace(s, "'", "|'")
|
|||||||
StringManip.tests.cpp:<line number>: passed: s == "didn|'t" for: "didn|'t" == "didn|'t"
|
StringManip.tests.cpp:<line number>: passed: s == "didn|'t" for: "didn|'t" == "didn|'t"
|
||||||
Misc.tests.cpp:<line number>: failed: false with 1 message: '3'
|
Misc.tests.cpp:<line number>: failed: false with 1 message: '3'
|
||||||
Message.tests.cpp:<line number>: failed: false with 2 messages: 'hi' and 'i := 7'
|
Message.tests.cpp:<line number>: failed: false with 2 messages: 'hi' and 'i := 7'
|
||||||
Tag.tests.cpp:<line number>: passed: testcase.tags, Catch::VectorContains(std::string("magic-tag")) && Catch::VectorContains(std::string(".")) for: { ".", "magic-tag" } ( Contains: "magic-tag" and Contains: "." )
|
Tag.tests.cpp:<line number>: passed: testcase.tags, Catch::VectorContains(std::string("magic-tag")) && Catch::VectorContains(std::string(".")) for: { "!hide", ".", "magic-tag" } ( Contains: "magic-tag" and Contains: "." )
|
||||||
StringManip.tests.cpp:<line number>: passed: splitStringRef("", ','), Equals(std::vector<StringRef>()) for: { } Equals: { }
|
StringManip.tests.cpp:<line number>: passed: splitStringRef("", ','), Equals(std::vector<StringRef>()) for: { } Equals: { }
|
||||||
StringManip.tests.cpp:<line number>: passed: splitStringRef("abc", ','), Equals(std::vector<StringRef>{"abc"}) for: { abc } Equals: { abc }
|
StringManip.tests.cpp:<line number>: passed: splitStringRef("abc", ','), Equals(std::vector<StringRef>{"abc"}) for: { abc } Equals: { abc }
|
||||||
StringManip.tests.cpp:<line number>: passed: splitStringRef("abc,def", ','), Equals(std::vector<StringRef>{"abc", "def"}) for: { abc, def } Equals: { abc, def }
|
StringManip.tests.cpp:<line number>: passed: splitStringRef("abc,def", ','), Equals(std::vector<StringRef>{"abc", "def"}) for: { abc, def } Equals: { abc, def }
|
||||||
|
@@ -1380,6 +1380,6 @@ due to unexpected exception with message:
|
|||||||
Why would you throw a std::string?
|
Why would you throw a std::string?
|
||||||
|
|
||||||
===============================================================================
|
===============================================================================
|
||||||
test cases: 304 | 230 passed | 70 failed | 4 failed as expected
|
test cases: 306 | 232 passed | 70 failed | 4 failed as expected
|
||||||
assertions: 1619 | 1467 passed | 131 failed | 21 failed as expected
|
assertions: 1676 | 1524 passed | 131 failed | 21 failed as expected
|
||||||
|
|
||||||
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
1731
projects/SelfTest/Baselines/sonarqube.sw.approved.txt
Normal file
1731
projects/SelfTest/Baselines/sonarqube.sw.approved.txt
Normal file
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -17,7 +17,7 @@
|
|||||||
|
|
||||||
inline Catch::TestCase fakeTestCase(const char* name, const char* desc = "") { return Catch::makeTestCase(nullptr, "", { name, desc }, CATCH_INTERNAL_LINEINFO); }
|
inline Catch::TestCase fakeTestCase(const char* name, const char* desc = "") { return Catch::makeTestCase(nullptr, "", { name, desc }, CATCH_INTERNAL_LINEINFO); }
|
||||||
|
|
||||||
TEST_CASE( "Parse test names and tags" ) {
|
TEST_CASE( "Parse test names and tags", "[command-line][test-spec]" ) {
|
||||||
|
|
||||||
using Catch::parseTestSpec;
|
using Catch::parseTestSpec;
|
||||||
using Catch::TestSpec;
|
using Catch::TestSpec;
|
||||||
@@ -269,7 +269,6 @@ TEST_CASE( "Parse test names and tags" ) {
|
|||||||
CHECK( spec.matches( fakeTestCase( " aardvark " ) ) );
|
CHECK( spec.matches( fakeTestCase( " aardvark " ) ) );
|
||||||
CHECK( spec.matches( fakeTestCase( "aardvark " ) ) );
|
CHECK( spec.matches( fakeTestCase( "aardvark " ) ) );
|
||||||
CHECK( spec.matches( fakeTestCase( "aardvark" ) ) );
|
CHECK( spec.matches( fakeTestCase( "aardvark" ) ) );
|
||||||
|
|
||||||
}
|
}
|
||||||
SECTION( "Leading and trailing spaces in test name" ) {
|
SECTION( "Leading and trailing spaces in test name" ) {
|
||||||
TestSpec spec = parseTestSpec( "aardvark" );
|
TestSpec spec = parseTestSpec( "aardvark" );
|
||||||
@@ -278,7 +277,18 @@ TEST_CASE( "Parse test names and tags" ) {
|
|||||||
CHECK( spec.matches( fakeTestCase( " aardvark " ) ) );
|
CHECK( spec.matches( fakeTestCase( " aardvark " ) ) );
|
||||||
CHECK( spec.matches( fakeTestCase( "aardvark " ) ) );
|
CHECK( spec.matches( fakeTestCase( "aardvark " ) ) );
|
||||||
CHECK( spec.matches( fakeTestCase( "aardvark" ) ) );
|
CHECK( spec.matches( fakeTestCase( "aardvark" ) ) );
|
||||||
|
}
|
||||||
|
SECTION("Shortened hide tags are split apart when parsing") {
|
||||||
|
TestSpec spec = parseTestSpec("[.foo]");
|
||||||
|
CHECK(spec.matches(fakeTestCase("hidden and foo", "[.][foo]")));
|
||||||
|
CHECK_FALSE(spec.matches(fakeTestCase("only foo", "[foo]")));
|
||||||
|
}
|
||||||
|
SECTION("Shortened hide tags also properly handle exclusion") {
|
||||||
|
TestSpec spec = parseTestSpec("~[.foo]");
|
||||||
|
CHECK_FALSE(spec.matches(fakeTestCase("hidden and foo", "[.][foo]")));
|
||||||
|
CHECK_FALSE(spec.matches(fakeTestCase("only foo", "[foo]")));
|
||||||
|
CHECK_FALSE(spec.matches(fakeTestCase("only hidden", "[.]")));
|
||||||
|
CHECK(spec.matches(fakeTestCase("neither foo nor hidden", "[bar]")));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -404,6 +414,30 @@ TEST_CASE( "Process can be configured on command line", "[config][command-line]"
|
|||||||
REQUIRE_THAT(result.errorMessage(), Contains("convert") && Contains("oops"));
|
REQUIRE_THAT(result.errorMessage(), Contains("convert") && Contains("oops"));
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SECTION("wait-for-keypress") {
|
||||||
|
SECTION("Accepted options") {
|
||||||
|
using tuple_type = std::tuple<char const*, Catch::WaitForKeypress::When>;
|
||||||
|
auto input = GENERATE(table<char const*, Catch::WaitForKeypress::When>({
|
||||||
|
tuple_type{"never", Catch::WaitForKeypress::Never},
|
||||||
|
tuple_type{"start", Catch::WaitForKeypress::BeforeStart},
|
||||||
|
tuple_type{"exit", Catch::WaitForKeypress::BeforeExit},
|
||||||
|
tuple_type{"both", Catch::WaitForKeypress::BeforeStartAndExit},
|
||||||
|
}));
|
||||||
|
CHECK(cli.parse({"test", "--wait-for-keypress", std::get<0>(input)}));
|
||||||
|
|
||||||
|
REQUIRE(config.waitForKeypress == std::get<1>(input));
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("invalid options are reported") {
|
||||||
|
auto result = cli.parse({"test", "--wait-for-keypress", "sometimes"});
|
||||||
|
CHECK(!result);
|
||||||
|
|
||||||
|
#ifndef CATCH_CONFIG_DISABLE_MATCHERS
|
||||||
|
REQUIRE_THAT(result.errorMessage(), Contains("never") && Contains("both"));
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("nothrow") {
|
SECTION("nothrow") {
|
||||||
@@ -493,17 +527,23 @@ TEST_CASE( "Process can be configured on command line", "[config][command-line]"
|
|||||||
REQUIRE(config.benchmarkResamples == 20000);
|
REQUIRE(config.benchmarkResamples == 20000);
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("resamples") {
|
SECTION("confidence-interval") {
|
||||||
CHECK(cli.parse({ "test", "--benchmark-confidence-interval=0.99" }));
|
CHECK(cli.parse({ "test", "--benchmark-confidence-interval=0.99" }));
|
||||||
|
|
||||||
REQUIRE(config.benchmarkConfidenceInterval == Catch::Detail::Approx(0.99));
|
REQUIRE(config.benchmarkConfidenceInterval == Catch::Detail::Approx(0.99));
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("resamples") {
|
SECTION("no-analysis") {
|
||||||
CHECK(cli.parse({ "test", "--benchmark-no-analysis" }));
|
CHECK(cli.parse({ "test", "--benchmark-no-analysis" }));
|
||||||
|
|
||||||
REQUIRE(config.benchmarkNoAnalysis);
|
REQUIRE(config.benchmarkNoAnalysis);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SECTION("warmup-time") {
|
||||||
|
CHECK(cli.parse({ "test", "--benchmark-warmup-time=10" }));
|
||||||
|
|
||||||
|
REQUIRE(config.benchmarkWarmupTime == 10);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -173,6 +173,58 @@ TEST_CASE("Generators internals", "[generators][internals]") {
|
|||||||
REQUIRE_FALSE(gen.next());
|
REQUIRE_FALSE(gen.next());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SECTION("Floating Point") {
|
||||||
|
SECTION("Exact") {
|
||||||
|
const auto rangeStart = -1.;
|
||||||
|
const auto rangeEnd = 1.;
|
||||||
|
const auto step = .1;
|
||||||
|
|
||||||
|
auto gen = range(rangeStart, rangeEnd, step);
|
||||||
|
auto expected = rangeStart;
|
||||||
|
while( (rangeEnd - expected) > step ) {
|
||||||
|
INFO( "Current expected value is " << expected )
|
||||||
|
REQUIRE(gen.get() == Approx(expected));
|
||||||
|
REQUIRE(gen.next());
|
||||||
|
|
||||||
|
expected += step;
|
||||||
|
}
|
||||||
|
REQUIRE(gen.get() == Approx( rangeEnd ) );
|
||||||
|
REQUIRE_FALSE(gen.next());
|
||||||
|
}
|
||||||
|
SECTION("Slightly over end") {
|
||||||
|
const auto rangeStart = -1.;
|
||||||
|
const auto rangeEnd = 1.;
|
||||||
|
const auto step = .3;
|
||||||
|
|
||||||
|
auto gen = range(rangeStart, rangeEnd, step);
|
||||||
|
auto expected = rangeStart;
|
||||||
|
while( (rangeEnd - expected) > step ) {
|
||||||
|
INFO( "Current expected value is " << expected )
|
||||||
|
REQUIRE(gen.get() == Approx(expected));
|
||||||
|
REQUIRE(gen.next());
|
||||||
|
|
||||||
|
expected += step;
|
||||||
|
}
|
||||||
|
REQUIRE_FALSE(gen.next());
|
||||||
|
}
|
||||||
|
SECTION("Slightly under end") {
|
||||||
|
const auto rangeStart = -1.;
|
||||||
|
const auto rangeEnd = .9;
|
||||||
|
const auto step = .3;
|
||||||
|
|
||||||
|
auto gen = range(rangeStart, rangeEnd, step);
|
||||||
|
auto expected = rangeStart;
|
||||||
|
while( (rangeEnd - expected) > step ) {
|
||||||
|
INFO( "Current expected value is " << expected )
|
||||||
|
REQUIRE(gen.get() == Approx(expected));
|
||||||
|
REQUIRE(gen.next());
|
||||||
|
|
||||||
|
expected += step;
|
||||||
|
}
|
||||||
|
REQUIRE_FALSE(gen.next());
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
SECTION("Negative manual step") {
|
SECTION("Negative manual step") {
|
||||||
SECTION("Integer") {
|
SECTION("Integer") {
|
||||||
@@ -259,6 +311,21 @@ TEST_CASE("GENERATE capture macros", "[generators][internals][approvals]") {
|
|||||||
REQUIRE(value == value2);
|
REQUIRE(value == value2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_CASE("#1809 - GENERATE_COPY and SingleValueGenerator does not compile", "[generators][compilation][approvals]") {
|
||||||
|
// Verify Issue #1809 fix, only needs to compile.
|
||||||
|
auto a = GENERATE_COPY(1, 2);
|
||||||
|
(void)a;
|
||||||
|
auto b = GENERATE_COPY(as<long>{}, 1, 2);
|
||||||
|
(void)b;
|
||||||
|
int i = 1;
|
||||||
|
int j = 2;
|
||||||
|
auto c = GENERATE_COPY(i, j);
|
||||||
|
(void)c;
|
||||||
|
auto d = GENERATE_COPY(as<long>{}, i, j);
|
||||||
|
(void)d;
|
||||||
|
SUCCEED();
|
||||||
|
}
|
||||||
|
|
||||||
TEST_CASE("Multiple random generators in one test case output different values", "[generators][internals][approvals]") {
|
TEST_CASE("Multiple random generators in one test case output different values", "[generators][internals][approvals]") {
|
||||||
SECTION("Integer") {
|
SECTION("Integer") {
|
||||||
auto random1 = Catch::Generators::random(0, 1000);
|
auto random1 = Catch::Generators::random(0, 1000);
|
||||||
|
@@ -4,39 +4,15 @@
|
|||||||
|
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
|
|
||||||
namespace Catch {
|
|
||||||
|
|
||||||
// Implementation of test accessors
|
|
||||||
struct StringRefTestAccess {
|
|
||||||
static auto isOwned( StringRef const& stringRef ) -> bool {
|
|
||||||
return stringRef.isOwned();
|
|
||||||
}
|
|
||||||
static auto isSubstring( StringRef const& stringRef ) -> bool {
|
|
||||||
return stringRef.isSubstring();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
namespace {
|
|
||||||
auto isOwned( StringRef const& stringRef ) -> bool {
|
|
||||||
return StringRefTestAccess::isOwned( stringRef );
|
|
||||||
}
|
|
||||||
auto isSubstring( StringRef const& stringRef ) -> bool {
|
|
||||||
return StringRefTestAccess::isSubstring( stringRef );
|
|
||||||
}
|
|
||||||
} // end anonymous namespace
|
|
||||||
|
|
||||||
} // namespace Catch
|
|
||||||
|
|
||||||
TEST_CASE( "StringRef", "[Strings][StringRef]" ) {
|
TEST_CASE( "StringRef", "[Strings][StringRef]" ) {
|
||||||
|
|
||||||
using Catch::StringRef;
|
using Catch::StringRef;
|
||||||
using Catch::isOwned; using Catch::isSubstring;
|
|
||||||
|
|
||||||
SECTION( "Empty string" ) {
|
SECTION( "Empty string" ) {
|
||||||
StringRef empty;
|
StringRef empty;
|
||||||
REQUIRE( empty.empty() );
|
REQUIRE( empty.empty() );
|
||||||
REQUIRE( empty.size() == 0 );
|
REQUIRE( empty.size() == 0 );
|
||||||
|
REQUIRE( empty.isNullTerminated() );
|
||||||
REQUIRE( std::strcmp( empty.c_str(), "" ) == 0 );
|
REQUIRE( std::strcmp( empty.c_str(), "" ) == 0 );
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -44,28 +20,22 @@ TEST_CASE( "StringRef", "[Strings][StringRef]" ) {
|
|||||||
StringRef s = "hello";
|
StringRef s = "hello";
|
||||||
REQUIRE( s.empty() == false );
|
REQUIRE( s.empty() == false );
|
||||||
REQUIRE( s.size() == 5 );
|
REQUIRE( s.size() == 5 );
|
||||||
REQUIRE( isSubstring( s ) == false );
|
REQUIRE( s.isNullTerminated() );
|
||||||
|
|
||||||
auto rawChars = s.currentData();
|
auto rawChars = s.data();
|
||||||
REQUIRE( std::strcmp( rawChars, "hello" ) == 0 );
|
REQUIRE( std::strcmp( rawChars, "hello" ) == 0 );
|
||||||
|
|
||||||
SECTION( "c_str() does not cause copy" ) {
|
REQUIRE_NOTHROW(s.c_str());
|
||||||
REQUIRE( isOwned( s ) == false );
|
|
||||||
|
|
||||||
REQUIRE(s.c_str() == rawChars);
|
REQUIRE(s.c_str() == rawChars);
|
||||||
|
REQUIRE(s.data() == rawChars);
|
||||||
REQUIRE( isOwned( s ) == false );
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
SECTION( "From sub-string" ) {
|
SECTION( "From sub-string" ) {
|
||||||
StringRef original = StringRef( "original string" ).substr(0, 8);
|
StringRef original = StringRef( "original string" ).substr(0, 8);
|
||||||
REQUIRE( original == "original" );
|
REQUIRE( original == "original" );
|
||||||
REQUIRE( isSubstring( original ) );
|
|
||||||
REQUIRE( isOwned( original ) == false );
|
|
||||||
|
|
||||||
original.c_str(); // Forces it to take ownership
|
REQUIRE_FALSE(original.isNullTerminated());
|
||||||
|
REQUIRE_THROWS(original.c_str());
|
||||||
REQUIRE( isOwned( original ) );
|
REQUIRE_NOTHROW(original.data());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -76,26 +46,9 @@ TEST_CASE( "StringRef", "[Strings][StringRef]" ) {
|
|||||||
SECTION( "zero-based substring" ) {
|
SECTION( "zero-based substring" ) {
|
||||||
REQUIRE( ss.empty() == false );
|
REQUIRE( ss.empty() == false );
|
||||||
REQUIRE( ss.size() == 5 );
|
REQUIRE( ss.size() == 5 );
|
||||||
REQUIRE( std::strcmp( ss.c_str(), "hello" ) == 0 );
|
REQUIRE( std::strncmp( ss.data(), "hello", 5 ) == 0 );
|
||||||
REQUIRE( ss == "hello" );
|
REQUIRE( ss == "hello" );
|
||||||
}
|
}
|
||||||
SECTION( "c_str() causes copy" ) {
|
|
||||||
REQUIRE( isSubstring( ss ) );
|
|
||||||
REQUIRE( isOwned( ss ) == false );
|
|
||||||
|
|
||||||
auto rawChars = ss.currentData();
|
|
||||||
REQUIRE( rawChars == s.currentData() ); // same pointer value
|
|
||||||
REQUIRE( ss.c_str() != rawChars );
|
|
||||||
|
|
||||||
REQUIRE( isOwned( ss ) );
|
|
||||||
|
|
||||||
SECTION( "Self-assignment after substring" ) {
|
|
||||||
ss = *&ss; // the *& are there to suppress warnings (see: "Improvements to Clang's diagnostics" in https://rev.ng/gitlab/revng-bar-2019/clang/raw/master/docs/ReleaseNotes.rst)
|
|
||||||
REQUIRE( isOwned(ss) == false );
|
|
||||||
REQUIRE( ss == "hello" );
|
|
||||||
REQUIRE( rawChars == ss.currentData() ); // same pointer value
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
SECTION( "non-zero-based substring") {
|
SECTION( "non-zero-based substring") {
|
||||||
ss = s.substr( 6, 6 );
|
ss = s.substr( 6, 6 );
|
||||||
@@ -105,21 +58,32 @@ TEST_CASE( "StringRef", "[Strings][StringRef]" ) {
|
|||||||
|
|
||||||
SECTION( "Pointer values of full refs should match" ) {
|
SECTION( "Pointer values of full refs should match" ) {
|
||||||
StringRef s2 = s;
|
StringRef s2 = s;
|
||||||
REQUIRE( s.c_str() == s2.c_str() );
|
REQUIRE( s.data() == s2.data() );
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION( "Pointer values of substring refs should not match" ) {
|
SECTION( "Pointer values of substring refs should also match" ) {
|
||||||
REQUIRE( s.c_str() != ss.c_str() );
|
REQUIRE( s.data() == ss.data() );
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("Past the end substring") {
|
SECTION("Past the end substring") {
|
||||||
REQUIRE(s.substr(s.size() + 1, 123).empty());
|
REQUIRE(s.substr(s.size() + 1, 123).empty());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SECTION("Substring off the end are trimmed") {
|
||||||
|
ss = s.substr(6, 123);
|
||||||
|
REQUIRE(std::strcmp(ss.c_str(), "world!") == 0);
|
||||||
|
}
|
||||||
|
// TODO: substring into string + size is longer than end
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION( "Comparisons" ) {
|
SECTION( "Comparisons are deep" ) {
|
||||||
REQUIRE( StringRef("hello") == StringRef("hello") );
|
char buffer1[] = "Hello";
|
||||||
REQUIRE( StringRef("hello") != StringRef("cello") );
|
char buffer2[] = "Hello";
|
||||||
|
CHECK((char*)buffer1 != (char*)buffer2);
|
||||||
|
|
||||||
|
StringRef left(buffer1), right(buffer2);
|
||||||
|
REQUIRE( left == right );
|
||||||
|
REQUIRE(left != left.substr(0, 3));
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION( "from std::string" ) {
|
SECTION( "from std::string" ) {
|
||||||
@@ -159,3 +123,28 @@ TEST_CASE( "StringRef", "[Strings][StringRef]" ) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_CASE("StringRef at compilation time", "[Strings][StringRef][constexpr]") {
|
||||||
|
using Catch::StringRef;
|
||||||
|
SECTION("Simple constructors") {
|
||||||
|
STATIC_REQUIRE(StringRef{}.size() == 0);
|
||||||
|
|
||||||
|
STATIC_REQUIRE(StringRef{ "abc", 3 }.size() == 3);
|
||||||
|
STATIC_REQUIRE(StringRef{ "abc", 3 }.isNullTerminated());
|
||||||
|
|
||||||
|
STATIC_REQUIRE(StringRef{ "abc", 2 }.size() == 2);
|
||||||
|
STATIC_REQUIRE_FALSE(StringRef{ "abc", 2 }.isNullTerminated());
|
||||||
|
}
|
||||||
|
SECTION("UDL construction") {
|
||||||
|
constexpr auto sr1 = "abc"_catch_sr;
|
||||||
|
STATIC_REQUIRE_FALSE(sr1.empty());
|
||||||
|
STATIC_REQUIRE(sr1.size() == 3);
|
||||||
|
STATIC_REQUIRE(sr1.isNullTerminated());
|
||||||
|
|
||||||
|
using Catch::operator"" _sr;
|
||||||
|
constexpr auto sr2 = ""_sr;
|
||||||
|
STATIC_REQUIRE(sr2.empty());
|
||||||
|
STATIC_REQUIRE(sr2.size() == 0);
|
||||||
|
STATIC_REQUIRE(sr2.isNullTerminated());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@@ -45,3 +45,10 @@ TEST_CASE("shortened hide tags are split apart") {
|
|||||||
auto testcase = Catch::makeTestCase(nullptr, "", {"fake test name", "[.magic-tag]"}, CATCH_INTERNAL_LINEINFO);
|
auto testcase = Catch::makeTestCase(nullptr, "", {"fake test name", "[.magic-tag]"}, CATCH_INTERNAL_LINEINFO);
|
||||||
REQUIRE_THAT(testcase.tags, Catch::VectorContains(std::string("magic-tag")) && Catch::VectorContains(std::string(".")));
|
REQUIRE_THAT(testcase.tags, Catch::VectorContains(std::string("magic-tag")) && Catch::VectorContains(std::string(".")));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_CASE("adding a hide tag implicitly enables all others", "[tags]") {
|
||||||
|
using Catch::VectorContains;
|
||||||
|
auto tag = GENERATE(as<char const*>{}, "[!hide]", "[.]", "[.foo]");
|
||||||
|
auto testcase = Catch::makeTestCase(nullptr, "", {"fake test name", tag}, CATCH_INTERNAL_LINEINFO);
|
||||||
|
REQUIRE_THAT(testcase.tags, VectorContains(std::string(".")) && VectorContains(std::string("!hide")));
|
||||||
|
}
|
||||||
|
@@ -40,10 +40,11 @@ TEST_CASE( "XmlEncode", "[XML]" ) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Thanks to Peter Bindels (dascandy) for some of the tests
|
// Thanks to Peter Bindels (dascandy) for some of the tests
|
||||||
TEST_CASE("XmlEncode: UTF-8", "[XML][UTF-8]") {
|
TEST_CASE("XmlEncode: UTF-8", "[XML][UTF-8][approvals]") {
|
||||||
|
#define ESC(lit) (char*)(lit)
|
||||||
SECTION("Valid utf-8 strings") {
|
SECTION("Valid utf-8 strings") {
|
||||||
CHECK(encode(u8"Here be 👾") == u8"Here be 👾");
|
CHECK(encode(ESC(u8"Here be 👾")) == ESC(u8"Here be 👾"));
|
||||||
CHECK(encode(u8"šš") == u8"šš");
|
CHECK(encode(ESC(u8"šš")) == ESC(u8"šš"));
|
||||||
|
|
||||||
CHECK(encode("\xDF\xBF") == "\xDF\xBF"); // 0x7FF
|
CHECK(encode("\xDF\xBF") == "\xDF\xBF"); // 0x7FF
|
||||||
CHECK(encode("\xE0\xA0\x80") == "\xE0\xA0\x80"); // 0x800
|
CHECK(encode("\xE0\xA0\x80") == "\xE0\xA0\x80"); // 0x800
|
||||||
@@ -55,18 +56,18 @@ TEST_CASE("XmlEncode: UTF-8", "[XML][UTF-8]") {
|
|||||||
}
|
}
|
||||||
SECTION("Invalid utf-8 strings") {
|
SECTION("Invalid utf-8 strings") {
|
||||||
SECTION("Various broken strings") {
|
SECTION("Various broken strings") {
|
||||||
CHECK(encode("Here \xFF be 👾") == u8"Here \\xFF be 👾");
|
CHECK(encode(ESC("Here \xFF be \xF0\x9F\x91\xBE")) == ESC(u8"Here \\xFF be 👾"));
|
||||||
CHECK(encode("\xFF") == "\\xFF");
|
CHECK(encode("\xFF") == "\\xFF");
|
||||||
CHECK(encode("\xC5\xC5\xA0") == u8"\\xC5Š");
|
CHECK(encode("\xC5\xC5\xA0") == ESC(u8"\\xC5Š"));
|
||||||
CHECK(encode("\xF4\x90\x80\x80") == u8"\\xF4\\x90\\x80\\x80"); // 0x110000 -- out of unicode range
|
CHECK(encode("\xF4\x90\x80\x80") == ESC(u8"\\xF4\\x90\\x80\\x80")); // 0x110000 -- out of unicode range
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("Overlong encodings") {
|
SECTION("Overlong encodings") {
|
||||||
CHECK(encode("\xC0\x80") == u8"\\xC0\\x80"); // \0
|
CHECK(encode("\xC0\x80") == "\\xC0\\x80"); // \0
|
||||||
CHECK(encode("\xF0\x80\x80\x80") == u8"\\xF0\\x80\\x80\\x80"); // Super-over-long \0
|
CHECK(encode("\xF0\x80\x80\x80") == "\\xF0\\x80\\x80\\x80"); // Super-over-long \0
|
||||||
CHECK(encode("\xC1\xBF") == u8"\\xC1\\xBF"); // ASCII char as UTF-8 (0x7F)
|
CHECK(encode("\xC1\xBF") == "\\xC1\\xBF"); // ASCII char as UTF-8 (0x7F)
|
||||||
CHECK(encode("\xE0\x9F\xBF") == u8"\\xE0\\x9F\\xBF"); // 0x7FF
|
CHECK(encode("\xE0\x9F\xBF") == "\\xE0\\x9F\\xBF"); // 0x7FF
|
||||||
CHECK(encode("\xF0\x8F\xBF\xBF") == u8"\\xF0\\x8F\\xBF\\xBF"); // 0xFFFF
|
CHECK(encode("\xF0\x8F\xBF\xBF") == "\\xF0\\x8F\\xBF\\xBF"); // 0xFFFF
|
||||||
}
|
}
|
||||||
|
|
||||||
// Note that we actually don't modify surrogate pairs, as we do not do strict checking
|
// Note that we actually don't modify surrogate pairs, as we do not do strict checking
|
||||||
@@ -78,35 +79,36 @@ TEST_CASE("XmlEncode: UTF-8", "[XML][UTF-8]") {
|
|||||||
}
|
}
|
||||||
|
|
||||||
SECTION("Invalid start byte") {
|
SECTION("Invalid start byte") {
|
||||||
CHECK(encode("\x80") == u8"\\x80");
|
CHECK(encode("\x80") == "\\x80");
|
||||||
CHECK(encode("\x81") == u8"\\x81");
|
CHECK(encode("\x81") == "\\x81");
|
||||||
CHECK(encode("\xBC") == u8"\\xBC");
|
CHECK(encode("\xBC") == "\\xBC");
|
||||||
CHECK(encode("\xBF") == u8"\\xBF");
|
CHECK(encode("\xBF") == "\\xBF");
|
||||||
// Out of range
|
// Out of range
|
||||||
CHECK(encode("\xF5\x80\x80\x80") == u8"\\xF5\\x80\\x80\\x80");
|
CHECK(encode("\xF5\x80\x80\x80") == "\\xF5\\x80\\x80\\x80");
|
||||||
CHECK(encode("\xF6\x80\x80\x80") == u8"\\xF6\\x80\\x80\\x80");
|
CHECK(encode("\xF6\x80\x80\x80") == "\\xF6\\x80\\x80\\x80");
|
||||||
CHECK(encode("\xF7\x80\x80\x80") == u8"\\xF7\\x80\\x80\\x80");
|
CHECK(encode("\xF7\x80\x80\x80") == "\\xF7\\x80\\x80\\x80");
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("Missing continuation byte(s)") {
|
SECTION("Missing continuation byte(s)") {
|
||||||
// Missing first continuation byte
|
// Missing first continuation byte
|
||||||
CHECK(encode("\xDE") == u8"\\xDE");
|
CHECK(encode("\xDE") == "\\xDE");
|
||||||
CHECK(encode("\xDF") == u8"\\xDF");
|
CHECK(encode("\xDF") == "\\xDF");
|
||||||
CHECK(encode("\xE0") == u8"\\xE0");
|
CHECK(encode("\xE0") == "\\xE0");
|
||||||
CHECK(encode("\xEF") == u8"\\xEF");
|
CHECK(encode("\xEF") == "\\xEF");
|
||||||
CHECK(encode("\xF0") == u8"\\xF0");
|
CHECK(encode("\xF0") == "\\xF0");
|
||||||
CHECK(encode("\xF4") == u8"\\xF4");
|
CHECK(encode("\xF4") == "\\xF4");
|
||||||
|
|
||||||
// Missing second continuation byte
|
// Missing second continuation byte
|
||||||
CHECK(encode("\xE0\x80") == u8"\\xE0\\x80");
|
CHECK(encode("\xE0\x80") == "\\xE0\\x80");
|
||||||
CHECK(encode("\xE0\xBF") == u8"\\xE0\\xBF");
|
CHECK(encode("\xE0\xBF") == "\\xE0\\xBF");
|
||||||
CHECK(encode("\xE1\x80") == u8"\\xE1\\x80");
|
CHECK(encode("\xE1\x80") == "\\xE1\\x80");
|
||||||
CHECK(encode("\xF0\x80") == u8"\\xF0\\x80");
|
CHECK(encode("\xF0\x80") == "\\xF0\\x80");
|
||||||
CHECK(encode("\xF4\x80") == u8"\\xF4\\x80");
|
CHECK(encode("\xF4\x80") == "\\xF4\\x80");
|
||||||
|
|
||||||
// Missing third continuation byte
|
// Missing third continuation byte
|
||||||
CHECK(encode("\xF0\x80\x80") == u8"\\xF0\\x80\\x80");
|
CHECK(encode("\xF0\x80\x80") == "\\xF0\\x80\\x80");
|
||||||
CHECK(encode("\xF4\x80\x80") == u8"\\xF4\\x80\\x80");
|
CHECK(encode("\xF4\x80\x80") == "\\xF4\\x80\\x80");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#undef ESC
|
||||||
}
|
}
|
||||||
|
1
projects/SelfTest/Misc/invalid-test-names.input
Normal file
1
projects/SelfTest/Misc/invalid-test-names.input
Normal file
@@ -0,0 +1 @@
|
|||||||
|
Test with special, characters in \" name
|
@@ -13,6 +13,7 @@
|
|||||||
#include "reporters/catch_reporter_teamcity.hpp"
|
#include "reporters/catch_reporter_teamcity.hpp"
|
||||||
#include "reporters/catch_reporter_tap.hpp"
|
#include "reporters/catch_reporter_tap.hpp"
|
||||||
#include "reporters/catch_reporter_automake.hpp"
|
#include "reporters/catch_reporter_automake.hpp"
|
||||||
|
#include "reporters/catch_reporter_sonarqube.hpp"
|
||||||
|
|
||||||
|
|
||||||
// Some example tag aliases
|
// Some example tag aliases
|
||||||
|
@@ -126,5 +126,19 @@ TEST_CASE("Benchmark containers", "[!benchmark]") {
|
|||||||
REQUIRE(v[i] == generated);
|
REQUIRE(v[i] == generated);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SECTION("construct and destroy example") {
|
||||||
|
BENCHMARK_ADVANCED("construct")(Catch::Benchmark::Chronometer meter) {
|
||||||
|
std::vector<Catch::Benchmark::storage_for<std::string>> storage(meter.runs());
|
||||||
|
meter.measure([&](int i) { storage[i].construct("thing"); });
|
||||||
|
};
|
||||||
|
|
||||||
|
BENCHMARK_ADVANCED("destroy")(Catch::Benchmark::Chronometer meter) {
|
||||||
|
std::vector<Catch::Benchmark::destructable_object<std::string>> storage(meter.runs());
|
||||||
|
for(auto&& o : storage)
|
||||||
|
o.construct("thing");
|
||||||
|
meter.measure([&](int i) { storage[i].destruct(); });
|
||||||
|
};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#endif // CATCH_CONFIG_ENABLE_BENCHMARKING
|
#endif // CATCH_CONFIG_ENABLE_BENCHMARKING
|
||||||
|
@@ -205,10 +205,19 @@ namespace { namespace CompilationTests {
|
|||||||
inline static void synchronizing_callback( void * ) { }
|
inline static void synchronizing_callback( void * ) { }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if defined (_MSC_VER)
|
||||||
|
#pragma warning(push)
|
||||||
|
// The function pointer comparison below triggers warning because of
|
||||||
|
// calling conventions
|
||||||
|
#pragma warning(disable:4244)
|
||||||
|
#endif
|
||||||
TEST_CASE("#925: comparing function pointer to function address failed to compile", "[!nonportable]" ) {
|
TEST_CASE("#925: comparing function pointer to function address failed to compile", "[!nonportable]" ) {
|
||||||
TestClass test;
|
TestClass test;
|
||||||
REQUIRE(utility::synchronizing_callback != test.testMethod_uponComplete_arg);
|
REQUIRE(utility::synchronizing_callback != test.testMethod_uponComplete_arg);
|
||||||
}
|
}
|
||||||
|
#if defined (_MSC_VER)
|
||||||
|
#pragma warning(pop)
|
||||||
|
#endif
|
||||||
|
|
||||||
TEST_CASE( "#1027: Bitfields can be captured" ) {
|
TEST_CASE( "#1027: Bitfields can be captured" ) {
|
||||||
struct Y {
|
struct Y {
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user